Repository navigation
ci: follow a copied producer back to the attempt that built its artifact #2792
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| # train/** runs the same checks on a train branch before it is fast-forwarded | |
| # onto master; required status checks on master are satisfied by that run. | |
| branches: [master, main, "train/**"] | |
| # The nightly run rechecks the Cargo graph pinned by Cargo.lock; | |
| # workflow_dispatch remains available for an operator-triggered run. | |
| schedule: | |
| - cron: "17 3 * * *" | |
| workflow_dispatch: | |
| # A train branch gets pushed again with each merge, and every run is about twenty | |
| # jobs against a shared runner limit, so a new push cancels the train's older run. | |
| # master keeps every run, so a failure still names the commit that broke it. | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: ${{ github.ref != 'refs/heads/master' && github.ref != 'refs/heads/main' }} | |
| permissions: | |
| contents: read | |
| actions: read | |
| env: | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| # Separate differential parity cases by name; when absent, lib shards cover the entire library. | |
| MC_PARITY_FILTER: 'test(/^providers::step_transform::parity_tests::r2_review_720_pass_differential/)' | |
| # Pipeline shape on every push to master/main: | |
| # | |
| # Consumers check out/install immediately, then wait for verified same-attempt artifacts. | |
| # preflight (layout, manifest, fmt, typecheck, lint, complete dists) | |
| # ├─ unit suites and packaging smokes | |
| # ├─ Docker install smokes (independent of unit/host results) | |
| # ├─ host behavior (OC1: four whole-file shards; OC2: two) | |
| # ├─ Rust clippy, lib archive → lib partitions + parity | |
| # └─ Rust integration/doctests/remaining crates and hermetic build → shards | |
| # ci-summary always checks every required leg, including cancelled/skipped jobs. | |
| # | |
| # Two e2e layers cover different concerns: | |
| # - Docker e2e: fresh-install smoke (plugin loads, doctor clean, one mock turn writes DB rows | |
| # under cortexkit path with right harness). Catches packaging / install-flow regressions. | |
| # - Host e2e: behavior suite with byte-level wire assertions, multi-turn cache stability, | |
| # historian publish behavior, tag-owner collision, synthetic todowrite, cross-harness memory, | |
| # etc. Spawns real `opencode serve` / Pi subprocesses against an embedded mock provider. | |
| # Catches cache-stability + correctness regressions that the smoke layer cannot see. | |
| # | |
| # Docker e2e was previously in a separate workflow (e2e-docker.yml). Folding it here means | |
| # every master/main push exercises all unit, Docker and host proofs. The | |
| # Rust jobs run on every push and scheduled run. Pushes use Cargo.lock-pinned crates; | |
| # the scheduled hermetic build additionally probes the subconscious default branch: | |
| # | |
| # rust-crates legacy-named aggregate for clippy, lib/parity, integration, | |
| # binary, doctest and remaining-workspace targets | |
| # e2e-rust-hermetic-build → e2e-rust-hermetic (4 shards) | |
| # | |
| # The mc-module integration tests always build ck-subc from its Cargo.lock revision. | |
| # Hermetic push builds use that same revision; the nightly build intentionally builds | |
| # subconscious default-branch HEAD and reports it as drift in the job summary. | |
| jobs: | |
| preflight: | |
| name: Preflight (checks and dists) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: "24" | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: rustfmt | |
| - name: Install dependencies | |
| run: bun install --frozen-lockfile | |
| - name: Layout, manifest and shard contracts | |
| run: | | |
| bash scripts/check-cortexkit-layout.sh | |
| bash scripts/check-docs-layout.sh | |
| bash scripts/check-docs-layout.test.sh | |
| python3 scripts/cargo-lock-pins.py --self-test | |
| python3 scripts/check-nextest-inventory.py --self-test | |
| python3 scripts/wait-ci-artifact.py --self-test | |
| timeout 180s python3 scripts/check-cargo-path-dependencies.py | |
| timeout 180s python3 scripts/check-cargo-path-dependencies.py --self-test | |
| bun packages/e2e-tests/scripts/validate-mode-manifest.ts | |
| cd packages/e2e-tests | |
| bun test scripts/validate-mode-manifest.test.ts scripts/select-rust-shard.test.ts scripts/select-host-shard.test.ts scripts/select-unit-shard.test.ts scripts/ci-workflow.test.ts | |
| - name: Format check | |
| if: ${{ !cancelled() }} | |
| run: cargo fmt --check | |
| - name: TypeScript typecheck | |
| if: ${{ !cancelled() }} | |
| run: | | |
| status=0 | |
| for package in plugin cli retina-local-fs pi-plugin dashboard; do | |
| bun run --cwd "packages/$package" typecheck || status=1 | |
| done | |
| bun run --cwd packages/e2e-tests tsc --noEmit -p tsconfig.ci.json || status=1 | |
| exit "$status" | |
| - name: Lint | |
| if: ${{ !cancelled() }} | |
| run: | | |
| status=0 | |
| for package in plugin cli retina-local-fs pi-plugin dashboard; do | |
| bun run --cwd "packages/$package" lint || status=1 | |
| done | |
| exit "$status" | |
| - name: Build complete dists | |
| run: | | |
| bun run build | |
| bun run --cwd packages/pi-plugin build:e2e-argv | |
| bun run --cwd packages/dashboard build | |
| - name: Check compiled contracts | |
| run: | | |
| bun run --cwd packages/plugin check:tui-compiled | |
| bun crates/mc-module/gen/gen-historian-prompt-golden.ts --check | |
| bun test packages/e2e-tests/scripts/ci-dists.test.ts | |
| - name: Package same-commit dists | |
| run: | | |
| tar -czf ci-dists.tar.gz packages/plugin/dist packages/pi-plugin/dist packages/cli/dist packages/retina-local-fs/dist packages/dashboard/dist tests/docker/.generated | |
| sha256sum ci-dists.tar.gz > ci-dists.sha256 | |
| printf '%s\n' "$GITHUB_SHA" > ci-dists.commit | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: ci-dists-${{ github.sha }}-${{ github.run_attempt }} | |
| path: | | |
| ci-dists.tar.gz | |
| ci-dists.sha256 | |
| ci-dists.commit | |
| compression-level: 0 | |
| if-no-files-found: error | |
| retention-days: 1 | |
| check-docs-layout: | |
| name: Check (public documentation layout) | |
| runs-on: ubuntu-latest | |
| needs: [preflight] | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Reject tracked ignored CortexKit files | |
| run: bash scripts/check-cortexkit-layout.sh | |
| - name: Reject internal documentation in docs | |
| run: bash scripts/check-docs-layout.sh | |
| - name: Exercise planted layout violations | |
| run: bash scripts/check-docs-layout.test.sh | |
| check-plugin-compat: | |
| name: Check (CLI, retina and packaging) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| # node:sqlite (the Pi / OpenCode-Desktop SQLite backend) is only reachable | |
| # under Node, not Bun. Node 24 also strips the smoke script's inline TS. | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: "24" | |
| - name: Install dependencies | |
| run: bun install --frozen-lockfile | |
| - uses: ./.github/actions/restore-ci-dists | |
| id: dists | |
| - name: Test (CLI and retina, normal and debug assertions) | |
| # Bun has no --no-fail-fast flag. Collect package/mode statuses explicitly; | |
| # each package wrapper still owns its preload, JSC flags and timeout. | |
| run: | | |
| status=0 | |
| for package in cli retina-local-fs; do | |
| bun run --cwd "packages/$package" test || status=1 | |
| done | |
| MAGIC_CONTEXT_DEBUG_ASSERTIONS=1 bun run --cwd packages/cli test || status=1 | |
| MAGIC_CONTEXT_DEBUG_ASSERTIONS=1 bun run --cwd packages/retina-local-fs test --timeout=60000 || status=1 | |
| exit "$status" | |
| # Exercise the node:sqlite branch of shared/sqlite.ts under REAL Node — | |
| # bun test only covers the bun:sqlite branch, so the transaction() shim, | |
| # readonly→readOnly mapping, and the array-bind normalization (#151) would | |
| # otherwise ship unverified on Pi/Desktop. | |
| - name: Smoke (node:sqlite backend) | |
| if: ${{ !cancelled() && steps.dists.outcome == 'success' }} | |
| run: node packages/plugin/scripts/smoke-node-sqlite.ts | |
| # The smart-note QuickJS sandbox loads a ~1MB WASM. `bun test` runs it from | |
| # src (wasm resolves via node_modules), so it cannot catch a BUNDLING break | |
| # where the wasm isn't embedded in dist. This bundles sandbox-runner exactly | |
| # like the package build and runs a real check against the bundle. | |
| - name: Smoke (smart-note wasm bundle) | |
| if: ${{ !cancelled() && steps.dists.outcome == 'success' }} | |
| run: bun packages/plugin/scripts/smoke-smartnote-wasm.ts | |
| # The raw-TSX ./tui entry imports @opentui/solid's JSX runtime. `bun test` | |
| # never imports it, so a missing/mismatched OpenTUI or Solid dep (as broke | |
| # on OpenCode 1.17.10's OpenTUI 0.4.2 bump) ships a TUI that won't load. | |
| # Import the entry the way OpenCode loads the ./tui export to catch it. | |
| - name: Smoke (TUI entry import) | |
| if: ${{ !cancelled() && steps.dists.outcome == 'success' }} | |
| run: bun packages/plugin/scripts/smoke-tui-import.ts | |
| # The dev-path import above cannot catch packaging breaks: OpenTUI's Solid | |
| # transform skips node_modules sources, so only a packed PROD install | |
| # exercises the resolution path OpenCode's plugin cache uses (v0.31.1 | |
| # shipped without runtime deps and passed every dev-path check). | |
| - name: Smoke (TUI packaged install import) | |
| if: ${{ !cancelled() && steps.dists.outcome == 'success' }} | |
| run: bun packages/plugin/scripts/smoke-tui-pack-install.ts --skip-build | |
| # Tokenizer loading is lazy, so an import-only smoke misses resolution | |
| # failures. Pack + npm-install prod deps, then exercise an estimate from a | |
| # compiled Bun host matching OpenCode's /$bunfs/root runtime. | |
| - name: Smoke (tokenizer packaged install estimate) | |
| if: ${{ !cancelled() && steps.dists.outcome == 'success' }} | |
| run: bun packages/plugin/scripts/smoke-tokenizer-pack-install.ts --skip-build | |
| unit-plugin: | |
| name: Unit (plugin ${{ matrix.mode }} ${{ matrix.shard }}/4) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| mode: [normal, assertions] | |
| shard: [0, 1, 2, 3] | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Install dependencies | |
| run: bun install --frozen-lockfile | |
| - uses: ./.github/actions/restore-ci-dists | |
| - name: Run whole-file plugin shard | |
| env: | |
| UNIT_MODE: ${{ matrix.mode }} | |
| run: | | |
| bun packages/e2e-tests/scripts/select-unit-shard.ts plugin "$UNIT_MODE" "${{ matrix.shard }}/4" > "$RUNNER_TEMP/unit-files.txt" | |
| mapfile -t files < "$RUNNER_TEMP/unit-files.txt" | |
| test "${#files[@]}" -gt 0 | |
| printf '%s\n' "${files[@]}" | |
| if [[ "$UNIT_MODE" == assertions ]]; then export MAGIC_CONTEXT_DEBUG_ASSERTIONS=1; fi | |
| bun run --cwd packages/plugin test --reporter=junit --reporter-outfile "$GITHUB_WORKSPACE/unit-junit.xml" "${files[@]}" | |
| - uses: actions/upload-artifact@v4 | |
| if: ${{ !cancelled() }} | |
| with: | |
| name: unit-plugin-${{ matrix.mode }}-${{ matrix.shard }}-${{ github.run_attempt }} | |
| path: unit-junit.xml | |
| if-no-files-found: error | |
| unit-pi-plugin: | |
| name: Unit (pi-plugin ${{ matrix.mode }} ${{ matrix.shard }}/4) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| mode: [normal, assertions] | |
| shard: [0, 1, 2, 3] | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Install dependencies | |
| run: bun install --frozen-lockfile | |
| - uses: ./.github/actions/restore-ci-dists | |
| - name: Run whole-file Pi shard | |
| env: | |
| UNIT_MODE: ${{ matrix.mode }} | |
| # Assertion shards keep one worker and the existing 60-second timeout. | |
| run: | | |
| bun packages/e2e-tests/scripts/select-unit-shard.ts pi-plugin "$UNIT_MODE" "${{ matrix.shard }}/4" > "$RUNNER_TEMP/unit-files.txt" | |
| mapfile -t files < "$RUNNER_TEMP/unit-files.txt" | |
| test "${#files[@]}" -gt 0 | |
| printf '%s\n' "${files[@]}" | |
| if [[ "$UNIT_MODE" == assertions ]]; then | |
| MAGIC_CONTEXT_DEBUG_ASSERTIONS=1 bun run --cwd packages/pi-plugin test --parallel=1 --timeout=60000 --reporter=junit --reporter-outfile "$GITHUB_WORKSPACE/unit-junit.xml" "${files[@]}" | |
| else | |
| bun run --cwd packages/pi-plugin test --reporter=junit --reporter-outfile "$GITHUB_WORKSPACE/unit-junit.xml" "${files[@]}" | |
| fi | |
| - uses: actions/upload-artifact@v4 | |
| if: ${{ !cancelled() }} | |
| with: | |
| name: unit-pi-plugin-${{ matrix.mode }}-${{ matrix.shard }}-${{ github.run_attempt }} | |
| path: unit-junit.xml | |
| if-no-files-found: error | |
| check-plugin: | |
| name: Check (plugin) | |
| runs-on: ubuntu-latest | |
| if: ${{ always() }} | |
| needs: [unit-plugin, check-plugin-compat] | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Require plugin unit and packaging legs | |
| env: | |
| CI_NEEDS: ${{ toJSON(needs) }} | |
| run: bun packages/e2e-tests/scripts/check-ci-results.ts check-plugin | |
| check-pi-plugin: | |
| name: Check (pi-plugin) | |
| runs-on: ubuntu-latest | |
| if: ${{ always() }} | |
| needs: [unit-pi-plugin] | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Require Pi unit legs | |
| env: | |
| CI_NEEDS: ${{ toJSON(needs) }} | |
| run: bun packages/e2e-tests/scripts/check-ci-results.ts check-pi-plugin | |
| check-dashboard: | |
| name: Check (dashboard) | |
| runs-on: ubuntu-latest | |
| needs: [preflight] | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Install dependencies | |
| run: bun install --frozen-lockfile | |
| # Frontend-only checks (no Rust/Tauri needed). The key gate is the test | |
| # step, which runs config-parity.test.ts — it fails the build if the | |
| # plugin config schema gains/renames/removes a field the dashboard's | |
| # ConfigEditor coverage manifest doesn't account for, so the form can't | |
| # silently drift out of sync with the schema again. | |
| - name: Test | |
| run: bun run --cwd packages/dashboard test | |
| e2e-opencode: | |
| name: E2E (OpenCode, Docker) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 25 | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Install workspace deps | |
| run: bun install --frozen-lockfile | |
| - uses: ./.github/actions/restore-ci-dists | |
| - name: Build E2E image | |
| run: | | |
| docker build \ | |
| --platform linux/amd64 \ | |
| -f tests/docker/Dockerfile.opencode \ | |
| -t mc-e2e-opencode \ | |
| . | |
| - name: Run E2E | |
| run: docker run --rm --platform linux/amd64 mc-e2e-opencode | |
| e2e-opencode2: | |
| name: E2E (OpenCode 2.0.22, Docker) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Install workspace dependencies | |
| run: bun install --frozen-lockfile | |
| - uses: ./.github/actions/restore-ci-dists | |
| # The wrapper is the single local/CI entrypoint. It builds the publishable | |
| # plugin, fails if Docker or opencode2 is missing, and runs the exact-pinned | |
| # GA host through a real transform, host fold, database check, and TUI boot. | |
| - name: Run pinned OpenCode 2 container lane | |
| run: tests/docker/opencode2/run.sh | |
| e2e-pi: | |
| name: E2E (Pi, Docker) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 25 | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Install workspace deps | |
| run: bun install --frozen-lockfile | |
| - uses: ./.github/actions/restore-ci-dists | |
| - name: Build E2E image | |
| # The Pi Dockerfile installs runtime deps fresh inside the image | |
| # (better-sqlite3 builds against linux/amd64), so no host-side | |
| # `npm install` is needed. | |
| run: | | |
| docker build \ | |
| --platform linux/amd64 \ | |
| -f tests/docker/Dockerfile.pi \ | |
| -t mc-e2e-pi \ | |
| . | |
| - name: Run E2E | |
| run: docker run --rm --platform linux/amd64 mc-e2e-pi | |
| e2e-omp: | |
| name: E2E (Oh My Pi, real Docker) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 25 | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Install workspace deps | |
| run: bun install --frozen-lockfile | |
| - uses: ./.github/actions/restore-ci-dists | |
| - name: Build real OMP E2E image | |
| run: | | |
| docker build \ | |
| --platform linux/amd64 \ | |
| -f tests/docker/Dockerfile.omp \ | |
| -t mc-e2e-omp \ | |
| . | |
| - name: Run real OMP install and session smoke | |
| run: docker run --rm --platform linux/amd64 mc-e2e-omp | |
| e2e-host-opencode: | |
| name: E2E (OpenCode, host behavior ${{ matrix.shard }}/4) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| shard: [0, 1, 2, 3] | |
| timeout-minutes: 40 | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Install workspace deps | |
| run: bun install --frozen-lockfile | |
| # Install opencode the same way the Docker image does — the host | |
| # suite spawns `opencode serve` from PATH. | |
| - name: Install opencode | |
| # Float to LATEST (no --version) so CI exercises the opencode version | |
| # users actually run and catches upstream breakage as it ships — not at | |
| # our release time. (A fixed pin previously hid opencode 1.16's | |
| # post-overflow change, commit 7e09660c3, until release; the | |
| # overflow-recovery host test is now version-agnostic.) Trade-off: a | |
| # known-bad upstream release can turn CI red for unrelated PRs — if that | |
| # happens, temporarily re-pin with `--version X.Y.Z` here until it's | |
| # resolved upstream. | |
| run: | | |
| OPENCODE_VERSION=latest bash tests/docker/install-opencode.sh | |
| echo "$HOME/.opencode/bin" >> "$GITHUB_PATH" | |
| - name: Verify opencode on PATH | |
| run: opencode --version | |
| - uses: ./.github/actions/restore-ci-dists | |
| id: dists | |
| # Strip inherited NODE_ENV=test so the spawned opencode subprocess | |
| # gets the same logging + runtime behavior as a normal local run | |
| # (documented in CONTRIBUTING / project memory). | |
| - name: Run host e2e suite (OpenCode tests only) | |
| env: | |
| NODE_ENV: "" | |
| MC_E2E_MODE: ts | |
| MC_E2E_HOST: opencode | |
| run: | | |
| cd packages/e2e-tests | |
| # A validator failure must fail the job, never fall through to an empty | |
| # list: `bun test` with no files runs every file in the package. | |
| set -o pipefail | |
| files=$(bun scripts/select-host-shard.ts opencode "${{ matrix.shard }}/4" | tr '\n' ' ') | |
| if [ -z "${files// /}" ]; then echo 'mode manifest selected no files'; exit 1; fi | |
| echo "Running OpenCode host tests from mode manifest: $files" | |
| # shellcheck disable=SC2086 # The repository-controlled file list must expand into Bun arguments. | |
| bun test --timeout 600000 $files | |
| # This oracle is outside tests/**/*.test.ts and runs once even if a host suite fails. | |
| - name: Cache analysis oracle | |
| if: ${{ !cancelled() && matrix.shard == 0 && steps.dists.outcome == 'success' }} | |
| env: | |
| NODE_ENV: "" | |
| MC_E2E_MODE: ts | |
| MC_E2E_HOST: opencode | |
| run: cd packages/e2e-tests && bun test --timeout 600000 src/cache-analysis.test.ts | |
| e2e-host-pi: | |
| name: E2E (Pi, host behavior) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 40 | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| # Pi tests resolve the Pi binary via createRequire against | |
| # @earendil-works/pi-coding-agent, which is a workspace dep of | |
| # packages/pi-plugin. `bun install` brings it in. | |
| - name: Install workspace deps | |
| run: bun install --frozen-lockfile | |
| # pi-cross-harness.test.ts spawns BOTH a Pi runner and an OpenCode | |
| # serve to verify cross-harness memory sharing, so this job needs | |
| # opencode on PATH too. Float to LATEST like the OpenCode host job | |
| # (see that step for the rationale + re-pin escape hatch). | |
| - name: Install opencode | |
| run: | | |
| OPENCODE_VERSION=latest bash tests/docker/install-opencode.sh | |
| echo "$HOME/.opencode/bin" >> "$GITHUB_PATH" | |
| - name: Verify opencode on PATH | |
| run: opencode --version | |
| - uses: ./.github/actions/restore-ci-dists | |
| # Per-test timeout bumped to 300s for the same cold-start reason as | |
| # the OpenCode host job. Pi historian publish path also crosses an | |
| # HTTP boundary into the mock provider, which is slower on shared | |
| # runners than on local hardware. | |
| - name: Run host e2e suite (Pi tests from mode manifest) | |
| env: | |
| NODE_ENV: "" | |
| MC_E2E_MODE: ts | |
| MC_E2E_HOST: pi | |
| run: | | |
| cd packages/e2e-tests | |
| # A validator failure must fail the job, never fall through to an empty | |
| # list: `bun test` with no files runs every file in the package. | |
| set -o pipefail | |
| files=$(bun scripts/validate-mode-manifest.ts --mode ts --harness pi | tr '\n' ' ') | |
| if [ -z "${files// /}" ]; then echo 'mode manifest selected no files'; exit 1; fi | |
| echo "Running Pi host tests from mode manifest: $files" | |
| # shellcheck disable=SC2086 # The repository-controlled file list must expand into Bun arguments. | |
| bun test --timeout 600000 $files | |
| e2e-host-opencode2: | |
| name: E2E (OpenCode 2.0.22, host behavior ${{ matrix.shard }}/2) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| shard: [0, 1] | |
| timeout-minutes: 40 | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| # The OpenCode 2 harness spawns the real GA host from @opencode/cli, a | |
| # workspace dev dependency whose postinstall unpacks the platform binary | |
| # (trustedDependencies at the workspace root lets bun run it). | |
| - name: Install workspace deps | |
| run: bun install --frozen-lockfile | |
| # The conversion regression boots both generations and doctor probes the | |
| # v1 CLI on PATH; the v2 binary comes from the pinned workspace dependency. | |
| # The installer one-liner resolves "latest" through the rate-limited GitHub API | |
| # and can exit 0 without installing; the repo's installer pins, retries and | |
| # asserts the binary runs. | |
| - name: Install OpenCode 1 for conversion coverage | |
| run: | | |
| OPENCODE_VERSION=1.18.31 bash tests/docker/install-opencode.sh | |
| echo "$HOME/.opencode/bin" >> "$GITHUB_PATH" | |
| - name: Verify the GA host binary | |
| run: bun -e "const { CLI } = await import('./packages/e2e-tests/src/opencode2-runner/spawn.ts'); const { execFileSync } = await import('node:child_process'); const version = execFileSync(CLI, ['--version']).toString().trim(); console.log(CLI, version); if (version !== 'opencode v2.0.22') throw new Error('OpenCode 2 host lane requires 2.0.22')" | |
| - uses: ./.github/actions/restore-ci-dists | |
| id: dists | |
| - name: Run host e2e suite (OpenCode 2 tests from mode manifest) | |
| env: | |
| NODE_ENV: "" | |
| MC_E2E_MODE: ts | |
| MC_E2E_HOST: opencode2 | |
| run: | | |
| cd packages/e2e-tests | |
| set -o pipefail | |
| files=$(bun scripts/select-host-shard.ts opencode2 "${{ matrix.shard }}/2" | tr '\n' ' ') | |
| if [ -z "${files// /}" ]; then echo 'mode manifest selected no files'; exit 1; fi | |
| echo "Running OpenCode 2 host tests from mode manifest: $files" | |
| # shellcheck disable=SC2086 # The repository-controlled file list must expand into Bun arguments. | |
| bun test --timeout 600000 $files | |
| # These long-lived dual-host fixtures manipulate separate throwaway stores, | |
| # but run sequentially to avoid contending with one another's live hosts. | |
| - name: Run OC2 conversion and marker regressions | |
| if: ${{ !cancelled() && matrix.shard == 0 && steps.dists.outcome == 'success' }} | |
| env: | |
| NODE_ENV: "" | |
| MC_E2E_MODE: ts | |
| MC_E2E_HOST: opencode2 | |
| run: | | |
| cd packages/e2e-tests | |
| status=0 | |
| bun test --timeout 600000 tests/opencode2/store-generation-conversion.test.ts || status=1 | |
| bun test --timeout 600000 tests/opencode2/marker-s3-runtime.test.ts || status=1 | |
| exit "$status" | |
| e2e-host-omp: | |
| name: E2E (Oh My Pi, host behavior) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 40 | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| # OMP runs the same Pi plugin through Pi's extension API; the harness | |
| # resolves @oh-my-pi/pi-coding-agent (a workspace dev dependency) when | |
| # MC_E2E_HOST=omp. | |
| - name: Install workspace deps | |
| run: bun install --frozen-lockfile | |
| - name: Install opencode | |
| run: | | |
| OPENCODE_VERSION=latest bash tests/docker/install-opencode.sh | |
| echo "$HOME/.opencode/bin" >> "$GITHUB_PATH" | |
| - uses: ./.github/actions/restore-ci-dists | |
| - name: Run host e2e suite (OMP tests from mode manifest) | |
| env: | |
| NODE_ENV: "" | |
| MC_E2E_MODE: ts | |
| MC_E2E_HOST: omp | |
| run: | | |
| cd packages/e2e-tests | |
| set -o pipefail | |
| files=$(bun scripts/validate-mode-manifest.ts --mode ts --harness omp | tr '\n' ' ') | |
| if [ -z "${files// /}" ]; then echo 'mode manifest selected no files'; exit 1; fi | |
| echo "Running OMP host tests from mode manifest: $files" | |
| # shellcheck disable=SC2086 # The repository-controlled file list must expand into Bun arguments. | |
| bun test --timeout 600000 $files | |
| rust-mc-module-integration: | |
| name: Rust (mc-module integration) | |
| # mc-module integration tests build ck-subc from the locked source revision. | |
| # Published commons and subconscious crates resolve from this repository's | |
| # Cargo.lock, so there is no commons checkout or floating crate source here. | |
| # | |
| # Keep daemon tests under libtest: its process-local build locks must not be | |
| # multiplied by nextest's process-per-test execution model. | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 | |
| permissions: | |
| contents: read | |
| actions: read | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: clippy, rustfmt | |
| # The hostless-store integration test provisions context.db through the CLI. | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Install CLI dependencies | |
| run: bun install --frozen-lockfile | |
| - name: Resolve Cargo.lock crate pins | |
| id: cargo-pins | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| python3 scripts/cargo-lock-pins.py --self-test | |
| pins="$(python3 scripts/cargo-lock-pins.py)" | |
| printf '%s\n' "$pins" >> "$GITHUB_OUTPUT" | |
| locked_crates="$(printf '%s\n' "$pins" | sed -n 's/^locked_crates=//p')" | |
| echo "Cargo.lock pins: $locked_crates" >> "$GITHUB_STEP_SUMMARY" | |
| # real_daemon.rs builds ck-subc and checks its launch-nonce history; this | |
| # exact locked checkout is therefore needed only by this integration-test job. | |
| - name: Check out locked subconscious source for daemon integration tests | |
| uses: actions/checkout@v5 | |
| with: | |
| repository: cortexkit/subconscious | |
| path: .siblings/subconscious | |
| ref: ${{ steps.cargo-pins.outputs.subc_revision }} | |
| fetch-depth: 0 | |
| # These integration tests use ../subconscious to build ck-subc. Cargo now | |
| # resolves commons crates from the registry/Git lock instead of ../commons. | |
| - name: Link locked daemon source for integration tests | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| ln -sfn "$GITHUB_WORKSPACE/.siblings/subconscious" "$GITHUB_WORKSPACE/../subconscious" | |
| test -f "$GITHUB_WORKSPACE/../subconscious/Cargo.lock" | |
| - uses: ./.github/actions/restore-ci-dists | |
| - name: Test mc-module (integration, binary and doctest targets) | |
| run: | | |
| status=0 | |
| cargo test --locked -p mc-module --test '*' --bins --no-fail-fast || status=1 | |
| cargo test --locked -p mc-module --doc --no-fail-fast || status=1 | |
| exit "$status" | |
| rust-clippy: | |
| name: Rust (clippy) | |
| runs-on: ubuntu-latest | |
| needs: [preflight] | |
| timeout-minutes: 45 | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: clippy | |
| - name: Clippy (including integration targets) | |
| run: cargo clippy --locked --workspace --all-targets -- -D warnings | |
| rust-workspace-crates: | |
| name: Rust (remaining crates) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Install workspace dependencies for migration-oracle tests | |
| run: bun install --frozen-lockfile | |
| - uses: ./.github/actions/restore-ci-dists | |
| - name: Test the remaining workspace crates | |
| run: cargo test --locked --workspace --exclude mc-module --no-fail-fast | |
| rust-lib-archive: | |
| name: Rust (mc-module lib archive) | |
| runs-on: ubuntu-latest | |
| needs: [preflight] | |
| timeout-minutes: 45 | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: taiki-e/install-action@v2 | |
| with: | |
| tool: cargo-nextest@0.9.138 | |
| - name: Compile the complete lib once and prove inventory equality | |
| run: | | |
| mkdir -p ci-rust-lib | |
| cargo nextest --version | |
| cargo nextest archive --locked -p mc-module --lib --archive-file ci-rust-lib/archive.tar.zst | |
| cargo test --locked -p mc-module --lib -- --list > ci-rust-lib/cargo-list.txt | |
| cargo test --locked -p mc-module --lib -- --list --ignored > ci-rust-lib/cargo-ignored.txt | |
| cargo nextest list --archive-file ci-rust-lib/archive.tar.zst --run-ignored all --message-format json > ci-rust-lib/all.json | |
| for shard in 1 2 3 4; do | |
| cargo nextest list --archive-file ci-rust-lib/archive.tar.zst --run-ignored all --partition "hash:$shard/4" -E "not ($MC_PARITY_FILTER)" --message-format json > "ci-rust-lib/lib-$shard.json" | |
| done | |
| cargo nextest list --archive-file ci-rust-lib/archive.tar.zst --run-ignored all -E "$MC_PARITY_FILTER" --message-format json > ci-rust-lib/parity.json | |
| python3 scripts/check-nextest-inventory.py ci-rust-lib | |
| diff -u ci-rust-lib/cargo-names.txt ci-rust-lib/union-names.txt | |
| rustc -vV > ci-rust-lib/rustc.txt | |
| printf '%s\n' "$GITHUB_SHA" > ci-rust-lib/commit.txt | |
| sha256sum ci-rust-lib/archive.tar.zst > ci-rust-lib/archive.sha256 | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: rust-lib-${{ github.sha }}-${{ github.run_attempt }} | |
| path: ci-rust-lib/ | |
| compression-level: 0 | |
| if-no-files-found: error | |
| retention-days: 1 | |
| rust-mc-module-lib: | |
| name: Rust (mc-module lib ${{ matrix.shard }}/4) | |
| runs-on: ubuntu-latest | |
| # The cap includes at most 45 minutes waiting plus the original execution allowance. | |
| timeout-minutes: 90 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| shard: [1, 2, 3, 4] | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: taiki-e/install-action@v2 | |
| with: | |
| tool: cargo-nextest@0.9.138 | |
| - uses: ./.github/actions/wait-ci-artifact | |
| id: archive | |
| with: | |
| artifact: rust-lib-${{ github.sha }} | |
| producer: Rust (mc-module lib archive) | |
| timeout-minutes: "45" | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| artifact-ids: ${{ steps.archive.outputs.artifact-id }} | |
| merge-multiple: true | |
| path: ci-rust-lib | |
| - name: Verify archive provenance | |
| run: | | |
| test "$(cat ci-rust-lib/commit.txt)" = "$GITHUB_SHA" | |
| sha256sum --check ci-rust-lib/archive.sha256 | |
| rustc -vV | diff - ci-rust-lib/rustc.txt | |
| - name: Run lib partition | |
| run: cargo nextest run --archive-file ci-rust-lib/archive.tar.zst --workspace-remap "$GITHUB_WORKSPACE" --profile ci --no-fail-fast --failure-output immediate-final --partition "hash:${{ matrix.shard }}/4" -E "not ($MC_PARITY_FILTER)" | |
| - name: Check every selected test executed | |
| if: ${{ !cancelled() }} | |
| run: python3 scripts/check-nextest-inventory.py --junit ci-rust-lib "lib-${{ matrix.shard }}" target/nextest/ci/junit.xml | |
| - uses: actions/upload-artifact@v4 | |
| if: ${{ !cancelled() }} | |
| with: | |
| name: rust-lib-results-${{ matrix.shard }} | |
| path: target/nextest/ci/junit.xml | |
| if-no-files-found: error | |
| rust-mc-module-parity: | |
| name: Rust (mc-module parity differential) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 90 | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: taiki-e/install-action@v2 | |
| with: | |
| tool: cargo-nextest@0.9.138 | |
| - uses: ./.github/actions/wait-ci-artifact | |
| id: archive | |
| with: | |
| artifact: rust-lib-${{ github.sha }} | |
| producer: Rust (mc-module lib archive) | |
| timeout-minutes: "45" | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| artifact-ids: ${{ steps.archive.outputs.artifact-id }} | |
| merge-multiple: true | |
| path: ci-rust-lib | |
| - name: Verify archive provenance | |
| run: | | |
| test "$(cat ci-rust-lib/commit.txt)" = "$GITHUB_SHA" | |
| sha256sum --check ci-rust-lib/archive.sha256 | |
| rustc -vV | diff - ci-rust-lib/rustc.txt | |
| - name: Run parity groups from the shared lib archive | |
| # Only parity permits an empty selection. The lib archive job compares the | |
| # disjoint lib/parity union to Cargo discovery, including ignored tests. | |
| run: cargo nextest run --archive-file ci-rust-lib/archive.tar.zst --workspace-remap "$GITHUB_WORKSPACE" --profile ci --no-fail-fast --failure-output immediate-final --no-tests=pass -E "$MC_PARITY_FILTER" | |
| - name: Check every selected parity test executed | |
| if: ${{ !cancelled() }} | |
| run: python3 scripts/check-nextest-inventory.py --junit ci-rust-lib parity target/nextest/ci/junit.xml | |
| - uses: actions/upload-artifact@v4 | |
| if: ${{ !cancelled() }} | |
| with: | |
| name: rust-parity-results | |
| path: target/nextest/ci/junit.xml | |
| if-no-files-found: error | |
| rust-crates: | |
| name: Rust (crates) | |
| runs-on: ubuntu-latest | |
| if: ${{ always() }} | |
| needs: [preflight, rust-clippy, rust-lib-archive, rust-mc-module-lib, rust-mc-module-parity, rust-mc-module-integration, rust-workspace-crates] | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Require every Rust leg | |
| env: | |
| CI_NEEDS: ${{ toJSON(needs) }} | |
| run: bun packages/e2e-tests/scripts/check-ci-results.ts rust-crates | |
| e2e-rust-hermetic-build: | |
| name: E2E (Rust hermetic build) | |
| # Cargo.lock pins the published crate versions and both git dependency revisions. | |
| # On schedule the daemon checkout below intentionally switches to upstream HEAD. | |
| runs-on: ubuntu-latest | |
| needs: [preflight] | |
| timeout-minutes: 120 | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Resolve Cargo.lock crate pins | |
| id: cargo-pins | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| python3 scripts/cargo-lock-pins.py --self-test | |
| pins="$(python3 scripts/cargo-lock-pins.py)" | |
| printf '%s\n' "$pins" >> "$GITHUB_OUTPUT" | |
| locked_crates="$(printf '%s\n' "$pins" | sed -n 's/^locked_crates=//p')" | |
| echo "Cargo.lock pins: $locked_crates" >> "$GITHUB_STEP_SUMMARY" | |
| # Cargo can resolve subc-core as a library dependency but does not build its | |
| # ck-subc binary target. Pushes use the root lockfile revision; only the scheduled | |
| # run deliberately checks the subconscious default branch for upstream drift. | |
| - name: Check out Cargo.lock-pinned subconscious source for ck-subc | |
| if: ${{ github.event_name != 'schedule' }} | |
| uses: actions/checkout@v5 | |
| with: | |
| repository: cortexkit/subconscious | |
| path: .siblings/subconscious | |
| ref: ${{ steps.cargo-pins.outputs.subc_revision }} | |
| - name: Check out subconscious default branch for scheduled drift | |
| if: ${{ github.event_name == 'schedule' }} | |
| uses: actions/checkout@v5 | |
| with: | |
| repository: cortexkit/subconscious | |
| path: .siblings/subconscious | |
| - name: Record ck-subc source revision | |
| id: daemon-source | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| sha="$(git -C "$GITHUB_WORKSPACE/.siblings/subconscious" rev-parse HEAD)" | |
| if [[ "$GITHUB_EVENT_NAME" == "schedule" ]]; then | |
| summary="ck-subc source drift: subconscious default-branch HEAD $sha" | |
| else | |
| summary="ck-subc source pinned by Cargo.lock: $sha" | |
| fi | |
| echo "$summary" | |
| echo "$summary" >> "$GITHUB_STEP_SUMMARY" | |
| echo "sha=$sha" >> "$GITHUB_OUTPUT" | |
| - name: Derive hermetic Cargo cache key | |
| id: cargo-cache-key | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| # Key on the resolved Cargo graph plus the exact daemon source, including | |
| # nightly HEAD, so pinned and drift builds never reuse one another's cache. | |
| lock_digest="$(sha256sum Cargo.lock | awk '{print $1}')" | |
| source_sha="${{ steps.daemon-source.outputs.sha }}" | |
| digest="$(printf '%s\n%s\n' "$lock_digest" "$source_sha" | sha256sum | awk '{print $1}')" | |
| echo "key=rust-hermetic-${RUNNER_OS}-${RUNNER_ARCH}-${digest}" >> "$GITHUB_OUTPUT" | |
| - name: Restore ck-subc and ckdev-mc-e2e Cargo target cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: packages/e2e-tests/.cache/rust-e2e-cargo-target | |
| key: ${{ steps.cargo-cache-key.outputs.key }} | |
| - name: Install workspace dependencies | |
| run: bun install --frozen-lockfile | |
| - name: Build hermetic binary pair (including fault-injection variant) | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| target="$GITHUB_WORKSPACE/packages/e2e-tests/.cache/rust-e2e-cargo-target" | |
| mkdir -p "$target/prebuilt" | |
| CARGO_TARGET_DIR="$target" cargo build --release -p mc-module | |
| cp "$target/release/ck-mc" "$target/prebuilt/ckdev-mc-e2e" | |
| CARGO_TARGET_DIR="$target" cargo build --release -p mc-module --features drive-fault | |
| cp "$target/release/ck-mc" "$target/prebuilt/ckdev-mc-e2e-drive-fault" | |
| (cd "$GITHUB_WORKSPACE/.siblings/subconscious" && CARGO_TARGET_DIR="$target" cargo build --release -p subc-core --bins) | |
| cp "$target/release/ck-subc" "$target/prebuilt/ckdev-subc" | |
| printf '%s\n' "$GITHUB_SHA" > "$target/prebuilt/commit.txt" | |
| tar -czf "$RUNNER_TEMP/rust-hermetic-binaries.tar.gz" -C "$target/prebuilt" . | |
| (cd "$RUNNER_TEMP" && sha256sum rust-hermetic-binaries.tar.gz > rust-hermetic-binaries.sha256) | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: rust-hermetic-binaries-${{ github.sha }}-${{ github.run_attempt }} | |
| path: | | |
| ${{ runner.temp }}/rust-hermetic-binaries.tar.gz | |
| ${{ runner.temp }}/rust-hermetic-binaries.sha256 | |
| compression-level: 0 | |
| if-no-files-found: error | |
| retention-days: 1 | |
| e2e-rust-hermetic: | |
| name: E2E (Rust hermetic ${{ matrix.shard }}/4) | |
| runs-on: ubuntu-latest | |
| # Waiting is capped at the producer's 120 minutes; tests retain their own timeouts. | |
| timeout-minutes: 180 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| shard: [0, 1, 2, 3] | |
| permissions: | |
| contents: read | |
| actions: read | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Install workspace dependencies | |
| run: bun install --frozen-lockfile | |
| - name: Install pinned OpenCode | |
| run: | | |
| OPENCODE_VERSION=1.18.32 bash tests/docker/install-opencode.sh | |
| echo "$HOME/.opencode/bin" >> "$GITHUB_PATH" | |
| - uses: ./.github/actions/restore-ci-dists | |
| - uses: ./.github/actions/wait-ci-artifact | |
| id: binaries | |
| with: | |
| artifact: rust-hermetic-binaries-${{ github.sha }} | |
| producer: E2E (Rust hermetic build) | |
| timeout-minutes: "120" | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| artifact-ids: ${{ steps.binaries.outputs.artifact-id }} | |
| merge-multiple: true | |
| path: ${{ runner.temp }}/hermetic-artifact | |
| - name: Restore executable and auxiliary binaries | |
| run: | | |
| (cd "$RUNNER_TEMP/hermetic-artifact" && sha256sum --check rust-hermetic-binaries.sha256) | |
| mkdir -p packages/e2e-tests/.cache/prebuilt | |
| tar -xzf "$RUNNER_TEMP/hermetic-artifact/rust-hermetic-binaries.tar.gz" -C packages/e2e-tests/.cache/prebuilt | |
| test "$(cat packages/e2e-tests/.cache/prebuilt/commit.txt)" = "$GITHUB_SHA" | |
| for binary in ckdev-mc-e2e ckdev-mc-e2e-drive-fault ckdev-subc; do | |
| test -x "packages/e2e-tests/.cache/prebuilt/$binary" | |
| done | |
| - name: Run manifest shard | |
| env: | |
| MC_E2E_SHARD: ${{ matrix.shard }}/4 | |
| MC_E2E_CK_MC_PREBUILT_BIN: ${{ github.workspace }}/packages/e2e-tests/.cache/prebuilt/ckdev-mc-e2e | |
| MC_E2E_CK_MC_DRIVE_FAULT_BIN: ${{ github.workspace }}/packages/e2e-tests/.cache/prebuilt/ckdev-mc-e2e-drive-fault | |
| MC_E2E_CK_SUBC_BIN: ${{ github.workspace }}/packages/e2e-tests/.cache/prebuilt/ckdev-subc | |
| run: scripts/run-rust-hermetic-e2e.sh | |
| ci-summary: | |
| name: CI (required) | |
| runs-on: ubuntu-latest | |
| if: ${{ always() }} | |
| needs: [preflight, check-docs-layout, check-plugin, check-pi-plugin, check-plugin-compat, unit-plugin, unit-pi-plugin, check-dashboard, e2e-opencode, e2e-opencode2, e2e-pi, e2e-omp, e2e-host-opencode, e2e-host-opencode2, e2e-host-pi, e2e-host-omp, rust-clippy, rust-lib-archive, rust-mc-module-lib, rust-mc-module-parity, rust-mc-module-integration, rust-workspace-crates, rust-crates, e2e-rust-hermetic-build, e2e-rust-hermetic] | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Require every CI leg | |
| env: | |
| CI_NEEDS: ${{ toJSON(needs) }} | |
| run: bun packages/e2e-tests/scripts/check-ci-results.ts ci-summary |