| # 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 running a specified script from a given repo.""" |
| |
| from urlparse import urlparse |
| |
| from PB.recipes.fuchsia.run_script import InputProperties |
| |
| DEPS = [ |
| "fuchsia/auto_roller", |
| "fuchsia/gerrit", |
| "fuchsia/git", |
| "fuchsia/repo", |
| "fuchsia/sso", |
| "fuchsia/status_check", |
| "recipe_engine/buildbucket", |
| "recipe_engine/cipd", |
| "recipe_engine/context", |
| "recipe_engine/file", |
| "recipe_engine/path", |
| "recipe_engine/properties", |
| "recipe_engine/python", |
| "recipe_engine/step", |
| ] |
| |
| PROPERTIES = InputProperties |
| |
| |
| def RunSteps(api, props): |
| checkout_dir = api.path["start_dir"].join("checkout") |
| with api.step.nest("checkout"), api.context(infra_steps=True): |
| if props.checkout_with_repo: |
| # For repo checkouts, Git must be configured to rewrite SSO URLs to |
| # HTTPS. |
| if props.remote.startswith("sso://"): |
| api.sso.configure_insteadof(props.remote) |
| api.repo.checkout_from_build_input( |
| props.remote, |
| path=checkout_dir, |
| fallback_ref=props.fallback_ref, |
| ) |
| else: |
| api.git.checkout_from_build_input( |
| repo=props.remote, |
| path=checkout_dir, |
| fallback_ref=props.fallback_ref, |
| ) |
| |
| with api.context(cwd=checkout_dir): |
| script_args = list(props.script_args) |
| if props.upload_to_cipd: |
| # Script must emit a newline-separated txt file of CIPD yaml paths, |
| # e.g. "/path/to/foo.yaml\n/path/to/bar.yaml" relative to the |
| # working dir i.e. the checkout dir. |
| assert ( |
| api.buildbucket.build.input.gitiles_commit.project |
| ), "we should only be uploading in CI" |
| cipd_yaml_manifest = api.path.mkstemp("cipd_manifest") |
| script_args += ["--cipd-yaml-manifest", cipd_yaml_manifest] |
| |
| step_name = "run %s" % props.script |
| if props.script.endswith(".py"): |
| # Run python scripts with vpython, rather than system Python, to |
| # enable installation of packages via .vpython files. |
| api.python(step_name, props.script, script_args, venv=True) |
| else: |
| api.step(step_name, [props.script] + script_args) |
| |
| if props.attempt_roll: |
| change = api.auto_roller.attempt_roll( |
| api.gerrit.host_from_remote_url(props.remote), |
| gerrit_project=urlparse(props.remote).path.lstrip("/"), |
| repo_dir=checkout_dir, |
| commit_message='Run "%s"' % props.script, |
| commit_untracked=props.roll_props.commit_untracked_files, |
| dry_run=props.roll_props.dry_run, |
| ) |
| return api.auto_roller.raw_result(change) |
| |
| if props.upload_to_cipd: |
| upload_to_cipd( |
| api, |
| checkout_dir, |
| cipd_yaml_manifest, |
| set_repo_tags=props.set_repo_tags, |
| ) |
| |
| |
| def upload_to_cipd(api, checkout_dir, cipd_yaml_manifest, set_repo_tags=False): |
| """Upload package(s) to CIPD from the script-generated CIPD .yaml manifest. |
| |
| Args: |
| cipd_yaml_manifest (Path): Path to CIPD .yaml manifest. |
| set_repo_tags (bool): If True, set CIPD tags based on a repo snapshot. |
| Otherwise, set CIPD tags based on the input gitiles commit. |
| """ |
| cipd_yaml_paths = ( |
| api.file.read_text( |
| "read CIPD yaml manifest", |
| cipd_yaml_manifest, |
| test_data="path/to/foo.yaml\npath/to/bar.yaml\n", |
| ) |
| .rstrip() |
| .split("\n") |
| ) |
| if set_repo_tags: |
| tags = api.repo.snapshot("repo snapshot", path=checkout_dir) |
| else: |
| tags = {"git_revision": api.buildbucket.build.input.gitiles_commit.id} |
| for cipd_yaml_path in cipd_yaml_paths: |
| api.cipd.create_from_yaml( |
| checkout_dir.join(cipd_yaml_path), |
| refs=["latest"], |
| tags=tags, |
| ) |
| |
| |
| def GenTests(api): |
| remote = "https://fuchsia.googlesource.com/foo" |
| sso_remote = "sso://fuchsia/foo" |
| |
| yield ( |
| api.status_check.test("ci") |
| + api.properties(script="run-tests.sh", remote=remote) |
| + api.buildbucket.ci_build(git_repo=remote) |
| ) |
| |
| yield ( |
| api.status_check.test("ci_with_repo") |
| + api.properties( |
| script="run-tests.sh", |
| remote=remote, |
| checkout_with_repo=True, |
| upload_to_cipd=True, |
| set_repo_tags=True, |
| ) |
| + api.buildbucket.ci_build(git_repo=remote) |
| + api.repo.snapshot("repo snapshot", ["projectA", "projectB"]) |
| ) |
| |
| yield ( |
| api.status_check.test("sso") |
| + api.properties( |
| script="run-tests.py", |
| remote=sso_remote, |
| checkout_with_repo=True, |
| script_args=["-flag", "flagval"], |
| ) |
| + api.buildbucket.ci_build(git_repo=remote) |
| ) |
| |
| yield ( |
| api.status_check.test("ci_upload") |
| + api.properties(script="build-pkg.sh", remote=remote, upload_to_cipd=True) |
| + api.buildbucket.ci_build(git_repo=remote) |
| ) |
| |
| yield ( |
| api.status_check.test("cq") |
| + api.properties(script="run-tests.sh", remote=remote) |
| + api.buildbucket.try_build(git_repo=remote) |
| ) |
| |
| yield ( |
| api.status_check.test("script_failed", status="failure") |
| + api.properties(script="run-tests.sh", remote=remote) |
| + api.buildbucket.ci_build(git_repo=remote) |
| + api.step_data("run run-tests.sh", retcode=1) |
| ) |
| |
| yield ( |
| api.status_check.test("no_buildbucket_input") |
| + api.properties(script="run-tests.sh", remote=remote) |
| ) |
| |
| yield ( |
| api.status_check.test("attempt_roll") |
| + api.properties(script="update.sh", remote=remote, attempt_roll=True) |
| + api.auto_roller.success() |
| ) |