From bf699b0f9caa5d75242bad2cb30154b7654e3b8a Mon Sep 17 00:00:00 2001 From: Tim Stranske Date: Fri, 31 Jul 2026 10:57:38 -0500 Subject: [PATCH 1/4] test(actions): validate setup-python contract semantically --- tests/scripts/test_consumer_sync_shadow_handoff.py | 6 +++++- tests/workflows/test_template_drift_workflow.py | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/scripts/test_consumer_sync_shadow_handoff.py b/tests/scripts/test_consumer_sync_shadow_handoff.py index bfa982c08..7c0d6c393 100644 --- a/tests/scripts/test_consumer_sync_shadow_handoff.py +++ b/tests/scripts/test_consumer_sync_shadow_handoff.py @@ -1,6 +1,7 @@ from __future__ import annotations import json +import re import subprocess import sys from pathlib import Path @@ -135,7 +136,10 @@ def test_workflow_has_no_write_or_apply_surface() -> None: assert "write_authority" not in workflow.lower() or "Write authority: false" in workflow assert "persist-credentials: false" in workflow assert "actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1" in workflow - assert "actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1" in workflow + assert re.search( + r"uses:\s+actions/setup-python@[0-9a-f]{40}\s+# v\d+\b", + workflow, + ) assert "actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a" in workflow assert "pyyaml==6.0.2" in workflow assert ( diff --git a/tests/workflows/test_template_drift_workflow.py b/tests/workflows/test_template_drift_workflow.py index 26cad474e..9d121d8e5 100644 --- a/tests/workflows/test_template_drift_workflow.py +++ b/tests/workflows/test_template_drift_workflow.py @@ -19,5 +19,8 @@ def test_template_drift_workflow_installs_pyyaml_before_checker() -> None: ) prior_steps = steps[:checker_index] - assert any(step.get("uses") == "actions/setup-python@v6" for step in prior_steps) + assert any( + str(step.get("uses", "")).startswith("actions/setup-python@") + for step in prior_steps + ) assert any("pip install pyyaml" in step.get("run", "").lower() for step in prior_steps) From d6521fe0b9082bacba6af5aef5ced9718ce22c20 Mon Sep 17 00:00:00 2001 From: Tim Stranske Date: Fri, 31 Jul 2026 11:04:29 -0500 Subject: [PATCH 2/4] test(actions): require valid setup-python major refs --- tests/workflows/test_template_drift_workflow.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/workflows/test_template_drift_workflow.py b/tests/workflows/test_template_drift_workflow.py index 9d121d8e5..cda6ee38a 100644 --- a/tests/workflows/test_template_drift_workflow.py +++ b/tests/workflows/test_template_drift_workflow.py @@ -1,5 +1,6 @@ from __future__ import annotations +import re from pathlib import Path import yaml @@ -20,7 +21,7 @@ def test_template_drift_workflow_installs_pyyaml_before_checker() -> None: prior_steps = steps[:checker_index] assert any( - str(step.get("uses", "")).startswith("actions/setup-python@") + re.fullmatch(r"actions/setup-python@v\d+", str(step.get("uses", ""))) for step in prior_steps ) assert any("pip install pyyaml" in step.get("run", "").lower() for step in prior_steps) From 99a7b1d42b157eefc913f24c664e2d712feb6e0e Mon Sep 17 00:00:00 2001 From: Tim Stranske Date: Fri, 31 Jul 2026 11:26:36 -0500 Subject: [PATCH 3/4] test(actions): execute shadow workflow on pin changes --- .../health-69-consumer-sync-shadow-evidence.yml | 8 ++++++++ tests/scripts/test_consumer_sync_shadow_handoff.py | 10 +++++++--- tests/workflows/test_template_drift_workflow.py | 7 +++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/.github/workflows/health-69-consumer-sync-shadow-evidence.yml b/.github/workflows/health-69-consumer-sync-shadow-evidence.yml index 9432471ee..61aa0a05b 100644 --- a/.github/workflows/health-69-consumer-sync-shadow-evidence.yml +++ b/.github/workflows/health-69-consumer-sync-shadow-evidence.yml @@ -2,11 +2,19 @@ name: Health 69 Consumer Sync Shadow Evidence on: workflow_dispatch: + pull_request: + paths: + - '.github/workflows/health-69-consumer-sync-shadow-evidence.yml' + - '.github/sync-manifest.yml' + - 'scripts/sync_manifest_compiler.py' + - 'scripts/build_consumer_sync_shadow_handoff.py' + - 'templates/consumer-repo/**' schedule: - cron: '17 8 * * 1' push: branches: [main] paths: + - '.github/workflows/health-69-consumer-sync-shadow-evidence.yml' - '.github/sync-manifest.yml' - 'scripts/sync_manifest_compiler.py' - 'scripts/build_consumer_sync_shadow_handoff.py' diff --git a/tests/scripts/test_consumer_sync_shadow_handoff.py b/tests/scripts/test_consumer_sync_shadow_handoff.py index 7c0d6c393..6c89f481f 100644 --- a/tests/scripts/test_consumer_sync_shadow_handoff.py +++ b/tests/scripts/test_consumer_sync_shadow_handoff.py @@ -124,9 +124,10 @@ def test_cli_reports_invalid_plan_without_writing_handoff(tmp_path: Path) -> Non def test_workflow_has_no_write_or_apply_surface() -> None: root = Path(__file__).parents[2] - workflow = ( + workflow_path = ( root / ".github" / "workflows" / "health-69-consumer-sync-shadow-evidence.yml" - ).read_text(encoding="utf-8") + ) + workflow = workflow_path.read_text(encoding="utf-8") assert "contents: read" in workflow assert "contents: write" not in workflow @@ -136,10 +137,13 @@ def test_workflow_has_no_write_or_apply_surface() -> None: assert "write_authority" not in workflow.lower() or "Write authority: false" in workflow assert "persist-credentials: false" in workflow assert "actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1" in workflow - assert re.search( + setup_python_refs = re.findall( r"uses:\s+actions/setup-python@[0-9a-f]{40}\s+# v\d+\b", workflow, ) + assert len(setup_python_refs) == 1 + assert "pull_request:" in workflow + assert f"- '{workflow_path.relative_to(root).as_posix()}'" in workflow assert "actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a" in workflow assert "pyyaml==6.0.2" in workflow assert ( diff --git a/tests/workflows/test_template_drift_workflow.py b/tests/workflows/test_template_drift_workflow.py index cda6ee38a..779d5cb9a 100644 --- a/tests/workflows/test_template_drift_workflow.py +++ b/tests/workflows/test_template_drift_workflow.py @@ -20,6 +20,13 @@ def test_template_drift_workflow_installs_pyyaml_before_checker() -> None: ) prior_steps = steps[:checker_index] + setup_python_steps = [ + step + for step in prior_steps + if re.fullmatch(r"actions/setup-python@v\d+", str(step.get("uses", ""))) + ] + + assert len(setup_python_steps) == 1 assert any( re.fullmatch(r"actions/setup-python@v\d+", str(step.get("uses", ""))) for step in prior_steps From 3246f8d58e84f5fc8184a827375ba22d835e37c3 Mon Sep 17 00:00:00 2001 From: Tim Stranske Date: Fri, 31 Jul 2026 11:33:23 -0500 Subject: [PATCH 4/4] style(tests): format shadow workflow contract --- tests/scripts/test_consumer_sync_shadow_handoff.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/scripts/test_consumer_sync_shadow_handoff.py b/tests/scripts/test_consumer_sync_shadow_handoff.py index 6c89f481f..a1e43edd1 100644 --- a/tests/scripts/test_consumer_sync_shadow_handoff.py +++ b/tests/scripts/test_consumer_sync_shadow_handoff.py @@ -124,9 +124,7 @@ def test_cli_reports_invalid_plan_without_writing_handoff(tmp_path: Path) -> Non def test_workflow_has_no_write_or_apply_surface() -> None: root = Path(__file__).parents[2] - workflow_path = ( - root / ".github" / "workflows" / "health-69-consumer-sync-shadow-evidence.yml" - ) + workflow_path = root / ".github" / "workflows" / "health-69-consumer-sync-shadow-evidence.yml" workflow = workflow_path.read_text(encoding="utf-8") assert "contents: read" in workflow