| # 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. |
| |
| """Ensure the MILESTONE file in integration.git is up-to-date.""" |
| |
| from PB.go.chromium.org.luci.buildbucket.proto import common as common_pb2 |
| from PB.recipe_engine.result import RawResult |
| from PB.recipes.fuchsia.release.milestone_roller import InputProperties |
| |
| PYTHON_VERSION_COMPATIBILITY = "PY3" |
| |
| DEPS = [ |
| "fuchsia/auto_roller", |
| "fuchsia/jiri", |
| "fuchsia/release", |
| "fuchsia/status_check", |
| "recipe_engine/file", |
| "recipe_engine/path", |
| "recipe_engine/properties", |
| "recipe_engine/step", |
| ] |
| |
| PROPERTIES = InputProperties |
| COMMIT_MESSAGE = """[roll] Roll MILESTONE from {current} to {target}""" |
| |
| |
| def RunSteps(api, props): |
| with api.step.nest("checkout"): |
| api.jiri.init() |
| api.jiri.import_manifest(props.manifest, props.remote, name=props.project) |
| api.jiri.update(run_hooks=False) |
| |
| project_dir = api.path["start_dir"].join(*props.project.split("/")) |
| with api.step.nest("resolve target milestone") as presentation: |
| branches = api.release.get_branches(repo_path=project_dir, remotes=True) |
| if not branches: |
| return RawResult( |
| summary_markdown="%s does not have any release branches" % props.remote, |
| status=common_pb2.FAILURE, |
| ) |
| # The target milestone is always 1 ahead of the latest milestone branch. |
| target_milestone = 1 + ( |
| max(api.release.get_milestone_from_branch(b) for b in branches) |
| ) |
| |
| current_milestone = api.release.get_major_number(repo_path=project_dir) |
| if current_milestone == target_milestone: |
| api.step.empty("nothing to roll", step_text="milestone up-to-date") |
| return api.auto_roller.nothing_to_roll() |
| |
| # If the target milestone isn't equal to or exactly 1 greater than the |
| # current milestone, either the MILESTONE file and/or the latest |
| # milestone branch are invalid. Raise an exception and do not roll. |
| if current_milestone + 1 != target_milestone: |
| return RawResult( |
| summary_markdown="invalid milestone numbers: target milestone " |
| "%d is not an increment of current milestone %d" |
| % (target_milestone, current_milestone), |
| status=common_pb2.INFRA_FAILURE, |
| ) |
| |
| api.release.write_major_number(target_milestone, repo_path=project_dir) |
| |
| if props.milestone_branches_path: |
| configured_branches = api.file.read_json( |
| "read milestone branch config", |
| project_dir.join(props.milestone_branches_path), |
| test_data=["f1"], |
| ) |
| # If the milestone branch config file doesn't already contain the |
| # current milestone branch, append it to the file. |
| current_milestone_branch = "f%d" % current_milestone |
| if current_milestone_branch not in configured_branches: |
| api.file.write_json( |
| "write milestone branch config", |
| project_dir.join(props.milestone_branches_path), |
| configured_branches + ["f%d" % current_milestone], |
| ) |
| api.step( |
| "generate configs", |
| [project_dir.join(props.config_generator_path)], |
| ) |
| |
| change = api.auto_roller.attempt_roll( |
| props.roll_options, |
| repo_dir=project_dir, |
| commit_message=COMMIT_MESSAGE.format( |
| current=current_milestone, target=target_milestone |
| ), |
| ) |
| return api.auto_roller.raw_result(change) |
| |
| |
| def GenTests(api): |
| default_props = api.properties( |
| project="integration", |
| manifest="minimal", |
| remote="https://fuchsia.googlesource.com/integration", |
| milestone_branches_path="config/milestone_branches.json", |
| config_generator_path="config/generator.sh", |
| roll_options=api.auto_roller.Options( |
| remote="https://fuchsia.googlesource.com/integration", |
| ), |
| ) |
| yield api.status_check.test("no_branches", status="failure") + default_props |
| |
| yield api.status_check.test("roll") + api.release.get_branches( |
| ["releases/foo", "releases/f1", "releases/f2"], |
| nesting="resolve target milestone", |
| ) + api.release.get_major_number( |
| 2, nesting="resolve target milestone" |
| ) + api.auto_roller.success() + default_props |
| |
| yield api.status_check.test("nothing_to_roll") + api.release.get_branches( |
| ["releases/foo", "releases/f1"], |
| nesting="resolve target milestone", |
| ) + api.release.get_major_number( |
| 2, nesting="resolve target milestone" |
| ) + default_props |
| |
| yield api.status_check.test( |
| "invalid_milestone_numbers", status="infra_failure" |
| ) + api.release.get_branches( |
| ["releases/foo", "releases/f1"], |
| nesting="resolve target milestone", |
| ) + api.release.get_major_number( |
| 5, nesting="resolve target milestone" |
| ) + default_props |