feat(ci): cheap matrix mode (matrix-mode input + CI_MATRIX_MODE variable)#27
Merged
Conversation
…riable Add a `matrix-mode` input to csharp-ci.yaml and scala-ci.yaml and a new org/repo Actions variable CI_MATRIX_MODE. `cheap` collapses the build/test matrix to a single free self-hosted Hetzner leg, overriding os-list and build-matrix; `full` forces the normal matrix; empty defers to the variable. Precedence: input > CI_MATRIX_MODE > normal matrix. normalize-ci-matrix.sh gains a 4th positional arg reusing private_default as the single source of the Hetzner leg, with loud failure on unknown modes.
Self-hosted Hetzner runners must not run public/fork-PR workloads, so cheap mode now falls through to the normal matrix (with a warning) on public repos. The reusable workflows always resolve repository visibility before invoking the normalizer so the guard can apply.
Internal review: the cheap-mode guard checked only "= public", so any non-public value (empty, garbled gh api response) collapsed to the self-hosted Hetzner leg — fail-open on a security boundary. Switch to an allowlist: private/internal collapse, public warns and falls through, anything else errors and refuses to route to self-hosted runners. Also qualify the README/CHANGELOG matrix-mode summaries as private/internal only, and add an uppercase-CHEAP-on-public regression test.
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a "cheap CI matrix mode" so paid GitHub-hosted matrix legs can be routed onto idle free self-hosted Hetzner runners during a refactor.
matrix-modeinput oncsharp-ci.yamlandscala-ci.yaml(string, optional, default'').CI_MATRIX_MODE.scripts/normalize-ci-matrix.shgains a 4th positional argmatrix_mode.Behaviour
cheap(case-insensitive): collapse the matrix to a single shard on the free self-hosted Hetzner pool (["self-hosted","hetzner"], coverage on), ignoringos-list,build-matrix, and visibility. The Hetzner leg reuses the existingprivate_defaultdefinition — no duplicated JSON literal.full/ empty: existing behaviour unchanged.Precedence
matrix-modeinput >CI_MATRIX_MODEvariable > normal matrix.Implemented in the "Compute effective matrix" step via
MATRIX_MODE: ${{ inputs.matrix-mode != '' && inputs.matrix-mode || vars.CI_MATRIX_MODE }},passed as the 4th arg to the helper. The visibility
gh apilookup is also skipped in cheap mode.How to use the org variable
Set
CI_MATRIX_MODE = cheapas an org- or repo-level Actions variable to flip every consumer onto Hetzner at once. A single caller can opt back out withmatrix-mode: full.Tests
Added cases to
test/normalize-ci-matrix_test.sh(wired intobuild-and-test.yaml): cheap overrides explicit build-matrix, cheap is case-insensitive, cheap ignores empty visibility,full/empty preserve existing behaviour, unknown mode errors. All pass;actionlint+shellcheckclean.Docs
README input tables (C# + Scala) updated and a new "Cheap matrix mode" section documenting the variable and precedence. SPDX headers untouched.