blob: 249134afc9c42c5abc5a8db5dcae2d0391755b77 [file] [log] [blame]
# Copyright 2018 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 automatically creating jiri snapshots from manifest commit."""
from recipe_engine.config import List
from recipe_engine.recipe_api import Property
import re
DEPS = [
'infra/git',
'infra/lkgs',
'recipe_engine/context',
'recipe_engine/path',
'recipe_engine/properties',
'recipe_engine/raw_io',
'recipe_engine/time',
]
PROPERTIES = {
'branch':
Property(
kind=str,
help='Branch on the repository to push the release snapshot',
default=None),
'builders':
Property(
kind=List(basestring),
help='Builders to check for the last known good snapshot.',
default=[]),
'remote':
Property(
kind=str,
help='Remote snapshot repository to checkout',
default=None),
}
TAG_FORMAT = """{date}_{release:0>2}_RC{release_candidate:0>2}"""
LATEST_ROLLUP_TAG = """LATEST_ROLLUP"""
COMMIT_MESSAGE = """\
[release] {tag}
"""
def GetNextReleaseTag(api, remote):
date = api.time.utcnow().date().strftime('%Y%m%d')
# Get current tags for today.
# This does not require being inside a git checkout,
# ls-remote functions outside of the tree when given
# a remote.
step_result = api.git(
'ls-remote',
'-q',
'-t',
remote,
'*%s*' % date,
stdout=api.raw_io.output(),
step_test_data=lambda: api.raw_io.test_api.stream_output('''
cc83301b8cf7ee60828623904bbf0bd310fde349 refs/tags/20180920_00_RC00
2bdcf7c40c23c3526092f708e28b0ba98f8fe4cd refs/tags/20180920_00_RC01'''))
step_result.presentation.logs['stdout'] = step_result.stdout.split('\n')
# Find all the current release_versions
m = re.findall(r'\d{8}_(\d{2})_RC00$', step_result.stdout, re.MULTILINE)
# Find the max release_version
release_version = -1
for match in m:
release_version = max(int(match), release_version)
# Increment the release_version for this cut
return TAG_FORMAT.format(
date=date, release=str(release_version + 1), release_candidate=0)
def RunSteps(api, branch, builders, remote):
api.lkgs.ensure_lkgs(version='latest')
with api.context(infra_steps=True):
# Check out releases repository so we can push new branches to it.
release_path = api.path['start_dir'].join('releases')
api.git.checkout(
url=remote,
path=release_path,
ref=branch,
)
snapshot_file = release_path.join('snapshot')
cherry_pick_file = release_path.join('cherrypick.json')
# Obtain the last-known-good-snapshot for the builders.
api.lkgs(
step_name='lkgs',
builder=builders,
output_file=snapshot_file,
)
# TODO(nmulcahey): Fetch previous snapshot, ensure today's is newer, else exit.
tag = GetNextReleaseTag(api, remote)
# Commit and push the snapshot.
with api.context(cwd=release_path):
api.git('add', snapshot_file)
# Remove an existing cherrypick file if it exists
if api.path.exists(cherry_pick_file):
api.git('rm', cherry_pick_file)
api.git.commit(message=COMMIT_MESSAGE.format(tag=tag))
api.git('tag', tag)
api.git('push', 'origin', 'HEAD:%s' % branch)
# Because we're moving a tag, we have to use --force.
# If the non-force push above fails, we won't get to this line.
# Thus we're guaranteed that this force push won't mess anything up.
api.git('tag', '--force', LATEST_ROLLUP_TAG)
api.git('push', '--force', '--tags')
def GenTests(api):
yield api.test('one builder') + api.properties(
builders=['garnet-x64-release-qemu_kvm'],
remote="http://fuchsia.googlesource.com/garnet",
branch="master",
)
yield api.test('many builders') + api.properties(
builders=['garnet-x64-release-qemu_kvm', 'garnet-arm64-release-qemu_kvm'],
remote="http://fuchsia.googlesource.com/garnet",
branch="master",
)
yield api.test('zero builders') + api.properties(
builders=[],
remote="http://fuchsia.googlesource.com/garnet",
branch="master",
)
yield api.test('invalid builder') + api.properties(
builders=['this-is-an-invalid-builder-name-that-should-never-exist'],
remote="http://fuchsia.googlesource.com/garnet",
branch="master",
)
yield api.test('one builder of many invalid') + api.properties(
builders=[
'garnet-x64-release-qemu_kvm',
'this-is-an-invalid-builder-name-that-should-never-exist'
],
remote="http://fuchsia.googlesource.com/garnet",
branch="master",
)
yield api.test('has existing cherrypick file') + api.properties(
builders=['garnet-x64-release-qemu_kvm'],
remote="http://fuchsia.googlesource.com/garnet",
branch="master",
) + api.path.exists(api.path['start_dir'].join('releases', 'cherrypick.json'))