Update prebuilt.py to sync to latest revision before pushing.
Sync prebuilt.py to trunk commit 1b6e67aef79696d74bcee3d2fce252c8397e592a.
Rev log below.
commit 1b6e67aef79696d74bcee3d2fce252c8397e592a
Author: David James <davidjames@chromium.org>
Date: Thu May 19 21:32:38 2011 -0700
Update prebuilt.py to sync to latest revision before pushing.
This fixes a bug where prebuilt.py is unable to push if it is using
manifest-versions to sync to an old revision. This bug occurs because
manifest-versions is pointing at an old version of the repository so
the prebuilt pusher is never able to push.
BUG=chrome-os-partner:3959
TEST=Test with --dry-run push. Also run unit test suite.
Change-Id: Ie4c03ab19a4de108df9a4a63edf2614b06fe1698
Reviewed-on: http://gerrit.chromium.org/gerrit/1239
Reviewed-by: Chris Sosa <sosa@chromium.org>
Tested-by: David James <davidjames@chromium.org>
commit fe0e68791efe2ee3a56ef6d1256e072f189d78ae
Author: Peter Mayo <petermayo@chromium.org>
Date: Wed Apr 20 00:52:08 2011 -0400
Fix trailing characters in commit
Change-Id: I9945d92432a349098578c4549715df4b9826fa15
BUG=crbug:79976
TEST=prebuilt unittest
Review URL: http://codereview.chromium.org/6882070
commit 193f68f10bf5d9379847f42b1f3f367e865beee0
Author: Peter Mayo <petermayo@chromium.org>
Date: Tue Apr 19 19:08:21 2011 -0400
Restart codereview issue 6792042
Change-Id: I052d4d713a7d15cc50290e68bc433a9f1c0792b4
BUG=78345
TEST=unittests
Review URL: http://codereview.chromium.org/6840064
commit f0e6fd7b0513295d7cc9386001d2034eb8ced342
Author: David James <davidjames@chromium.org>
Date: Fri Apr 15 15:58:07 2011 -0700
Fix typo in Packages URLs.
BUG=none
TBR=scottz@chromium.org
TEST=Ran unit tests
Change-Id: I2941d5313250c372f167175ae9196f266712e4db
Review URL: http://codereview.chromium.org/6871033
commit 8fa34ea013e00421d1c8e6b6cf5f5b221ae20cad
Author: David James <davidjames@chromium.org>
Date: Fri Apr 15 13:00:20 2011 -0700
Update prebuilt.py to support uploading a board tarball to Google Storage.
Change-Id: Ic81562ce7b6370924e0aa1bf49ecf552720b3c75
R=scottz@chromium.org
BUG=chromium-os:8777
TEST=Upload prebuilts with and without board tarball. Ran unit tests.
Review URL: http://codereview.chromium.org/6851021
commit f4db112778f374ecef9ffa6508f402109b1d50c4
Author: David James <davidjames@chromium.org>
Date: Thu Mar 17 16:18:05 2011 -0700
Fix bug in prebuilt.py where None is substituted into a string.
Change-Id: I4c69375b0f0fca38c06e8ee97a68568337b4768c
R=scottz@chromium.org
BUG=None
TEST=Run prebuilt_unittest.py
Review URL: http://codereview.chromium.org/6690026
commit ab1bed3ac39a768cd37cbf8269402eb74b47ab4e
Author: Scott Zawalski <scottz@google.com>
Date: Wed Mar 16 15:24:24 2011 -0700
Update prebuilt.py to handle private google storage uploads.
Remove boto configuration, anyone using this script should either have ~/.boto set
or they should be starting it with BOTO_CONFIG=....
Add in support for acl xml files, If we pass an ACL xml file we first upload the file to
google storage with the canned acl of private then apply the ACL.
Automatically derive the binhost_url for private Google Storage uploads and warn
if people set --private and --binhost-base-url.
Update unittests to pass with the new private assumptions.
BUG=NA
TEST=Ran on a canary build chroot to make sure we upload and set URLs properly
Review URL: http://codereview.chromium.org/6677023
Change-Id: I60be80ef9645b3eec2495a73011688dcec09c60b
Reviewed-on: http://gerrit.chromium.org/gerrit/1698
Tested-by: David James <davidjames@chromium.org>
Reviewed-by: David James <davidjames@chromium.org>
diff --git a/buildbot/prebuilt.py b/buildbot/prebuilt.py
index cf93078..2945e64 100755
--- a/buildbot/prebuilt.py
+++ b/buildbot/prebuilt.py
@@ -51,10 +51,10 @@
_CATEGORIES_PATH = 'chroot/etc/portage/categories'
_HOST_TARGET = 'amd64'
_BOARD_PATH = 'chroot/build/%(board)s'
-# board/board-target/version/packages/'
-_REL_BOARD_PATH = 'board/%(board)s/%(version)s/packages'
-# host/host-target/version/packages/'
-_REL_HOST_PATH = 'host/%(target)s/%(version)s/packages'
+# board/board-target/version/'
+_REL_BOARD_PATH = 'board/%(board)s/%(version)s'
+# host/host-target/version/'
+_REL_HOST_PATH = 'host/%(target)s/%(version)s'
# Private overlays to look at for builds to filter
# relative to build path
_PRIVATE_OVERLAY_DIR = 'src/private-overlays'
@@ -131,10 +131,12 @@
new_file_fh.close()
-def RevGitPushWithRetry(retries=5):
+def RevGitPushWithRetry(tracking_branch, cwd, retries=5):
"""Repo sync and then push git changes in flight.
Args:
+ tracking_branch: Branch to rebase against.
+ cwd: Directory to push in.
retries: The number of times to retry before giving up, default: 5
Raises:
@@ -142,8 +144,9 @@
"""
for retry in range(1, retries + 1):
try:
- cros_build_lib.RunCommand('repo sync .', shell=True)
- cros_build_lib.RunCommand('git push', shell=True)
+ cros_build_lib.RunCommand(['git', 'remote', 'update'], cwd=cwd)
+ cros_build_lib.RunCommand(['git', 'rebase', tracking_branch], cwd=cwd)
+ cros_build_lib.RunCommand(['git', 'push'], cwd=cwd)
break
except cros_build_lib.RunCommandError:
if retry < retries:
@@ -153,6 +156,22 @@
raise GitPushFailed('Failed to push change after %s retries' % retries)
+def _GetTrackingBranch(branch, cwd):
+ """Get the tracking branch for the specified branch / directory.
+
+ Args:
+ branch: Branch to examine for tracking branch.
+ cwd: Directory to look in.
+ """
+ info = {}
+ for key in ('remote', 'merge'):
+ cmd = ['git', 'config', 'branch.%s.%s' % (branch, key)]
+ info[key] = cros_build_lib.RunCommand(cmd, redirect_stdout=True,
+ cwd=cwd).output.strip()
+ assert info["merge"].startswith("refs/heads/")
+ return info["merge"].replace("refs/heads", info["remote"])
+
+
def RevGitFile(filename, value, retries=5, key='PORTAGE_BINHOST'):
"""Update and push the git file.
@@ -165,28 +184,31 @@
(Default: PORTAGE_BINHOST)
"""
prebuilt_branch = 'prebuilt_branch'
- old_cwd = os.getcwd()
- os.chdir(os.path.dirname(filename))
-
- commit = cros_build_lib.RunCommand('git rev-parse HEAD', shell=True,
- redirect_stdout=True).output
- cros_build_lib.RunCommand('git remote update', shell=True)
- cros_build_lib.RunCommand('repo start %s .' % prebuilt_branch, shell=True)
- git_ssh_config_cmd = (
- 'git config url.ssh://git@gitrw.chromium.org:9222.pushinsteadof '
- 'http://git.chromium.org/git')
- cros_build_lib.RunCommand(git_ssh_config_cmd, shell=True)
+ cwd = os.path.abspath(os.path.dirname(filename))
+ commit = cros_build_lib.RunCommand(['git', 'rev-parse', 'HEAD'], cwd=cwd,
+ redirect_stdout=True).output.rstrip()
+ git_ssh_config_cmd = [
+ 'git',
+ 'config',
+ 'url.ssh://gerrit.chromium.org:29418.insteadof',
+ 'http://git.chromium.org']
+ cros_build_lib.RunCommand(git_ssh_config_cmd, cwd=cwd)
+ cros_build_lib.RunCommand(['git', 'remote', 'update'], cwd=cwd)
+ cros_build_lib.RunCommand(['repo', 'start', prebuilt_branch, '.'], cwd=cwd)
+ tracking_branch = _GetTrackingBranch(prebuilt_branch, cwd=cwd)
description = 'Update %s="%s" in %s' % (key, value, filename)
print description
try:
UpdateLocalFile(filename, value, key)
- cros_build_lib.RunCommand('git config push.default tracking', shell=True)
- cros_build_lib.RunCommand('git commit -am "%s"' % description, shell=True)
- RevGitPushWithRetry(retries)
+ cros_build_lib.RunCommand(['git', 'config', 'push.default', 'tracking'],
+ cwd=cwd)
+ cros_build_lib.RunCommand(['git', 'add', filename], cwd=cwd)
+ cros_build_lib.RunCommand(['git', 'commit', '-m', description], cwd=cwd)
+ RevGitPushWithRetry(tracking_branch, cwd, retries)
finally:
- cros_build_lib.RunCommand('repo abandon %s .' % prebuilt_branch, shell=True)
- cros_build_lib.RunCommand('git checkout %s' % commit, shell=True)
- os.chdir(old_cwd)
+ cros_build_lib.RunCommand(['git', 'checkout', commit], cwd=cwd)
+ cros_build_lib.RunCommand(['repo', 'abandon', 'prebuilt_branch', '.'],
+ cwd=cwd)
def GetVersion():
@@ -240,7 +262,7 @@
return False
-def _RetryRun(cmd, print_cmd=True, shell=False, cwd=None):
+def _RetryRun(cmd, print_cmd=True, cwd=None):
"""Run the specified command, retrying if necessary.
Args:
@@ -257,13 +279,13 @@
# cros_build_lib.
for attempt in range(_RETRIES):
try:
- output = cros_build_lib.RunCommand(cmd, print_cmd=print_cmd, shell=shell,
+ output = cros_build_lib.RunCommand(cmd, print_cmd=print_cmd,
cwd=cwd)
return True
except cros_build_lib.RunCommandError:
- print 'Failed to run %s' % cmd
+ print 'Failed to run %r' % cmd
else:
- print 'Retry failed run %s, giving up' % cmd
+ print 'Retry failed run %r, giving up' % cmd
return False
@@ -283,11 +305,11 @@
'public-read-write']
acl_cmd = None
if acl in CANNED_ACLS:
- cmd = '%s cp -a %s %s %s' % (_GSUTIL_BIN, acl, local_file, remote_file)
+ cmd = [_GSUTIL_BIN, 'cp', '-a', acl, local_file, remote_file]
else:
# For private uploads we assume that the overlay board is set up properly
# and a googlestore_acl.xml is present, if not this script errors
- cmd = '%s cp -a private %s %s' % (_GSUTIL_BIN, local_file, remote_file)
+ cmd = [_GSUTIL_BIN, 'cp', '-a', 'private', local_file, remote_file]
if not os.path.exists(acl):
print >> sys.stderr, ('You are specifying either a file that does not '
'exist or an unknown canned acl: %s. Aborting '
@@ -295,14 +317,14 @@
# emulate the failing of an upload since we are not uploading the file
return (local_file, remote_file)
- acl_cmd = '%s setacl %s %s' % (_GSUTIL_BIN, acl, remote_file)
+ acl_cmd = [_GSUTIL_BIN, 'setacl', acl, remote_file]
- if not _RetryRun(cmd, print_cmd=False, shell=True):
+ if not _RetryRun(cmd, print_cmd=False):
return (local_file, remote_file)
if acl_cmd:
# Apply the passed in ACL xml file to the uploaded object.
- _RetryRun(acl_cmd, print_cmd=False, shell=True)
+ _RetryRun(acl_cmd, print_cmd=False)
def RemoteUpload(acl, files, pool=10):
@@ -422,10 +444,9 @@
config_file = file(path, 'w')
config_file.close()
UpdateLocalFile(path, value, key)
- cros_build_lib.RunCommand('git add %s' % filename, cwd=cwd, shell=True)
+ cros_build_lib.RunCommand(['git', 'add', filename], cwd=cwd)
description = 'Update %s=%s in %s' % (key, value, filename)
- cros_build_lib.RunCommand('git commit -m "%s"' % description, cwd=cwd,
- shell=True)
+ cros_build_lib.RunCommand(['git', 'commit', '-m', description], cwd=cwd)
def _GrabAllRemotePackageIndexes(binhost_urls):
@@ -499,21 +520,45 @@
error_msg = ['%s -> %s\n' % args for args in failed_uploads if args]
raise UploadFailed('Error uploading:\n%s' % error_msg)
else:
- pkgs = ' '.join(p['CPV'] + '.tbz2' for p in uploads)
+ pkgs = [p['CPV'] + '.tbz2' for p in uploads]
ssh_server, remote_path = remote_location.split(':', 1)
- d = { 'pkg_index': tmp_packages_file.name,
- 'pkgs': pkgs,
- 'remote_packages': '%s/Packages' % remote_location.rstrip('/'),
- 'remote_path': remote_path.rstrip('/'),
- 'remote_location': remote_location.rstrip('/'),
- 'ssh_server': ssh_server }
- cmds = ['ssh %(ssh_server)s mkdir -p %(remote_path)s' % d,
- 'rsync -av --chmod=a+r %(pkg_index)s %(remote_packages)s' % d]
+ remote_path = remote_path.rstrip('/')
+ pkg_index = tmp_packages_file.name
+ remote_location = remote_location.rstrip('/')
+ remote_packages = '%s/Packages' % remote_location
+ cmds = [['ssh', ssh_server, 'mkdir', '-p', remote_path],
+ ['rsync', '-av', '--chmod=a+r', pkg_index, remote_packages]]
if pkgs:
- cmds.append('rsync -Rav %(pkgs)s %(remote_location)s/' % d)
+ cmds.append(['rsync', '-Rav'] + pkgs + [remote_location + '/'])
for cmd in cmds:
- if not _RetryRun(cmd, shell=True, cwd=package_path):
- raise UploadFailed('Could not run %s' % cmd)
+ if not _RetryRun(cmd, cwd=package_path):
+ raise UploadFailed('Could not run %r' % cmd)
+
+ def _UploadBoardTarball(self, board_path, url_suffix):
+ """Upload a tarball of the board at the specified path to Google Storage.
+
+ Args:
+ board_path: The path to the board dir.
+ url_suffix: The remote subdirectory where we should upload the packages.
+ """
+ remote_location = '%s/%s' % (self._upload_location.rstrip('/'), url_suffix)
+ assert remote_location.startswith('gs://')
+ cwd, boardname = os.path.split(board_path.rstrip(os.path.sep))
+ tmpdir = tempfile.mkdtemp()
+ try:
+ tarfile = os.path.join(tmpdir, '%s.tbz2' % boardname)
+ cmd = ['sudo', 'tar', '-I', 'pbzip2', '-cf', tarfile]
+ excluded_paths = ('usr/lib/debug', 'usr/local/autotest', 'packages',
+ 'tmp')
+ for path in excluded_paths:
+ cmd.append('--exclude=%s/%s/*' % (boardname, path))
+ cmd.append(boardname)
+ cros_build_lib.RunCommand(cmd, cwd=cwd)
+ remote_tarfile = '%s/%s.tbz2' % (remote_location.rstrip('/'), boardname)
+ if _GsUpload((tarfile, remote_tarfile, self._acl)):
+ sys.exit(1)
+ finally:
+ cros_build_lib.RunCommand(['sudo', 'rm', '-rf', tmpdir], cwd=cwd)
def _SyncHostPrebuilts(self, build_path, version, key, git_sync,
sync_binhost_conf):
@@ -540,11 +585,12 @@
# Upload prebuilts.
package_path = os.path.join(build_path, _HOST_PACKAGES_PATH)
url_suffix = _REL_HOST_PATH % {'version': version, 'target': _HOST_TARGET}
- self._UploadPrebuilt(package_path, url_suffix)
+ packages_url_suffix = '%s/packages' % url_suffix.rstrip('/')
+ self._UploadPrebuilt(package_path, packages_url_suffix)
# Record URL where prebuilts were uploaded.
url_value = '%s/%s/' % (self._binhost_base_url.rstrip('/'),
- url_suffix.rstrip('/'))
+ packages_url_suffix.rstrip('/'))
if git_sync:
git_file = os.path.join(build_path, _PREBUILT_MAKE_CONF[_HOST_TARGET])
RevGitFile(git_file, url_value, key=key)
@@ -554,7 +600,7 @@
UpdateBinhostConfFile(binhost_conf, key, url_value)
def _SyncBoardPrebuilts(self, board, build_path, version, key, git_sync,
- sync_binhost_conf):
+ sync_binhost_conf, upload_board_tarball):
"""Synchronize board prebuilt files.
Args:
@@ -567,16 +613,30 @@
prebuilt packages generated here.
sync_binhost_conf: If set, update binhost config file in
chromiumos-overlay for the current board.
+ upload_board_tarball: Include a tarball of the board in our upload.
"""
- # Upload prebuilts.
board_path = os.path.join(build_path, _BOARD_PATH % {'board': board})
package_path = os.path.join(board_path, 'packages')
url_suffix = _REL_BOARD_PATH % {'board': board, 'version': version}
- self._UploadPrebuilt(package_path, url_suffix)
+ packages_url_suffix = '%s/packages' % url_suffix.rstrip('/')
+
+ # Upload board tarballs in the background.
+ if upload_board_tarball:
+ tar_process = multiprocessing.Process(target=self._UploadBoardTarball,
+ args=(board_path, url_suffix))
+ tar_process.start()
+
+ # Upload prebuilts.
+ self._UploadPrebuilt(package_path, packages_url_suffix)
+
+ # Make sure we finished uploading the board tarballs.
+ if upload_board_tarball:
+ tar_process.join()
+ assert tar_process.exitcode == 0
# Record URL where prebuilts were uploaded.
url_value = '%s/%s/' % (self._binhost_base_url.rstrip('/'),
- url_suffix.rstrip('/'))
+ packages_url_suffix.rstrip('/'))
if git_sync:
git_file = DeterminePrebuiltConfFile(build_path, board)
RevGitFile(git_file, url_value, key=key)
@@ -627,6 +687,9 @@
help='Update binhost.conf')
parser.add_option('-P', '--private', dest='private', action='store_true',
default=False, help='Mark gs:// uploads as private.')
+ parser.add_option('', '--upload-board-tarball', dest='upload_board_tarball',
+ action='store_true', default=False,
+ help='Upload board tarball to Google Storage.')
options, args = parser.parse_args()
if not options.build_path:
@@ -634,6 +697,11 @@
if not options.upload:
usage(parser, 'Error: you need to provide an upload location using -u')
+
+ if options.upload_board_tarball and not options.upload.startswith('gs://'):
+ usage(parser, 'Error: --upload-board-tarball only works with gs:// URLs.\n'
+ '--upload must be a gs:// URL.')
+
if options.private:
if options.sync_host:
usage(parser, 'Error: --private and --sync-host/-s cannot be specified '
@@ -684,7 +752,8 @@
if options.board:
uploader._SyncBoardPrebuilts(options.board, options.build_path, version,
options.key, options.git_sync,
- options.sync_binhost_conf)
+ options.sync_binhost_conf,
+ options.upload_board_tarball)
if __name__ == '__main__':
main()
diff --git a/buildbot/prebuilt_unittest.py b/buildbot/prebuilt_unittest.py
index 27506a3..ef5f25c 100755
--- a/buildbot/prebuilt_unittest.py
+++ b/buildbot/prebuilt_unittest.py
@@ -6,6 +6,7 @@
import copy
import mox
import os
+import multiprocessing
import shutil
import sys
import tempfile
@@ -397,11 +398,12 @@
self.mox.StubOutWithMock(prebuilt, '_RetryRun')
remote_path = '/dir/%s' % suffix.rstrip('/')
full_remote_path = 'chromeos-prebuilt:%s' % remote_path
- cmds = ['ssh chromeos-prebuilt mkdir -p %s' % remote_path,
- 'rsync -av --chmod=a+r fake %s/Packages' % full_remote_path,
- 'rsync -Rav private.tbz2 %s/' % full_remote_path]
+ cmds = [['ssh', 'chromeos-prebuilt', 'mkdir', '-p', remote_path],
+ ['rsync', '-av', '--chmod=a+r', 'fake',
+ full_remote_path + '/Packages'],
+ ['rsync', '-Rav', 'private.tbz2', full_remote_path + '/']]
for cmd in cmds:
- prebuilt._RetryRun(cmd, shell=True, cwd='/packages').AndReturn(True)
+ prebuilt._RetryRun(cmd, cwd='/packages').AndReturn(True)
self.mox.ReplayAll()
uri = self.pkgindex.header['URI']
uploader = prebuilt.PrebuiltUploader('chromeos-prebuilt:/dir',
@@ -441,8 +443,8 @@
self.version = '1'
self.binhost = 'http://prebuilt/'
self.key = 'PORTAGE_BINHOST'
- self.uploader = prebuilt.PrebuiltUploader(self.upload_location,
- 'public-read', self.binhost, [])
+ self.uploader = prebuilt.PrebuiltUploader(
+ self.upload_location, 'public-read', self.binhost, [])
self.mox.StubOutWithMock(self.uploader, '_UploadPrebuilt')
def tearDown(self):
@@ -454,8 +456,10 @@
prebuilt._HOST_PACKAGES_PATH)
url_suffix = prebuilt._REL_HOST_PATH % {'version': self.version,
'target': prebuilt._HOST_TARGET }
- self.uploader._UploadPrebuilt(package_path, url_suffix)
- url_value = '%s/%s/' % (self.binhost.rstrip('/'), url_suffix.rstrip('/'))
+ packages_url_suffix = '%s/packages' % url_suffix.rstrip('/')
+ self.uploader._UploadPrebuilt(package_path, packages_url_suffix)
+ url_value = '%s/%s/' % (self.binhost.rstrip('/'),
+ packages_url_suffix.rstrip('/'))
prebuilt.RevGitFile(mox.IgnoreArg(), url_value, key=self.key)
prebuilt.UpdateBinhostConfFile(mox.IgnoreArg(), self.key, url_value)
self.mox.ReplayAll()
@@ -469,14 +473,26 @@
package_path = os.path.join(board_path, 'packages')
url_suffix = prebuilt._REL_BOARD_PATH % {'version': self.version,
'board': board }
- self.uploader._UploadPrebuilt(package_path, url_suffix)
- url_value = '%s/%s/' % (self.binhost.rstrip('/'), url_suffix.rstrip('/'))
+ packages_url_suffix = '%s/packages' % url_suffix.rstrip('/')
+ process = None
+ self.mox.StubOutWithMock(multiprocessing.Process, '__init__')
+ self.mox.StubOutWithMock(multiprocessing.Process, 'exitcode')
+ self.mox.StubOutWithMock(multiprocessing.Process, 'start')
+ self.mox.StubOutWithMock(multiprocessing.Process, 'join')
+ multiprocessing.Process.__init__(target=self.uploader._UploadBoardTarball,
+ args=(board_path, url_suffix))
+ multiprocessing.Process.start()
+ self.uploader._UploadPrebuilt(package_path, packages_url_suffix)
+ multiprocessing.Process.join()
+ multiprocessing.Process.exitcode = 0
+ url_value = '%s/%s/' % (self.binhost.rstrip('/'),
+ packages_url_suffix.rstrip('/'))
prebuilt.DeterminePrebuiltConfFile(self.build_path, board).AndReturn('foo')
prebuilt.RevGitFile('foo', url_value, key=self.key)
prebuilt.UpdateBinhostConfFile(mox.IgnoreArg(), self.key, url_value)
self.mox.ReplayAll()
self.uploader._SyncBoardPrebuilts(board, self.build_path, self.version,
- self.key, True, True)
+ self.key, True, True, True)
class TestMain(unittest.TestCase):
@@ -498,6 +514,7 @@
options.private = True
options.sync_host = True
options.git_sync = True
+ options.upload_board_tarball = True
options.upload = 'gs://upload/'
options.binhost_base_url = options.upload
options.prepend_version = True
@@ -526,7 +543,7 @@
self.mox.StubOutWithMock(prebuilt.PrebuiltUploader, '_SyncBoardPrebuilts')
prebuilt.PrebuiltUploader._SyncBoardPrebuilts(options.board,
options.build_path, mox.IgnoreArg(), options.key, options.git_sync,
- options.sync_binhost_conf)
+ options.sync_binhost_conf, options.upload_board_tarball)
self.mox.ReplayAll()
prebuilt.main()