Repository navigation
CD never syncs or bakes plugin source; the reconcile gets its own concurrency lane - #2491
Conversation
…currency lane
Two rules from the plugin build contract, enforced in the workflow that violated both.
THE PLATFORM NEVER BAKES A PLUGIN. main-cd.yml checked out MeshWeaver.Plugins
("every plugin is baked in this run"), Roslyn-compiled every module against the
image, and published the result as the `plugins` source — the SAME shelf Plugins'
own publish-bake writes on every main push and on a half-hourly poll. Two
producers, one shelf, whichever sealed last winning; and a full compile of source
the platform does not own, on every platform push. CiContentBake.md already said
this bake was "not the delivery lane"; the workflow disagreed with the doc.
Removed: the checkout, the bake, its gate, its identity assert, its publish — 98
lines, five steps. The two Plugins checkouts that REMAIN fetch the portal host
and migration worker projects (in that repo since #2293): source the image is
built from, not a plugin being baked.
THE RECONCILE HAS ITS OWN LANE. The hourly schedule is the delivery path
(dotnet-test.yml says so where it justifies cancel-in-progress on main), and it
was starved by the push path: six all-skipped workflow_run runs fired on ONE sha
inside 20 minutes on 2026-08-27, each holding the group's single pending slot,
and the cron did not fire at 07:23 or 08:23 at all (#2490). Earlier a scheduled
run that DID start was evicted with zero jobs. A no-op holding the slot is the
defect. The concurrency group is now keyed `reconcile` for schedule and the ref
for everything else, so a reconcile is never queued behind a push-path run.
Docs: CiContentBake.md no longer describes core baking a Plugins checkout;
PluginBuildContract.md gains the three rules (platform never bakes a plugin;
nothing syncs plugin source to bake it; a source install is git on disk, never
rows in a database — GitPackageSource reads the tree, it does not ingest it).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR aligns core CD and documentation with the plugin build contract by removing core’s responsibility for baking/publishing plugin source outputs, and by ensuring the hourly reconcile path is not blocked by push-path no-op runs.
Changes:
- Removed the
MeshWeaver.Pluginscheckout + “bake every plugin” + publish steps frommain-cd.yml, so core CD only bakes/publishes platform-owned content. - Split CD concurrency so scheduled reconciles run in a dedicated lane (
main-cd-reconcile) instead of queueing behindworkflow_runruns. - Updated architecture docs (
CiContentBake.md,PluginBuildContract.md) to explicitly state the “platform never bakes plugins” rule and to clarify source-vs-publication expectations.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
src/MeshWeaver.Documentation/Data/Architecture/PluginBuildContract.md |
Adds explicit “three rules” to prevent reintroducing plugin-source baking and to clarify what “source installs” mean operationally. |
src/MeshWeaver.Documentation/Data/Architecture/CiContentBake.md |
Updates the CI/bake narrative to match the contract: platform bakes only its own content; plugins are baked/published by plugin repos. |
.github/workflows/main-cd.yml |
Removes core’s plugin-source bake/publish lane and gives scheduled reconcile its own concurrency group to avoid starvation. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| # this group's single pending slot, and the cron did not fire at 07:23 or 08:23 at all (#2490). | ||
| # Earlier a scheduled run that DID start was evicted with zero jobs by the one-pending-slot | ||
| # rule. A no-op that holds the slot is the defect; keying the reconcile separately removes it. | ||
| group: main-cd-${{ github.event_name == 'schedule' && 'reconcile' || github.ref }} |
Test Results (shard 0)1 379 tests 1 379 ✅ 6m 11s ⏱️ Results for commit efc71f2. |
Test Results (shard 3)1 078 tests 1 078 ✅ 17m 24s ⏱️ Results for commit efc71f2. |
Test Results (shard 2)1 001 tests 809 ✅ 6m 28s ⏱️ Results for commit efc71f2. |
Test Results (shard 1)849 tests 845 ✅ 6m 29s ⏱️ Results for commit efc71f2. |
Test Results (shard 4) 7 files 7 suites 11m 17s ⏱️ Results for commit efc71f2. |
Test Results (shard 5)1 579 tests 1 578 ✅ 9m 39s ⏱️ Results for commit efc71f2. |
Test Results 45 files 45 suites 57m 32s ⏱️ Results for commit efc71f2. |
Two rules from the plugin build contract (
Doc/Architecture/PluginBuildContract, #2478), enforced in the workflow that violated both.The platform never bakes a plugin
main-cd.ymlchecked outMeshWeaver.Plugins("every plugin is baked in this run"), Roslyn-compiled every module against the image, and published the result as thepluginssource — the same shelf Plugins' ownpublish-bakewrites on every main push and on a half-hourly poll. Two producers, one shelf, whichever sealed last winning; and a full compile of source the platform does not own, on every platform push.CiContentBake.mdalready said this bake was "not the delivery lane"; the workflow disagreed with the doc.Removed: the checkout, the bake, its gate, its identity assert, its publish — five steps, 98 lines.
BAKE_PLUGINS_DIR/PLUGINS_SHAhave no surviving reference (asserted). The two Plugins checkouts that remain fetch the portal host and migration worker projects (in that repo since #2293) — source the image is built from, not a plugin being baked.The reconcile has its own lane
The hourly schedule is the delivery path, and it was starved by the push path: six all-skipped
workflow_runruns on one sha inside 20 minutes today, each holding the group's single pending slot; the cron did not fire at 07:23 or 08:23 at all (#2490). A no-op holding the slot is the defect.Docs
CiContentBake.mdno longer describes core baking a Plugins checkout.PluginBuildContract.mdgains three rules: the platform never bakes a plugin; nothing syncs plugin source to bake it; a source install is git on disk, never rows in a database —GitPackageSourcereads the tree, it does not ingest it.Verified: YAML parses,
bash -nclean on everyrun:inpublish-bake, no dangling env references.Closes #2490. Refs #2478.
🤖 Generated with Claude Code