Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(97)

Unified Diff: scripts/slave/recipes/infra/gae_sdk_cipd_packager.py

Issue 2355483004: Add CIPD GAE SDK recipe module and packager. (Closed)
Patch Set: pylint Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: scripts/slave/recipes/infra/gae_sdk_cipd_packager.py
diff --git a/scripts/slave/recipes/infra/gae_sdk_cipd_packager.py b/scripts/slave/recipes/infra/gae_sdk_cipd_packager.py
new file mode 100644
index 0000000000000000000000000000000000000000..be49e4ebcd7fd31e236f4bf6fd1dd85ba2545686
--- /dev/null
+++ b/scripts/slave/recipes/infra/gae_sdk_cipd_packager.py
@@ -0,0 +1,164 @@
+# Copyright 2016 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 collections
+import re
+
+
+DEPS = [
+ 'depot_tools/cipd',
+ 'gae_sdk',
+ 'gsutil',
+ 'recipe_engine/path',
+ 'recipe_engine/python',
+ 'recipe_engine/raw_io',
+ 'recipe_engine/step',
+ 'zip',
+]
+
+# CIPD builder service account, deployed by Puppet.
+_CIPD_CREDENTIAL_PATH = ('/creds/service_accounts/'
+ 'service-account-cipd-builder.json')
+
+
+def RunSteps(api):
+ pb = _PackageBuilder(api)
+
+ # Determine the current GAE SDK version.
+ try:
+ version = pb.latest_upstream_version()
+ except pb.VersionParseError as e:
+ api.python.failing_step('Version Fetch',
+ 'Failed to fetch latest version: %s' % (e,))
+
+ # Make sure the CIPD client is installed.
+ api.cipd.install_client()
+ api.cipd.set_service_account_credentials(_CIPD_CREDENTIAL_PATH)
+
+ # Iterate over all of the GAE SDK packages and build any that don't exist.
+ version_tag = pb.version_tag(version)
+ pkg_outdir = api.path.mkdtemp('gae_sdk_package')
+ for plat, arch in api.gae_sdk.all_packages:
+ pkg_name = api.gae_sdk.package(plat, arch=arch)
+ with api.step.nest('Sync %s' % (pkg_name,)):
+ step = api.cipd.search(pkg_name, '%s:%s' % (version_tag))
+ if len(step.json.output['result']) > 0:
+ api.python.succeeding_step('Synced', 'Package is up to date.')
+ continue
+
+ # Create a temporary directory to build the package in.
+ pkg_base = pb.download_and_unpack(plat, arch, version)
+
+ # Build and register our CIPD package.
+ pkg_path = pkg_outdir.join('gae_sdk_%s_%s.pkg' % (plat, arch))
+ api.cipd.build(
+ pkg_base,
+ pkg_path,
+ pkg_name,
+ install_mode='copy',
+ )
+ api.cipd.register(
+ pkg_name,
+ pkg_path,
+ refs=[api.gae_sdk.latest_ref],
+ tags={version_tag[0]: version_tag[1]},
+ )
+
+
+class _PackageBuilder(object):
+ # The Google Storage GAE SDK bucket base. All SDK packages are stored in here
+ # under a basename + version ZIP file.
+ _GS_BUCKET_BASE = 'gs://appengine-sdks/featured'
+ # The GS path to the "LATEST" YAML file.
+ _GS_VERSION_YAML = '%s/VERSION' % (_GS_BUCKET_BASE,)
+
+ # Hacky regex for the "release" YAML variable.
+ _RE_RELEASE = re.compile(r'^release:\s+"([^"]+)"$')
+
+ class VersionParseError(Exception):
+ pass
+
+ def __init__(self, api):
+ self._api = api
+
+ def version_tag(self, version):
+ return ('gae_sdk_version', version)
+
+ @property
+ def api(self):
+ return self._api
+
+ def latest_upstream_version(self):
+ step_result = self.api.gsutil.cat(
+ self._GS_VERSION_YAML,
+ name='Get Latest',
+ stdout=self.api.raw_io.output())
+ latest = self._parse_latest_yaml(step_result.stdout)
+ step_result.presentation.step_text += ' %s' % (latest,)
+ return latest
+
+ @classmethod
+ def _parse_latest_yaml(cls, text):
+ # Rather than import a YAML parser, we will specifically search for the
+ # string:
+ #
+ # release: "<version>"
+ for line in text.splitlines():
+ m = cls._RE_RELEASE.match(line)
+ if m:
+ return m.group(1)
+ raise cls.VersionParseError('Could not parse release version from YAML.')
+
+ def download_and_unpack(self, plat, arch, version):
+ # Get the package base for this OS.
+ _, base, dirname = self.api.gae_sdk.package_spec(plat, arch)
+ name = '%s%s.zip' % (base, version)
+ artifact_url = '%s/%s' % (self._GS_BUCKET_BASE, name)
+
+ tdir = self.api.path.mkdtemp('gae_sdk')
+ dst = tdir.join(name) # Store the ZIP file here.
+ unzip_dir = tdir.join('unpack') # Unzip contents here.
+ self.api.gsutil.download_url(
+ artifact_url,
+ dst,
+ name='Download %s %s' % (plat, arch,))
+ self.api.zip.unzip(
+ 'Unzip %s %s' % (plat, arch),
+ dst,
+ unzip_dir,
+ quiet=True)
+
+ pkg_dir = unzip_dir.join(dirname)
+ self.api.path.mock_add_paths(pkg_dir)
+ assert self.api.path.exists(pkg_dir), (
+ 'Package directory [%s] does not exist' % (pkg_dir,))
+ return pkg_dir
+
+
+def GenTests(api):
+ LATEST_YAML = '\n'.join((
+ 'release: "1.2.3"',
+ 'foo: bar',
+ 'baz:',
+ ' - qux',
+ ))
+
+ def cipd_pkg(plat, pkg_base, exists):
+ pkg_name = 'infra/gae_sdk/%s/%s' % (plat, pkg_base)
+ cipd_step = 'cipd search %s gae_sdk_version:1.2.3' % (pkg_name,)
+ instances = (2) if exists else (0)
+ return api.step_data('Sync %s.%s' % (pkg_name, cipd_step),
+ api.cipd.example_search(pkg_name, instances=instances))
+
+ yield (api.test('packages') +
+ api.step_data('gsutil Get Latest',
+ api.raw_io.stream_output(LATEST_YAML, stream='stdout')) +
+ cipd_pkg('go', 'linux-amd64', False) +
+ cipd_pkg('go', 'linux-386', True) +
+ cipd_pkg('go', 'mac-amd64', True) +
+ cipd_pkg('python', 'all', False))
+
+ yield (api.test('bad_version_yaml') +
+ api.step_data('gsutil Get Latest',
+ api.raw_io.stream_output('', stream='stdout')))

Powered by Google App Engine
This is Rietveld 408576698