diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index a1a3566..8ccbed7 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -11,38 +11,47 @@ # backend - uv + Python 3.12: ruff, mypy, pytest # frontend - Node 22 + pnpm 12.6.0: typecheck, lint, test, build # -# Runner label: `employee-runner`, named by coreci-sre on researchx#24 -# (comment 14316): "runner label for uv+pnpm is employee-runner ... any -# employee label carries the fleet toolchain". The shared `ubuntu-latest` -# pool is deliberately not used: the toolchain (uv + pnpm 12.6.0) must come -# from ONE image, and a split across images is how a first fire comes back -# red on toolchain instead of on code. +# Runner label: `ubuntu-latest` - the org CI fleet's published label whose +# image is docker.gitea.com/runner-images:ubuntu-latest (label map read at +# source: coreci/nextcraft deploy/ci/docker-compose.yaml + deploy/ci/README.md, +# R-3). The previous string `employee-runner` was a fleet NAME, not a label: +# the employee fleet's labels are `employee-py` and `employee-coder` (read +# from a live job log of this seat's own home), and the CI fleet's are node / +# ubuntu-latest / python / release - no runner carried the old label, so a +# merged file asking for it could still buy no run. # -# The commands are the repo's own documented gates (README "Monorepo -# command map"): backend `uv run ruff check src tests`, `uv run mypy src`, -# `uv run pytest`; frontend `pnpm typecheck`, `pnpm lint`, `pnpm test`, -# `pnpm build`. The frontend lane mirrors the release image's own recipe -# (frontend/Dockerfile: node:22-alpine, corepack, pnpm install -# --frozen-lockfile, pnpm build), so the gate tests what the product ships. +# Toolchain: measured, not assumed. From the runner's own logs (job 56393, +# coreci/nova-platform, 2026-10-26T23:17Z, and job 57005, coreci/inboxos-v1, +# 2026-10-27T03:01Z): the image carries python 3.12.3, pip, git, node (the +# actions run in it), pypi REACHABLE and github REACHABLE; actions/checkout@v4, +# actions/setup-python@v5 and actions/setup-go@v5 all run inside it. It does +# NOT carry uv or pnpm, so this file installs them: uv from pypi (pip), pnpm +# 12.6.0 through corepack - the repo's own documented way (README command map). +# The gates are the repo's documented commands: backend `uv run ruff check src +# tests`, `uv run mypy src`, `uv run pytest`; frontend `pnpm typecheck`, +# `pnpm lint`, `pnpm test`, `pnpm build`. The frontend lane mirrors the +# release image's own recipe (frontend/Dockerfile: node:22-alpine, corepack, +# pnpm install --frozen-lockfile, pnpm build), so the gate tests what the +# product ships. # # Owner of a red leg (the clause asks for the owner of the fix next to the # owner of the product line): toolchain / image / dispatch problems -> -# coreci-sre (employee-runner-fleet); product-line problems -> -# coreci-researchx-po. Approval for this file rides the merge request +# coreci-sre (employee-runner-fleet + gitea-instance); product-line problems +# -> coreci-researchx-po. Approval for this file rides the merge request # (merge = approval, constitution v1.3). name: ci on: push: - branches: ["main"] pull_request: branches: ["main"] + workflow_dispatch: {} jobs: backend: name: backend (uv, Python 3.12: ruff/mypy/pytest) - runs-on: employee-runner + runs-on: ubuntu-latest timeout-minutes: 20 steps: - name: Checkout @@ -53,6 +62,15 @@ jobs: with: python-version: "3.12" + # uv is not in the CI image; pypi is reachable from it (measured). The + # install is a toolchain leg, not a product gate: the gates still run + # from the repo's own committed lockfile (backend/uv.lock). + - name: Install uv (from pypi) + run: | + set -eu + python -m pip install --upgrade uv + uv --version + - name: Install dependencies (uv, from the committed lockfile) working-directory: backend run: uv sync --frozen @@ -71,12 +89,13 @@ jobs: frontend: name: frontend (Next.js on pnpm: typecheck/lint/test/build) - runs-on: employee-runner + runs-on: ubuntu-latest timeout-minutes: 25 steps: - name: Checkout uses: actions/checkout@v4 + # Node 22 to mirror the release image (frontend/Dockerfile: node:22). - name: Setup Node 22 uses: actions/setup-node@v4 with: @@ -87,14 +106,24 @@ jobs: with: python-version: "3.12" + - name: Install uv (from pypi) + run: | + set -eu + python -m pip install --upgrade uv + + # pnpm 12.6.0 is pinned by frontend/package.json `packageManager`; + # corepack reads it from there. If the image carries no corepack, npm + # installs the same pinned version. - name: pnpm 12.6.0 (corepack, pinned by frontend/package.json) working-directory: frontend run: | set -eu - # `corepack enable` exits EEXIST when the image already ships a pnpm - # shim; the shim below still resolves the pinned version. - corepack enable pnpm || true - pnpm --version + node --version + corepack enable pnpm 2>/dev/null || true + if ! pnpm --version >/dev/null 2>&1; then + npm i -g pnpm@12.6.0 + fi + test "$(pnpm --version)" = "12.6.0" - name: Install dependencies (from the committed lockfile) working-directory: frontend