test/container.sh runs test/run.sh in an image built from the Dockerfile (forge:test unless FORGE_TEST_IMAGE says otherwise), as root, the way the forge runs there: Debian's dash, its git, Caddy 2.6 and litestream, a git user that restores are handed to, and no curl. It mounts this checkout read-only and runs a copy of it with the image's node_modules and DuckDB extensions, so only a change to the Dockerfile or the packages needs a new image. README.md says how, next to how to run the scenarios at all.
- commit
- e28b6f339e2cff74247745d2732ece5a0239c196
- parent
- 2f1c626cfc0f9c6aa1ed656bc7680eda3e850af0
- author
- cat <admin@dev.site>
- ci
- ✓ passed in 115s, signed by cat
- kind
- build risk score 0.5 of 3, Jev's estimate
- review
- #5 Pass the scenarios in the container, as root
ci attestation
forge-attestation 1 type ci commit e28b6f339e2cff74247745d2732ece5a0239c196 tree ead68c784ee10768202ccb44868399539dd2d81b script .forge/ci e6f038ae810b87f90a4be115a762a9c91dd76a01 result pass exit 0 started 2026-10-18T23:04:54Z duration 115s runner (not shown here; refs/notes/ci has it) system Darwin 25.5.0 arm64 env host log sha256:af35a83b25e2d9532f88e3432af06b4480e6f189eaa19b891394079ddfb6c934 240 lines |remote: review #4: /dami/greet/reviews/4/ |pushed wip/i18n |eab0e48 running .forge/ci: greet.sh: say what it is | | sh: /bin/sh | | ok greet |eab0e48 pass in 0s, signed |pushed main |remote: review #4: /dami/greet/reviews/4/ |pushed wip/i18n |23bd74c running .forge/ci: wave at the world | | sh: /bin/sh | | FAIL greet : got 'hello, world o/', want 'hello, world' |23bd74c fail in 0s, signed |forge: 1 commit(s) did not pass |remote: review #6: /dami/greet/reviews/6/ |pushed ana/wave |30535b5 running .forge/ci: update the test for the wave | | sh: /bin/sh | | ok greet |30535b5 pass in 0s, signed |remote: review #6: /dami/greet/reviews/6/ |pushed ana/wave |warning: You appear to have cloned an empty repository. |site home: deployed ceda2a0 -> /sites/ana/dotfiles/home/ |created ana/notes |remote: review #1: /ana/notes/reviews/1/ |pushed ana/todo |landing #1 A todo list: ana/todo -> main |ce247d7 running .forge/ci: web, server and Python versions of greet | | sh: /bin/sh | | ok greet |ce247d7 pass in 0s, signed |pushed main |2effb80 running .forge/ci: messages: notes for the later regions | | sh: /bin/sh | | ok greet |2effb80 pass in 0s, signed |remote: review #7: /dami/greet/reviews/7/ |pushed dami/regions |created dami/forge |warning: You appear to have cloned an empty repository. |site guide: deployed cca2d68 -> /sites/dami/forge/guide/ |(node:22900) ExperimentalWarning: stripTypeScriptTypes is an experimental feature and might change at any time |(Use `node --trace-warnings ...` to show where the warning was created) |built ana/dotfiles in 1s -> /Users/dami/Library/Caches/forge/ci/35f7a65d0235/demo/root/.forge/www |(node:23042) ExperimentalWarning: stripTypeScriptTypes is an experimental feature and might change at any time |(Use `node --trace-warnings ...` to show where the warning was created) |built ana/notes in 1s -> /Users/dami/Library/Caches/forge/ci/35f7a65d0235/demo/root/.forge/www |(node:23191) ExperimentalWarning: stripTypeScriptTypes is an experimental feature and might change at any time |(Use `node --trace-warnings ...` to show where the warning was created) |built dami/forge in 1s -> /Users/dami/Library/Caches/forge/ci/35f7a65d0235/demo/root/.forge/www |(node:23340) ExperimentalWarning: stripTypeScriptTypes is an experimental feature and might change at any time |(Use `node --trace-warnings ...` to show where the warning was created) |built dami/greet in 4s -> /Users/dami/Library/Caches/forge/ci/35f7a65d0235/demo/root/.forge/www |(node:24058) ExperimentalWarning: stripTypeScriptTypes is an experimental feature and might change at any time |(Use `node --trace-warnings ...` to show where the warning was created) |built - in 1s -> /Users/dami/Library/Caches/forge/ci/35f7a65d0235/demo/root/.forge/www |226 of 226 pages render the same without 11ty |guide: 4 files, links ok |ok
Signature: good, cat
| M | README.md | 12 | ++++++++++++ |
| A | test/ | 29 | +++++++++++++++++++++++++++++ |
@@ -1177,6 +1177,18 @@ process, since a running one can't pick up changed TypeScript modules. It
11771177 only reads `demo/root`: no incremental build, and caches go to `.cache/dev/`.11781178 Live updates have no event stream there, so the status line stays empty.11791179 1180+The scenarios (`test/scenarios/`, one behavior each, end to end in a1181+throwaway forge) run with `sh test/run.sh [word...]`, as CI does. They need1182+git, ssh-keygen and Node, and use Caddy and litestream where they are1183+installed; HTTP goes through `test/http.ts`, not curl. To run them where the1184+forge runs, in the container as root (Debian's sh, a git user that restores1185+are handed to, Caddy and litestream, no curl):1186+1187+```sh1188+docker build -t forge:test . # once, and after Dockerfile or package changes1189+sh test/container.sh [word...] # this checkout's code, the image's node_modules1190+```1191+11801192 ## Reading pages11811193 11821194 The index and each owner's page show repos as cards on shelves by category,@@ -0,0 +1,29 @@
1+2+# Run the scenarios in the forge's container, as root, the way the forge3+# runs there: Debian's sh (dash), its git, Caddy, restic and litestream, a4+# git user to hand restores to, and no curl. This checkout's code runs with5+# the image's node_modules and DuckDB extensions, so only a change to the6+# Dockerfile or the packages needs a new image.7+#8+# docker build -t forge:test . the image, once9+# sh test/container.sh every scenario10+# sh test/container.sh private release the ones whose names contain a word11+# FORGE_TEST_IMAGE=forge:local sh test/container.sh another image12+# FORGE_TEST_JOBS=1 sh test/container.sh one at a time13+set -eu14+if [ "${1:-}" = --inside ]; then15+ shift16+ # A copy of the checkout without its own node_modules (built for the17+ # host, maybe not Linux) or anything the forge writes into it.18+ w=$(mktemp -d /tmp/forge-src.XXXXXX)19+ tar -C /opt/forge-src --exclude=./.git --exclude=./node_modules --exclude=./.duckdb --exclude=./.cache \20+ --exclude=./_site --exclude=./demo/root --exclude=./demo/work -cf - . | tar -C "$w" -xf -21+ ln -s /opt/forge/node_modules "$w/node_modules"22+ ln -s /opt/forge/.duckdb "$w/.duckdb"23+ exec sh "$w/test/run.sh" "$@"24+fi25+src=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)26+image=${FORGE_TEST_IMAGE:-forge:test}27+docker image inspect "$image" >/dev/null 2>&1 || { echo "no image $image: docker build -t $image $src" >&2; exit 1; }28+exec docker run --rm ${FORGE_TEST_JOBS:+-e FORGE_TEST_JOBS} -v "$src:/opt/forge-src:ro" "$image" \29+ sh /opt/forge-src/test/container.sh --inside "$@"