ci: per-variant journey gates and an affected-scoped framework matrix - #744
Conversation
Rungs 2+3 on the affected-gating probe. Per-variant journey gating (rung 2), expressed in task space: server:test is the go-side signal (deliberately not server:build — console embeds into the server binary, so console-only changes mark server:build affected while the journeys never render the console; embedding breakage is server:build's own job inside the moon ci graph). The passkey-preset and test-kit journeys gate on the shared next-scaffold surface (go, cli, api, config, testing kit, login-ui, components, sdk-core/next); the fresh-app journey additionally answers to every sdk-*:build because its framework matrix exists to cover the SDKs; any journey-project change triggers all. Snapshot runs iff any journey does. Net: console-only PRs run the e2e suites but zero journeys; single-SDK PRs run only the fresh-app matrix. Matrix scoping (rung 3): journey_matrix=single collapses the fresh-app run to --framework next unless an SDK build, cli:build, or the journey project moved — the scaffolded flow widget is framework-independent, so a server-only change proves as much on one framework as on five. Also makes affected-query failures diagnosable from the run log: PR #710's docs-only run went full-tail on 2026-08-03 because the moon query failed transiently and the fail-open path was silent (the theory that a moved base tip poisons moon's diff was reproduced against and disproved — moon merge-bases internally). Failure exit codes and non-JSON stdout now print to the step log. Fixtures refreshed from live captures on current main (sdk-vue, console, login-ui, testing classes); 19 node-tests wired through workspace:test.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
There was a problem hiding this comment.
Pull request overview
This PR refines the full-pr CI tail gating to be more granular and cheaper: journeys are no longer all-or-nothing, and the fresh-app journey’s framework matrix is reduced to a single representative framework unless framework-specific surfaces are affected.
Changes:
- Split the single
journeysgate into per-variant gates (journey_fresh_app,journey_passkey,journey_testkit) driven by an explicit task-space trigger map inscripts/ci-mode.mjs. - Add
journey_matrixoutput (fullvssingle) and wire it into the fresh-app journey step to optionally constrain the framework matrix to--framework next. - Improve observability for affected-query failures (stderr passthrough + explicit failure line) and extend the unit test suite with new change-class fixtures.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| scripts/ci-mode.mjs | Implements per-variant journey gates, journey_matrix scope, and better query-failure logging while preserving fail-open behavior. |
| scripts/ci-mode.test.mjs | Expands coverage to new gating variants and matrix-collapsing behavior across representative affected-task slices. |
| .github/workflows/ci.yml | Consumes the new per-variant gates and passes journey_matrix into the fresh-app journey step to optionally constrain the framework selection. |
| CONTRIBUTING.md | Updates CI documentation to describe per-variant journey gating, matrix collapsing, and snapshot coupling behavior. |
…t artifact docs The components test now uses the full 91-task capture from current main (all 8 sdk builds + the journey project present, so the real class resolves journey_matrix=full and gates every journey; go_tests stays false because server:test never enters the set) — the old trimmed slice asserted a combination the graph never produces. A clearly-labeled synthetic slice keeps the :test-browser-alone browsers trigger covered. Matrix comments say 'the full matrix' and point at frameworks.mjs instead of hard-coding a framework count that is already stale. The CONTRIBUTING artifacts sentence now matches the snapshot gate: no journey lane, no snapshot artifact.
Summary
Rungs 2+3 on the affected-gating probe from #731: the three journey steps stop being all-or-nothing, and the fresh-app framework matrix scales to what actually moved.
Per-variant journey gating (rung 2). The variant↔surface map lives as task-space constants in
scripts/ci-mode.mjs— never file globs, moon's graph stays the authority:sdk-*:build∪ journey projectserver:test,cli:build,api:build,config:build,testing:build,login-ui:build,components:build,sdk-core:build,sdk-next:buildThe key discriminator is
server:testas the go-side signal instead ofserver:build: console embeds into the server binary, so console-only changes markserver:buildaffected — but the journeys never render the console, and embedding breakage isserver:build's own job inside themoon cigraph.server:testmoves only when Go/API sources move. The snapshot runs iff any journey does (tarball handoff stays a filesystem contract moon cannot see).Net effect, live-probed against real moon queries: console-only PRs run the e2e suites but zero journeys and no snapshot (~6.4 min off that class); single-SDK PRs run only the fresh-app matrix (passkey/testkit skip, −2.7 min); login-ui/testing-kit/journey changes still run all three.
Affected-scoped matrix (rung 3).
journey_matrix=singlecollapses the fresh-app journey to--framework nextunless an SDK build,cli:build(owns the scaffold templates), or the journey project moved — the scaffolded flow widget is framework-independent, so a server-only change proves as much on one framework as on five (~1.3 min off every go-side PR).Query-failure observability. Investigating why the docs-only #710 ran the full 9.6-min tail post-#731: its moon query failed transiently (658 ms step, silent) and correctly failed open — but nothing said so. The initial theory (a moved base tip poisons moon's two-dot diff) was reproduced against and disproved — moon merge-bases internally — so no base-handling change ships; instead, query failure exit codes and non-JSON stdout now print to the step log, and the forced-full reason prints to stdout as well as the step summary.
Validation
node --test scripts/ci-mode.test.mjs— 19/19; fixtures are livemoon querycaptures from current main (new sdk-vue class; console/login-ui/testing refreshed 2026-08-04).moon run workspace:test— same suite through moon (:testselection).journey_matrix=single; aging-branch repro (fork 3 commits back, current-tip base) → correctly gated, disproving the base-staleness theory.scripts/+.github/) — the safety rule, as designed.Release notes / changeset
Notes
release-snapshotartifact (their journeys skip). Console review happens on the Vercel preview, and any code path that genuinely feeds the snapshot re-enables it via the surface map — flag it if you want a console-triggered snapshot anyway.🤖 Generated with Claude Code