feat(ci): pin container.image to ci-python:3.14 + ship ci-requirements.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-21 09:19:30 -04:00
parent 1fe259fa14
commit 4a09cca46e
3 changed files with 58 additions and 18 deletions
+4
View File
@@ -13,6 +13,8 @@ on:
jobs: jobs:
build-web: build-web:
runs-on: python-ci runs-on: python-ci
container:
image: git.fabledsword.com/bvandeusen/ci-python:3.14
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -42,6 +44,8 @@ jobs:
build-ml: build-ml:
runs-on: python-ci runs-on: python-ci
container:
image: git.fabledsword.com/bvandeusen/ci-python:3.14
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
+17 -18
View File
@@ -1,14 +1,9 @@
name: CI name: CI
# CI policy (amends the older FabledRulebook/forgejo.md "lint + unit only" # CI lanes per FabledRulebook/forgejo.md "CI philosophy":
# stance — operator opted in to running integration in CI): # - backend-lint-and-test: ruff + `pytest -m "not integration"`, no service containers.
# - backend-lint-and-test: fast feedback — ruff + `pytest -m "not
# integration"`, no service containers.
# - frontend-build: vitest unit + vite build. # - frontend-build: vitest unit + vite build.
# - integration: spins up pgvector Postgres + Redis service containers, # - integration: pgvector + redis service containers; alembic + `pytest -m integration`.
# migrates a throwaway test DB, runs `pytest -m integration`. This is
# the first time the integration suite runs anywhere, so expect a
# debugging tail until it goes green.
on: on:
push: push:
@@ -18,10 +13,9 @@ on:
jobs: jobs:
backend-lint-and-test: backend-lint-and-test:
# Runner must have Python 3.14 + ruff + Node 22 pre-installed. The
# python-ci runner image lives at CI-Runner/CI-python/ in the operator's
# workspace; see that Dockerfile + Makefile to roll/push the image.
runs-on: python-ci runs-on: python-ci
container:
image: git.fabledsword.com/bvandeusen/ci-python:3.14
env: env:
# DB_PASSWORD and SECRET_KEY are required by config.py at import time # DB_PASSWORD and SECRET_KEY are required by config.py at import time
# even though unit tests don't actually touch the DB or use the secret. # even though unit tests don't actually touch the DB or use the secret.
@@ -31,9 +25,9 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Install Python deps - name: Install Python deps
# ruff is pre-installed in the python-ci runner image (see # ruff is pre-installed in the ci-python image (see CI-Runner/CI-python/
# CI-Runner/CI-python/Dockerfile's RUFF_VERSION). Per FabledRulebook # Dockerfile's RUFF_VERSION). Per FabledRulebook ci-runners.md, toolchain
# forgejo.md, toolchain versions live on the runner image, not here. # versions live on the runner image, not here.
run: pip install -r requirements.txt pytest pytest-asyncio run: pip install -r requirements.txt pytest pytest-asyncio
- name: Ruff lint - name: Ruff lint
@@ -44,6 +38,8 @@ jobs:
frontend-build: frontend-build:
runs-on: python-ci runs-on: python-ci
container:
image: git.fabledsword.com/bvandeusen/ci-python:3.14
defaults: defaults:
run: run:
working-directory: frontend working-directory: frontend
@@ -67,11 +63,14 @@ jobs:
# ports collides with the operator's running docker-compose dev stack on # ports collides with the operator's running docker-compose dev stack on
# the same shared daemon. Workaround: publish NO host ports, and reach # the same shared daemon. Workaround: publish NO host ports, and reach
# each service by its bridge IP — discovered at runtime via the mounted # each service by its bridge IP — discovered at runtime via the mounted
# docker socket (the python-ci image ships /usr/bin/docker; build.yml # docker socket (the ci-python image ships /usr/bin/docker). Default-bridge
# relies on it). Default-bridge containers can talk by IP (only embedded # containers can talk by IP (only embedded DNS is missing), so IP
# DNS is missing), so IP addressing is reliable here. Everything runs in # addressing is reliable here. Everything runs in ONE step so resolved
# ONE step so resolved values don't depend on cross-step env passing. # values don't depend on cross-step env passing. Pattern documented in
# FabledRulebook/forgejo.md "CI philosophy".
runs-on: python-ci runs-on: python-ci
container:
image: git.fabledsword.com/bvandeusen/ci-python:3.14
env: env:
DB_USER: fabledcurator DB_USER: fabledcurator
DB_PASSWORD: ci_integration DB_PASSWORD: ci_integration
+37
View File
@@ -0,0 +1,37 @@
# 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 — Forgejo registry push)
## Per-job tool installs
- `pip install -r requirements.txt pytest pytest-asyncio` — in `backend-lint-and-test` and `integration` jobs
- `npm install --no-audit --no-fund` — in `frontend-build` job
## Notes
- Integration wall time ~3 min, dominated by pgvector container start + the
`pip install` step (~30-45s on cold cache) + alembic + 300+ integration tests.
- The `pip install` in two jobs is intentional and per `docs/process.md`'s
"add deps to image when used by >1 project" rule: FC alone is one Python
project, so the deps live in `requirements.txt` and install per-job.
Reconsider when a second Fabled-family Python backend lands.
- Integration uses Forgejo Actions `services:` + socket-discovered bridge IPs
because `act_runner` (swarm-runner v0.6+) puts services on the default
bridge with no embedded DNS. The pattern is documented in the rulebook's
`forgejo.md` "CI philosophy" section and FC's `ci.yml` is the canonical
example.
- No `package-lock.json` is tracked yet (FC's `feedback_no_local_runs`
memory bans `npm install` locally). Using `npm install` rather than
`npm ci` until a lockfile lands.
- No `imagemagick` / `pandoc` per-job installs needed.