| # 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 platform version in fuchsia.git is up-to-date. |
| |
| The platform version should always be one ahead of the latest milestone branch's |
| milestone number. |
| """ |
| |
| import json |
| |
| 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.platform_version_roller import InputProperties |
| |
| DEPS = [ |
| "fuchsia/auto_roller", |
| "fuchsia/build", |
| "fuchsia/checkout", |
| "fuchsia/git", |
| "fuchsia/git_checkout", |
| "fuchsia/gitiles", |
| "fuchsia/release", |
| "fuchsia/sso", |
| "fuchsia/status_check", |
| "recipe_engine/context", |
| "recipe_engine/properties", |
| "recipe_engine/step", |
| ] |
| |
| PROPERTIES = InputProperties |
| COMMIT_MESSAGE = """[roll] Update platform version from {current} to {target}""" |
| |
| |
| def RunSteps(api, props): |
| # This should be a minimal checkout only so that we can read the state of |
| # the integration repository's branches. |
| with api.step.nest("checkout integration"): |
| integration_dir, _ = api.git_checkout(api.sso.sso_to_https(props.remote)) |
| |
| with api.step.nest("resolve target platform version"), api.context( |
| cwd=integration_dir |
| ): |
| api.git.fetch(all_remotes=True) |
| branches = api.release.get_branches(repo_path=integration_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 API level is always 1 ahead of the latest milestone |
| # branch's milestone number. |
| target_platform_version = 1 + ( |
| max(api.release.get_milestone_from_branch(b) for b in branches) |
| ) |
| |
| with api.step.nest("resolve current platform version"): |
| # Use the Gitiles API to resolve the platform version, as this is much |
| # faster than doing a full checkout. A full checkout will be performed |
| # later if we realize that an update is needed. |
| file_content = api.gitiles.fetch( |
| "fuchsia.googlesource.com", |
| "fuchsia", |
| "build/config/fuchsia/platform_version.json", |
| ).decode() |
| current_platform_version = json.loads(file_content)["current_fuchsia_api_level"] |
| if current_platform_version == target_platform_version: |
| api.step.empty("nothing to roll", step_text="platform version up-to-date") |
| return api.auto_roller.nothing_to_roll() |
| |
| # If the target platform version isn't equal to or exactly 1 greater |
| # than the current platform version, either the current platform version |
| # and/or the latest milestone branch are invalid. Raise an exception and |
| # do not roll. |
| if current_platform_version + 1 != target_platform_version: |
| return RawResult( |
| summary_markdown="invalid platform versions: target platform " |
| "version %d is not an increment of the current platform " |
| "version %d" % (target_platform_version, current_platform_version), |
| status=common_pb2.INFRA_FAILURE, |
| ) |
| |
| # At this point we've determined that we need to attempt a roll, so perform |
| # a full checkout. |
| checkout = api.checkout.fuchsia_with_options( |
| manifest=props.manifest, |
| remote=props.remote, |
| ) |
| |
| # Build Fuchsia to generate the golden files for API level N. |
| build_results = api.build.with_options( |
| checkout=checkout, fint_params_path=props.fint_params_path |
| ) |
| |
| # Run update_platform_version.py which bumps the platform version and updates the golden |
| # files used for compatibility testing |
| # TODO Drop the explict call to update_platform_version.py once single GN target is implemented. |
| with api.context(cwd=checkout.root_dir): |
| api.step( |
| "update platform version", |
| [ |
| build_results.gn_results.tool("python3"), |
| checkout.root_dir.join( |
| "scripts", |
| "versioning", |
| "update_platform_version.py", |
| ), |
| "--fuchsia-api-level", |
| target_platform_version, |
| ], |
| ) |
| |
| change = api.auto_roller.attempt_roll( |
| props.roll_options, |
| repo_dir=checkout.root_dir, |
| commit_message=COMMIT_MESSAGE.format( |
| current=current_platform_version, target=target_platform_version |
| ), |
| ) |
| return api.auto_roller.raw_result(change) |
| |
| |
| def GenTests(api): |
| default_props = api.properties( |
| project="integration", |
| manifest="flower", |
| remote="https://fuchsia.googlesource.com/integration", |
| fint_params_path="fint_params/platform-version-roller.textproto", |
| roll_options=api.auto_roller.Options( |
| remote="https://fuchsia.googlesource.com/fuchsia", |
| ), |
| ) |
| 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 platform version", |
| ) + api.auto_roller.success() + api.gitiles.fetch( |
| "resolve current platform version.fetch", |
| '{"current_fuchsia_api_level": 2}', |
| ) + default_props |
| |
| yield api.status_check.test("nothing_to_roll") + api.release.get_branches( |
| ["releases/foo", "releases/f1"], |
| nesting="resolve target platform version", |
| ) + api.gitiles.fetch( |
| "resolve current platform version.fetch", '{"current_fuchsia_api_level": 2}' |
| ) + default_props |
| |
| yield api.status_check.test( |
| "invalid_platform_version", status="infra_failure" |
| ) + api.release.get_branches( |
| ["releases/foo", "releases/f1"], |
| nesting="resolve target platform version", |
| ) + api.gitiles.fetch( |
| "resolve current platform version.fetch", |
| '{"current_fuchsia_api_level": 5}', |
| ) + default_props |