Skip to content

CD never syncs or bakes plugin source; the reconcile gets its own concurrency lane - #2491

Merged
rbuergi merged 1 commit into
mainfrom
ci/cd-never-bakes-plugins
Aug 27, 2026
Merged

rbuergi merged 1 commit into
mainfrom
ci/cd-never-bakes-plugins

Conversation

@rbuergi

@rbuergi rbuergi commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

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.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 — five steps, 98 lines. BAKE_PLUGINS_DIR / PLUGINS_SHA have 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_run runs 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.

group: main-cd-${{ github.event_name == 'schedule' && 'reconcile' || github.ref }}

Docs

CiContentBake.md no longer describes core baking a Plugins checkout. PluginBuildContract.md gains 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 — GitPackageSource reads the tree, it does not ingest it.

Verified: YAML parses, bash -n clean on every run: in publish-bake, no dangling env references.

Closes #2490. Refs #2478.

🤖 Generated with Claude Code

…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>
Copilot AI lite review requested due to automatic review settings August 27, 2026 08:57
@rbuergi
rbuergi enabled auto-merge August 27, 2026 08:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.Plugins checkout + “bake every plugin” + publish steps from main-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 behind workflow_run runs.
  • 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 }}
@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 0)

1 379 tests   1 379 ✅  6m 11s ⏱️
    6 suites      0 💤
    6 files        0 ❌

Results for commit efc71f2.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 3)

1 078 tests   1 078 ✅  17m 24s ⏱️
    8 suites      0 💤
    8 files        0 ❌

Results for commit efc71f2.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 2)

1 001 tests   809 ✅  6m 28s ⏱️
    7 suites  192 💤
    7 files      0 ❌

Results for commit efc71f2.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 1)

849 tests   845 ✅  6m 29s ⏱️
  8 suites    4 💤
  8 files      0 ❌

Results for commit efc71f2.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 4)

    7 files      7 suites   11m 17s ⏱️
4 402 tests 4 399 ✅ 3 💤 0 ❌
4 995 runs  4 992 ✅ 3 💤 0 ❌

Results for commit efc71f2.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 5)

1 579 tests   1 578 ✅  9m 39s ⏱️
    9 suites      1 💤
    9 files        0 ❌

Results for commit efc71f2.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results

    45 files      45 suites   57m 32s ⏱️
10 286 tests 10 086 ✅ 200 💤 0 ❌
10 881 runs  10 681 ✅ 200 💤 0 ❌

Results for commit efc71f2.

@rbuergi
rbuergi merged commit 203cc7e into main Aug 27, 2026
24 checks passed
@rbuergi
rbuergi deleted the ci/cd-never-bakes-plugins branch August 28, 2026 08:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The hourly CD reconcile is STARVED by no-op workflow_run runs — the cron missed 07:23 and 08:23 while six no-op runs occupied its slot

2 participants