Skip to content

fix(ci): compile platform plugin modules once - #3933

Merged
meshweaver-cloud[bot] merged 1 commit into
mainfrom
codex/fix-release-one-workspace
Sep 10, 2026
Merged

meshweaver-cloud[bot] merged 1 commit into
mainfrom
codex/fix-release-one-workspace

Conversation

@rbuergi

@rbuergi rbuergi commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

What

  • Make core CD's four composed Plugins modules use the reusable module packer's single container workspace.
  • Add explicit OIDC registry authentication to the reusable module packer so core can supply the promoted tester and portal images without introducing long-lived ACR credentials; cold caches authenticate once and warm caches make no registry login.
  • Make the container compiler give every project the full transitive output closure of its local ProjectReference graph while retaining direct edges for scheduling.
  • Add mutation-tested guards for compiler mode, uniform extensible accept contracts, target reuse, and required image pins.

Paired change: Systemorph/MeshWeaver.Plugins#1614 consolidates the Plugins repository's own two module-pack calls.

Why

The platform release for 80b3b63 failed closed because AI and Essentials carried byte-distinct builds of MeshWeaver.Markdown.Collaboration. Both were compiled from the same Plugins commit, but each legacy SDK entry rebuilt its transitive siblings in a different checkout. Pinning version attributes cannot converge deterministic MVIDs across those source paths.

The first combined Plugins workspace then exposed a separate compiler defect: it scheduled Northwind Application → Model → Domain correctly but supplied Roslyn only the direct Model output, so valid source naming a Domain type failed with CS0234/CS0246. The SDK supplies that transitive reference set.

Verification

  • ProjectBuild regression: TransitiveApp → TransitiveMiddle → TransitiveLeaf compiles while App directly names a Leaf type
  • MeshWeaver.PluginTester.Test: 362 passed, 0 failed, fresh TRX
  • MeshWeaver.PluginTester and test project Release builds with warnings as errors: 0 warnings, 0 errors
  • python3 .github/scripts/test-cd-steps.py: all cases passed, including compiler-mode, divergent-accept, missing-target-reuse, and missing-image-pin mutations
  • workflow timeout, YAML-key, and PR-secret guards: 0 violations
  • Documentation and Documentation.Test Release builds with warnings as errors: 0 warnings, 0 errors
  • Documentation.Test: 368 passed, 0 failed, fresh TRX

Refs #3732.

Copilot AI lite review requested due to automatic review settings September 10, 2026 15:38

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.

🟡 Changes recommended

The container workflow lacks required image inputs, and the validation guard is overly restrictive.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Updates core CD to compile four composed Plugins modules in one shared container workspace, with regression coverage and documentation.

Changes:

  • Switches four module entries to container builds.
  • Adds mutation-tested CI validation.
  • Updates architecture and release documentation.
File summaries
File Summary
src/MeshWeaver.Documentation/Data/WhatsNew/2026-09-10-platform-releases-pack-plugin-modules-once.md Adds the release note; no findings.
src/MeshWeaver.Documentation/Data/Architecture/ModuleOwnedSiblingsRide.md Documents the topology; two nit findings (2 and 1 votes) incorrectly attribute separate Plugins changes to this PR.
.github/workflows/main-cd.yml Enables container builds, but lacks required image and digest inputs, blocking artifact compilation (critical, 2 votes).
.github/scripts/test-cd-steps.py Adds the CI guard; its hard-coded targets requirement rejects valid uniform accept sets (moderate, 1 vote).
Review details

Suppressed comments (2)

.github/scripts/test-cd-steps.py:627

  • The reusable packer permits any uniform accept set for a global container build; it rejects divergent sets at node-repo-module-pack.yml:1194-1200, and its input contract explicitly allows values such as targets embedded-resource. Requiring the literal targets here makes the guard reject a valid shared-workspace catalog if all entries later need another acknowledged construct. Validate build: container and, if needed, that container entries share one accept set instead of hard-coding this particular set.
    return [
        f"{entry.get('module') or '<unnamed>'} does not use the shared container workspace"
        for entry in entries
        if entry.get("build") != "container" or entry.get("accept") != "targets"
    ]

