diff --git a/tools/linter/adapters/workflow_consistency_linter.py b/tools/linter/adapters/workflow_consistency_linter.py index f3e3c7f7b45..54a98df699c 100644 --- a/tools/linter/adapters/workflow_consistency_linter.py +++ b/tools/linter/adapters/workflow_consistency_linter.py @@ -16,9 +16,6 @@ from typing import Any, NamedTuple, TYPE_CHECKING from yaml import dump, load -REPO_ROOT = Path(__file__).resolve().parent.parent.parent.parent - - if TYPE_CHECKING: from collections.abc import Iterable @@ -85,25 +82,6 @@ def print_lint_message(path: Path, job: dict[str, Any], sync_tag: str) -> None: print(json.dumps(lint_message._asdict()), flush=True) -def get_jobs_with_sync_tag( - job: dict[str, Any], -) -> tuple[str, Path, dict[str, Any]] | None: - sync_tag = job.get("with", {}).get("sync-tag") - if sync_tag is None: - return None - - # remove the "if" field, which we allow to be different between jobs - # (since you might have different triggering conditions on pull vs. - # trunk, say.) - if "if" in job: - del job["if"] - - # same is true for ['with']['test-matrix'] - if "test-matrix" in job.get("with", {}): - del job["with"]["test-matrix"] - return (sync_tag, path, {job_id: job}) - - if __name__ == "__main__": parser = argparse.ArgumentParser( description="workflow consistency linter.", @@ -116,38 +94,41 @@ if __name__ == "__main__": ) args = parser.parse_args() - # Go through all files, aggregating jobs with the same sync tag + # Go through the provided files, aggregating jobs with the same sync tag tag_to_jobs = defaultdict(list) - for path in REPO_ROOT.glob(".github/workflows/*"): - if not path.is_file() or path.suffix not in {".yml", ".yaml"}: - continue - workflow = load_yaml(path) - if not is_workflow(workflow): - continue - jobs = workflow.get("jobs", {}) - for job_id, job in jobs.items(): - res = get_jobs_with_sync_tag(job) - if res is None: - continue - sync_tag, path, job_dict = res - tag_to_jobs[sync_tag].append((path, {job_id: job})) - - # Check the files passed as arguments for path in args.filenames: workflow = load_yaml(Path(path)) jobs = workflow["jobs"] for job_id, job in jobs.items(): - res = get_jobs_with_sync_tag(job) - if res is None: + try: + sync_tag = job["with"]["sync-tag"] + except KeyError: continue - sync_tag, path, job_dict = res - # For each sync tag, check that all the jobs have the same code. - for baseline_path, baseline_dict in tag_to_jobs[sync_tag]: - baseline_str = dump(baseline_dict) + # remove the "if" field, which we allow to be different between jobs + # (since you might have different triggering conditions on pull vs. + # trunk, say.) + if "if" in job: + del job["if"] - printed_baseline = False + # same is true for ['with']['test-matrix'] + if "test-matrix" in job.get("with", {}): + del job["with"]["test-matrix"] - job_str = dump(job_dict) - if baseline_str != job_str: - print_lint_message(path, job_dict, sync_tag) + tag_to_jobs[sync_tag].append((path, {job_id: job})) + + # For each sync tag, check that all the jobs have the same code. + for sync_tag, path_and_jobs in tag_to_jobs.items(): + baseline_path, baseline_dict = path_and_jobs.pop() + baseline_str = dump(baseline_dict) + + printed_baseline = False + + for path, job_dict in path_and_jobs: + job_str = dump(job_dict) + if baseline_str != job_str: + print_lint_message(path, job_dict, sync_tag) + + if not printed_baseline: + print_lint_message(baseline_path, baseline_dict, sync_tag) + printed_baseline = True