blob: f8fd68b508afb53a7c454d1c665a75254c84ffe4 [file] [log] [blame]
# Copyright 2021 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.
"""Apply a tagged, empty commit to an integration.git release branch.
The tag increments the candidate version at branch HEAD, i.e. if branch HEAD is
A.B.C.D, then the new tag is A.B.C.D+1.
This recipe can be used to activate LUCI schedulers watching release refs in
Gitiles e.g. to retry failed builds free of side-effects (unlike cherry-picks).
Options
- Dryrun: Run recipe without modifying anything remotely.
"""
from PB.recipes.fuchsia.release.increment_version import InputProperties
PYTHON_VERSION_COMPATIBILITY = "PY3"
DEPS = [
"fuchsia/git",
"fuchsia/git_checkout",
"fuchsia/release",
"fuchsia/sso",
"fuchsia/status_check",
"recipe_engine/context",
"recipe_engine/properties",
"recipe_engine/raw_io",
"recipe_engine/step",
]
PROPERTIES = InputProperties
COMMIT_MESSAGE = "{prefix} Increment release version to {version}\n\nBug: {bug}"
def RunSteps(api, props):
with api.step.nest("check inputs"):
if not props.remote:
api.step.empty(
"missing remote input",
step_text="`remote` must be specified",
status=api.step.FAILURE,
)
if not props.bug:
api.step.empty(
"missing bug input",
step_text="`bug` must be specified",
status=api.step.FAILURE,
)
if not api.release.validate_branch(props.target_branch):
api.step.empty(
"invalid target branch input",
step_text='`target_branch` must start with "releases"',
status=api.step.FAILURE,
)
https_remote = api.sso.sso_to_https(props.remote)
revision = api.git.get_remote_branch_head(
step_name="get target branch HEAD",
url=https_remote,
branch=props.target_branch,
)
if not revision:
api.step.empty(
"target branch does not exist",
step_text="target branch %s does not exist" % props.target_branch,
status=api.step.FAILURE,
)
checkout_root, _ = api.git_checkout(
https_remote,
revision=revision,
cache=False,
step_name="checkout base revision",
)
with api.step.nest("resolve release version"):
release_version = api.release.get_next_candidate_version(
ref=revision,
repo_path=checkout_root,
)
if api.git.get_remote_tag(url=https_remote, tag=release_version.tag_name):
api.step.empty(
"release version conflict",
step_text=(
"attempting increment would conflict with existing "
"version %s, indicating source revision %s has already moved forward"
% (release_version.tag_name, revision)
),
status=api.step.FAILURE,
)
with api.context(cwd=checkout_root), api.step.nest(
"create release version"
) as presentation:
commit_message = COMMIT_MESSAGE.format(
prefix=api.release._COMMIT_MESSAGE_PREFIX,
version=str(release_version),
bug=props.bug,
)
api.git.commit(
step_name="create empty commit",
message=commit_message,
allow_empty=True,
)
api.git.tag(
step_name="tag release",
name=str(release_version.tag_name),
)
api.git.push(
step_name="push release",
refs=[
"HEAD:refs/heads/%s" % props.target_branch,
"refs/tags/%s" % release_version.tag_name,
],
atomic=True,
dryrun=props.dryrun,
)
release_revision = api.git.get_hash()
api.release.set_output_properties(
presentation,
release_revision,
release_version,
)
if not props.dryrun and props.downstream_builders:
api.release.lookup_builds(
builders=props.downstream_builders,
revision=release_revision,
remote=https_remote,
)
def GenTests(api):
default_branch = "releases/targetbranch"
default_remote = "sso://fuchsia/integration"
default_bug = "123456"
empty_output = api.raw_io.stream_output_text("")
yield api.status_check.test("missing_remote_input", status="failure")
yield (
api.status_check.test("missing_bug_input", status="failure")
+ api.properties(
remote=default_remote,
)
)
yield (
api.status_check.test("invalid_branch_input", status="failure")
+ api.properties(
target_branch="invalidbranch",
remote=default_remote,
bug=default_bug,
)
)
yield (
api.status_check.test("branch_does_not_exist", status="failure")
+ api.properties(
target_branch=default_branch,
remote=default_remote,
bug=default_bug,
)
+ api.step_data(
"check inputs.get target branch HEAD",
empty_output,
)
)
yield (
api.status_check.test("release_version_conflict", status="failure")
+ api.properties(
target_branch=default_branch,
remote=default_remote,
bug=default_bug,
)
+ api.release.ref_to_release_version(
"releases/0.20200102.0.1",
nesting="resolve release version",
)
)
yield (
api.status_check.test("increment_version")
+ api.properties(
target_branch=default_branch,
remote=default_remote,
bug=default_bug,
downstream_builders=["a/b/c"],
)
+ api.release.ref_to_release_version(
"releases/0.20200102.0.1",
nesting="resolve release version",
)
+ api.step_data(
"resolve release version.get remote tag",
empty_output,
)
)