From f886bfe116939306aabe6243a20d2b16ee30b837 Mon Sep 17 00:00:00 2001 From: Pedro Paulo Favato Barcelos Date: Tue, 8 Sep 2026 14:17:22 +0200 Subject: [PATCH] fix(validation): lint workflows by explicit path --- scripts/tests/test_pr_automation.py | 21 +++++++++++++++++++++ scripts/validate_pr_state.py | 27 +++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/scripts/tests/test_pr_automation.py b/scripts/tests/test_pr_automation.py index e16a7bf89..f16c88318 100644 --- a/scripts/tests/test_pr_automation.py +++ b/scripts/tests/test_pr_automation.py @@ -528,6 +528,27 @@ def test_container_does_not_mount_host_credentials_or_docker_socket(tmp_path): assert "-r /repo/scripts/requirements.txt" in command[-1] +def test_actionlint_uses_explicit_workflow_paths_without_git_mount(tmp_path): + snapshot = tmp_path / "source" + workflow_root = snapshot / ".github" / "workflows" + workflow_root.mkdir(parents=True) + (workflow_root / "publish.yml").write_text("name: publish\n", encoding="utf-8") + (workflow_root / "validate.yaml").write_text("name: validate\n", encoding="utf-8") + (workflow_root / "README.md").write_text("ignored\n", encoding="utf-8") + + command = validation.actionlint_command(snapshot) + + assert command[-3] == "-shellcheck=" + assert command[-2:] == [ + ".github/workflows/publish.yml", + ".github/workflows/validate.yaml", + ] + assert not any( + argument.startswith("--mount") and ".git" in argument + for argument in command + ) + + def test_docs_only_container_does_not_install_model_dependencies(tmp_path): command = validation.container_command(tmp_path / "source", tmp_path / "trusted", tmp_path / "plan.json", "data", dependencies=False) assert "pip install" not in command[-1] diff --git a/scripts/validate_pr_state.py b/scripts/validate_pr_state.py index a8861e5fb..44db665d3 100644 --- a/scripts/validate_pr_state.py +++ b/scripts/validate_pr_state.py @@ -128,6 +128,28 @@ def container_command(source, trusted, plan_file, phase, *, dependencies=True): "python:3.11", "sh", "-c", bootstrap] +def actionlint_command(snapshot): + workflow_root = snapshot / ".github" / "workflows" + workflow_files = sorted( + path.relative_to(snapshot).as_posix() + for suffix in (".yml", ".yaml") + for path in workflow_root.glob(f"*{suffix}") + if path.is_file() + ) + require( + workflow_files, + "Workflow changes detected but no workflow files were found", + ) + return [ + "docker", "run", "--rm", "--network=none", "--read-only", + "--cap-drop=ALL", "--security-opt=no-new-privileges", + "--user", "65534:65534", "--workdir", "/repo", + "--mount", f"type=bind,src={snapshot},dst=/repo,readonly", + "rhysd/actionlint:1.7.12", "-shellcheck=", + *workflow_files, + ] + + def prepare_snapshot(source, trusted, number, head, base, plan_file): require(SHA.fullmatch(head) and SHA.fullmatch(base), "Invalid dispatch SHA") api = GitHub(os.environ["GITHUB_REPOSITORY"], os.environ["GH_TOKEN"]) @@ -161,10 +183,7 @@ def run_containers(source, trusted, plan_file): if plan["code"]: subprocess.run(container_command(snapshot, harness, plan_file, "code"), check=True) if plan["workflows"]: - subprocess.run(["docker", "run", "--rm", "--network=none", "--read-only", "--cap-drop=ALL", - "--security-opt=no-new-privileges", "--user", "65534:65534", - "--workdir", "/repo", "--mount", f"type=bind,src={snapshot},dst=/repo,readonly", - "rhysd/actionlint:1.7.12", "-shellcheck="], check=True) + subprocess.run(actionlint_command(snapshot), check=True) def main():