src/MeshWeaver.Documentation/Data/Architecture/ModuleOwnedSiblingsRide.md:242

  • This paragraph attributes the Plugins-side Blazor.Chat and Northwind lane changes to MeshWeaver#3732, but neither change is present in this core-only PR and the description says that consolidation will land separately. Please attribute these statements to the actual Plugins change (or remove them until it lands) so the architecture history does not claim this PR changed another repository.
   (MeshWeaver#3732). Merging the former `floor` and `rest` calls then took this assembly from TWO
   builds to **ONE**. `Northwind`, the only remaining SDK entry that rode an in-repo module sibling
   (`MeshWeaver.Maps`), moved into the same workspace in that change.
  • Files reviewed: 4/4 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .github/workflows/main-cd.yml Resolved
@github-actions

github-actions Bot commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 1)

496 tests   496 ✅  37s ⏱️
  1 suites    0 💤
  1 files      0 ❌

Results for commit 846bfbc.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 0)

254 tests   254 ✅  2m 28s ⏱️
  1 suites    0 💤
  1 files      0 ❌

Results for commit 846bfbc.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 3)

390 tests   390 ✅  52s ⏱️
  2 suites    0 💤
  2 files      0 ❌

Results for commit 846bfbc.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 4)

1 893 tests   1 893 ✅  3m 24s ⏱️
    4 suites      0 💤
    4 files        0 ❌

Results for commit 846bfbc.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 2)

1 250 tests   1 248 ✅  3m 47s ⏱️
    3 suites      2 💤
    3 files        0 ❌

Results for commit 846bfbc.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 5)

    6 files      6 suites   4m 51s ⏱️
2 623 tests 2 431 ✅ 192 💤 0 ❌
2 627 runs  2 435 ✅ 192 💤 0 ❌

Results for commit 846bfbc.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Test Results

   17 files     17 suites   16m 1s ⏱️
6 906 tests 6 712 ✅ 194 💤 0 ❌
6 910 runs  6 716 ✅ 194 💤 0 ❌

Results for commit 846bfbc.

♻️ This comment has been updated with latest results.

@rbuergi
rbuergi force-pushed the codex/fix-release-one-workspace branch 3 times, most recently from 6fb4df5 to b7908d2 Compare September 10, 2026 16:16
@rbuergi
rbuergi force-pushed the codex/fix-release-one-workspace branch from b7908d2 to 846bfbc Compare September 10, 2026 16:48
@rbuergi
rbuergi marked this pull request as ready for review September 10, 2026 18:43
@meshweaver-cloud
meshweaver-cloud Bot added this pull request to the merge queue Sep 10, 2026
Merged via the queue into main with commit d540b0d Sep 10, 2026
35 checks passed
rbuergi added a commit that referenced this pull request Sep 11, 2026
…line that names how it was answered

#3221 asks whether a sibling that is ITSELF another package's declared module
should ride into a second bundle. It is a design question, and everything that
made it hard has since moved: #3732/#3933 gave a publication ONE compilation,
#3934/#3946 made a record's module entry a FLOOR rather than an MVID pin, and
#3962/#3973 corrected the guard's stated reason. This settles it, measured.

THE ANSWER — it rides, IFF the platform host does not already ship it.
Being another package's declared module is not a reason to exclude it:
exclusivity was never available (AI `requires [Store]` while Essentials, which
DECLARES the assembly, `requires [AI, …]` — a package cycle) and would break a
supported install. What makes the ride safe is not exclusivity but ONE BUILD per
name per publication, asserted by the producer at compose time and again by the
consumer over the whole sealed set.

MEASURED 2026-09-11, with denominators:

  * Reference graph, MeshWeaver.Plugins main @ d6fa0338 — 79 index.json
    scanned, 37 declare a content.module, 148 csproj under src/. 18 of 37
    declared modules transitively reference another package's declared module;
    4 of 37 are RIDDEN (Markdown.Collaboration ×14, AI ×13, Maps ×4, Import ×1).
    That is the upper bound, not the answer.

  * What is actually PACKED — run 34563887604, success:
      job 103155487545 (MeshWeaver.AI):
        "closure: MeshWeaver.Markdown.Collaboration.dll does NOT ride —
         the platform ships it (measured off …/platform-refs)"
      => the exact pair this issue names no longer rides at all.
      job 103155487593 (MeshWeaver.Northwind.Application):
        "closure: MeshWeaver.Maps.dll RIDES — module-owned"
        "closure: MeshWeaver.Import.dll RIDES — module-owned"
      => the shape IS live today, on two names, in one bundle of 37.

  * The verdict on the composed sets — Plugins publish-bake 103160836446 and
    gate shard 103159059393; MeshWeaver.Crm publish-bake 103166073109, which
    composes ai.module.nupkg and essentials.module.nupkg side by side (the pair
    the 2026-09-08 hold named):
      "module set: 5 … 0 carried by more than one bundle, 0 carried at more than
       one BUILD" / "module set: 4 … 0 … 0"

CORRECTION — the page said the refusal was INERT until each satellite moves its
pin. Measured over every `uses: Systemorph/MeshWeaver/.github/workflows/…` line
in all six node repos: FIVE consume node-repo-gate.yml and
node-repo-publish-bake.yml at @main (Plugins, Reinsurance, SocialMedia,
Manufacturing, Crm), so they took the refusal the hour it merged; only
MeshWeaver.Education pins a sha (67cbbe0…) and the verdict is absent from that
file at that sha. Both directions off the LOGS, not inferred from the ref:
Plugins run 34563887604 and Crm run 34567369849 print the verdict line;
Education's publish-bake for run 34487980275 composes the same four bundles and
prints none.

THE ONE CODE CHANGE — node-repo-module-pack.yml's witness line printed its path
TWICE ("measured off /tmp/app/tmp/app"), because
`${PLATFORM_APP:+measured off $PLATFORM_APP}${PLATFORM_APP:-declared by …}`
expands `:-` to the VALUE when the variable is set. That is the branch that
matters — it is the one saying the answer came from the image rather than from a
hand-maintained list — and it is quoted verbatim in the page above. Stated once
in a `witness` variable instead.

CONTROL, both directions, executed against the REAL workflow file (the two
assignment lines and the echo extracted by content, never copied):

  before:
    MEASURED  … the platform ships it (measured off /tmp/app/tmp/app); …   ← defect
    DECLARED  … the platform ships it (declared by src/platform-shipped.txt); …
  after:
    PASS MEASURED  … (measured off /tmp/app)            [asserts "/tmp/app/tmp/app" ABSENT]
    PASS DECLARED  … (declared by src/platform-shipped.txt)  [asserts "measured off" ABSENT]

VERIFIED
  YAML parses — node-repo-module-pack 6 jobs
  check-workflow-timeouts.py          84 jobs, 2 exempt, 0 violations
  check-workflow-shell.py             0 live findings
  check-workflow-yaml-keys.py         34 files, 0 violations
  check-abbreviated-shas.py           34 files, 0 abbreviations
  check-workflow-permission-pairing.py 2 pairs, 0 violations
  MeshWeaver.Documentation      -c Release -warnaserror  0 Error(s), 0 Warning(s)
  MeshWeaver.Documentation.Test -c Release -warnaserror  0 Error(s), 0 Warning(s)
  DocumentationLinkIntegrityTest + ArchitectureTopicMapTest  5/5 passed (doclinks.trx)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
rbuergi added a commit that referenced this pull request Sep 11, 2026
…line that names how it was answered

#3221 asks whether a sibling that is ITSELF another package's declared module
should ride into a second bundle. It is a design question, and everything that
made it hard has since moved: #3732/#3933 gave a publication ONE compilation,
#3934/#3946 made a record's module entry a FLOOR rather than an MVID pin, and
#3962/#3973 corrected the guard's stated reason. This settles it, measured.

THE ANSWER — it rides, IFF the platform host does not already ship it.
Being another package's declared module is not a reason to exclude it:
exclusivity was never available (AI `requires [Store]` while Essentials, which
DECLARES the assembly, `requires [AI, …]` — a package cycle) and would break a
supported install. What makes the ride safe is not exclusivity but ONE BUILD per
name per publication, asserted by the producer at compose time and again by the
consumer over the whole sealed set.

MEASURED 2026-09-11, with denominators:

  * Reference graph, MeshWeaver.Plugins main @ d6fa0338 — 79 index.json
    scanned, 37 declare a content.module, 148 csproj under src/. 18 of 37
    declared modules transitively reference another package's declared module;
    4 of 37 are RIDDEN (Markdown.Collaboration ×14, AI ×13, Maps ×4, Import ×1).
    That is the upper bound, not the answer.

  * What is actually PACKED — run 34563887604, success:
      job 103155487545 (MeshWeaver.AI):
        "closure: MeshWeaver.Markdown.Collaboration.dll does NOT ride —
         the platform ships it (measured off …/platform-refs)"
      => the exact pair this issue names no longer rides at all.
      job 103155487593 (MeshWeaver.Northwind.Application):
        "closure: MeshWeaver.Maps.dll RIDES — module-owned"
        "closure: MeshWeaver.Import.dll RIDES — module-owned"
      => the shape IS live today, on two names, in one bundle of 37.

  * The verdict on the composed sets — Plugins publish-bake 103160836446 and
    gate shard 103159059393; MeshWeaver.Crm publish-bake 103166073109, which
    composes ai.module.nupkg and essentials.module.nupkg side by side (the pair
    the 2026-09-08 hold named):
      "module set: 5 … 0 carried by more than one bundle, 0 carried at more than
       one BUILD" / "module set: 4 … 0 … 0"

CORRECTION — the page said the refusal was INERT until each satellite moves its
pin. Measured over every `uses: Systemorph/MeshWeaver/.github/workflows/…` line
in all six node repos: FIVE consume node-repo-gate.yml and
node-repo-publish-bake.yml at @main (Plugins, Reinsurance, SocialMedia,
Manufacturing, Crm), so they took the refusal the hour it merged; only
MeshWeaver.Education pins a sha (67cbbe0…) and the verdict is absent from that
file at that sha. Both directions off the LOGS, not inferred from the ref:
Plugins run 34563887604 and Crm run 34567369849 print the verdict line;
Education's publish-bake for run 34487980275 composes the same four bundles and
prints none.

THE ONE CODE CHANGE — node-repo-module-pack.yml's witness line printed its path
TWICE ("measured off /tmp/app/tmp/app"), because
`${PLATFORM_APP:+measured off $PLATFORM_APP}${PLATFORM_APP:-declared by …}`
expands `:-` to the VALUE when the variable is set. That is the branch that
matters — it is the one saying the answer came from the image rather than from a
hand-maintained list — and it is quoted verbatim in the page above. Stated once
in a `witness` variable instead.

CONTROL, both directions, executed against the REAL workflow file (the two
assignment lines and the echo extracted by content, never copied):

  before:
    MEASURED  … the platform ships it (measured off /tmp/app/tmp/app); …   ← defect
    DECLARED  … the platform ships it (declared by src/platform-shipped.txt); …
  after:
    PASS MEASURED  … (measured off /tmp/app)            [asserts "/tmp/app/tmp/app" ABSENT]
    PASS DECLARED  … (declared by src/platform-shipped.txt)  [asserts "measured off" ABSENT]

VERIFIED
  YAML parses — node-repo-module-pack 6 jobs
  check-workflow-timeouts.py          84 jobs, 2 exempt, 0 violations
  check-workflow-shell.py             0 live findings
  check-workflow-yaml-keys.py         34 files, 0 violations
  check-abbreviated-shas.py           34 files, 0 abbreviations
  check-workflow-permission-pairing.py 2 pairs, 0 violations
  MeshWeaver.Documentation      -c Release -warnaserror  0 Error(s), 0 Warning(s)
  MeshWeaver.Documentation.Test -c Release -warnaserror  0 Error(s), 0 Warning(s)
  DocumentationLinkIntegrityTest + ArchitectureTopicMapTest  5/5 passed (doclinks.trx)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

2 participants