From 2feb841a6ce8f98dd0f1bb05d35043a6d91db0b4 Mon Sep 17 00:00:00 2001 From: Lindsay Holmwood Date: Tue, 20 Oct 2026 14:08:55 +1100 Subject: [PATCH 1/6] ci: trial RunsOn runner sizes for Mutants and Test JS (do not merge) Runs the Mutants gate and Test JS's run-tests job on the current Blacksmith runner, on GitHub's runner and on several RunsOn sizes, in one workflow run, so the runners can be compared on the same commit before choosing one. Collapse each matrix back to one runner before merging. The RunsOn labels carry the two fixes cipherstash/vitaminc#487 found: an 80 GB volume, because the default root volume fills during a Rust build and rust-lld dies with SIGBUS, and the s3-cache extra, which serves actions/cache from the RunsOn stack's own bucket instead of fetching GitHub's cache over the internet. The Mutants entries also ask for the Ubuntu 22.04 image to match the Blacksmith baseline. The Mutants entries pin the c8a family. cargo-mutants builds and tests one mutant at a time, so per-core speed decides its run time, and c8a has the best x64 single-thread score in RunsOn's EC2 benchmark at about the price of m8i. The Mutants trial mutates a fixed stack-auth/stack-encrypt commit range (15 mutants) instead of the PR diff, which touches no crate source and would yield no mutants. Its mise cache is off, because a matrix runs-on names no image to key the cache by, which workflow-mise-cache-image.test.mjs requires. Claude-Session: https://claude.ai/code/session_017GMWYNGir7bpQacaUzN84U --- .github/workflows/mutants.yml | 54 ++++++++++++++++++++++++++++------- .github/workflows/tests.yml | 28 ++++++++++++++++-- 2 files changed, 70 insertions(+), 12 deletions(-) diff --git a/.github/workflows/mutants.yml b/.github/workflows/mutants.yml index 65cabc4c0..7ea689e40 100644 --- a/.github/workflows/mutants.yml +++ b/.github/workflows/mutants.yml @@ -62,10 +62,40 @@ env: CARGO_NET_GIT_FETCH_WITH_CLI: true jobs: + # RunsOn trial: the same job on the current Blacksmith runner, GitHub's + # runner and RunsOn sizes, for a side-by-side timing comparison. Collapse + # back to a single runner before merging. mutants: - name: Mutants gate - runs-on: blacksmith-16vcpu-ubuntu-2204 + name: Mutants gate (${{ matrix.name }}) + runs-on: ${{ matrix.label }} timeout-minutes: 120 + strategy: + fail-fast: false + matrix: + # The run id is shared by every entry, so each RunsOn label must + # differ, or one entry's runner can be taken by another. + # `family=c8a`: cargo-mutants builds and tests one mutant at a time, + # so per-core speed decides the run time. c8a (AMD Turin) has the + # best x64 single-thread score in RunsOn's EC2 benchmark and about + # 1.7x m8i's multi-core score at about the same price; older + # generations save ~5% an hour and run slower. + # `image=ubuntu22-full-x64` matches the Blacksmith baseline's Ubuntu + # 22.04; RunsOn defaults to 24.04. + # The default root volume leaves ~10 GiB free, which a Rust build + # fills; rust-lld then dies with SIGBUS (seen in cipherstash/vitaminc#487). + # `s3-cache` serves actions/cache from the stack's S3 bucket, so + # RunsOn entries share no cache entries with GitHub's or Blacksmith's. + include: + - name: blacksmith 16vcpu + label: blacksmith-16vcpu-ubuntu-2204 + - name: github + label: ubuntu-22.04 + - name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - name: runs-on c8a 16cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache permissions: contents: read # Posts and updates the report comment on the PR. @@ -83,21 +113,24 @@ jobs: install: true working_directory: . install_args: rust cargo:cargo-nextest cargo:cargo-mutants - cache: true - # Must name runs-on's image; see scripts/__tests__/workflow-mise-cache-image.test.mjs - cache_key_prefix: mise-v1-ubuntu-2204 + # Off for the trial: a matrix `runs-on` names no image to key the + # cache by (scripts/__tests__/workflow-mise-cache-image.test.mjs). + # Every entry pays the same tool install, so compare the + # "Run cargo-mutants" step times, not only the job totals. + cache: false - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 # PR only: a manual dispatch has no base to diff against, so it sweeps # both crates instead (see the next step). + # RunsOn trial: this PR changes no crate source, so its own diff has no + # mutants and every runner would finish in seconds. Mutate the lines of + # a fixed stack-auth/stack-encrypt commit range instead (15 mutants), so + # every entry does the same real work. - name: Compute the PR diff if: github.event_name == 'pull_request' - env: - BASE_REF: ${{ github.base_ref }} run: | - git fetch --no-tags origin "$BASE_REF" - git diff "origin/$BASE_REF" > pr.diff + git diff cef0a1c620159ad13f2af9b80dc537cce5a9c222 9b7e122e4a0b74215743e6b4a60770160d38884e > pr.diff echo "Changed lines under mutation:" cat pr.diff @@ -164,7 +197,8 @@ jobs: # Posted before the gate, so the comment always shows what tripped it. # Best effort: a comment failure must not turn the gate red. - name: Post the report as a sticky PR comment - if: always() && github.event_name == 'pull_request' + # Trial: one entry posts, so the matrix does not race on the comment. + if: always() && github.event_name == 'pull_request' && matrix.name == 'blacksmith 16vcpu' continue-on-error: true uses: actions/github-script@v9 with: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b596f07b9..9ae26711e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -51,13 +51,37 @@ jobs: - name: Biome check (format + lint) run: pnpm run code:check + # RunsOn trial: the same job on the current Blacksmith runner, GitHub's + # runner and RunsOn sizes, for a side-by-side timing comparison. Collapse + # back to a single runner before merging. run-tests: - name: Run Tests (Node ${{ matrix.node-version }}) - runs-on: blacksmith-4vcpu-ubuntu-2404 + name: Run Tests (Node ${{ matrix.node-version }}, ${{ matrix.runner.name }}) + runs-on: ${{ matrix.runner.label }} strategy: + fail-fast: false matrix: node-version: [22, 24] postgres-version: [16, 17] + # The run id is shared by every entry, so each RunsOn size's label + # must differ, or one size's runner can be taken by another's job. + # The two Node entries on one size share a label, which is harmless: + # the runners they launch are identical. + # The default root volume leaves ~10 GiB free, which the Rust binding + # builds can fill; rust-lld then dies with SIGBUS (seen in + # cipherstash/vitaminc#487). + # `s3-cache` serves actions/cache from the stack's S3 bucket, so + # RunsOn entries share no cache entries with GitHub's or Blacksmith's. + runner: + - name: blacksmith 4vcpu + label: blacksmith-4vcpu-ubuntu-2404 + - name: github + label: ubuntu-latest + - name: runs-on 2cpu + label: runs-on=${{ github.run_id }}/runner=2cpu-linux-x64/volume=80gb/extras=s3-cache + - name: runs-on 4cpu + label: runs-on=${{ github.run_id }}/runner=4cpu-linux-x64/volume=80gb/extras=s3-cache + - name: runs-on 8cpu + label: runs-on=${{ github.run_id }}/runner=8cpu-linux-x64/volume=80gb/extras=s3-cache exclude: - node-version: 22 postgres-version: 17 From 0f2123b7f797cc99479fdc62c3c9e67347a74243 Mon Sep 17 00:00:00 2001 From: Lindsay Holmwood Date: Tue, 20 Oct 2026 15:16:01 +1100 Subject: [PATCH 2/6] ci: pin Test JS trial to c8a and give the Mutants trial 125 mutants The first trial left two questions open. RunsOn's built-in Ncpu-linux-x64 runners chose a different instance family on every Test JS run (m8id, m8i-flex, c8i-flex, m8i), so the size comparison mixed CPU generations. Pinning family=c8a, as the Mutants entries already do, holds the CPU constant across sizes. The Mutants workload was 15 mutants, about two minutes of mutation testing, while the real gate averaged 11.9 minutes a run last week. The fb75f40d..9b7e122e range of stack-auth/stack-encrypt changes yields 125 mutants, so differences between sizes show up at the scale the gate actually runs. Claude-Session: https://claude.ai/code/session_017GMWYNGir7bpQacaUzN84U --- .github/workflows/mutants.yml | 4 ++-- .github/workflows/tests.yml | 15 +++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/mutants.yml b/.github/workflows/mutants.yml index 7ea689e40..fc66b5aa2 100644 --- a/.github/workflows/mutants.yml +++ b/.github/workflows/mutants.yml @@ -125,12 +125,12 @@ jobs: # both crates instead (see the next step). # RunsOn trial: this PR changes no crate source, so its own diff has no # mutants and every runner would finish in seconds. Mutate the lines of - # a fixed stack-auth/stack-encrypt commit range instead (15 mutants), so + # a fixed stack-auth/stack-encrypt commit range instead (125 mutants), so # every entry does the same real work. - name: Compute the PR diff if: github.event_name == 'pull_request' run: | - git diff cef0a1c620159ad13f2af9b80dc537cce5a9c222 9b7e122e4a0b74215743e6b4a60770160d38884e > pr.diff + git diff fb75f40d541df8158154b86ec5b7708aefe66836 9b7e122e4a0b74215743e6b4a60770160d38884e > pr.diff echo "Changed lines under mutation:" cat pr.diff diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9ae26711e..7c3062f35 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -66,6 +66,9 @@ jobs: # must differ, or one size's runner can be taken by another's job. # The two Node entries on one size share a label, which is harmless: # the runners they launch are identical. + # `family=c8a` pins one instance family, so the sizes compare cleanly; + # the built-in `Ncpu-linux-x64` runners picked a different family on + # each run. # The default root volume leaves ~10 GiB free, which the Rust binding # builds can fill; rust-lld then dies with SIGBUS (seen in # cipherstash/vitaminc#487). @@ -76,12 +79,12 @@ jobs: label: blacksmith-4vcpu-ubuntu-2404 - name: github label: ubuntu-latest - - name: runs-on 2cpu - label: runs-on=${{ github.run_id }}/runner=2cpu-linux-x64/volume=80gb/extras=s3-cache - - name: runs-on 4cpu - label: runs-on=${{ github.run_id }}/runner=4cpu-linux-x64/volume=80gb/extras=s3-cache - - name: runs-on 8cpu - label: runs-on=${{ github.run_id }}/runner=8cpu-linux-x64/volume=80gb/extras=s3-cache + - name: runs-on c8a 2cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=2/volume=80gb/extras=s3-cache + - name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/volume=80gb/extras=s3-cache + - name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/volume=80gb/extras=s3-cache exclude: - node-version: 22 postgres-version: 17 From 8f19afd7f135f644a83b63c2d3f35b2307092ecb Mon Sep 17 00:00:00 2001 From: Lindsay Holmwood Date: Tue, 20 Oct 2026 15:37:49 +1100 Subject: [PATCH 3/6] ci: extend the RunsOn trial to every job of eleven workflows Runs each job of Test EQL, Tests (Go), Tests (crates), Test JS, the four integration suites, Fuzz (crates), Unused dependencies (crates) and CRAP gate (crates) on its current Blacksmith runner, on GitHub's runner, and on three RunsOn c8a sizes, so every job gets the same side-by-side comparison the Mutants and run-tests trials gave. Each job's sizes follow its current tier: a 16 vCPU Ubuntu 22.04 job runs on c8a 4, 8 and 16 cpu with the ubuntu22 image, and a 4 vCPU Ubuntu 24.04 job on c8a 2, 4 and 8 cpu with the ubuntu24 image. GitHub's entry names the same Ubuntu release, so every entry of a job runs one image. That is what lets the mise caches stay on. workflow-mise-cache-image now resolves a matrix runs-on to the labels of its axis and accepts the prefix when every label names the same image, reading a RunsOn label's image= segment. A RunsOn label without one names no image, because its default is stack configuration the label does not show. Fuzz's include-only matrix becomes an explicit target-by-runner cross product: a runner axis beside include rows would merge every row into every runner, and each later row would overwrite the one before. Two jobs upload an artifact other jobs download (Test EQL's nextest-archive, Go's wasm-guests). An artifact name is unique per run, so only the Blacksmith entry uploads, and every runner's consumers test that build. Left on their current runners: Test EQL's changes, setup and ci-required, which publish outputs or aggregate results; Go's macOS and Windows jobs, which RunsOn does not cover; and the schedule-only fuzz campaign, which a pull request never runs. Claude-Session: https://claude.ai/code/session_017GMWYNGir7bpQacaUzN84U --- .github/workflows/crap-crates.yml | 48 ++- .github/workflows/fuzz.yml | 222 ++++++++++++- .github/workflows/integration-drizzle.yml | 21 +- .github/workflows/integration-prisma-next.yml | 21 +- .github/workflows/integration-protect-ffi.yml | 24 +- .github/workflows/integration-supabase.yml | 22 +- .github/workflows/test-eql.yml | 309 ++++++++++++++++-- .github/workflows/tests-crates.yml | 48 ++- .github/workflows/tests-golang.yml | 75 ++++- .github/workflows/tests.yml | 96 +++++- .github/workflows/udeps.yml | 24 +- .../workflow-mise-cache-image.test.mjs | 121 ++++++- 12 files changed, 957 insertions(+), 74 deletions(-) diff --git a/.github/workflows/crap-crates.yml b/.github/workflows/crap-crates.yml index 8a325ab1a..0b8b79bf5 100644 --- a/.github/workflows/crap-crates.yml +++ b/.github/workflows/crap-crates.yml @@ -58,8 +58,28 @@ env: jobs: crap-stack-auth: - name: CRAP (stack-auth) - runs-on: blacksmith-16vcpu-ubuntu-2204 + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: CRAP (stack-auth) (${{ matrix.runner.name }}) + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 16vcpu + label: blacksmith-16vcpu-ubuntu-2204 + - id: github + name: github + label: ubuntu-22.04 + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-16 + name: runs-on c8a 16cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache timeout-minutes: 45 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 @@ -82,8 +102,28 @@ jobs: run: mise run crap:stack-auth -- --format github crap-stack-encrypt: - name: CRAP (stack-encrypt) - runs-on: blacksmith-16vcpu-ubuntu-2204 + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: CRAP (stack-encrypt) (${{ matrix.runner.name }}) + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 16vcpu + label: blacksmith-16vcpu-ubuntu-2204 + - id: github + name: github + label: ubuntu-22.04 + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-16 + name: runs-on c8a 16cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache timeout-minutes: 45 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index baa8e8cd8..f4c9244a9 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -61,23 +61,227 @@ env: jobs: fuzz-regression: - name: fuzz regression (${{ matrix.slug }}) + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: fuzz regression (${{ matrix.slug }}) (${{ matrix.runner.name }}) # Not on the nightly schedule, which is the campaign's. A manual dispatch # runs both jobs. if: github.event_name != 'schedule' - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ${{ matrix.runner.label }} timeout-minutes: 30 strategy: fail-fast: false matrix: include: - - { task: "fuzz:access-key", slug: access-key } - - { task: "fuzz:jwt-decode", slug: jwt-decode } - - { task: "fuzz:client-key", slug: client-key } - - { task: "fuzz:sealed-value", slug: sealed-value } - - { task: "fuzz:term-decode", slug: term-decode } - - { task: "fuzz:check-record", slug: check-record } - - { task: "fuzz:plan-build", slug: plan-build } + - task: "fuzz:access-key" + slug: access-key + runner: + id: blacksmith + name: blacksmith 4vcpu + label: blacksmith-4vcpu-ubuntu-2404 + - task: "fuzz:access-key" + slug: access-key + runner: + id: github + name: github + label: ubuntu-24.04 + - task: "fuzz:access-key" + slug: access-key + runner: + id: runs-on-2 + name: runs-on c8a 2cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=2/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - task: "fuzz:access-key" + slug: access-key + runner: + id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - task: "fuzz:access-key" + slug: access-key + runner: + id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - task: "fuzz:jwt-decode" + slug: jwt-decode + runner: + id: blacksmith + name: blacksmith 4vcpu + label: blacksmith-4vcpu-ubuntu-2404 + - task: "fuzz:jwt-decode" + slug: jwt-decode + runner: + id: github + name: github + label: ubuntu-24.04 + - task: "fuzz:jwt-decode" + slug: jwt-decode + runner: + id: runs-on-2 + name: runs-on c8a 2cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=2/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - task: "fuzz:jwt-decode" + slug: jwt-decode + runner: + id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - task: "fuzz:jwt-decode" + slug: jwt-decode + runner: + id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - task: "fuzz:client-key" + slug: client-key + runner: + id: blacksmith + name: blacksmith 4vcpu + label: blacksmith-4vcpu-ubuntu-2404 + - task: "fuzz:client-key" + slug: client-key + runner: + id: github + name: github + label: ubuntu-24.04 + - task: "fuzz:client-key" + slug: client-key + runner: + id: runs-on-2 + name: runs-on c8a 2cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=2/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - task: "fuzz:client-key" + slug: client-key + runner: + id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - task: "fuzz:client-key" + slug: client-key + runner: + id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - task: "fuzz:sealed-value" + slug: sealed-value + runner: + id: blacksmith + name: blacksmith 4vcpu + label: blacksmith-4vcpu-ubuntu-2404 + - task: "fuzz:sealed-value" + slug: sealed-value + runner: + id: github + name: github + label: ubuntu-24.04 + - task: "fuzz:sealed-value" + slug: sealed-value + runner: + id: runs-on-2 + name: runs-on c8a 2cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=2/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - task: "fuzz:sealed-value" + slug: sealed-value + runner: + id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - task: "fuzz:sealed-value" + slug: sealed-value + runner: + id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - task: "fuzz:term-decode" + slug: term-decode + runner: + id: blacksmith + name: blacksmith 4vcpu + label: blacksmith-4vcpu-ubuntu-2404 + - task: "fuzz:term-decode" + slug: term-decode + runner: + id: github + name: github + label: ubuntu-24.04 + - task: "fuzz:term-decode" + slug: term-decode + runner: + id: runs-on-2 + name: runs-on c8a 2cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=2/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - task: "fuzz:term-decode" + slug: term-decode + runner: + id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - task: "fuzz:term-decode" + slug: term-decode + runner: + id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - task: "fuzz:check-record" + slug: check-record + runner: + id: blacksmith + name: blacksmith 4vcpu + label: blacksmith-4vcpu-ubuntu-2404 + - task: "fuzz:check-record" + slug: check-record + runner: + id: github + name: github + label: ubuntu-24.04 + - task: "fuzz:check-record" + slug: check-record + runner: + id: runs-on-2 + name: runs-on c8a 2cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=2/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - task: "fuzz:check-record" + slug: check-record + runner: + id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - task: "fuzz:check-record" + slug: check-record + runner: + id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - task: "fuzz:plan-build" + slug: plan-build + runner: + id: blacksmith + name: blacksmith 4vcpu + label: blacksmith-4vcpu-ubuntu-2404 + - task: "fuzz:plan-build" + slug: plan-build + runner: + id: github + name: github + label: ubuntu-24.04 + - task: "fuzz:plan-build" + slug: plan-build + runner: + id: runs-on-2 + name: runs-on c8a 2cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=2/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - task: "fuzz:plan-build" + slug: plan-build + runner: + id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - task: "fuzz:plan-build" + slug: plan-build + runner: + id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: diff --git a/.github/workflows/integration-drizzle.yml b/.github/workflows/integration-drizzle.yml index ddbf73c2c..4d32f7ac8 100644 --- a/.github/workflows/integration-drizzle.yml +++ b/.github/workflows/integration-drizzle.yml @@ -203,8 +203,9 @@ on: jobs: integration: - name: Drizzle v3 integration (db=${{ matrix.db }}) - runs-on: blacksmith-4vcpu-ubuntu-2404 + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: Drizzle v3 integration (db=${{ matrix.db }}) (${{ matrix.runner.name }}) + runs-on: ${{ matrix.runner.label }} # No concurrency group: `integration-db` gives each job its own compose # project and ephemeral host ports, so live-DB jobs no longer contend and do # not need serialising. See that action for why the old @@ -232,6 +233,22 @@ jobs: # harness assert the `anon` path on the database it is actually running # against.) matrix: + runner: + - id: blacksmith + name: blacksmith 4vcpu + label: blacksmith-4vcpu-ubuntu-2404 + - id: github + name: github + label: ubuntu-24.04 + - id: runs-on-2 + name: runs-on c8a 2cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=2/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache db: [postgres, supabase] env: diff --git a/.github/workflows/integration-prisma-next.yml b/.github/workflows/integration-prisma-next.yml index ed74631f2..768f57539 100644 --- a/.github/workflows/integration-prisma-next.yml +++ b/.github/workflows/integration-prisma-next.yml @@ -113,8 +113,9 @@ on: jobs: integration: - name: prisma-next v3 integration (db=${{ matrix.db }}) - runs-on: blacksmith-4vcpu-ubuntu-2404 + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: prisma-next v3 integration (db=${{ matrix.db }}) (${{ matrix.runner.name }}) + runs-on: ${{ matrix.runner.label }} # No concurrency group: `integration-db` gives each job its own compose # project and ephemeral host ports, so live-DB jobs no longer contend and do # not need serialising. See that action for why the old @@ -137,6 +138,22 @@ jobs: # is not a superuser, so the EQL install takes its self-skipping path. A # suite that passes on a superuser database can still fail there. matrix: + runner: + - id: blacksmith + name: blacksmith 4vcpu + label: blacksmith-4vcpu-ubuntu-2404 + - id: github + name: github + label: ubuntu-24.04 + - id: runs-on-2 + name: runs-on c8a 2cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=2/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache db: [postgres, supabase] env: diff --git a/.github/workflows/integration-protect-ffi.yml b/.github/workflows/integration-protect-ffi.yml index 8b8f4ff03..f92940121 100644 --- a/.github/workflows/integration-protect-ffi.yml +++ b/.github/workflows/integration-protect-ffi.yml @@ -159,8 +159,28 @@ concurrency: jobs: integration: - name: protect-ffi integration suite - runs-on: blacksmith-4vcpu-ubuntu-2404 + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: protect-ffi integration suite (${{ matrix.runner.name }}) + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 4vcpu + label: blacksmith-4vcpu-ubuntu-2404 + - id: github + name: github + label: ubuntu-24.04 + - id: runs-on-2 + name: runs-on c8a 2cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=2/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache # Generous, because a cold `build-ffi-binding` compiles the cipherstash # client graph from scratch. It is also the backstop for `mise run # start-db`, whose readiness loop retries `pg_isready` forever rather than diff --git a/.github/workflows/integration-supabase.yml b/.github/workflows/integration-supabase.yml index 16d4da21e..9dbc0475c 100644 --- a/.github/workflows/integration-supabase.yml +++ b/.github/workflows/integration-supabase.yml @@ -172,8 +172,9 @@ on: jobs: integration: - name: Supabase v3 integration (db=${{ matrix.db }}) - runs-on: blacksmith-4vcpu-ubuntu-2404 + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: Supabase v3 integration (db=${{ matrix.db }}) (${{ matrix.runner.name }}) + runs-on: ${{ matrix.runner.label }} # No concurrency group: `integration-db` gives each job its own compose # project and ephemeral host ports, so live-DB jobs no longer contend and do # not need serialising. See that action for why the old @@ -190,10 +191,27 @@ jobs: if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} strategy: + fail-fast: false # A one-element matrix, not a cross-product: the Supabase adapter only ever # runs against the Supabase variant. Kept as a matrix so adding a second # database is a one-line change. matrix: + runner: + - id: blacksmith + name: blacksmith 4vcpu + label: blacksmith-4vcpu-ubuntu-2404 + - id: github + name: github + label: ubuntu-24.04 + - id: runs-on-2 + name: runs-on c8a 2cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=2/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache db: [supabase] env: diff --git a/.github/workflows/test-eql.yml b/.github/workflows/test-eql.yml index b3d0c2d60..121a94110 100644 --- a/.github/workflows/test-eql.yml +++ b/.github/workflows/test-eql.yml @@ -291,7 +291,8 @@ jobs: # Compile the test binaries ONCE. Runs on every non-PR event, and on PRs only # when relevant files changed (docs-only PRs never pay the ~4-min compile). build-archive: - name: "Build test archive" + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: "Build test archive (${{ matrix.runner.name }})" needs: [changes] # This repo is PUBLIC and accepts fork PRs (the approval policy only gates # first-time contributors). build-archive is the sole holder of the CS_* @@ -313,7 +314,26 @@ jobs: || needs.changes.outputs.relevant == 'true') && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) - runs-on: blacksmith-16vcpu-ubuntu-2204 + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 16vcpu + label: blacksmith-16vcpu-ubuntu-2204 + - id: github + name: github + label: ubuntu-22.04 + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-16 + name: runs-on c8a 16cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache env: # test:sqlx:archive depends on test:sqlx:prep, which copies the built EQL # into migrations/, applies it to a live Postgres, and regenerates the @@ -380,6 +400,9 @@ jobs: # `nextest.tar.zst` and `release/*.sql` at its top level and the shard's # `download-artifact` puts them back where the archive expects them. - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + # RunsOn trial: one entry uploads, because an artifact name is unique per + # run; every runner's consumers test the baseline's build. + if: matrix.runner.id == 'blacksmith' with: name: nextest-archive path: | @@ -391,16 +414,33 @@ jobs: # Sharded sqlx suite. No longer needs [schema, codegen] (gate removed) — # shards start right after build-archive. test: - name: "Shard PG${{ matrix.postgres-version }} ${{ matrix.shard }}/${{ needs.setup.outputs.shard-total }}" + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: "Shard PG${{ matrix.postgres-version }} ${{ matrix.shard }}/${{ needs.setup.outputs.shard-total }} (${{ matrix.runner.name }})" needs: [changes, setup, build-archive] # Exclusion, not an allowlist — see the note on `build-archive`. if: >- github.event_name != 'pull_request' || needs.changes.outputs.relevant == 'true' - runs-on: blacksmith-16vcpu-ubuntu-2204 + runs-on: ${{ matrix.runner.label }} strategy: fail-fast: false matrix: + runner: + - id: blacksmith + name: blacksmith 16vcpu + label: blacksmith-16vcpu-ubuntu-2204 + - id: github + name: github + label: ubuntu-22.04 + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-16 + name: runs-on c8a 16cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache postgres-version: ${{ fromJSON(needs.setup.outputs.pg-versions) }} shard: ${{ fromJSON(needs.setup.outputs.shards) }} env: @@ -453,16 +493,33 @@ jobs: # they follow the event's PG set (PG17 on PR; 14-17 in the queue). Moved out # of the old per-version test job so they run ONCE per version, not per shard. validate: - name: "Validate (Postgres ${{ matrix.postgres-version }})" + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: "Validate (Postgres ${{ matrix.postgres-version }}) (${{ matrix.runner.name }})" needs: [changes, setup] # Exclusion, not an allowlist — see the note on `build-archive`. if: >- github.event_name != 'pull_request' || needs.changes.outputs.relevant == 'true' - runs-on: blacksmith-16vcpu-ubuntu-2204 + runs-on: ${{ matrix.runner.label }} strategy: fail-fast: false matrix: + runner: + - id: blacksmith + name: blacksmith 16vcpu + label: blacksmith-16vcpu-ubuntu-2204 + - id: github + name: github + label: ubuntu-22.04 + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-16 + name: runs-on c8a 16cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache postgres-version: ${{ fromJSON(needs.setup.outputs.pg-versions) }} env: POSTGRES_VERSION: ${{ matrix.postgres-version }} @@ -512,13 +569,33 @@ jobs: mise run test:clean_install_v3 schema: - name: "JSON Schema validation" + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: "JSON Schema validation (${{ matrix.runner.name }})" needs: [changes] # Exclusion, not an allowlist — see the note on `build-archive`. if: >- github.event_name != 'pull_request' || needs.changes.outputs.relevant == 'true' - runs-on: blacksmith-16vcpu-ubuntu-2204 + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 16vcpu + label: blacksmith-16vcpu-ubuntu-2204 + - id: github + name: github + label: ubuntu-22.04 + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-16 + name: runs-on c8a 16cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: @@ -541,13 +618,33 @@ jobs: mise run test:schema rust-crates: - name: "Rust workspace crates" + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: "Rust workspace crates (${{ matrix.runner.name }})" needs: [changes] # Exclusion, not an allowlist — see the note on `build-archive`. if: >- github.event_name != 'pull_request' || needs.changes.outputs.relevant == 'true' - runs-on: blacksmith-16vcpu-ubuntu-2204 + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 16vcpu + label: blacksmith-16vcpu-ubuntu-2204 + - id: github + name: github + label: ubuntu-22.04 + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-16 + name: runs-on c8a 16cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache services: encryption-postgres: image: postgres:17 @@ -669,13 +766,33 @@ jobs: exit "$status" codegen: - name: "Encrypted-domain codegen" + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: "Encrypted-domain codegen (${{ matrix.runner.name }})" needs: [changes] # Exclusion, not an allowlist — see the note on `build-archive`. if: >- github.event_name != 'pull_request' || needs.changes.outputs.relevant == 'true' - runs-on: blacksmith-16vcpu-ubuntu-2204 + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 16vcpu + label: blacksmith-16vcpu-ubuntu-2204 + - id: github + name: github + label: ubuntu-22.04 + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-16 + name: runs-on c8a 16cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: @@ -701,13 +818,33 @@ jobs: mise run test:schemas:parity self-contained-v3: - name: "eql_v3 self-containment" + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: "eql_v3 self-containment (${{ matrix.runner.name }})" needs: [changes] # Exclusion, not an allowlist — see the note on `build-archive`. if: >- github.event_name != 'pull_request' || needs.changes.outputs.relevant == 'true' - runs-on: blacksmith-16vcpu-ubuntu-2204 + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 16vcpu + label: blacksmith-16vcpu-ubuntu-2204 + - id: github + name: github + label: ubuntu-22.04 + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-16 + name: runs-on c8a 16cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: @@ -737,13 +874,33 @@ jobs: run: mise run test:build_ordering_helpers matrix-coverage: - name: "Matrix coverage inventory" + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: "Matrix coverage inventory (${{ matrix.runner.name }})" needs: [changes] # Exclusion, not an allowlist — see the note on `build-archive`. if: >- github.event_name != 'pull_request' || needs.changes.outputs.relevant == 'true' - runs-on: blacksmith-16vcpu-ubuntu-2204 + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 16vcpu + label: blacksmith-16vcpu-ubuntu-2204 + - id: github + name: github + label: ubuntu-22.04 + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-16 + name: runs-on c8a 16cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: @@ -779,13 +936,33 @@ jobs: run: mise run test:matrix:catalog-coverage splinter: - name: "Supabase splinter" + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: "Supabase splinter (${{ matrix.runner.name }})" needs: [changes] # Exclusion, not an allowlist — see the note on `build-archive`. if: >- github.event_name != 'pull_request' || needs.changes.outputs.relevant == 'true' - runs-on: blacksmith-16vcpu-ubuntu-2204 + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 16vcpu + label: blacksmith-16vcpu-ubuntu-2204 + - id: github + name: github + label: ubuntu-22.04 + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-16 + name: runs-on c8a 16cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache env: POSTGRES_VERSION: "17" steps: @@ -844,8 +1021,28 @@ jobs: # validated. DB-free and creds-free (the psql-backed syntax check stays in the # per-version `validate` job). docs-static: - name: "SQL doc validation" - runs-on: blacksmith-16vcpu-ubuntu-2204 + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: "SQL doc validation (${{ matrix.runner.name }})" + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 16vcpu + label: blacksmith-16vcpu-ubuntu-2204 + - id: github + name: github + label: ubuntu-22.04 + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-16 + name: runs-on c8a 16cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: @@ -883,8 +1080,28 @@ jobs: # Credential-free and DB-free — it only reads the registry and asks GitHub for # issue state, so it runs on every PR rather than hiding behind the e2e job. known-failures: - name: "known-failure markers" - runs-on: blacksmith-16vcpu-ubuntu-2204 + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: "known-failure markers (${{ matrix.runner.name }})" + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 16vcpu + label: blacksmith-16vcpu-ubuntu-2204 + - id: github + name: github + label: ubuntu-22.04 + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-16 + name: runs-on c8a 16cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache permissions: contents: read issues: read @@ -921,8 +1138,28 @@ jobs: # `relevant` filter (src/**, crates/**) would skip it on exactly the docs-only # PRs it exists to check. doc-anchors: - name: "doc anchor links" - runs-on: blacksmith-16vcpu-ubuntu-2204 + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: "doc anchor links (${{ matrix.runner.name }})" + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 16vcpu + label: blacksmith-16vcpu-ubuntu-2204 + - id: github + name: github + label: ubuntu-22.04 + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-16 + name: runs-on c8a 16cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: @@ -946,7 +1183,8 @@ jobs: # e2e oracle. Like build-archive, it holds CS_* and so carries the same # fork-PR guard to keep the secrets off fork runs. e2e: - name: "e2e property suite (fresh encryption)" + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: "e2e property suite (fresh encryption) (${{ matrix.runner.name }})" needs: [changes, setup] # Exclusion, not an allowlist — see the note on `build-archive`, which # carries the same two clauses for the same two reasons. @@ -955,7 +1193,26 @@ jobs: || needs.changes.outputs.relevant == 'true') && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) - runs-on: blacksmith-16vcpu-ubuntu-2204 + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 16vcpu + label: blacksmith-16vcpu-ubuntu-2204 + - id: github + name: github + label: ubuntu-22.04 + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-16 + name: runs-on c8a 16cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache env: POSTGRES_VERSION: "17" CS_CLIENT_ACCESS_KEY: ${{ secrets.CS_CLIENT_ACCESS_KEY }} diff --git a/.github/workflows/tests-crates.yml b/.github/workflows/tests-crates.yml index 40cc572cc..b4aa5f70b 100644 --- a/.github/workflows/tests-crates.yml +++ b/.github/workflows/tests-crates.yml @@ -78,8 +78,28 @@ env: jobs: rust: - name: fmt, clippy, nextest, doctests, rustdoc - runs-on: blacksmith-16vcpu-ubuntu-2204 + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: fmt, clippy, nextest, doctests, rustdoc (${{ matrix.runner.name }}) + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 16vcpu + label: blacksmith-16vcpu-ubuntu-2204 + - id: github + name: github + label: ubuntu-22.04 + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-16 + name: runs-on c8a 16cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache timeout-minutes: 60 env: # Job-level, not workflow-level: RUSTFLAGS replaces the @@ -157,8 +177,28 @@ jobs: run: cargo publish --locked --dry-run --allow-dirty -p stack-profile -p stack-auth -p stack-kms -p stack-encrypt-derive -p stack-encrypt node-bindings: - name: node bindings, napi typings, stack-auth-wasm - runs-on: blacksmith-16vcpu-ubuntu-2204 + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: node bindings, napi typings, stack-auth-wasm (${{ matrix.runner.name }}) + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 16vcpu + label: blacksmith-16vcpu-ubuntu-2204 + - id: github + name: github + label: ubuntu-22.04 + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-16 + name: runs-on c8a 16cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache timeout-minutes: 45 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 diff --git a/.github/workflows/tests-golang.yml b/.github/workflows/tests-golang.yml index 9bfff334a..e7141a7dc 100644 --- a/.github/workflows/tests-golang.yml +++ b/.github/workflows/tests-golang.yml @@ -94,8 +94,28 @@ env: jobs: wasi-check: - name: WASI check, guests and Go (Linux) - runs-on: blacksmith-16vcpu-ubuntu-2204 + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: WASI check, guests and Go (Linux) (${{ matrix.runner.name }}) + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 16vcpu + label: blacksmith-16vcpu-ubuntu-2204 + - id: github + name: github + label: ubuntu-22.04 + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-16 + name: runs-on c8a 16cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache timeout-minutes: 60 env: # wasm:guest:test and wasm:auth-guest:test run nextest, which is pinned @@ -191,6 +211,9 @@ jobs: done - name: Hand the guests to the other jobs + # RunsOn trial: one entry uploads, because an artifact name is unique per + # run; every runner's consumers test the baseline's build. + if: matrix.runner.id == 'blacksmith' uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: wasm-guests @@ -241,8 +264,28 @@ jobs: # Linux only: macOS and Windows would report the same findings. Needs no # guests: the packages embed a directory and compile without them. go-lint: - name: Go lint - runs-on: blacksmith-4vcpu-ubuntu-2404 + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: Go lint (${{ matrix.runner.name }}) + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 4vcpu + label: blacksmith-4vcpu-ubuntu-2404 + - id: github + name: github + label: ubuntu-24.04 + - id: runs-on-2 + name: runs-on c8a 2cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=2/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache timeout-minutes: 15 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 @@ -332,9 +375,29 @@ jobs: # stack-encrypt examples read CS_* through `StackCipher::new()`; tests-crates # builds them, and this job runs them. live: - name: Go live tests and stack-encrypt examples + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: Go live tests and stack-encrypt examples (${{ matrix.runner.name }}) needs: wasi-check - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 4vcpu + label: blacksmith-4vcpu-ubuntu-2404 + - id: github + name: github + label: ubuntu-24.04 + - id: runs-on-2 + name: runs-on c8a 2cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=2/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache timeout-minutes: 30 env: CS_WORKSPACE_CRN: ${{ vars.CS_WORKSPACE_CRN }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7c3062f35..e938737e0 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -20,8 +20,28 @@ jobs: # plugin (at `warn`) surfaces new `as any`/`never`/`unknown` without blocking. # Tightening to fail on warnings is tracked in #625. lint: - name: Lint (Biome) - runs-on: blacksmith-4vcpu-ubuntu-2404 + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: Lint (Biome) (${{ matrix.runner.name }}) + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 4vcpu + label: blacksmith-4vcpu-ubuntu-2404 + - id: github + name: github + label: ubuntu-24.04 + - id: runs-on-2 + name: runs-on c8a 2cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=2/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache steps: - name: Checkout Repo uses: actions/checkout@v6 @@ -412,8 +432,28 @@ jobs: run: pnpm exec turbo run test:e2e --filter stash e2e-tests: - name: Run E2E Tests - runs-on: blacksmith-4vcpu-ubuntu-2404 + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: Run E2E Tests (${{ matrix.runner.name }}) + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 4vcpu + label: blacksmith-4vcpu-ubuntu-2404 + - id: github + name: github + label: ubuntu-24.04 + - id: runs-on-2 + name: runs-on c8a 2cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=2/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache # Auth-dependent suites in `e2e/` skip themselves unless these env vars # are set. We expose them at the job level so the wizard subprocess @@ -493,8 +533,28 @@ jobs: # bindings available. The deno.json deliberately omits --allow-ffi so # a silent fallback to the NAPI module is impossible. wasm-e2e-tests: - name: Run WASM E2E Tests (Deno) - runs-on: blacksmith-4vcpu-ubuntu-2404 + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: Run WASM E2E Tests (Deno) (${{ matrix.runner.name }}) + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 4vcpu + label: blacksmith-4vcpu-ubuntu-2404 + - id: github + name: github + label: ubuntu-24.04 + - id: runs-on-2 + name: runs-on c8a 2cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=2/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache permissions: contents: read @@ -636,8 +696,28 @@ jobs: run: deno task test run-tests-bun: - name: Run Tests (Bun) - runs-on: blacksmith-4vcpu-ubuntu-2404 + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: Run Tests (Bun) (${{ matrix.runner.name }}) + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 4vcpu + label: blacksmith-4vcpu-ubuntu-2404 + - id: github + name: github + label: ubuntu-24.04 + - id: runs-on-2 + name: runs-on c8a 2cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=2/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache continue-on-error: true services: diff --git a/.github/workflows/udeps.yml b/.github/workflows/udeps.yml index db3d33b98..c22688c66 100644 --- a/.github/workflows/udeps.yml +++ b/.github/workflows/udeps.yml @@ -67,8 +67,28 @@ env: jobs: udeps: - name: Check unused Rust dependencies - runs-on: blacksmith-4vcpu-ubuntu-2404 + # RunsOn trial: this job on every runner in `runner`. Collapse before merging. + name: Check unused Rust dependencies (${{ matrix.runner.name }}) + runs-on: ${{ matrix.runner.label }} + strategy: + fail-fast: false + matrix: + runner: + - id: blacksmith + name: blacksmith 4vcpu + label: blacksmith-4vcpu-ubuntu-2404 + - id: github + name: github + label: ubuntu-24.04 + - id: runs-on-2 + name: runs-on c8a 2cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=2/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-4 + name: runs-on c8a 4cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-8 + name: runs-on c8a 8cpu + label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache timeout-minutes: 45 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 diff --git a/scripts/__tests__/workflow-mise-cache-image.test.mjs b/scripts/__tests__/workflow-mise-cache-image.test.mjs index 4007ba9d3..2e74e25cd 100644 --- a/scripts/__tests__/workflow-mise-cache-image.test.mjs +++ b/scripts/__tests__/workflow-mise-cache-image.test.mjs @@ -24,8 +24,12 @@ import { readWorkflow, workflowFiles } from './lib/workflows.mjs' * * So each cached step sets `cache_key_prefix: mise-v1-`, where `` * is the `ubuntu-NNNN` its job's `runs-on` names (`ubuntu-24.04` counts as - * `ubuntu-2404`). A job whose `runs-on` names no image (a matrix, - * `ubuntu-latest`) must turn the cache off. No step sets `cache_key`, which + * `ubuntu-2404`, and a RunsOn label's `image=ubuntu24-full-x64` does too). A + * `runs-on` that is one matrix value (`${{ matrix.runner.label }}`) names the + * image every value of that axis names, and only when they all name the same + * one. A job whose `runs-on` names no image (`ubuntu-latest`, a RunsOn label + * with no `image=`, a matrix mixing images) must turn the cache off. No step + * sets `cache_key`, which * mise-action prefers over the prefix and so would bring the shared key back. * A step with the cache off sets no prefix: it would read as a cache in use, * on paths `scripts/lint-no-workflow-caching.mjs` keeps cache-free. @@ -51,7 +55,13 @@ function miseSteps() { for (const [job, def] of Object.entries(readWorkflow(file)?.jobs ?? {})) { for (const step of def?.steps ?? []) { if (isMise(step)) - found.push({ file, job, runsOn: def['runs-on'], step }) + found.push({ + file, + job, + runsOn: def['runs-on'], + matrix: def.strategy?.matrix, + step, + }) } } } @@ -63,12 +73,45 @@ const IMAGE_INDEPENDENT_TOOLS = new Set(['aqua:wasm-bindgen/wasm-pack']) /** The `ubuntu-NNNN` a runs-on label names, or undefined. */ function imageOf(runsOn) { - const m = /ubuntu-(\d{2})\.?(\d{2})/.exec(String(runsOn)) + const label = String(runsOn) + // RunsOn picks its image from an `image=` segment, and only ships LTS ones. + if (label.startsWith('runs-on=')) { + const m = /\/image=ubuntu(\d{2})-/.exec(label) + return m ? `ubuntu-${m[1]}04` : undefined + } + const m = /ubuntu-(\d{2})\.?(\d{2})/.exec(label) return m ? `ubuntu-${m[1]}${m[2]}` : undefined } +/** + * Every label a `${{ matrix. }}` or `${{ matrix.. }}` runs-on + * can take, read from the axis and the include rows, or undefined when runs-on + * is not one matrix value. + */ +function matrixLabels(runsOn, matrix) { + const m = /^\$\{\{\s*matrix\.([\w-]+)(?:\.([\w-]+))?\s*\}\}$/.exec( + String(runsOn), + ) + if (!m || !matrix || typeof matrix !== 'object') return undefined + const [, key, field] = m + const values = [ + ...(Array.isArray(matrix[key]) ? matrix[key] : []), + ...(Array.isArray(matrix.include) + ? matrix.include.map((row) => row?.[key]) + : []), + ].filter((value) => value !== undefined) + return values.map((value) => (field ? value?.[field] : value)) +} + +/** The one image every label names, or undefined. */ +function imageOfAll(labels) { + const images = new Set(labels.map(imageOf)) + if (labels.length === 0 || images.size !== 1) return undefined + return [...images][0] +} + /** The finding for one mise step, or null when the step is correct. */ -function cacheKeyFinding({ file, job, runsOn, step }) { +function cacheKeyFinding({ file, job, runsOn, matrix, step }) { const where = `${file} ${job}` const prefix = step.with?.cache_key_prefix if (step.with?.cache_key !== undefined) @@ -77,9 +120,12 @@ function cacheKeyFinding({ file, job, runsOn, step }) { return prefix === undefined ? null : `${where}: the cache is off, so cache_key_prefix ${prefix} does nothing; remove it` - const image = imageOf(runsOn) + const labels = matrixLabels(runsOn, matrix) + const image = labels ? imageOfAll(labels) : imageOf(runsOn) if (!image) - return `${where}: runs-on ${runsOn} names no ubuntu-NNNN image, so the mise cache must be off (cache: false)` + return labels + ? `${where}: runs-on ${runsOn} takes ${labels.join(', ')}, which name no single ubuntu-NNNN image between them, so the mise cache must be off (cache: false)` + : `${where}: runs-on ${runsOn} names no ubuntu-NNNN image, so the mise cache must be off (cache: false)` const want = `mise-v1-${image}` return prefix === want ? null @@ -141,12 +187,73 @@ describe('mise-action cache keys', () => { ).toBeNull() }) + it('keys a matrix runs-on by the image its every value names', () => { + // biome-ignore lint/suspicious/noTemplateCurlyInString: a GitHub Actions expression, the literal `runs-on` value under test. + const runsOn = '${{ matrix.runner.label }}' + const runOn = (...labels) => ({ + runner: labels.map((label) => ({ label })), + }) + const check = (matrix, input) => + cacheKeyFinding({ + file: 'w.yml', + job: 'j', + runsOn, + matrix, + step: { uses: 'jdx/mise-action@sha', with: input }, + }) + const same = runOn( + 'blacksmith-16vcpu-ubuntu-2204', + 'ubuntu-22.04', + 'runs-on=1/family=c8a/cpu=4/image=ubuntu22-full-x64', + ) + expect(check(same, { cache_key_prefix: 'mise-v1-ubuntu-2204' })).toBeNull() + expect(check(same, { cache_key_prefix: 'mise-v1-ubuntu-2404' })).toMatch( + /want mise-v1-ubuntu-2204/, + ) + // One prefix cannot key two images: the glibc split this file exists for. + expect( + check(runOn('blacksmith-16vcpu-ubuntu-2204', 'ubuntu-24.04'), { + cache_key_prefix: 'mise-v1-ubuntu-2204', + }), + ).toMatch(/no single ubuntu-NNNN image/) + // RunsOn's default image is stack configuration, not something a label shows. + expect( + check(runOn('runs-on=1/family=c8a/cpu=4'), { + cache_key_prefix: 'mise-v1-ubuntu-2404', + }), + ).toMatch(/no single ubuntu-NNNN image/) + expect(check(runOn('ubuntu-latest'), { cache: false })).toBeNull() + // An include-only matrix whose rows carry the label. + expect( + cacheKeyFinding({ + file: 'w.yml', + job: 'j', + // biome-ignore lint/suspicious/noTemplateCurlyInString: a GitHub Actions expression, the literal `runs-on` value under test. + runsOn: '${{ matrix.label }}', + matrix: { + include: [ + { label: 'ubuntu-22.04' }, + { label: 'blacksmith-4vcpu-ubuntu-2204' }, + ], + }, + step: { + uses: 'jdx/mise-action@sha', + with: { cache_key_prefix: 'mise-v1-ubuntu-2204' }, + }, + }), + ).toBeNull() + }) + it('reads both forms of an image label', () => { expect(imageOf('blacksmith-4vcpu-ubuntu-2404')).toBe('ubuntu-2404') expect(imageOf('ubuntu-22.04')).toBe('ubuntu-2204') expect(imageOf('ubuntu-24.04-arm')).toBe('ubuntu-2404') expect(imageOf('ubuntu-latest')).toBeUndefined() expect(imageOf(undefined)).toBeUndefined() + expect( + imageOf('runs-on=1/family=c8a/cpu=4/image=ubuntu24-full-x64/volume=80gb'), + ).toBe('ubuntu-2404') + expect(imageOf('runs-on=1/runner=4cpu-linux-x64')).toBeUndefined() }) it('lets a composite action cache only image-independent tools', () => { From 4058c00a39a42bb52a208e9a40bdcd4de17e82bd Mon Sep 17 00:00:00 2001 From: Lindsay Holmwood Date: Tue, 20 Oct 2026 16:12:53 +1100 Subject: [PATCH 4/6] ci: give each Test EQL trial runner its own test archive The GitHub entry of Shard PG17 2/4 failed nine payload_schema_tests with "failed to read /home/runner/_work/stack/stack/packages/eql/...". Those tests locate their schema files through env!("CARGO_MANIFEST_DIR"), which the compiler bakes into the binary, and the shards ran the archive Blacksmith built. Blacksmith and RunsOn check out under _work/, GitHub-hosted runners under work/, so only GitHub's shards looked in a directory that was not there. Each build-archive entry now uploads nextest-archive- and each shard downloads its own runner's, which also times the whole build-then-test pipeline on every runner. Claude-Session: https://claude.ai/code/session_017GMWYNGir7bpQacaUzN84U --- .github/workflows/test-eql.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test-eql.yml b/.github/workflows/test-eql.yml index 121a94110..d3187c0c3 100644 --- a/.github/workflows/test-eql.yml +++ b/.github/workflows/test-eql.yml @@ -400,11 +400,11 @@ jobs: # `nextest.tar.zst` and `release/*.sql` at its top level and the shard's # `download-artifact` puts them back where the archive expects them. - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 - # RunsOn trial: one entry uploads, because an artifact name is unique per - # run; every runner's consumers test the baseline's build. - if: matrix.runner.id == 'blacksmith' + # RunsOn trial: one archive per runner. The test binaries bake in + # their build's checkout path (`env!("CARGO_MANIFEST_DIR")`), and + # GitHub-hosted runners check out to `work/`, not `_work/`. with: - name: nextest-archive + name: nextest-archive-${{ matrix.runner.id }} path: | packages/eql/nextest.tar.zst packages/eql/release/*.sql @@ -478,7 +478,7 @@ jobs: # workspace remap and the build_validation_tests expect them. - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: - name: nextest-archive + name: nextest-archive-${{ matrix.runner.id }} path: packages/eql - name: Setup database (Postgres ${{ matrix.postgres-version }}) From b52c3d613437755e41dbcb3f49443b083ca07929 Mon Sep 17 00:00:00 2001 From: Lindsay Holmwood Date: Tue, 20 Oct 2026 20:00:30 +1100 Subject: [PATCH 5/6] ci: add Graviton (c8g arm64) entries to the Mutants and Test JS trials Adds c8g at 16 and 8 cpu to the Mutants gate and at 4 and 8 cpu to each Test JS job (Node 22, Node 24, E2E, Bun, WASM E2E, Lint), beside the c8a x64 entries of the same sizes, so arm64 can be compared on speed and cost one CPU against another. The family is pinned to c8g alone for the same reason c8a is. The images keep each job's Ubuntu release (ubuntu22-full-arm64 for Mutants, ubuntu24-full-arm64 for Test JS). Nothing else needed to change for the caches to stay apart by architecture: rust-cache, the mise cache and the protect-ffi index.node cache all put the runner's architecture in their keys, and the protect-ffi WASM cache holds wasm32 output, which is the same on either host. workflow-mise-cache-image now pins that an arm64 RunsOn label names its Ubuntu release like an x64 one, and that one prefix serves both. Claude-Session: https://claude.ai/code/session_017GMWYNGir7bpQacaUzN84U --- .github/workflows/mutants.yml | 6 ++++ .github/workflows/tests.yml | 28 ++++++++++++++++ .../workflow-mise-cache-image.test.mjs | 32 ++++++++++++++++++- 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/.github/workflows/mutants.yml b/.github/workflows/mutants.yml index fc66b5aa2..17ce0e9e6 100644 --- a/.github/workflows/mutants.yml +++ b/.github/workflows/mutants.yml @@ -96,6 +96,12 @@ jobs: label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache - name: runs-on c8a 16cpu label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache + # arm64 (Graviton4) at the c8a sizes above, c8g only so the + # comparison is one CPU against another. + - name: runs-on c8g 16cpu arm64 + label: runs-on=${{ github.run_id }}/family=c8g/cpu=16/image=ubuntu22-full-arm64/volume=80gb/extras=s3-cache + - name: runs-on c8g 8cpu arm64 + label: runs-on=${{ github.run_id }}/family=c8g/cpu=8/image=ubuntu22-full-arm64/volume=80gb/extras=s3-cache permissions: contents: read # Posts and updates the report comment on the PR. diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e938737e0..9d52748c2 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -42,6 +42,12 @@ jobs: - id: runs-on-8 name: runs-on c8a 8cpu label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-c8g-4 + name: runs-on c8g 4cpu arm64 + label: runs-on=${{ github.run_id }}/family=c8g/cpu=4/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache + - id: runs-on-c8g-8 + name: runs-on c8g 8cpu arm64 + label: runs-on=${{ github.run_id }}/family=c8g/cpu=8/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache steps: - name: Checkout Repo uses: actions/checkout@v6 @@ -105,6 +111,10 @@ jobs: label: runs-on=${{ github.run_id }}/family=c8a/cpu=4/volume=80gb/extras=s3-cache - name: runs-on c8a 8cpu label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/volume=80gb/extras=s3-cache + - name: runs-on c8g 4cpu arm64 + label: runs-on=${{ github.run_id }}/family=c8g/cpu=4/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache + - name: runs-on c8g 8cpu arm64 + label: runs-on=${{ github.run_id }}/family=c8g/cpu=8/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache exclude: - node-version: 22 postgres-version: 17 @@ -454,6 +464,12 @@ jobs: - id: runs-on-8 name: runs-on c8a 8cpu label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-c8g-4 + name: runs-on c8g 4cpu arm64 + label: runs-on=${{ github.run_id }}/family=c8g/cpu=4/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache + - id: runs-on-c8g-8 + name: runs-on c8g 8cpu arm64 + label: runs-on=${{ github.run_id }}/family=c8g/cpu=8/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache # Auth-dependent suites in `e2e/` skip themselves unless these env vars # are set. We expose them at the job level so the wizard subprocess @@ -555,6 +571,12 @@ jobs: - id: runs-on-8 name: runs-on c8a 8cpu label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-c8g-4 + name: runs-on c8g 4cpu arm64 + label: runs-on=${{ github.run_id }}/family=c8g/cpu=4/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache + - id: runs-on-c8g-8 + name: runs-on c8g 8cpu arm64 + label: runs-on=${{ github.run_id }}/family=c8g/cpu=8/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache permissions: contents: read @@ -718,6 +740,12 @@ jobs: - id: runs-on-8 name: runs-on c8a 8cpu label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache + - id: runs-on-c8g-4 + name: runs-on c8g 4cpu arm64 + label: runs-on=${{ github.run_id }}/family=c8g/cpu=4/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache + - id: runs-on-c8g-8 + name: runs-on c8g 8cpu arm64 + label: runs-on=${{ github.run_id }}/family=c8g/cpu=8/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache continue-on-error: true services: diff --git a/scripts/__tests__/workflow-mise-cache-image.test.mjs b/scripts/__tests__/workflow-mise-cache-image.test.mjs index 2e74e25cd..a0e2e8679 100644 --- a/scripts/__tests__/workflow-mise-cache-image.test.mjs +++ b/scripts/__tests__/workflow-mise-cache-image.test.mjs @@ -27,7 +27,10 @@ import { readWorkflow, workflowFiles } from './lib/workflows.mjs' * `ubuntu-2404`, and a RunsOn label's `image=ubuntu24-full-x64` does too). A * `runs-on` that is one matrix value (`${{ matrix.runner.label }}`) names the * image every value of that axis names, and only when they all name the same - * one. A job whose `runs-on` names no image (`ubuntu-latest`, a RunsOn label + * one. The architecture is no part of ``: mise-action puts + * `linux-` in the key after the prefix, so an arm64 entry + * (`image=ubuntu22-full-arm64`) and an x64 one never share a cache. + * A job whose `runs-on` names no image (`ubuntu-latest`, a RunsOn label * with no `image=`, a matrix mixing images) must turn the cache off. No step * sets `cache_key`, which * mise-action prefers over the prefix and so would bring the shared key back. @@ -253,9 +256,36 @@ describe('mise-action cache keys', () => { expect( imageOf('runs-on=1/family=c8a/cpu=4/image=ubuntu24-full-x64/volume=80gb'), ).toBe('ubuntu-2404') + expect( + imageOf( + 'runs-on=1/family=c8g/cpu=8/image=ubuntu22-full-arm64/volume=80gb', + ), + ).toBe('ubuntu-2204') expect(imageOf('runs-on=1/runner=4cpu-linux-x64')).toBeUndefined() }) + it('keys a matrix mixing x64 and arm64 entries of one image', () => { + expect( + cacheKeyFinding({ + file: 'w.yml', + job: 'j', + // biome-ignore lint/suspicious/noTemplateCurlyInString: a GitHub Actions expression, the literal `runs-on` value under test. + runsOn: '${{ matrix.label }}', + matrix: { + include: [ + { label: 'blacksmith-16vcpu-ubuntu-2204' }, + { label: 'runs-on=1/family=c8a/cpu=16/image=ubuntu22-full-x64' }, + { label: 'runs-on=1/family=c8g/cpu=16/image=ubuntu22-full-arm64' }, + ], + }, + step: { + uses: 'jdx/mise-action@sha', + with: { cache_key_prefix: 'mise-v1-ubuntu-2204' }, + }, + }), + ).toBeNull() + }) + it('lets a composite action cache only image-independent tools', () => { const checked = [] const wrong = [] From dd4df4d5d373be378e285427fd51a79a2c36b3cb Mon Sep 17 00:00:00 2001 From: Lindsay Holmwood Date: Tue, 20 Oct 2026 22:23:25 +1100 Subject: [PATCH 6/6] ci: pin the arm64 trial entries to c8g exactly family=c8g is a prefix match, so RunsOn also launched c8gd (local NVMe) and c8gn (network-optimised) instances for those entries: of the arm64 jobs on b52c3d6, the 16 cpu Mutants entry ran on c8g.4xlarge and c8gd.4xlarge, and the 4 cpu Test JS entries on c8g, c8gd and c8gn. That mixes families into a comparison meant to be c8g against c8a. RunsOn's wildcard form, family=c8g.*, matches the c8g family alone. Claude-Session: https://claude.ai/code/session_017GMWYNGir7bpQacaUzN84U --- .github/workflows/mutants.yml | 7 ++++--- .github/workflows/tests.yml | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/.github/workflows/mutants.yml b/.github/workflows/mutants.yml index 17ce0e9e6..5c8809708 100644 --- a/.github/workflows/mutants.yml +++ b/.github/workflows/mutants.yml @@ -97,11 +97,12 @@ jobs: - name: runs-on c8a 16cpu label: runs-on=${{ github.run_id }}/family=c8a/cpu=16/image=ubuntu22-full-x64/volume=80gb/extras=s3-cache # arm64 (Graviton4) at the c8a sizes above, c8g only so the - # comparison is one CPU against another. + # comparison is one CPU against another. `c8g.*`, not `c8g`: a bare + # family is a prefix, and RunsOn handed out c8gd and c8gn for it. - name: runs-on c8g 16cpu arm64 - label: runs-on=${{ github.run_id }}/family=c8g/cpu=16/image=ubuntu22-full-arm64/volume=80gb/extras=s3-cache + label: runs-on=${{ github.run_id }}/family=c8g.*/cpu=16/image=ubuntu22-full-arm64/volume=80gb/extras=s3-cache - name: runs-on c8g 8cpu arm64 - label: runs-on=${{ github.run_id }}/family=c8g/cpu=8/image=ubuntu22-full-arm64/volume=80gb/extras=s3-cache + label: runs-on=${{ github.run_id }}/family=c8g.*/cpu=8/image=ubuntu22-full-arm64/volume=80gb/extras=s3-cache permissions: contents: read # Posts and updates the report comment on the PR. diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9d52748c2..a28ff44c4 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -44,10 +44,10 @@ jobs: label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache - id: runs-on-c8g-4 name: runs-on c8g 4cpu arm64 - label: runs-on=${{ github.run_id }}/family=c8g/cpu=4/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache + label: runs-on=${{ github.run_id }}/family=c8g.*/cpu=4/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache - id: runs-on-c8g-8 name: runs-on c8g 8cpu arm64 - label: runs-on=${{ github.run_id }}/family=c8g/cpu=8/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache + label: runs-on=${{ github.run_id }}/family=c8g.*/cpu=8/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache steps: - name: Checkout Repo uses: actions/checkout@v6 @@ -112,9 +112,9 @@ jobs: - name: runs-on c8a 8cpu label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/volume=80gb/extras=s3-cache - name: runs-on c8g 4cpu arm64 - label: runs-on=${{ github.run_id }}/family=c8g/cpu=4/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache + label: runs-on=${{ github.run_id }}/family=c8g.*/cpu=4/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache - name: runs-on c8g 8cpu arm64 - label: runs-on=${{ github.run_id }}/family=c8g/cpu=8/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache + label: runs-on=${{ github.run_id }}/family=c8g.*/cpu=8/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache exclude: - node-version: 22 postgres-version: 17 @@ -466,10 +466,10 @@ jobs: label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache - id: runs-on-c8g-4 name: runs-on c8g 4cpu arm64 - label: runs-on=${{ github.run_id }}/family=c8g/cpu=4/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache + label: runs-on=${{ github.run_id }}/family=c8g.*/cpu=4/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache - id: runs-on-c8g-8 name: runs-on c8g 8cpu arm64 - label: runs-on=${{ github.run_id }}/family=c8g/cpu=8/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache + label: runs-on=${{ github.run_id }}/family=c8g.*/cpu=8/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache # Auth-dependent suites in `e2e/` skip themselves unless these env vars # are set. We expose them at the job level so the wizard subprocess @@ -573,10 +573,10 @@ jobs: label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache - id: runs-on-c8g-4 name: runs-on c8g 4cpu arm64 - label: runs-on=${{ github.run_id }}/family=c8g/cpu=4/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache + label: runs-on=${{ github.run_id }}/family=c8g.*/cpu=4/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache - id: runs-on-c8g-8 name: runs-on c8g 8cpu arm64 - label: runs-on=${{ github.run_id }}/family=c8g/cpu=8/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache + label: runs-on=${{ github.run_id }}/family=c8g.*/cpu=8/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache permissions: contents: read @@ -742,10 +742,10 @@ jobs: label: runs-on=${{ github.run_id }}/family=c8a/cpu=8/image=ubuntu24-full-x64/volume=80gb/extras=s3-cache - id: runs-on-c8g-4 name: runs-on c8g 4cpu arm64 - label: runs-on=${{ github.run_id }}/family=c8g/cpu=4/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache + label: runs-on=${{ github.run_id }}/family=c8g.*/cpu=4/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache - id: runs-on-c8g-8 name: runs-on c8g 8cpu arm64 - label: runs-on=${{ github.run_id }}/family=c8g/cpu=8/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache + label: runs-on=${{ github.run_id }}/family=c8g.*/cpu=8/image=ubuntu24-full-arm64/volume=80gb/extras=s3-cache continue-on-error: true services: