feat: --github-matrix#17
Conversation
Emit a GitHub Actions matrix as JSON from a camas matrix-bearing task, so
the matrix definition lives once in tasks.py instead of being duplicated
in workflow YAML. Output is the object-of-arrays form
({"PY": ["3.10", "3.11"]}), consumable as the whole matrix via
`matrix: ${{ fromJSON(...) }}` or one axis at a time via
`<axis>: ${{ fromJSON(...).<axis> }}`. TTY-aware: indented for
interactive preview, compact one-liner for `>> $GITHUB_OUTPUT`.
Validation: emitted JSON is tested against the GHA workflow schema's
matrix subset (vendored from SchemaStore, sha dbc0fd17).
Dogfooded in ci.yaml: the `check` job's hardcoded
`python: ["3.10"..."3.15"]` is replaced by a `discover` job that runs
`camas matrix --github-matrix`. `.python-version` becomes the single
source.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #17 +/- ##
==========================================
Coverage 100.00% 100.00%
==========================================
Files 52 54 +2
Lines 4773 4977 +204
Branches 257 263 +6
==========================================
+ Hits 4773 4977 +204
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Adds a new CLI preview mode (--github-matrix) that emits a GitHub Actions-compatible matrix JSON derived from a task’s declared matrix axes, enabling CI workflows to source matrix definitions directly from tasks.py rather than duplicating them in YAML.
Changes:
- Add
--github-matrixCLI flag (mutually exclusive with--dry-run) and dispatch path to emit TTY-aware JSON. - Introduce
camas.main.github_matrixhelpers to project matrix axes and format JSON output. - Add schema-backed tests + vendored schema fixture; update CI workflow to “discover” the Python matrix dynamically.
Reviewed changes
Copilot reviewed 8 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
src/camas/main/parser.py |
Adds --github-matrix flag and reserves its name from axis overrides. |
src/camas/main/dispatch.py |
Implements --github-matrix execution path (rejects passthrough, applies overrides, prints JSON). |
src/camas/main/github_matrix.py |
New helper module to project matrix axes and format/emit JSON. |
src/camas/main/format.py |
Updates per-task help usage line to optionally mention --github-matrix. |
tests/main/test_github_matrix.py |
Adds extensive unit + CLI integration tests and schema validation. |
tests/fixtures/github-actions-matrix-schema.json |
Vendors GHA matrix subschema used for validation tests. |
.github/workflows/ci.yaml |
Adds discover job and uses emitted matrix for Python versions in check job. |
pyproject.toml |
Adds jsonschema + types to dev dependencies for schema validation tests. |
uv.lock |
Locks new dev dependencies (jsonschema, types-jsonschema, and transitive deps). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
PR review:
- Per-task --help usage line now shows `[--dry-run | --github-matrix]` to
reflect the argparse mutex (was: two independent optional flags, implying
they could be combined).
- New `RESERVED_DESTS` constant (hyphen→underscore normalization of
`RESERVED_FLAGS`); dispatch uses it when filtering axis names so an axis
literally named `github_matrix` no longer silently shares argparse's
auto-derived dest with `--github-matrix`.
- Fix malformed URL anchor in the vendored schema fixture description.
- Drop section-divider comments in test_github_matrix.py.
CI deps:
- Make jsonschema conditional on `python_version < '3.15'` — its transitive
`rpds-py` dep currently won't build on 3.15 (PyO3 0.27.2 max-supports
3.14). `pytest.importorskip("jsonschema")` lets schema-validation tests
skip cleanly on 3.15 instead of erroring at import.
- Add `jsonschema` to wheels `CIBW_TEST_REQUIRES` and nix
`nativeCheckInputs` so those test envs can run the new test file.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous conditional on `jsonschema` alone wasn't sufficient:
`types-jsonschema` depends on `referencing` (unconditional), which
depends on `rpds-py` — so the whole rpds-py → PyO3 build chain still
fires on 3.15. Mirror the marker onto `types-jsonschema` so the entire
sub-tree is excluded on 3.15.
Test-side is unaffected: `pytest.importorskip("jsonschema")` returns
`Any`, so the stubs weren't doing static-type work on the test file
anyway.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
--github-matrixflag emits a GitHub Actions matrix as JSON for the task's axes, so the matrix definition lives once intasks.pyinstead of being duplicated in workflow YAML.{"PY": ["3.10", "3.11"]}), consumable either as the whole matrix (matrix: ${{ fromJSON(...) }}) or per-axis (PY: ${{ fromJSON(...).PY }}) — the latter lets you combine with extra YAML-side axes likeos.>> $GITHUB_OUTPUT.camas matrix --github-matrix --PY 3.13emits the filtered matrix.--dry-run; errors helpfully if the task has no matrix axes; rejects--passthrough.--helpadvertises[--github-matrix]when matrix axes exist.Validation
Emitted JSON is tested against the GHA workflow schema's matrix subset, vendored from SchemaStore (
tests/fixtures/github-actions-matrix-schema.json, shadbc0fd17). Two adversarial tests against the fixture itself (empty axis / empty object) guard against fixture drift.34 new tests covering pure helpers, schema conformance for six matrix shapes, CLI integration through
dispatch, override + mutex + passthrough cases, TTY vs pipe formatting, and per-task help. All 643 existing tests still pass.Dogfood
The
checkjob's hardcodedpython: ["3.10".."3.15"]is replaced by a newdiscoverjob that runscamas matrix --github-matrix; thecheckjob consumes${{ fromJSON(needs.discover.outputs.matrix).PY }}..python-versionbecomes the single source of truth. Runner shape unchanged (4 OS × 6 PY = 24).Test plan
uv run camas checkpasses locally (it does — minus pre-existing pyrefly worktree-path issue)discoverjob emits matrix;checkjobs fan out across the emitted PY listcamas matrix --github-matrixin a TTY shows indented JSONcamas matrix --github-matrix | catshows compact JSONcamas check --github-matrixfails with "no matrix axes" (sincecheckhas no matrix)camas matrix --dry-run --github-matrixis rejected as mutexcamas matrix --helpshows[--github-matrix];camas test --helpdoes not🤖 Generated with Claude Code