diff --git a/.github/dependabot.yml b/.github/dependabot.yml index d82bd615dc..524fe6c9d0 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -23,6 +23,21 @@ updates: update-types: - "minor" - "patch" + # scripts/release_control/action_consumer_manifests.json pins each + # release-consumed action to an exact SHA plus the upstream action.yml + # sha256, and release_promotion_policy_test.py requires every workflow step + # to match that manifest. Refreshing a pin needs the upstream action bytes + # through the reviewed pin-refresh route, so keep these actions as explicit + # work rather than opening proposals the manifest contract cannot accept. + ignore: + - dependency-name: "actions/attest" + - dependency-name: "azure/setup-helm" + - dependency-name: "docker/build-push-action" + - dependency-name: "docker/login-action" + - dependency-name: "docker/setup-buildx-action" + - dependency-name: "docker/setup-qemu-action" + - dependency-name: "signpath/github-action-submit-signing-request" + - dependency-name: "tailscale/github-action" - package-ecosystem: "gomod" directories: diff --git a/scripts/tests/test_dependabot_config.py b/scripts/tests/test_dependabot_config.py index 2052a3af9b..8aba5d798d 100644 --- a/scripts/tests/test_dependabot_config.py +++ b/scripts/tests/test_dependabot_config.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 """Guard the low-noise dependency update policy and its covered manifests.""" +import json from pathlib import Path import unittest @@ -10,6 +11,7 @@ import yaml ROOT = Path(__file__).resolve().parents[2] CONFIG = ROOT / ".github" / "dependabot.yml" SECURITY_SCAN = ROOT / ".github" / "workflows" / "security-scan.yml" +ACTION_MANIFESTS = ROOT / "scripts" / "release_control" / "action_consumer_manifests.json" def manifest_directories(filename: str) -> list[str]: @@ -159,6 +161,20 @@ class DependabotConfigTest(unittest.TestCase): {"version-update:semver-major"}, ) + def test_github_actions_updates_preserve_reviewed_action_pins(self) -> None: + # action_consumer_manifests.json pins each release-consumed action to an + # exact SHA plus the upstream action.yml sha256, and + # release_promotion_policy_test.py requires every workflow step to match + # it. Refreshing a pin needs the upstream bytes through the reviewed + # pin-refresh route, so Dependabot must not propose version updates the + # manifest contract would reject. + manifests = json.loads(ACTION_MANIFESTS.read_text(encoding="utf-8")) + ignored = { + item["dependency-name"] + for item in self.updates["github-actions"]["ignore"] + } + self.assertEqual(ignored, set(manifests)) + def test_weekly_scan_covers_the_same_lockfiles(self) -> None: workflow = yaml.safe_load(SECURITY_SCAN.read_text(encoding="utf-8")) jobs = workflow["jobs"]