blob: d5069bb1b4ded3cd3937b4cd64bcffdae7da7ac2 [file] [log] [blame]
# Copyright 2020 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 testing Recipes."""
from recipe_engine.recipe_api import Property
DEPS = [
"fuchsia/build_input_resolver",
"fuchsia/checkout",
"fuchsia/commit_queue",
"fuchsia/recipe_testing",
"fuchsia/status_check",
"recipe_engine/buildbucket",
"recipe_engine/context",
"recipe_engine/json",
"recipe_engine/path",
"recipe_engine/properties",
"recipe_engine/step",
]
PROPERTIES = {
"project": Property(kind=str, help="Jiri remote manifest project", default=None),
"manifest": Property(kind=str, help="Jiri manifest to use"),
"remote": Property(kind=str, help="Remote manifest repository"),
"unittest_only": Property(kind=bool, help="Finish after unit tests", default=False),
"use_buildbucket": Property(
kind=bool,
help="Launch tryjobs through Buildbucket API instead of led",
default=False,
),
"include_includable_only": Property(
kind=bool,
help="Include includable_only tryjobs",
default=True,
),
"include_public": Property(kind=bool, help="Include public tryjobs", default=True),
"include_private": Property(
kind=bool, help="Include private tryjobs", default=False
),
"commit_queue_project": Property(
kind=str, help="Commit queue project", default="fuchsia"
),
"check_deps": Property(
kind=bool,
help="Whether to check for out-of-order and unused recipe deps",
default=False,
),
"cq_config_name": Property(
kind=str,
help="Name of the CQ config file to load, if different from the default",
default="",
),
}
# If this build is being triggered from a change to this recipe, we need
# to explicitly pass a CL. The most recent passing run of
# fuchsia.try/recipes could take anywhere from about three to 200 minutes,
# and the three minute version does not test much of what this recipe
# actually does. In that case alter the recipes build to run on a specific
# CL that modifies the cobalt recipe alone. (The cobalt build usually
# takes less than 10 minutes.)
SELFTEST_CL = "https://fuchsia-review.googlesource.com/c/infra/recipes/+/303171"
# If this build is being triggered from a change to this recipe, and we're
# using the Buildbucket testing codepath, then we need to explicitly pass a
# builder. This builder will run in the case that the only affected recipe is
# this one, so we are guaranteed to exercise the scheduling codepath without
# recursing infinitely.
SELFTEST_BUILDER = "fuchsia/try/bringup.x64-debug-no_opt-build_only"
def RunSteps(
api,
project,
manifest,
remote,
unittest_only,
use_buildbucket,
include_includable_only,
include_public,
include_private,
commit_queue_project,
check_deps,
cq_config_name,
):
"""Run tests for recipes."""
# Resolve the build input to always contain a Gitiles commit.
api.build_input_resolver.resolve()
with api.context(infra_steps=True):
api.checkout.with_options(
path=api.path["start_dir"],
manifest=manifest,
remote=remote,
project=project,
# Override defaults. We should always attempt to patch.
skip_patch_projects=(),
)
recipes_path = api.path["start_dir"].join("infra", "recipes")
if check_deps:
with api.context(cwd=recipes_path):
run_check_deps(api, recipes_path)
with api.step.defer_results():
# TODO(olivernewman): Stop allowlisting pipes after it's no longer used by
# gcc_toolchain.
api.recipe_testing.run_lint(recipes_path, allowlist=r"^pipes$")
api.recipe_testing.run_unit_tests(recipes_path)
if not unittest_only:
api.recipe_testing.projects = (commit_queue_project,)
api.recipe_testing.run_tests(
recipes_path,
SELFTEST_CL,
include_includable_only=include_includable_only,
include_public=include_public,
include_private=include_private,
use_buildbucket=use_buildbucket,
selftest_builder=SELFTEST_BUILDER,
cq_config_name=cq_config_name,
)
def run_check_deps(api, recipes_path):
step = api.step(
"check deps",
[
recipes_path.join("scripts", "cleanup_deps.py"),
"--check",
"--json-output",
api.json.output(),
],
ok_ret=(0, 1),
step_test_data=lambda: api.json.test_api.output([]),
)
if not step.retcode:
return
step.presentation.status = api.step.FAILURE
bad_files = step.json.output
summary = (
"Files with malformatted DEPS (run ./scripts/cleanup_deps.py to fix):\n\n"
+ "\n".join(["- `%s`" % path for path in bad_files])
)
raise api.step.StepFailure(summary)
def GenTests(api): # pylint: disable=invalid-name
def test(name, status="success", run_tests=True, **props):
ret = (
api.status_check.test(name, status=status)
+ api.buildbucket.try_build(
project="fuchsia",
git_repo="https://fuchsia.googlesource.com/infra/recipes",
)
+ api.properties(
manifest="manifest/minimal",
remote="https://fuchsia.googlesource.com/infra/recipes",
check_deps=True,
cq_config_name="alternate-commit-queue.cfg",
**props
)
)
if run_tests:
ret += api.commit_queue.test_data(
"fuchsia", config_name=ret.properties["cq_config_name"]
) + api.recipe_testing.affected_recipes_data(["none"])
return ret
yield (
test("cq_try")
+ api.recipe_testing.build_data(
"fuchsia/try/core.x64-debug", "fuchsia", skip=True
)
+ api.recipe_testing.build_data(
"fuchsia/try/core.arm64-debug", "fuchsia", skip=True
)
+ api.recipe_testing.build_data(
"fuchsia/try/cobalt-x64-linux", "cobalt", skip=True
)
)
yield (
test("cq_try_private", include_public=False, include_private=True)
+ api.recipe_testing.build_data("fuchsia/try/secret-tryjob", "docs", skip=True)
)
yield (
test("check_deps_fails", run_tests=False, status="failure")
+ api.step_data("check deps", api.json.output(["recipes/foo.py"]), retcode=1)
)