blob: edcccd86ca3b2e6fc1ef5ccfab18f927086e96b5 [file] [log] [blame]
# Copyright 2019 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Recipe for rolling a CIPD package which other packages depend on."""
from recipe_engine.config import List
from recipe_engine.post_process import StepSuccess
from recipe_engine.recipe_api import Property
DEPS = [
'fuchsia/jiri',
'fuchsia/auto_roller',
'fuchsia/cipd_dependencies',
'recipe_engine/archive',
'recipe_engine/buildbucket',
'recipe_engine/cipd',
'recipe_engine/context',
'recipe_engine/file',
'recipe_engine/json',
'recipe_engine/properties',
'recipe_engine/path',
'recipe_engine/step',
]
PROPERTIES = {
'manifests':
Property(
kind=List(dict),
help=(
'A list of dictionaries with project, manifest and remote key.'
)),
'package':
Property(
kind=str, help='The list of CIPD packages to update in $import_in'),
'ref':
Property(
kind=str,
default='latest',
help='A common CIPD ref to resolve when rolling a set of packages'),
'owners':
Property(
kind=List(str),
default=(),
help=('The owners responsible for watching this roller '
'(example: "username@google.com").')),
'dependents':
Property(
kind=List(dict), default=(),
help=('Dependent package properties.')),
'versions_file':
Property(
kind=str,
help=('A string with the path to the versions file inside '
'the CIPD package.'))
}
COMMIT_MESSAGE = """[roll] Roll {roller} CIPD packages:
{packages}
From: {old_version}
To: {version}
Test: CQ
CQ-Do-Not-Cancel-Tryjobs: true"""
CIPD_URL = 'https://chrome-infra-packages.appspot.com/p/{package}/+/{version}'
def RunSteps(api, manifests, ref, owners, versions_file, dependents, package):
"""Run the recipe steps."""
with api.context(infra_steps=True):
if owners:
with api.step.nest('owners') as owners_presentation:
owners_presentation.step_summary_text = ', '.join(owners)
# Import manifests
api.jiri.init(use_lock_file=True)
for manifest_config in manifests:
api.jiri.import_manifest(
manifest=manifest_config['manifest'],
remote=manifest_config['remote'],
name=manifest_config['project'])
api.jiri.update(run_hooks=False)
api.jiri.run_hooks()
deps_info = api.jiri.package([package])
cipd_description = api.cipd.describe(package, ref)
# Is there a new version to roll?
if cipd_description.tags[0].tag == deps_info.json.output[0]['version']:
api.step('manifest up-to-date; nothing to roll', None)
return
# Read main package versions file.
main_package_version_dict = api.cipd_dependencies.get_dependencies(
'read versions', package, cipd_description.pin.instance_id, versions_file)
# For every dependent read version file and validate versions.
validation_summary = []
for dep in dependents:
cipd_dep_desc = api.cipd.describe(dep['package'], dep['ref'])
version_dict = api.cipd_dependencies.get_dependencies(
'read dep versions', dep['package'], cipd_dep_desc.pin.instance_id,
dep['versions_file'])
summary = api.cipd_dependencies.validate_against_package(
package=dep,
dependencies=dep['dependencies'],
package_versions=main_package_version_dict,
dependent_versions=version_dict)
if summary:
validation_summary.append(summary)
if validation_summary:
msg = 'Project-dependent version mismatching: {}'.format(
'\n'.join(validation_summary))
# After a new version of the main package is available, dependents may still
# need more time to build versions with it. We mark this step as successful
# to avoid disruption to build cops looking for a solution to something that
# is expected.
api.step('validation_summary', cmd=None).presentation.step_text = msg
return
# Roll everything
api.step('Rolling-Success', None)
def GenTests(api):
properties = {
'manifests': [{
'project': 'integration',
'manifest': 'other/dependency',
'remote': 'sso://fuchsia/integration'
}, {
'project': 'integration',
'manifest': 'fuchsia/flower',
'remote': 'sso://fuchsia/integration'
}],
'package': 'flutter/fuchsia/${platform}',
'package_dependencies': [
'package=dart',
'project=skia',
],
'dependents': [{
'package': 'abc/dependent',
'ref': 'latest',
'versions_file': 'dependent.json',
'dependencies': ['engine_version']
}],
'import_in': 'fuchsia/prebuilts',
'versions_file': 'flutter/versions.json',
'owners': ['abc@gmail.com']
}
package_no_match_test_data = api.step_data(
'cipd describe flutter/fuchsia/${platform}',
api.cipd.example_describe(
package_name='flutter/fuchsia',
version='version_abc',
test_data_tags=['git_revision:revision_abc']))
jiri_package_test_data = [
{
'name': 'flutter/fuchsia',
'path': 'flutter/fuchsia',
'version': 'git_revision:revision_abc',
'manifest': 'manifest1'
},
]
default_properties = api.properties(**properties)
# Version of the cipd package is the same as the one currently in the
# source tree.
yield (
api.test('nothing_to_roll') + default_properties +
package_no_match_test_data +
api.step_data('jiri package', api.jiri.package(jiri_package_test_data)))
package_match_test_data = api.step_data(
'cipd describe flutter/fuchsia/${platform}',
api.cipd.example_describe(
package_name='flutter/fuchsia',
version='version_abc',
test_data_tags=['git_revision:revision_jkl']))
package_versions = {
'engine_version': 'engine_version_xyz',
}
dependent_versions = {
'engine_version': 'engine_version_lmn',
}
# Version of the cipd package is different from the one in the tree and ready
# to get rolled but the latest dependent version does not match the versions
# being rolled.
yield (api.test('dependent_not_matching_versions') + default_properties +
package_match_test_data + api.step_data(
'jiri package', api.jiri.package(jiri_package_test_data)) +
api.step_data('read versions',
api.file.read_json(json_content=package_versions)) +
api.step_data('read dep versions',
api.file.read_json(json_content=dependent_versions)) +
api.post_process(StepSuccess, 'validation_summary'))
dependent_versions_match = {
'engine_version': 'engine_version_xyz',
}
# Version of the cipd package is different from the one in the tree and ready
# to get rolled but the dependent latest version match the versions
# being rolled.
yield (
api.test('dependent_matching_versions') + default_properties +
package_match_test_data +
api.step_data('jiri package', api.jiri.package(jiri_package_test_data)) +
api.step_data('read versions',
api.file.read_json(json_content=package_versions)) +
api.step_data('read dep versions',
api.file.read_json(json_content=dependent_versions_match)) +
api.post_process(StepSuccess, 'Rolling-Success'))