testing: publish/preview/cache action logic has no automated tests
Nobody has claimed this yet.
- Dominant language
- Shell
- Stars
- 0
- Forks
- 1
- Avg merge
- 32m
- Merged PRs (30d)
- 3
Description
Surfaced by the v0.8.0 validation study.
Problem
Containers are covered end-to-end (build-containers.yml → test-container.yml / test-containers-lectures.yml), and since v0.10.0 so are the cache and environment actions, on the PR's own code. Untested: the publish and preview layer, plus the @v0 sibling-pin chain only a released ref can reach.
Coverage — harness (.github/workflows/test-actions.yml, via uses: ./; bare :N are its lines) / canary (QuantEcon/test-actions-lecture-intro, pinned @v0):
restore-jupyter-cache✅ both cache types × both modes,fail-on-missfiring and staying quiet (:195,:234,:268,:301,:332,:362,:394) / ✅ci.yml:23setup-environment✅ standard-mode conda cache, two-run miss→hit chain (:431,:461) / ✅ viabuild-jupyter-cachebuild-lectures✅ real executed HTML build, both directions (:461,:508) / ✅ six call sites inci.yml,publish.ymlbuild-jupyter-cache⚠️ runs (:591,:638,:698,:784,:818) but its internal calls execute@v0, not the PR / ✅cache.yml:27preview-netlify❌ needs a real deploy target / ⚠️ci.yml:54, fires only on a PR opened there — no successful deploy between 2026-02-10 and 2026-08-05preview-cloudflare❌ / ❌ called nowhere — no harness job, no canary call sitepublish-gh-pages❌ would publish this repo's own Pages / ⚠️publish.yml:56, fires only on apublish*tag pushed there — last run 2026-02-10, so v0.7.0–v0.11.1 never went through it
Behind the ❌s: uses: takes no expressions and build-jupyter-cache pins siblings hardcoded (setup-environment@v0 at build-jupyter-cache/action.yml:149; build-lectures@v0 at :164, :174, :184), so that chain is untestable pre-release; the previews and publish-gh-pages need real deploy targets end to end, hence TESTING.md:37 assigns them to the canary — but see stage 1.5 below, which that framing has been writing off. The relevance gate is blind too — the IGNORED list at test-actions.yml:112 misses preview-*/action.yml, so a preview-only PR runs all 15 substantive jobs and reports the required check Action harness: all checks green without running a line of preview code. Publish/preview confidence rests on code review plus production publishes in the lecture repos, which is where this issue started.
Why it matters
A publish or cache regression surfaces only when a real build fails — the layer whose gaps hid #28 (see #83). preview-cloudflare, uncovered everywhere, shipped PR comments linking the per-deployment hash rather than the stable pr-N alias, and a deploy-url returning the alias on one wrangler release and the hash on another; both caught by reading, fixed in v0.11.1 (#131). #105 (preview deploy errors swallowed) is the same shape, still open. Canaries also decay untended: the weekly cache.yml build ran every Sunday to 2026-04-12, missed 16 consecutive Sundays, resumed 2026-08-09 — the first Sunday after activity returned 2026-08-05, the signature of GitHub disabling a schedule after 60 days of repository inactivity. v0.7.0, v0.8.0 and v0.9.0 all shipped in that window, unnoticed.
Stage 1 — shipped
-
A PR-time harness in this repo using— done in v0.10.0 (#114, #118), extended in v0.11.0 (#120, #122, #124, #127)../local paths, so it exercises the code on the PR rather than a released ref
17 jobs: a relevance gate (:75), 15 substantive jobs, and harness-summary (:854), whose job name Action harness: all checks is the required check on main. Fixtures are salted per run, jobs assert on outputs and filesystem, and negative jobs unit-build-miss-guard (:301), build-fail-guard (:508), bjc-fail-guard (:638), bjc-abort-guard (:698) stop a swallowed failure passing green. TESTING.md:25 documents it as stage 1. #29's env-test half landed with it — env-seed (:431), env-hit-build (:461), the two-run standard-mode conda miss→hit chain, done under PLAN.md backlog item 9; #29's docs half remains.
- Make the harness's green honest about what it did not run — naming the un-exercised actions in
harness-summary's output is enough.
Stage 2 — make the canary consume the shipped templates
The canary — named in PLAN.md's "Consumers in production" table and TESTING.md:47, superseding QuantEcon/test-lectures from the design proposal comment below — is live, pinned @v0 and runs the full chain, but does not consume templates/ verbatim, so what we ship consumers is validated nowhere.
- Re-sync the canary's
cache.yml,ci.ymlandpublish.ymlfromtemplates/, and keep them synced. Drift:templates/publish.ymltriggers on push tomainplusworkflow_dispatchwhere the canary's uses apublish*tag, so the trigger we hand consumers is never exercised;templates/cache.ymlcrons0 0 * * 0against the canary's0 3 * * 0. Also keeps #109's template fixes from re-drifting. Coordinate with #135, which changes the canary's publish trigger too. - Detect a silent canary, not only a red one — the 16 missed Sundays produced no signal because absence is indistinguishable from success. (#135 covers a red canary reaching a human, and scheduling; neither addresses liveness.)
Stage 3 — coverage needing a real deploy target
-
— the canary deploys real Netlify previews atpreview-netlify— a call site on a real deploy targetci.yml:54, with the tokens it needs. -
— the canary publishes atpublish-gh-pages— a call site on a real Pages targetpublish.yml:56; that it has not run since 2026-02-10 is a trigger problem, and belongs to #135. -
preview-cloudflare— the only action with zero coverage in either harness. Needs a Cloudflare Pages project and an API token on the canary, plus a call site: a second preview job in itsci.yml, or a dedicated workflow. Also the action most recently found broken by reading, which argues for doing it first.
Scope boundary
- Stage 4 — canary on release, green before
v0moves — is now #135: all ten of the canary's action references are@v0, the tag a release moves, so it always exercises the previous release, which no trigger change fixes; #135 proposes av0-nextstaging tag. - #136 goes further — a floating
:latestcontainer, build-time network reads and live Dependabot each make a red there ambiguous — and proposes a frozen fixture repo for the gate role, keeping the canary as the sandbox. Stages 2–3 stay here either way; if #136 lands, the gate fixture is its work. - Container fixture gaps (
containers/quantecon/tests/minimal-jupyter-book/) stay with #108: those exercise the image, these the action logic. - Uncovered even then: the pre-release
build-jupyter-cachesibling chain, structurally — #135 narrows the ungated surface rather than closing it; real-scale performance and content diversity, sotest-containers-lectures.ymlagainst the three real lecture repos stays as-is; thelecture-jaxGPU path, while QuantEcon/lecture-jax#284 is open. - QuantEcon/workspace-lectures#31 sequences the lecture family's move to floating
@v0behind this gap; QuantEcon/workspace-lectures#33 is the consumer view of the gating decision.
Stage 1.5 — the deploy-action logic that needs no deploy target
"Needs real deploy targets and secrets" is true of the deploy itself and false of most of what these three actions actually do. The following are pure functions of their inputs, testable in this harness today with no Cloudflare project, no Netlify account, no canary and no #136 fixture repo — and they are the parts that have silently shipped wrong before:
- Extract the duplicated ~87-line PR-comment renderer from
preview-netlifyandpreview-cloudflareinto a shared script (PLAN item 6) and assert the rendered URL paths, including thestrip-lectures-dirvariants - Extract
publish-gh-pages' release-asset packaging and assert the tarball, its SHA256 checksum, and the JSON manifest fields against a fixture directory - Assert CNAME injection and build-directory validation against a fixture
- Correct the "needs real deploy targets and secrets" line here and at
TESTING.md:37, which currently writes off work that needs neither
This matters more now than when this issue was filed: #135/#136 have moved the real-deploy route behind a new fixture repo that does not exist yet, so the pure-logic half is the only preview/publish coverage reachable in the near term. It also removes the duplication PLAN item 6 tracks, so the extraction pays for itself twice.
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 with .github/workflows/test-actions.yml, TESTING.md, PLAN.md, and the action files for preview-netlify, preview-cloudflare, and publish-gh-pages. Map the unchecked coverage and existing canary workflows before choosing a stage, coordinating with the referenced issues where required. Done means the relevant pure logic or canary paths are covered and the harness reports untested actions honestly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- github-actions, shell
- Domain
- ci-cd, devops, testing-qa
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100