From f661c68272b45c8c944aa91cfaddd7304860302e Mon Sep 17 00:00:00 2001 From: Richard McDaniel <1130888+rmcdaniel@users.noreply.github.com> Date: Thu, 5 Nov 2026 19:39:15 +0000 Subject: [PATCH] Require the separate native promotion workflow after Server migration --- qualification/policy.json | 7 +------ tests/test_qualification_policy.py | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/qualification/policy.json b/qualification/policy.json index 63398ca..d0dc3fa 100644 --- a/qualification/policy.json +++ b/qualification/policy.json @@ -147,7 +147,6 @@ "server/native-release.yml": { "environment": "dockerhub-native", "jobs": [ - "aliases", "build-amd64", "build-arm64", "publish" @@ -164,17 +163,13 @@ "run": "scripts/ci/verify-native-release-dispatch.sh" }, "tag_input": "tag", - "tag_ref_condition": "github.ref == format('refs/tags/{0}', inputs.tag)", - "optional_jobs": [ - "aliases" - ] + "tag_ref_condition": "github.ref == format('refs/tags/{0}', inputs.tag)" }, "server/native-alias-promotion.yml": { "environment": "dockerhub-native", "jobs": [ "promote" ], - "optional": true, "plan_job": "plan", "plan_verifier": { "env": { diff --git a/tests/test_qualification_policy.py b/tests/test_qualification_policy.py index 27bf0ae..8d045ad 100644 --- a/tests/test_qualification_policy.py +++ b/tests/test_qualification_policy.py @@ -937,9 +937,19 @@ def publishing_job(name: str, condition: str) -> str: {publishing_job("aliases", gate + " && needs.plan.outputs.dockerhub == 'true'")}{extra_job}""" +def native_promotion_transition_policy() -> dict[str, object]: + """Retain the legacy topology only in explicit transition controls.""" + policy = policy_fixture() + bindings = policy["workflow_trust"]["privileged_tag_dispatch_workflows"] + bindings["server/native-release.yml"]["jobs"].insert(0, "aliases") + bindings["server/native-release.yml"]["optional_jobs"] = ["aliases"] + bindings["server/native-alias-promotion.yml"]["optional"] = True + return policy + + class TagDispatchPolicyTest(unittest.TestCase): def setUp(self) -> None: - self.policy = policy_fixture() + self.policy = native_promotion_transition_policy() def scan(self, source: str, policy: dict[str, object] | None = None) -> dict[str, dict[str, object]]: return scan_workflow_sources( @@ -1113,7 +1123,7 @@ class NativePromotionTransitionTest(unittest.TestCase): """Presence exceptions cannot relax any present workflow's trust binding.""" def setUp(self) -> None: - self.policy = policy_fixture() + self.policy = native_promotion_transition_policy() self.path = ".github/workflows/native-alias-promotion.yml" binding = self.policy["workflow_trust"]["privileged_tag_dispatch_workflows"]["server/native-alias-promotion.yml"] env = "\n".join(f" {name}: {value}" for name, value in binding["plan_verifier"]["env"].items()) @@ -1196,11 +1206,7 @@ def test_presence_exception_cannot_name_unregistered_jobs_or_nonboolean_flags(se validate_policy(policy) def test_tightened_post_transition_policy_requires_promotion_and_refuses_legacy_aliases(self) -> None: - policy = copy.deepcopy(self.policy) - bindings = policy["workflow_trust"]["privileged_tag_dispatch_workflows"] - del bindings["server/native-alias-promotion.yml"]["optional"] - del bindings["server/native-release.yml"]["optional_jobs"] - bindings["server/native-release.yml"]["jobs"].remove("aliases") + policy = policy_fixture() scan_workflow_sources(policy, "server", self.sources(self.promotion, False)) for promotion, legacy in ((None, False), (self.promotion, True)): with self.subTest(promotion=promotion is not None, legacy=legacy), self.assertRaises(PolicyError):