The release gate needs its own fixture repo — the canary cannot be trusted as one
Nobody has claimed this yet.
- Dominant language
- Shell
- Stars
- 0
- Forks
- 1
- Avg merge
- 32m
- Merged PRs (30d)
- 3
Description
#135 proposes gating a release on a green canary. This issue argues that test-actions-lecture-intro cannot serve as that gate, and proposes splitting the two roles across two repos.
Raised from the consumer side (QuantEcon/workspace-lectures#33), but the work is entirely local to this repo and its fixtures.
The role conflict
test-actions-lecture-intro is, by its own history, the feature sandbox — the place a new action or version gets tried end to end. Recent commits: feat: enable PR-scoped build caching in CI (#36), feat: build PDF and notebooks in CI preview (#35), Test: Migrate to quantecon/actions@v0 (#26), chore: update to quantecon/actions v0.5.0 (#33). PR #49 relabelled it the canary, but nothing about its shape changed to match.
That is a genuinely useful role. It is just not compatible with being a gate, because a gate's whole value is that red means stop — and red in that repo is ambiguous.
Three things that can turn it red without the release being at fault
Each verified against the repo as it stands today:
| Hazard | Evidence |
|---|---|
| Floating container | cache.yml:15, ci.yml:10, publish.yml:22 all run ghcr.io/quantecon/quantecon-build:latest. The environment changes underneath independently of the candidate, so a red may be a new image rather than a bad release |
| Build-time network reads | The fixture carries roughly a dozen remote data URLs, including high_dim_data and media.githubusercontent.com, with at least one lecture reading a CSV at build time (added in #48). Those exact URLs are being moved right now by the datasets migration, and media.githubusercontent.com 404s on plain-git files. A gate that fails on someone else's repoint is not a gate |
| Dependabot is enabled | .github/dependabot.yml is active with three open PRs, including sphinx-proof and Python 3.13 → 3.14. Merging any of them changes gate behaviour without a release having happened |
A fourth, milder point: it runs container mode only, which today is lecture-dp's shape. The other six lecture repos still run conda/miniconda, so the gate would currently certify a path most consumers do not use. That resolves itself as QuantEcon/workspace-lectures#31 section B lands, but not before.
Proposal: split by role, not by consumer
Let each repo be good at one question.
| Repo | Question it answers | Shape |
|---|---|---|
test-actions-lecture-intro (existing) |
Does the new thing work against a real-ish repo? | Realistic, messy, Dependabot on, :latest, pinned @v0. Keep as-is |
| New gate repo | Is this candidate releasable? | Frozen and boring — see below |
Gate repo properties
Every one of these is a direct answer to a hazard above, so none is decoration:
- container pinned by digest, never a moving tag — a gate must vary only the thing under test;
- zero network reads at build time — every data file vendored into the repo;
- Dependabot off, no open dependency PRs, no ambient drift;
- small — roughly five lectures, so a run is minutes rather than the current fixture's fifty. A slow gate gets bypassed, which is the same failure as no gate;
- pinned
@v0-next, per #135, so it exercises the candidate rather than the previous release; - content chosen to exercise what has actually broken in production rather than to look like a lecture site: a plotly cell forcing static export through kaleido (the #85 path), a real matplotlib render, and
quantecon_book_themeunder xelatex. This is the fixture critique from #100's design comment, which the current fixture never adopted.
Why not a second workflow set in the existing repo
The hazards are repo-level properties, not workflow-level ones. Dependabot config is per repo. Vendored versus remote data is per repo. A frozen fixture and a drifting one cannot coexist in one tree. Two Pages targets is also a feature rather than a cost — a gate publishing over the sandbox's site would be its own problem.
Why not a repo per consumer shape yet
There are two axes, and only one justifies a new repo today. Role (sandbox versus gate) is immediate and is what the hazards above are about. Consumer shape (container versus conda, LaTeX-first versus tojupyter-first) is real today but is actively being migrated away by QuantEcon/workspace-lectures#31 section B — building per-shape fixtures now means maintaining fixtures for a shape being deleted.
Fixture-maintenance cost is what let the current fixture drift out of usefulness in the first place; multiplying it is the failure mode to avoid. Name the new repo for its role, and add a shape-specific one only if a genuinely divergent shape persists. lecture-jax's GPU path is the plausible candidate, already parked behind QuantEcon/lecture-jax#284.
The tradeoff, stated plainly
A small synthetic fixture can go green while a real fifty-lecture build fails. That is the price of determinism, and it is exactly why the sandbox should keep existing rather than be replaced. Gate catches regressions; sandbox catches integration surprises. Different questions, neither redundant.
Open questions
| Question | Notes |
|---|---|
| Name | test-actions-release, test-actions-gate, or another member of the test-actions-* family |
| Fixture provenance | Purpose-built minimal lectures, or a trimmed copy of intro? Leaning purpose-built — a trimmed copy inherits the remote data URLs that are hazard #2 |
| Does the sandbox's role get written into its README? | So the next person does not try to gate on it again, which is how this issue came about |
Related
- #135 — release gating and the
v0-nextstaging tag; this is the fixture half of it - #100 — testing; its stage 2 assumed one canary repo could do both jobs, and its design comment already described the fixture this proposes
- #85 — the kaleido static-export failure the fixture should deliberately exercise
- #108 — the smoke tests that could not fail; the same "fixture that cannot detect what it is for" problem, one level down
- QuantEcon/workspace-lectures#33 — the consumer-side view
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading #135 and the existing cache.yml, ci.yml, publish.yml, and .github/dependabot.yml files in test-actions-lecture-intro, then review the fixture requirements and related issues #100 and #85. Done means a separate, small gate fixture is defined with pinned container and action versions, vendored data, no dependency drift, and coverage for the listed production failure paths.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, github-actions, latex, python
- Domain
- build-system, ci-cd, release, testing
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100