[cipd] Try to bootstrap CIPD from scratch if selfupdate fails.
When updating the CIPD client to be identified by SHA256 hash, old clients (that
have no idea about SHA256) fail during 'selfupdate'.
We'll roll our SHA256 support in two stages:
1. Deploy new client that understand SHA256 using its SHA1 name, so
self-update from old clients works.
2. Deploy same (or newer) client using its SHA256 name. This would work since
the client doing the self-update already understands SHA256 at this point.
But we can't guarantee that ALL depot_tools deployments will update through
stages (1) and (2) sequentially. Some of them may skip (1) and end-up directly
in (2), failing on 'selfupdate'.
This CL makes sure they can recover from this state by rebootstraping the client
from scratch (this works with SHA256 hashes).
R=nodir@chromium.org, iannucci@chromium.org
BUG=821194
Change-Id: I27dece19e0305b5b2d6f8b0130631c1bf5f6499c
Reviewed-on: https://chromium-review.googlesource.com/1149454
Commit-Queue: Vadim Shtayura <vadimsh@chromium.org>
Reviewed-by: Robbie Iannucci <iannucci@chromium.org>
changes/54/1149454/9
parent
c87d45b102
commit
7e50ee376b
@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) 2018 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import unittest
|
||||
import tempfile
|
||||
|
||||
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
|
||||
# CIPD client version to use for self-update from an "old" checkout to the tip.
|
||||
#
|
||||
# This version is from Jan 2018.
|
||||
OLD_VERSION = 'git_revision:a1f61935faa60feb73e37556fdf791262c2dedce'
|
||||
|
||||
|
||||
class CipdBootstrapTest(unittest.TestCase):
|
||||
"""Tests that CIPD client can bootstrap from scratch and self-update from some
|
||||
old version to a most recent one.
|
||||
|
||||
WARNING: This integration test touches real network and real CIPD backend and
|
||||
downloads several megabytes of stuff.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.tempdir = tempfile.mkdtemp('depot_tools_cipd')
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.tempdir)
|
||||
|
||||
def stage_files(self, cipd_version=None):
|
||||
"""Copies files needed for cipd bootstrap into the temp dir.
|
||||
|
||||
Args:
|
||||
cipd_version: if not None, a value to put into cipd_client_version file.
|
||||
"""
|
||||
for f in ('cipd', 'cipd.bat', 'cipd.ps1', 'cipd_client_version'):
|
||||
shutil.copy2(os.path.join(ROOT_DIR, f), os.path.join(self.tempdir, f))
|
||||
if cipd_version is not None:
|
||||
with open(os.path.join(self.tempdir, 'cipd_client_version'), 'wt') as f:
|
||||
f.write(cipd_version+'\n')
|
||||
|
||||
def call_cipd_help(self):
|
||||
"""Calls 'cipd help' bootstrapping the client in tempdir.
|
||||
|
||||
Returns (exit code, merged stdout and stderr).
|
||||
"""
|
||||
exe = 'cipd.bat' if sys.platform == 'win32' else 'cipd'
|
||||
p = subprocess.Popen(
|
||||
[os.path.join(self.tempdir, exe), 'help'],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
out, _ = p.communicate()
|
||||
return p.returncode, out
|
||||
|
||||
def test_new_bootstrap(self):
|
||||
"""Bootstrapping the client from scratch."""
|
||||
self.stage_files()
|
||||
ret, out = self.call_cipd_help()
|
||||
if ret:
|
||||
self.fail('Bootstrap from scratch failed:\n%s' % out)
|
||||
|
||||
def test_self_update(self):
|
||||
"""Updating the existing client in-place."""
|
||||
self.stage_files(cipd_version=OLD_VERSION)
|
||||
ret, out = self.call_cipd_help()
|
||||
if ret:
|
||||
self.fail('Update to %s fails:\n%s' % (OLD_VERSION, out))
|
||||
self.stage_files()
|
||||
ret, out = self.call_cipd_help()
|
||||
if ret:
|
||||
self.fail('Update from %s to the tip fails:\n%s' % (OLD_VERSION, out))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Loading…
Reference in New Issue