| # 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 running Tricium analyzers.""" |
| |
| import collections |
| |
| from recipe_engine.config import ConfigList, ConfigGroup, Single |
| from recipe_engine.recipe_api import Property |
| |
| DEPS = [ |
| "fuchsia/git", |
| "fuchsia/tricium_analyze", |
| "recipe_engine/buildbucket", |
| "recipe_engine/cipd", |
| "recipe_engine/context", |
| "recipe_engine/path", |
| "recipe_engine/platform", |
| "recipe_engine/properties", |
| "recipe_engine/raw_io", |
| "recipe_engine/step", |
| "recipe_engine/tricium", |
| ] |
| |
| PROPERTIES = { |
| "cipd_packages": |
| Property( |
| help="CIPD packages containing necessary binaries.", |
| kind=ConfigList( |
| lambda: ConfigGroup( |
| # Package name. |
| name=Single(str), |
| # Version. |
| version=Single(str), |
| # Language subdirectory (e.g. clang) in which to put the package. The Tricium modules assume a Fuchsia prebuilts-like layout. |
| subdir=Single(str), |
| ) |
| ), |
| default={}, |
| ), |
| } |
| |
| # Namedtuple to simulate a class generated by jiri checkout because flutter is |
| # not using jiri. |
| _CheckoutResult = collections.namedtuple( |
| '_CheckoutResult', ['root_dir', 'release_version'] |
| ) |
| |
| |
| def RunSteps(api, cipd_packages): # pragma: no cover |
| # TODO(godofredoc): Fix tricium recipe. |
| return |
| |
| with api.context(infra_steps=True): |
| checkout_root = api.path["start_dir"] |
| checkout_path = api.path['start_dir'].join('recipes') |
| # tricium is expecting a dictionary as a checkout. |
| checkout = _CheckoutResult(checkout_path, '') |
| |
| bb_input = api.buildbucket.build.input |
| if bb_input.gerrit_changes: |
| api.git.checkout_cl(bb_input.gerrit_changes[0], checkout_path) |
| |
| # If specified, download CIPD packages. |
| if cipd_packages: |
| with api.step.nest("ensure_packages"): |
| with api.context(infra_steps=True): |
| cipd_dir = checkout_root.join("cipd") |
| pkgs = api.cipd.EnsureFile() |
| for package in cipd_packages: |
| pkgs.add_package( |
| package["name"], package["version"], subdir=package["subdir"] |
| ) |
| api.cipd.ensure(cipd_dir, pkgs) |
| platform = "%s-%s" % ( |
| api.platform.name.replace("win", "windows"), |
| { |
| "intel": { |
| 32: "386", |
| # Note that this is different from the CIPD norm (this is how |
| # //prebuilt/third_party is laid out). |
| 64: "x64", |
| }, |
| "arm": { |
| 32: "armv6", |
| 64: "arm64", |
| }, |
| }[api.platform.arch][api.platform.bits], |
| ) |
| # Only these tools are being downloaded from CIPD, so directly set the |
| # paths if cipd_packages is defined. |
| api.tricium_analyze.black = cipd_dir.join("black") |
| api.tricium_analyze.yapf = cipd_dir.join("yapf") |
| |
| with api.context(cwd=checkout_path): |
| # --diff-filter=d excludes deleted files, because we don't want to |
| # check those. |
| paths = api.git( |
| "get changed files", |
| "diff-tree", |
| "--no-commit-id", |
| "--name-only", |
| "--diff-filter=d", |
| "-r", |
| "HEAD", |
| stdout=api.raw_io.output_text(), |
| ).stdout.splitlines() |
| |
| api.tricium_analyze.checkout = checkout |
| for path in paths: |
| # TODO(haowei): fxb/44823 Call git-check-attr on all files at once to speed it up |
| attr_result = api.git( |
| "check attr of %s" % path, |
| "check-attr", |
| "tricium", |
| "--", |
| path, |
| stdout=api.raw_io.output_text(), |
| ).stdout.strip() |
| if attr_result.endswith(": unset"): |
| continue |
| api.tricium_analyze([path]) |
| api.tricium.write_comments() |
| |
| |
| def GenTests(api): |
| # TODO(godofredoc): Fix tricium recipe. |
| return |
| |
| DIFF = """diff --git a/{0} b/{0} |
| index e684c1e..a76a10e 100644 |
| --- a/{0} |
| +++ b/{0} |
| @@ -1,2 +1,4 @@ |
| + foo |
| + bar |
| """ |
| |
| changed_files_data = lambda files: api.step_data( |
| "get changed files", |
| api.raw_io.stream_output_text("\n".join(files)), |
| ) |
| get_changed_files_data = lambda files: api.step_data( |
| "analyze %s.get changed files" % files[0], |
| api.raw_io.stream_output_text("\n".join(DIFF.format(f) for f in files)), |
| ) |
| |
| formatted_files_data = lambda files: api.step_data( |
| "analyze %s.get formatted files" % files[0], |
| api.raw_io.stream_output_text("\n".join(DIFF.format(f) for f in files)), |
| ) |
| |
| try_build = api.buildbucket.try_build( |
| git_repo="https://flutter.googlesource.com/recipes" |
| ) |
| basic_properties = api.properties(ref="refs/changes/12345/2",) |
| |
| yield ( |
| api.test("default") + try_build + basic_properties + |
| api.properties(analyses=["Yapf"],) + changed_files_data(["flutter.py"]) + |
| get_changed_files_data(["flutter.py"]) + |
| formatted_files_data(["flutter.py"]) |
| ) |
| |
| yield ( |
| api.test("with_cipd_packages") + try_build + basic_properties + |
| api.properties( |
| analyses=["Yapf"], |
| cipd_packages=[{ |
| "name": "fuchsia/go/${platform}", |
| "version": "integration", |
| "subdir": "go", |
| }], |
| ) + changed_files_data(["flutter.py"]) + |
| get_changed_files_data(["flutter.py"]) + |
| formatted_files_data(["flutter.py"]) |
| ) |
| |
| yield ( |
| api.test("attribute disable") + try_build + basic_properties + |
| api.properties(analyses=["ClangFormat", "GNFormat"],) + |
| changed_files_data(["BUILD.gn", "hello.go"]) + api.step_data( |
| "check attr of BUILD.gn", |
| api.raw_io.stream_output_text("BUILD.gn: tricium: unset\n"), |
| ) |
| ) |