Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: CI

# Build + test gate. Runs on every PR and on pushes to main, so a branch must
# Build + typecheck + test gate. Runs on every PR and on pushes to main, so a branch must
# be green before it is merged (enable "Require status checks to pass" on the
# main branch protection rule to enforce it). Deploy lives in deploy.yml and
# runs only after a merge to main.
Expand Down Expand Up @@ -37,8 +37,24 @@ jobs:
- name: Install dependencies
run: npm ci

- name: Build (type-checked)
# This step was called "Build (type-checked)". It was not type-checked, and neither was anything
# else: Astro and vitest both hand .ts to esbuild, which strips annotations without ever asking
# the compiler. So a build being green said nothing about types — proof, before the Typecheck step
# below existed: `tsc --noEmit` reported a real TS2345 in tests/skyShader.test.ts while `npm run
# build` and `npm test` were both green. Renamed to stop the name making a promise it cannot keep.
- name: Build
run: npm run build

# THE ONLY PLACE TYPES ARE CHECKED. Two checkers, because neither covers the other: `astro check`
# is the only thing that reads the ~4,400 lines of <script> bodies inside .astro files (tsc cannot
# parse .astro at all), and plain `tsc --noEmit` is the only thing that covers tests/ and src/lib
# on their own terms. `npm run typecheck` runs both.
#
# Placed after Build and before Test on purpose. After Build, so the generated content-collection
# types in .astro/ exist on a fresh checkout; before Test, because a type error is cheaper to read
# than the assertion failure it causes three steps later.
- name: Typecheck
run: npm run typecheck

- name: Test
run: npm test
27 changes: 25 additions & 2 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ jobs:
# Gate the deploy on the SAME test suite CI runs. deploy.yml triggers on push
# to main independently of ci.yml, so without this a red `npm test` could still
# ship. build (and therefore deploy) waits on this passing.
#
# TESTS ONLY, NOT `npm run typecheck` — and that asymmetry with ci.yml is deliberate. A type error
# cannot change the shipped bytes: Astro strips types with esbuild, so the HTML/CSS/JS built from a
# type-error-ridden tree is byte-identical to the same tree with the annotation fixed. Blocking a
# deploy on it would leave the LIVE SITE STALE to punish a mistake that is not in the output, which
# is the worse failure. Types are the merge gate's job (ci.yml, required check on main); tests gate
# the deploy because a red assertion means the logic behind the pixels is actually wrong.
test:
runs-on: ubuntu-latest
steps:
Expand All @@ -30,6 +37,17 @@ jobs:
node-version-file: .nvmrc # single source of truth (matches ci.yml)
cache: npm
- run: npm ci
# THE BUILD IS PART OF THE TEST GATE NOW, and without it this job cannot pass.
#
# tests/distSmoke.test.ts reads dist/**/*.html — it is the only coverage the suite has of RENDERED
# output, and it deliberately THROWS when dist/ is missing rather than skipping, because a test that
# quietly passes when its subject is absent is worse than no test. dist/ is gitignored, so a fresh
# checkout has none: this job ran `npm ci && npm test` and would have failed 8 assertions on push to
# main, and since `build` needs `test` and `deploy` needs `build`, EVERY DEPLOY WOULD HAVE STOPPED —
# while ci.yml stayed green, because ci.yml happens to build before it tests.
# Caught by a cleanup sweep before this branch merged, not by CI, precisely because CI cannot see it.
- name: Build (dist/ is what distSmoke reads)
run: npm run build
- name: Test
run: npm test

Expand All @@ -41,8 +59,13 @@ jobs:
- name: Build with Astro
uses: withastro/action@v3
with:
# Astro 6 requires Node >=22.12; the action defaults to 20. Keep this
# in step with .nvmrc (local) and ci.yml.
# Astro 6 requires Node >=22.12 (astro's own `engines`, mirrored in package.json); the action
# defaults to 20, which it rejects. HARDCODED ON PURPOSE, AND THE ONE PLACE THAT IS:
# withastro/action takes only `node-version` — it has no `node-version-file` input, and it
# does its own checkout, so .nvmrc is not readable before it runs. Everywhere else
# (ci.yml, the test job above) reads .nvmrc directly. EDIT THIS LINE AND .nvmrc TOGETHER;
# they both say 24 today, and a bump that changes only one of them would build the site on a
# different Node than every check that approved it.
node-version: 24
# Installs deps, runs `astro build`, and uploads the Pages artifact.

Expand Down
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,13 @@ docs/
# art gallery working directories (ephemeral)
_incoming-photos/
_originals/

# Ad-hoc verification scratch — measurement probes, driver scripts and screenshots written while
# checking a change, then abandoned. 164 of these had accumulated untracked at the repo root and a
# single `git add -A` swept every one of them into a commit; the pattern belongs here so that cannot
# happen again. Deliberately BROAD (any .tmp-* directory, any tmp_* file) because each of these was
# named on the spot by whoever was measuring, and a list of specific names would go stale immediately.
# Anything worth keeping gets a real name and a real home; anything named tmp_ is disposable by
# declaration.
.tmp-*/
tmp_*
Loading
Loading