mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-03 12:47:49 +00:00
docs(release): record the private Pro pair preflight contract
The create-release prepare job now verifies that pulse-enterprise declares docs/release-source-pairs/<expected_source_sha>.json and that it names the frozen public commit before any draft release object exists. Record that obligation in the deployment-installability contract and add the release-promotion policy proof that guards the step and its ordering ahead of create_release. Change-source: pulse-maintainer
This commit is contained in:
parent
f43a7a3e62
commit
a23ba2f5dc
2 changed files with 28 additions and 0 deletions
|
|
@ -1932,6 +1932,14 @@ artifact-selection behaviour.
|
|||
workflow-run details from GitHub and poll the exact returned run ID; it must
|
||||
never infer its child from the newest matching workflow/branch/timestamp,
|
||||
because version-scoped release concurrency and manual dispatches can overlap.
|
||||
Before it creates the unpublished draft, `create-release.yml` must prove the
|
||||
private payload can resolve its source: the `prepare` job must read
|
||||
`docs/release-source-pairs/<expected_source_sha>.json` from
|
||||
`rcourtman/pulse-enterprise` and fail unless that file exists and declares
|
||||
`pulse_sha` equal to the frozen public commit. A missing or mismatched
|
||||
declaration must stop the run before any draft release object exists, so a
|
||||
private build that cannot resolve its pair never orphans another draft. The
|
||||
check is a fact check only; the release steward still selects the pair.
|
||||
Only after public release asset validation, staged install smoke, exact
|
||||
public Docker publication, exact Helm OCI publication, durable convergence
|
||||
dispatch, and the publicly readable activation-commit marker may the
|
||||
|
|
|
|||
|
|
@ -2895,6 +2895,26 @@ class CandidatePublicationBoundaryTest(unittest.TestCase):
|
|||
def setUp(self) -> None:
|
||||
self.jobs = yaml.load(read(".github/workflows/create-release.yml"), Loader=UniqueKeyLoader)["jobs"]
|
||||
|
||||
def test_private_pro_pair_is_verified_before_any_draft_exists(self) -> None:
|
||||
prepare_steps = self.jobs["prepare"]["steps"]
|
||||
step = next(
|
||||
(candidate for candidate in prepare_steps
|
||||
if candidate.get("name") == "Verify the private Pro source pair is declared"),
|
||||
None,
|
||||
)
|
||||
self.assertIsNotNone(step, "prepare must verify the private Pro source pair before dispatch")
|
||||
condition = step["if"]
|
||||
self.assertIn("startsWith(github.event.inputs.version, '6.')", condition)
|
||||
self.assertIn("historical_asset_backfill_only != 'true'", condition)
|
||||
self.assertIn("draft_only != 'true'", condition)
|
||||
self.assertEqual(step["env"]["PRIVATE_PAIR_REPOSITORY"], "rcourtman/pulse-enterprise")
|
||||
script = step["run"]
|
||||
self.assertIn("docs/release-source-pairs/${EXPECTED_SOURCE_SHA}.json", script)
|
||||
self.assertIn("pulse_sha", script)
|
||||
self.assertIn("exit 1", script)
|
||||
# The draft is created only after the prepare gate can refuse the run.
|
||||
self.assertIn("prepare", self.jobs["create_release"]["needs"])
|
||||
|
||||
def condition(self, job: str, results: dict[str, str], *, draft: bool = False, cancelled: bool = False) -> bool:
|
||||
# Execute the workflow's Boolean condition with explicit job outcomes.
|
||||
# This intentionally fails if the workflow adds an unsupported expression.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue