Skip to content

The shared gate INSTALLS its upstreams: upstream-seed fetches the sealed publication and hands it to the tester as --seed - #2481

Merged
rbuergi merged 2 commits into
mainfrom
feat/gate-consumes-upstream-bake
Aug 27, 2026
Merged

rbuergi merged 2 commits into
mainfrom
feat/gate-consumes-upstream-bake

Conversation

@rbuergi

@rbuergi rbuergi commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Draft until #2478 lands — it works only once published bundles carry node definitions; before that the seed stamps nothing and the tester's Shortfall verdict correctly refuses the run.

Step 2 of the plugin build contract (Doc/Architecture/PluginBuildContract, on #2478): install my dependencies — as built artifacts, served by MeshWeaver.

The gap

The reusable gate had eight inputs and no way to consume a bake. stage-repo copied the upstream's source into the mount and the tester recompiled it. Measured today: core passes --seed in 9 places, every plugin repo in 0.

What upstream-seed: plugins does

  1. Resolves the framework identity its own image resolves — composed exactly as the tester step composes it (digest-pinned), so the seed is addressed to the identity that will consume it.
  2. Asserts each upstream has a sealed publication under that identity (_complete, existence-first, fail-closed — the publish script's own rule). Fails red if not: a gate that silently compiled its upstream is indistinguishable from one that installed it, which is BakeSeed's own warning.
  3. Downloads the bundles into a seed dir with framework-mvid.txt beside them, mounts it read-only, passes --seed /seed. The tester checks the seed before the mesh boots (usage error, exit 2 — never green) and refuses a run that compiled what it was handed.

Reads storage with the same OIDC identity publish-bake writes with, declared the same way: three optional secrets, id-token: write, a preflight that names what is missing rather than skipping.

Empty upstream-seed is today's behaviour byte for byte.

Verified

  • YAML parses; every steps.* / inputs.* / secrets.* reference resolves to a declaration (the checker caught a phantom steps.pin on the first pass — fixed to compose the image as the tester step does).
  • bash -n clean on every run:.

Then, per satellite (one small PR each)

with:
  upstream-seed: plugins
  bake-publish-targets: ${{ vars.BAKE_PUBLISH_TARGETS }}
secrets:
  azure-client-id: …   # the three already provisioned for publish-bake
permissions: { contents: read, id-token: write }

and drop stage-repo / stage-modules.

🤖 Generated with Claude Code

…sealed publication and hands it to the tester as --seed

Step 2 of the plugin build contract (Doc/Architecture/PluginBuildContract):
"install my dependencies" — as built artifacts, served by MeshWeaver. The
reusable gate had eight inputs and no way to consume a bake: `stage-repo` copied
the upstream's SOURCE into the mount and the tester recompiled it. Measured
2026-08-27: core passes --seed in 9 places, every plugin repo in 0.

`upstream-seed: plugins` now makes the gate:

  1. resolve the framework identity its OWN image resolves — composed exactly as
     the tester step composes it, digest-pinned, so the seed is addressed to the
     identity that will consume it;
  2. assert each upstream has a SEALED publication under that identity
     (`_complete` — existence first, fail closed, the publish script's own rule),
     and fail RED if not: a gate that silently compiled its upstream is
     indistinguishable from one that installed it (BakeSeed's own warning);
  3. download the bundles into a seed dir with `framework-mvid.txt` beside them,
     mount it read-only, and pass `--seed /seed`. The tester checks the seed
     before the mesh boots (usage error, exit 2 — never green) and REFUSES a run
     that compiled what it was handed (BakeSeedConsumer.Shortfall).

Reads storage with the same OIDC identity publish-bake writes with, declared the
same way (three optional secrets, id-token: write, a preflight that names what is
missing). Adds `bake-publish-targets` so the gate reads where publish-bake wrote.

Empty upstream-seed is today's behaviour, byte for byte. Runtime depends on core
#2478 (bundles carrying node definitions) — without it the seed stamps nothing
and the Shortfall verdict correctly refuses the run.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 27, 2026 07:51

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

Updates the reusable node-repo gate workflow to support “install upstream dependencies” by fetching prebuilt, sealed upstream bundle publications from portal storage and passing them to the tester as a --seed, instead of staging upstream source and recompiling it.

Changes:

  • Adds new workflow_call inputs/secrets to enable upstream bundle seeding (upstream-seed, bake-publish-targets, and Azure OIDC secrets).
  • Introduces an OIDC-based Azure preflight/login + framework-identity resolution step to fetch sealed upstream publications into a seed directory.
  • Mounts the seed read-only into the tester container and passes --seed /seed when present.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +344 to +349
az storage file download-batch --account-name "$account" --share-name "$share" \
--source "$share/$dir" --destination "$SEED_DIR" --pattern '*.zip' \
--auth-mode login --backup-intent --only-show-errors > /dev/null
n=$(ls "$SEED_DIR"/*.zip 2>/dev/null | wc -l | tr -d ' ')
echo "upstream '$src': $n bundle(s) from $account/$share/$dir"
fetched=$((fetched + n))
@rbuergi

rbuergi commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

⚠️ Cannot go green on a PR until a federated credential exists for it — maintainer decision

The first run of upstream-seed on a PR failed at the OIDC login, and the reason is provisioning, not code:

AADSTS700213: No matching federated identity record found for presented assertion subject
  'repo:Systemorph@77832550/MeshWeaver.SocialMedia@1320607286:pull_request'

github-actions-bake holds four federated credentials, every one scoped to ref:refs/heads/main:

gh-meshweaver-reinsurance-main   repo:Systemorph@77832550/MeshWeaver.Reinsurance@881295217:ref:refs/heads/main
gh-meshweaver-socialmedia-main   repo:Systemorph@77832550/MeshWeaver.SocialMedia@1320607286:ref:refs/heads/main
gh-reinsurance-main-classic      repo:Systemorph/MeshWeaver.Reinsurance:ref:refs/heads/main
gh-socialmedia-main-classic      repo:Systemorph/MeshWeaver.SocialMedia:ref:refs/heads/main

That is exactly right for publish-bake, which runs on main. The gate runs on pull requests, whose subject is …:pull_request, and nothing matches it — so the gate can install its upstream on main and never on the PR that most needs it.

What closes it — one credential per repo for the PR subject, in both subject formats (AGENTS.md: never normalise to one; the format varies per repo within the org):

repo:Systemorph@77832550/MeshWeaver.SocialMedia@1320607286:pull_request
repo:Systemorph/MeshWeaver.SocialMedia:pull_request
repo:Systemorph@77832550/MeshWeaver.Reinsurance@881295217:pull_request
repo:Systemorph/MeshWeaver.Reinsurance:pull_request

Read-only on storage, same role the identity already holds. Adding a credential to a live identity is a system change, so I have not done it and have not armed this PR. Until it exists this PR is correct code that cannot be verified on its own CI.

@rbuergi

rbuergi commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

Direction change, per maintainer: the Azure-OIDC fetch in this PR is the interim. The target is the mesh verifying GitHub's OIDC identity directly — no secret, a Store/BuildPrincipal trust node per repo, and the registry serving publications so the gate never touches Azure. Scoped in #2483; design on #2478. This PR stays draft; the pull_request credential gap above becomes moot once that lands.

@github-actions

github-actions Bot commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 3)

999 tests  ±0   995 ✅ ±0   20m 49s ⏱️ + 2m 31s
  9 suites ±0     4 💤 ±0 
  9 files   ±0     0 ❌ ±0 

Results for commit f0a9fed. ± Comparison against base commit 6600d35.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 1)

    8 files  ±0      8 suites  ±0   7m 32s ⏱️ -10s
1 092 tests ±0    900 ✅ ±0  192 💤 ±0  0 ❌ ±0 
1 685 runs  ±0  1 493 ✅ ±0  192 💤 ±0  0 ❌ ±0 

Results for commit f0a9fed. ± Comparison against base commit 6600d35.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 5)

4 482 tests  ±0   4 376 ✅ ±0   11m 35s ⏱️ -28s
    9 suites ±0     106 💤 ±0 
    9 files   ±0       0 ❌ ±0 

Results for commit f0a9fed. ± Comparison against base commit 6600d35.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 4)

   10 files  ±0     10 suites  ±0   8m 33s ⏱️ +33s
2 399 tests ±0  2 397 ✅ ±0  2 💤 ±0  0 ❌ ±0 
2 400 runs  ±0  2 398 ✅ ±0  2 💤 ±0  0 ❌ ±0 

Results for commit f0a9fed. ± Comparison against base commit 6600d35.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 0)

959 tests  ±0   959 ✅ ±0   6m 30s ⏱️ +6s
  8 suites ±0     0 💤 ±0 
  8 files   ±0     0 ❌ ±0 

Results for commit f0a9fed. ± Comparison against base commit 6600d35.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 2)

1 483 tests  ±0   1 483 ✅ ±0   6m 24s ⏱️ -36s
    8 suites ±0       0 💤 ±0 
    8 files   ±0       0 ❌ ±0 

Results for commit f0a9fed. ± Comparison against base commit 6600d35.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Test Results

    52 files  ±0      52 suites  ±0   1h 1m 25s ⏱️ + 1m 55s
11 412 tests ±0  11 108 ✅ ±0  304 💤 ±0  0 ❌ ±0 
12 008 runs  ±0  11 704 ✅ ±0  304 💤 ±0  0 ❌ ±0 

Results for commit f0a9fed. ± Comparison against base commit 6600d35.

♻️ This comment has been updated with latest results.

…y-key, MeshWeaver#2487) — HTTPS + instance key, no Azure, works on pull_request; the Azure share stays as the fallback mode
@rbuergi

rbuergi commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

Registry mode added (registry-url input + registry-key secret): upstream-seed now fetches the sealed publication over HTTPS from GET /api/plugins/bundles/prebuilt/<identity>/<source> (MeshWeaver#2487) with an instance key holding a whole-source grant — no Azure, no federated credential, works on pull_request. The Azure mode stays as the fallback when registry-url is empty. The AADSTS700213 gap above is moot on this path; what each repo needs instead is one mwi_ key with plugins/*.

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