CI / lint (push) Successful in 3s
CI / extension-version (push) Successful in 3s
CI / frontend-build (push) Successful in 21s
extension / lint (push) Failing after 28s
CI / backend-lint-and-test (push) Successful in 47s
CI / integration (push) Successful in 4m1s
Milestone #271 steps 2 and 3. Neither changes what gets published. STEP 2 -- shadow mode. build.yml's sign-extension and ci.yml's extension-version guard now log the version that WOULD be derived from git history alongside the hand-maintained one. Nothing reads the derived value, and neither site can fail because of it. This exists because `web-ext sign` is one-shot per version: AMO 409s on a repeat, so a wrong formula burns a real version number that cannot be reclaimed. Comparing the two across real builds is the only way to validate it at zero cost. sign-extension runs on main only, so main pushes are the sole source of truth for whether the derived number moves exactly when the shipped extension changes -- the dev-side log is a convenience, not the evidence. sign-extension now checks out with fetch-depth: 0. The derived version is a commit count and a depth-1 clone cannot produce one. STEP 3 -- XPI content verification. Every other packaging assertion checks our declaration against itself. This is the first that asks web-ext what it ACTUALLY wrote into the archive. That assumption was both unverified and fragile: `test/**` only survives to web-ext because callers `set -f` before substituting it, so losing that quoting would silently start shipping dev files with no other signal. The step builds the XPI and asserts test/, scripts/, vitest.config.js, package.json, package-lock.json, README.md and node_modules are absent -- and, because an over-matching exclusion would break the extension at runtime rather than at build time, that manifest.json, all four lib/*.js and every UI directory are present. unzip is installed only when missing; node:24-bookworm-slim may not carry it. Refs #2399, #2400 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
3.6 KiB
3.6 KiB
CI Requirements — FabledCurator
Spec: https://git.fabledsword.com/bvandeusen/CI-runner/src/branch/main/docs/process.md
Runtime image
git.fabledsword.com/bvandeusen/ci-python:3.14
Image deps used
- python 3.14
- ruff (analyzer for
backend/,tests/,alembic/) - node (frontend job:
npm install+ vitest + vite build) - docker CLI + buildx (
.forgejo/workflows/build.yml: build-web, build-ml — Fabled-Git registry push)
Secondary runtime image
node:24-bookworm-slim — .forgejo/workflows/extension.yml only.
The extension lane is the one job that does NOT run on ci-python:3.14: it
needs a current Node for web-ext and vitest and nothing Python at all. Kept
on the upstream slim image rather than adding a Node toolchain to ci-python,
per docs/process.md's "add deps to the image when used by >1 project".
Per-job tool installs
pip install -r requirements.txt pytest pytest-asyncio— inbackend-lint-and-testandintegrationjobsnpm install --no-audit --no-fund— infrontend-buildjobnpm install --no-audit --no-fund— inextension.yml'slintjob (web-ext + vitest)unzip— inextension.yml's "Verify XPI contents" step, installed via apt only when absent (node:24-bookworm-slimmay or may not carry it). Debian package, ~2s. Not worth baking into a shared image for a single consumer, perdocs/process.md's ">1 project" rule.
Notes
- Integration wall time ~3 min, dominated by pgvector container start + the
pip installstep (~30-45s on cold cache) + alembic + 300+ integration tests. - The
pip installin two jobs is intentional and perdocs/process.md's "add deps to image when used by >1 project" rule: FC alone is one Python project, so the deps live inrequirements.txtand install per-job. Reconsider when a second Fabled-family Python backend lands. - Integration uses Fabled-Git Actions
services:+ socket-discovered bridge IPs becauseact_runner(swarm-runner v0.6+) puts services on the default bridge with no embedded DNS. The pattern is documented in the rulebook'sfabled-git.md"CI philosophy" section and FC'sci.ymlis the canonical example. - No
package-lock.jsonis tracked yet (FC'sfeedback_no_local_runsmemory bansnpm installlocally). Usingnpm installrather thannpm ciuntil a lockfile lands. - No
imagemagick/pandocper-job installs needed. extension/'s vitest specs loadlib/*.jsby evaluating the real file as a classic script (test/helpers/loadLib.js) rather than addingmodule.exportsshims to production code — the libs ship asbackground.scripts, not ES modules, so the specs exercise exactly the bytes packaged into the XPI.extension/scripts/packaging.shis the single definition of what ships inside the XPI. Three consumers read from it rather than keeping their own copy: web-ext's--ignore-files(extension/package.json), the:(exclude)pathspec inci.yml'sextension-versionguard, and the commit count that derives the extension version. Three hand-kept copies of that one fact is what allowed issue #2397.build.yml'ssign-extensionchecks out withfetch-depth: 0— the derived extension version is a commit count, which a shallow clone cannot produce.- Callers MUST
set -fbefore substituting the script's output. Without it the shell expandstest/**against the working tree and silently narrows the pattern to whatever files exist at that moment — a failure that looks like nothing until dev files start appearing in the XPI.test/version.spec.jsasserts every--ignore-filesconsumer sets it, and that no consumer has quietly reinstated a hardcoded list.