ci: consume shared ci-python:3.14 image; bump runtime to 3.14
Migrate to the FabledRulebook CI-Runner contract: - .forgejo/workflows/ci.yml: all four jobs (typecheck/lint/test/build) now schedule on the `python-ci` runner label and run inside container.image: git.fabledsword.com/bvandeusen/ci-python:3.14 (Python 3.14 + Node 24 + ruff + uv + Docker CLI). Dropped the inline uv install in the test job — uv is now baked into the image. - Dockerfile: production runtime bumped to python:3.14-slim so test results stay representative against what we ship. - ci-requirements.md: new file at repo root declaring image deps and per-job installs (per FabledRulebook ci-runners.md). - infra/Dockerfile.runner-base: deleted. The in-repo runner base (Ubuntu 24.04 + Python 3.12 + Node 22) is superseded by the shared ci-python image. The runner-host deployment files (runner-compose.yml + act-runner-config.yml) stay as deployment-shape documentation; source of truth is the deployed config. - docs/development.md: CI/CD + Runner sections refreshed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -64,7 +64,9 @@ jobs:
|
|||||||
name: TypeScript typecheck
|
name: TypeScript typecheck
|
||||||
# Skip on main merge-commit pushes — see workflow header comment.
|
# Skip on main merge-commit pushes — see workflow header comment.
|
||||||
if: github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/v')
|
if: github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/v')
|
||||||
runs-on: ci-runner
|
runs-on: python-ci
|
||||||
|
container:
|
||||||
|
image: git.fabledsword.com/bvandeusen/ci-python:3.14
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
@@ -86,11 +88,13 @@ jobs:
|
|||||||
lint:
|
lint:
|
||||||
name: Python lint
|
name: Python lint
|
||||||
if: github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/v')
|
if: github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/v')
|
||||||
runs-on: ci-runner
|
runs-on: python-ci
|
||||||
|
container:
|
||||||
|
image: git.fabledsword.com/bvandeusen/ci-python:3.14
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
# ruff is pre-installed in the ci-runner base image — no install
|
# ruff is pre-installed in the ci-python image — no install
|
||||||
# step needed, lint runs in ~2s.
|
# step needed, lint runs in ~2s.
|
||||||
- name: Lint
|
- name: Lint
|
||||||
run: ruff check src/
|
run: ruff check src/
|
||||||
@@ -98,7 +102,9 @@ jobs:
|
|||||||
test:
|
test:
|
||||||
name: Python tests
|
name: Python tests
|
||||||
if: github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/v')
|
if: github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/v')
|
||||||
runs-on: ci-runner
|
runs-on: python-ci
|
||||||
|
container:
|
||||||
|
image: git.fabledsword.com/bvandeusen/ci-python:3.14
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
@@ -132,7 +138,9 @@ jobs:
|
|||||||
# pushes skip here too, so no production image is ever built from a
|
# pushes skip here too, so no production image is ever built from a
|
||||||
# raw main push (only from the v* tag the release creates).
|
# raw main push (only from the v* tag the release creates).
|
||||||
if: github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/v')
|
if: github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/v')
|
||||||
runs-on: ci-runner
|
runs-on: python-ci
|
||||||
|
container:
|
||||||
|
image: git.fabledsword.com/bvandeusen/ci-python:3.14
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
|
|||||||
+2
-1
@@ -8,7 +8,8 @@ COPY frontend/ .
|
|||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
# Stage 2: Python runtime
|
# Stage 2: Python runtime
|
||||||
FROM python:3.12-slim AS runtime
|
# Tracks CI image (ci-python:3.14) so test results stay representative.
|
||||||
|
FROM python:3.14-slim AS runtime
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY pyproject.toml .
|
COPY pyproject.toml .
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# CI Requirements — FabledScribe
|
||||||
|
|
||||||
|
> Spec lives in [`docs/process.md`](https://git.fabledsword.com/bvandeusen/CI-runner/src/branch/main/docs/process.md)
|
||||||
|
> in the CI-Runner repo.
|
||||||
|
|
||||||
|
## Runtime image
|
||||||
|
|
||||||
|
```
|
||||||
|
git.fabledsword.com/bvandeusen/ci-python:3.14
|
||||||
|
```
|
||||||
|
|
||||||
|
Used by all four jobs in `.forgejo/workflows/ci.yml`: typecheck (Vue/TS),
|
||||||
|
lint (ruff), test (pytest), build (docker buildx).
|
||||||
|
|
||||||
|
## Image deps used
|
||||||
|
|
||||||
|
- python 3.14
|
||||||
|
- node 24 (used for `npm ci` + `vue-tsc` in the typecheck job, and as the
|
||||||
|
frontend builder stage inside the production `Dockerfile`)
|
||||||
|
- ruff (lint job runs `ruff check src/` with zero install overhead)
|
||||||
|
- docker CLI + buildx (build job pushes the production image to the
|
||||||
|
Forgejo registry)
|
||||||
|
|
||||||
|
## Per-job tool installs
|
||||||
|
|
||||||
|
Anything CI installs at job time that isn't in the image. Promotion
|
||||||
|
candidates if more than one project needs them.
|
||||||
|
|
||||||
|
- `uv` — installed inline in the test job (`curl -LsSf
|
||||||
|
https://astral.sh/uv/install.sh | sh`). **Temporary**: belongs in the
|
||||||
|
ci-python image so every consumer doesn't re-install on cold start.
|
||||||
|
Tracked at [CI-Runner](https://git.fabledsword.com/bvandeusen/CI-runner).
|
||||||
|
- `http-ece` is `--no-build-isolation`-installed before the editable
|
||||||
|
package install because http-ece doesn't declare `setuptools` as a
|
||||||
|
build dep and uv creates bare venvs without it. Not promotion-worthy
|
||||||
|
(one project, one wheel).
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Production runtime image (`Dockerfile`) also tracks Python 3.14 — the
|
||||||
|
CI image and runtime image stay aligned by design so test results are
|
||||||
|
representative.
|
||||||
|
- Build wall time: dominated by `pytest` (full async test suite). Cold
|
||||||
|
ci-python pulls add ~30s; not a blocker.
|
||||||
|
- Registry-backed BuildKit layer cache (`type=registry,ref=…:cache,mode=max`)
|
||||||
|
gives ~80% speedup on warm builds — see the build job comment.
|
||||||
|
- `pyproject.toml` keeps `requires-python = ">=3.12"` permissive so the
|
||||||
|
package can still be installed against older interpreters by external
|
||||||
|
consumers, but the CI/runtime target is 3.14.
|
||||||
+12
-6
@@ -57,7 +57,9 @@ Migration conventions:
|
|||||||
|
|
||||||
### Pipeline
|
### Pipeline
|
||||||
|
|
||||||
CI runs on Forgejo Actions with a custom runner base image (`py3.12-node22`):
|
CI runs on Forgejo Actions, consuming the shared
|
||||||
|
[`ci-python:3.14`](https://git.fabledsword.com/bvandeusen/CI-runner) image
|
||||||
|
via `container.image` (Python 3.14 + Node 24 + ruff + uv + Docker CLI):
|
||||||
|
|
||||||
| Trigger | Jobs | Docker tags pushed |
|
| Trigger | Jobs | Docker tags pushed |
|
||||||
|---------|------|--------------------|
|
|---------|------|--------------------|
|
||||||
@@ -77,13 +79,17 @@ CI runs on Forgejo Actions with a custom runner base image (`py3.12-node22`):
|
|||||||
git checkout dev && git merge main && git push origin dev
|
git checkout dev && git merge main && git push origin dev
|
||||||
```
|
```
|
||||||
|
|
||||||
### Custom Runner
|
### Runner
|
||||||
|
|
||||||
Runner base image: `infra/Dockerfile.runner-base` (Ubuntu 24.04 + Python 3.12 + Node 22 LTS).
|
CI jobs schedule against the `python-ci` runner label and run inside the
|
||||||
Runner config: `infra/act-runner-config.yml` (label: `py3.12-node22`).
|
shared `git.fabledsword.com/bvandeusen/ci-python:3.14` image (see
|
||||||
Runner compose: `infra/runner-compose.yml`.
|
`ci-requirements.md` for what this project relies on from the image).
|
||||||
|
The runner deployment lives outside this repo; image bumps happen in
|
||||||
|
[CI-Runner](https://git.fabledsword.com/bvandeusen/CI-runner) via Renovate.
|
||||||
|
|
||||||
To activate a new runner registration, copy `infra/act-runner-config.yml` to the runner's config directory, delete the `.runner` registration file in the runner container, and restart the stack.
|
`infra/runner-compose.yml` + `infra/act-runner-config.yml` document the
|
||||||
|
runner-host deployment shape; the source of truth is the deployed
|
||||||
|
config on the runner host.
|
||||||
|
|
||||||
### Docker Registry
|
### Docker Registry
|
||||||
|
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
# Runner base image for Forgejo act_runner job containers.
|
|
||||||
# Pre-installs Python 3.12, Node 22, uv, and ruff so workflows skip
|
|
||||||
# lengthy runtime installs on every run.
|
|
||||||
#
|
|
||||||
# Build and push (re-run when this file changes):
|
|
||||||
# docker build -f infra/Dockerfile.runner-base \
|
|
||||||
# -t git.fabledsword.com/bvandeusen/runner-base:ci-runner .
|
|
||||||
# docker push git.fabledsword.com/bvandeusen/runner-base:ci-runner
|
|
||||||
#
|
|
||||||
# Then redeploy the act_runner stack in Portainer to pick up the new image.
|
|
||||||
|
|
||||||
FROM ubuntu:24.04
|
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
|
||||||
ENV TZ=UTC
|
|
||||||
|
|
||||||
# Split into separate RUN steps so each pushed layer is smaller — one
|
|
||||||
# combined layer exceeds the nginx upload timeout on the self-hosted
|
|
||||||
# Forgejo registry.
|
|
||||||
|
|
||||||
# Python 3.12 (ships in Ubuntu 24.04 main repos) + core tools
|
|
||||||
RUN apt-get update -qq && \
|
|
||||||
apt-get install -y -qq \
|
|
||||||
python3.12 python3.12-dev python3.12-venv \
|
|
||||||
git curl ca-certificates gnupg jq tzdata && \
|
|
||||||
apt-get clean && rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Node 22 LTS via NodeSource
|
|
||||||
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \
|
|
||||||
apt-get install -y -qq nodejs && \
|
|
||||||
apt-get clean && rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Docker CLI — daemon comes from the host socket mount, only CLI needed.
|
|
||||||
# docker.io from Ubuntu repos is sufficient for docker login + buildx.
|
|
||||||
RUN apt-get update -qq && \
|
|
||||||
apt-get install -y -qq docker.io && \
|
|
||||||
apt-get clean && rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# uv — fast Python package installer/resolver (~10x faster than pip).
|
|
||||||
# Used by test jobs instead of pip for venv creation + dep installs.
|
|
||||||
RUN curl -LsSf https://astral.sh/uv/install.sh | env INSTALLER_NO_MODIFY_PATH=1 sh && \
|
|
||||||
mv /root/.local/bin/uv /usr/local/bin/ && \
|
|
||||||
mv /root/.local/bin/uvx /usr/local/bin/
|
|
||||||
|
|
||||||
# ruff — Python linter. Baked in so the lint job is just
|
|
||||||
# `ruff check src/` with zero install overhead.
|
|
||||||
RUN curl -LsSf https://astral.sh/ruff/install.sh | env INSTALLER_NO_MODIFY_PATH=1 sh && \
|
|
||||||
mv /root/.local/bin/ruff /usr/local/bin/
|
|
||||||
Reference in New Issue
Block a user