Merge pull request 'ci: register the phase-4 gate - backend + frontend jobs, one dispatched green run on main opens the code phase (researchx#24)' (#25) from po/phase4-ci-gate into main

Reviewed-on: #25
This commit was merged in pull request #25.
This commit is contained in:
2026-10-26 23:18:24 +00:00
+128
View File
@@ -0,0 +1,128 @@
# .gitea/workflows/ci.yml - ResearchX phase-4 CI gate (researchx#24).
#
# This file IS the gate. The pre-code clause (coreci/company#105, c14057):
# a code phase opens only when the product repo's gating workflow file has
# dispatched at least one run on `main` and every job in that file is green
# in that run. Until this file exists, coreci/researchx has no workflow and
# no run at all - that is the case the clause was amended for (researchx#24,
# c14093). A half-green pipeline does not open the phase either.
#
# Two jobs:
# 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.
#
# 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.
#
# 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
# (merge = approval, constitution v1.3).
name: ci
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
jobs:
backend:
name: backend (uv, Python 3.12: ruff/mypy/pytest)
runs-on: employee-runner
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies (uv, from the committed lockfile)
working-directory: backend
run: uv sync --frozen
- name: Lint (ruff)
working-directory: backend
run: uv run ruff check src tests
- name: Typecheck (mypy)
working-directory: backend
run: uv run mypy src
- name: Test (pytest)
working-directory: backend
run: uv run pytest
frontend:
name: frontend (Next.js on pnpm: typecheck/lint/test/build)
runs-on: employee-runner
timeout-minutes: 25
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node 22
uses: actions/setup-node@v4
with:
node-version: "22"
- name: Setup Python 3.12 (for the real-stack e2e bridge)
uses: actions/setup-python@v5
with:
python-version: "3.12"
- 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
- name: Install dependencies (from the committed lockfile)
working-directory: frontend
run: pnpm install --frozen-lockfile
# frontend/src/lib/api/e2e-real-stack.test.ts drives the real FastAPI
# stack: it spawns `uv run python -m researchx.api.dev_bridge` from
# ../backend (loopback :8000, fakes only, zero API keys). Without a
# synced backend venv that test cannot come up, so the lane provisions
# it. Provisioning only - the backend gates stay in the backend job.
- name: Backend venv for the real-stack e2e bridge
working-directory: backend
run: uv sync --frozen
- name: Typecheck
working-directory: frontend
run: pnpm typecheck
- name: Lint
working-directory: frontend
run: pnpm lint
- name: Test
working-directory: frontend
run: pnpm test
- name: Build
working-directory: frontend
env:
NEXT_TELEMETRY_DISABLED: "1"
run: pnpm build