Repository navigation
Push the release wave to dependent repos (event-driven) instead of waiting to be polled - #2691
Merged
Merged
Conversation
A plugin repo is built against a PINNED platform, so when the platform releases — images here, NuGet packages on a tag — every plugin repo must rebuild and republish or its portals read `FrameworkDeclined (built against <old>, live <new>)` and adopt nothing. That wave was only ever PULLED. Each repo's `schedule` noticed the release at its next poll, up to a full interval late, and this file stated that a GitHub→GitHub dispatch "never will be" added, for two reasons: * no credential in the release path * no subscriber list that would not drift Both are answered now. `DEPENDENT_DISPATCH_APP_ID` / `_PRIVATE_KEY` were provisioned on 2026-08-19 and, until this commit, were referenced by NOTHING in this repository — a credential minted for exactly this and never wired. And there is no list. The subscribers are the repositories the App is INSTALLED on, read at run time from `GET /installation/repositories`. Adding a repo to the wave is installing the App on it; nothing in this file can go stale, which was the specific objection. This does not replace memex's broadcast — the two are independent paths to the same event. The reason for a second one is that a wave depending on a single hop through a mesh stops whenever that hop is unreachable, and that is not observable from here. 🚨 It FAILS RED when it notifies nobody. Its predecessor printed "NOT CONFIGURED" and went green for its entire life, which is why nothing was ever notified and nobody noticed. A fan-out reaching zero repositories is indistinguishable from one that never ran, so it is an error. Per-repo failures are COLLECTED rather than fatal on the first, because a wave that stops at the first unreachable repo leaves the rest of the fleet stale with the partial state invisible. An empty `inputs.version` is refused for the same reason: `needs.<skipped>.outputs.*` is the empty string rather than an error, and a CD run already died that way (#2496). release-packages.yml's version now goes to $GITHUB_OUTPUT as well as $GITHUB_ENV — the latter is invisible to a dependent job, which is how a downstream job silently receives "". The `schedule` poll in each repo stays as the fallback, so a lost dispatch costs one delayed wave rather than a missed one. What changes is that the normal case is seconds instead of an interval. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR makes the “release wave” to dependent repositories event-driven by adding a reusable repository_dispatch fan-out workflow and invoking it from both the platform CD pipeline and the NuGet release workflow, so dependent repos rebuild immediately rather than waiting for scheduled polls.
Changes:
- Expose the release version from
release-packages.ymlas a job output (in addition to$GITHUB_ENV) so downstream jobs can consume it safely. - Add a reusable workflow (
notify-dependents.yml) that mints a GitHub App installation token, discovers subscriber repos via/installation/repositories, and dispatchesmeshweaver-framework-releasedto each, failing if no subscribers or any dispatch fails. - Invoke the reusable fan-out workflow from
main-cd.yml(platform/images) andrelease-packages.yml(NuGet/packages).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| .github/workflows/release-packages.yml | Publishes a version job output and triggers dependent-repo notifications after a successful package release. |
| .github/workflows/notify-dependents.yml | New reusable workflow that discovers subscriber repos from the App installation and dispatches release events with version + reason. |
| .github/workflows/main-cd.yml | Adds a post-promote job to push the platform release event to dependent repos via the reusable workflow. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Contributor
Contributor
Contributor
Contributor
Contributor
Contributor
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Makes the release wave event-driven — pushed to every dependent repo the moment the platform releases, instead of each repo noticing at its next
schedulepoll.Why this is not "another poll optimisation"
A plugin repo compiles against a pinned platform. When the platform releases — images from
main-cd, NuGet packages from av*tag — every plugin repo must rebuild and republish, or its portals readFrameworkDeclined (built against <old>, live <new>)and adopt nothing. Until now that wave only travelled by pull.The two objections in
main-cd.yml, answeredThat file states a dispatch job here "never will be" added. Both reasons were true when written:
DEPENDENT_DISPATCH_APP_ID/_PRIVATE_KEYwere provisioned 2026-08-19 and, until this PR, referenced by nothing in this repo.grep -rn DEPENDENT_DISPATCH .github/returned zero hits.GET /installation/repositories. Adding a repo to the wave is installing the App on it.This does not replace memex's broadcast; the two are independent paths to the same event. The reason for a second is that a wave depending on one hop through a mesh stops whenever that hop is unreachable — and that is not observable from here. The
schedulepoll stays as the fallback, so a lost dispatch costs one delayed wave rather than a missed one.Failure modes this refuses to repeat
It fails RED when it notifies nobody. Its predecessor printed
NOT CONFIGUREDand went green for its entire life — which is exactly why nothing was ever notified and nobody noticed. A fan-out reaching zero repositories is indistinguishable from one that never ran.Per-repo failures are collected, not fatal on the first. A wave that stops at the first unreachable repo leaves the rest of the fleet stale, with the partial state invisible.
An empty version is refused.
needs.<skipped-job>.outputs.*is the empty string, not an error, and a CD run already died on precisely that (#2496). Relatedly,release-packages.ymlwrote its version only to$GITHUB_ENV, which a dependent job cannot read — it now writes$GITHUB_OUTPUTtoo, since that silent""is the same defect one layer down.Verified
Receivers already exist and agree on the event name —
types: [meshweaver-framework-released]in MeshWeaver.Plugins, SocialMedia, Reinsurance, Education and Crm. MeshWeaver.Manufacturing has norepository_dispatchreceiver at all and will need one added separately to be part of "every repo".Both workflows parse (
yaml.safe_load).repository_dispatchthere.Companion work: the ordered rebuild that each notified repo should then perform is Systemorph/MeshWeaver.Plugins#925 — a package may not rebuild until every package it requires has republished at the new version.