Repository navigation
ci(wave): the platform bake reads Plugins with an App credential, and ONE fan-out fires after the Plugins publication - #2705
Conversation
… ONE fan-out fires after the Plugins publication The first push-driven release wave (main-cd run 33276813173) failed three ways at once: - plugins-modules died at checkout: 'repository Systemorph/MeshWeaver.Plugins not found'. The reusable module-pack and publish-bake checked out content-repository with the run's GITHUB_TOKEN, which is scoped to the calling repo. Both now take content-app-id / content-app-private-key, assert them RED when content-repository is set, mint a Contents:Read installation token and check out with it. main-cd passes the dispatch App (installed on Plugins) as that credential. - Two fan-outs existed: an inline dispatch-dependents job (#2696) and the reusable notify-dependents.yml built in parallel. The reusable fired straight after promote — BEFORE the Plugins bake — with a payload of {version, reason} that the receivers cannot use (Manufacturing refuses without a sha256: digest; Education bakes against client_payload.image). The inline job is deleted; notify-dependents now needs plugins-bake success and carries sha/image/digest/source/chain, asserted RED for a platform release. - The verdict's LEGS name notify-dependents; PlatformReleaseNotifyGuard pins the single job, its gate on plugins-bake, the payload, and the reusable's RED-on-failure. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR hardens the release “wave” in GitHub Actions so the platform run can (1) bake Plugins content from a private repo using an App-scoped token and (2) notify downstream repos exactly once, only after the Plugins publication is sealed, with a payload that downstream gates can consume.
Changes:
- Add an App-credentialed “content repository” checkout path to the reusable
node-repo-module-packandnode-repo-publish-bakeworkflows (soMeshWeaver.Pluginscan be read from platform CD). - Make
main-cduse a single reusable fan-out (notify-dependents) gated onplugins-bakesuccess, and remove the prior inline fan-out job. - Extend
notify-dependents.ymlpayload to includesha,image, anddigest, and update the guard test + WhatsNew entry to pin the intended shape.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
test/MeshWeaver.Documentation.Test/PlatformReleaseNotifyGuard.cs |
Updates the CI-shape guard to enforce one fan-out and validate the reusable workflow’s structure. |
src/MeshWeaver.Documentation/Data/WhatsNew/2026-08-30-a-platform-release-wakes-the-fleet-once-and-after-plugins.md |
Adds a changelog entry describing the fixed wave semantics and credentialing. |
.github/workflows/notify-dependents.yml |
Adds sha/image/digest inputs, validates platform payload completeness, and posts JSON payloads to subscribers. |
.github/workflows/node-repo-publish-bake.yml |
Adds App-based token minting for cross-repo content checkout when content-repository is set. |
.github/workflows/node-repo-module-pack.yml |
Adds App-based token minting for cross-repo content checkout for both select and pack jobs. |
.github/workflows/main-cd.yml |
Wires the new content credential into Plugins jobs and gates a single downstream notify job on Plugins bake completion. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…s release is not a platform event release-packages.yml calls the same reusable with reason: packages; hard-coding source:"platform" / chain:[platform, plugins] would label a NuGet release as an image release and seed the receivers' cycle guard with a Plugins publication that was never made. source is now the reason, and only a platform release carries Plugins in its chain. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Test Results (shard 0)913 tests +658 913 ✅ +659 5m 44s ⏱️ + 5m 29s Results for commit 7f0a118. ± Comparison against base commit a9b3483. This pull request removes 1 and adds 659 tests. Note that renamed tests count towards both. |
Test Results 41 files ± 0 41 suites ±0 33m 31s ⏱️ + 4m 14s Results for commit 7f0a118. ± Comparison against base commit a9b3483. This pull request removes 1 and adds 660 tests. Note that renamed tests count towards both. |
What broke (main-cd run 33276813173, the first push-driven wave)
plugins-modulesdied at checkout —fatal: repository 'https://github.com/Systemorph/MeshWeaver.Plugins/' not found. The reusablenode-repo-module-pack.yml/node-repo-publish-bake.ymlcheck outcontent-repositorywith the calling run'sGITHUB_TOKEN, which cannot read the private Plugins repo.dispatch-dependentsjob (ci: the release wave is a GitHub Actions trigger — platform + plugins built together, dependents dispatched, packages cascade #2696) and the reusablenotify-dependents.yml(built in parallel). The reusable fired right afterpromote, before the Plugins bake, so every woken satellite would seed a Plugins publication that was not sealed yet — and its payload was{version, reason}, which Manufacturing refuses (nosha256:digest) and Education cannot bake from (noclient_payload.image).plugins-modules=failure … dispatch-dependents=skipped).What this does
content-app-id/content-app-private-key; whencontent-repositoryis set they assert the credential RED, mint aContents: Readinstallation token scoped to that one repo, and check out with it. Node repos calling them with nocontent-repositoryare byte-identical to before.main-cdpasses the dispatch App (installed on Plugins) as the content credential toplugins-modulesandplugins-bake.notify-dependentsnowneeds: plugins-bake(+plugins-bake-image), runs only onplugins-bake == success, and carriessha,image,digest,source: platform,chain: [platform, plugins]— asserted RED forreason: platform. The inline job is deleted; the verdict's LEGS namenotify-dependents.PlatformReleaseNotifyGuardpins: a single job (nodispatch-dependents:key can come back), the gate onplugins-bake, the payload fields, and the reusable's collected-then-exit 1failure handling.Verified locally
check-workflow-shell.py: 0 live findings. YAML parses.MeshWeaver.Documentation.Testbuilds-c Release -warnaserror(0 errors);PlatformReleaseNotifyGuard+UpstreamBuildGateGuard+ workflow-shell guards: 10/10 passed.Not in scope
The satellite gates'
bake consumption: N DECLINED(module MVID skew, #2698) is a Plugins-side convergence; the wave PRs in the satellites stay red on that until it lands.🤖 Generated with Claude Code