Skip to content

Merge pull request #14 from jakesterns/feat-local-testing #24

Merge pull request #14 from jakesterns/feat-local-testing

Merge pull request #14 from jakesterns/feat-local-testing #24

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
# ── MVP release gate ─────────────────────────────────────────────────────────
#
# Single authoritative job: sets up Node + Python, then invokes the canonical
# cross-platform release gate script exactly as a local developer would.
#
# Local: node scripts/release-gate.js (or make release-gate / pnpm run release:gate)
# CI: node scripts/release-gate.js (same script, same steps, same exit codes)
#
# The script runs six steps sequentially and exits non-zero on the first
# failure, matching local failure semantics exactly:
# [1/6] pnpm install --frozen-lockfile
# [2/6] pnpm run build
# [3/6] pnpm run typecheck
# [4/6] pnpm run coverage (web lines>=22%, node lines>=55% -- vitest thresholds)
# [5/6] pip install (Python API dependencies)
# [6/6] python -m pytest (API tests + >=64% -- pytest --cov-fail-under)
#
# Coverage artifacts are uploaded after the gate runs. The `if: always()`
# flag on upload steps ensures artifacts are preserved even when the gate
# fails part-way through (e.g. a coverage threshold miss still produces
# the coverage report for inspection).
#
# Branch protection: require this job to pass before merging to main.
release-gate:
name: MVP release gate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# ── Runtime setup ──────────────────────────────────────────────────────
# Node + pnpm are required by the script for JS/TS steps [1–4].
# Python is required for API steps [5–6].
# Both must be available before the script runs.
- name: Set up pnpm
uses: pnpm/action-setup@v4
# version is read from packageManager field in package.json (pnpm@9.15.0)
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
# ── Canonical release gate ─────────────────────────────────────────────
# This is the single source of truth. No inline gate logic in YAML.
- name: Run release gate
run: node scripts/release-gate.js
# ── Wiring verification ────────────────────────────────────────────────
# Confirms that local developer entrypoints (make, pnpm) still delegate
# to the same script CI just ran. Fails loudly if either drifts to an
# inline command that could silently drop steps (e.g. omit the Python API).
- name: Verify local entrypoint wiring
run: |
grep -q '"release:gate": "node scripts/release-gate.js"' package.json || \
(echo "ERROR: pnpm release:gate does not delegate to scripts/release-gate.js" && exit 1)
grep -q 'node scripts/release-gate.js' Makefile || \
(echo "ERROR: make release-gate does not delegate to scripts/release-gate.js" && exit 1)
echo "✓ pnpm release:gate -> scripts/release-gate.js"
echo "✓ make release-gate -> scripts/release-gate.js"
echo "All entrypoints unified. Repo is in MVP release-candidate shape."
# ── Coverage artifacts ─────────────────────────────────────────────────
# Generated by step [4/6] (pnpm run coverage) and [6/6] (python -m pytest).
# Uploaded with if: always() so they are preserved for inspection even
# when the gate fails — a threshold miss is most useful when you can see
# the actual coverage numbers.
- name: Upload web coverage
uses: actions/upload-artifact@v4
if: always()
with:
name: web-coverage
path: apps/web/coverage/
if-no-files-found: warn
- name: Upload node coverage
uses: actions/upload-artifact@v4
if: always()
with:
name: node-coverage
path: apps/node/coverage/
if-no-files-found: warn
- name: Upload API coverage
uses: actions/upload-artifact@v4
if: always()
with:
name: api-coverage
path: apps/api/coverage.xml
if-no-files-found: warn