Files
CIAgent 1a88ab3199
Release / release (push) Successful in 3m45s
CI / python (push) Successful in 1m52s
CI / node (push) Successful in 1m0s
merge: milestone/v0.8-ship-anywhere -> main (v0.8 complete — Ship Anywhere)
The v0.8 milestone: installable on any Debian-based server via docker
(Gitea registry image, honest sandbox degrade), deb (amd64+arm64,
advisory postinst), and arch-aware binary — with release consistency
enforced by pre-commit hooks + Gitea Actions (3-runner fleet on CT 113,
machine-made releases with the full 8-asset matrix + registry image), the
CLI carrying the full suite (guide, channel-aware doctor), and the admin
runbook (deploy/README.md, evidence-backed recipes).

---ci---
phase: 6
milestone: v0.8
status: complete
requirements:
  covered: [REQ-8-001, REQ-8-002, REQ-8-003, REQ-8-004, REQ-8-005]
  partial: []
---/ci---
2026-09-29 16:04:40 +00:00

131 lines
5.8 KiB
YAML

# Push lanes — every branch, every push (REQ-8-001, D-063).
#
# Two jobs, two runner labels, NEVER wholesale `turbo lint`/`turbo typecheck`
# in the node lane (RESEARCH R-8): those turbo tasks pull in
# @nextcraft/ai-service#lint/typecheck, which hard-fail without the Python
# venv (apps/ai-service/scripts/lint.sh:8, typecheck.sh:13) — a venv that
# does not exist in the node:24-bookworm job container. The node lane runs
# lint/typecheck via `pnpm --filter` over the 5 TS workspaces only; the
# python lane invokes the three ai-service bash scripts directly (no pnpm
# needed in that container at all).
#
# Concurrency: serialize per-ref so a rapid-fire branch push reuses one lane
# instead of stacking jobs on the capacity-1 runners (R-4).
name: CI
on: push
concurrency:
group: ci-${{ gitea.ref }}
cancel-in-progress: true
jobs:
node:
# Fleet label `node` -> container docker.io/library/node:24-bookworm
# (deploy/ci/docker-compose.yaml, R-3 label map).
runs-on: node
steps:
# actions/checkout@v4 downloads from github.com (DEFAULT_ACTIONS_URL
# default). github.com egress is verified reachable from the LAN;
# the CT-local probe is still pending (Wave 1-1 blocked on founder
# deploy-key install). If checkout fails at the first real run, the
# fallback is raw git fetch steps using the automatic job token:
# - run: |
# git init -q .
# git remote add origin "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git"
# git fetch --depth=1 origin "$GITHUB_SHA"
# git checkout FETCH_HEAD
- name: Checkout
uses: actions/checkout@v4
# Optional pnpm store cache (R-12). Depends on the runner cache server
# being reachable from job containers (R-5: cache.host = CT IP + a
# published port — configured in deploy/ci/). If the cache server
# ETIMEDOUTs on first real runs, drop this block (fallback: a
# volume-mounted pnpm store per R-12, or no cache at all — install is
# affordable on the LAN). continue-on-error keeps cache flakiness
# from ever turning the lane red; repeated timeouts = delete.
- name: Cache pnpm store
uses: actions/cache@v4
with:
path: ~/.local/share/pnpm/store
key: pnpm-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
restore-keys: pnpm-${{ runner.os }}-
continue-on-error: true
# pnpm 12.3.4 is pinned by root package.json `packageManager`.
# node:24-bookworm still bundles corepack (24.x retains it, deprecated
# — Node >= 25 dropped it; R-11). Fallback if corepack is absent:
# npm i -g pnpm@12.3.4
- name: Enable pnpm
run: corepack enable pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
# Lint: per-workspace filters over the 5 TS workspaces ONLY — never
# `turbo lint` (see header note).
- name: Lint (TS workspaces)
run: >-
pnpm --filter web --filter @nextcraft/cli --filter @nextcraft/ui
--filter @nextcraft/types --filter @nextcraft/mock-data lint
# Typecheck: same filter set, per-workspace tsc --noEmit.
- name: Typecheck (TS workspaces)
run: >-
pnpm --filter web --filter @nextcraft/cli --filter @nextcraft/ui
--filter @nextcraft/types --filter @nextcraft/mock-data typecheck
- name: Web tests (node:test via tsx)
run: pnpm web:test
# CLI default test script (tsx --test tests/*.test.ts) excludes the
# env-gated E2E (apps/cli/package.json `test:e2e`, CLI_E2E=1) — the
# fresh-clone E2E stays out of job containers per D-063.
- name: CLI tests (node:test via tsx, E2E env-gated out)
run: pnpm cli:test
python:
# Fleet label `python` -> container docker.io/library/python:3.11-bookworm
# (R-3). The three scripts below are self-contained venv-relative bash
# (R-9) — no pnpm, no node, no turbo in this lane.
#
# P1 CI finding: actions/checkout@v4 is a NODE-based action — it cannot
# exec in the python:3.11-bookworm container (exit 127: "node" not in
# $PATH). This lane checks out via raw git steps with the automatic job
# token instead (the R-8 fallback path, promoted to primary here).
runs-on: python
steps:
- name: Checkout (raw git — node actions cannot run in this container)
run: |
git init -q .
git remote add origin "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git"
git fetch --depth=1 origin "$GITHUB_SHA"
git checkout FETCH_HEAD
# NOTE: no actions/cache here — it is a node-based action and this
# container has no node (exit 127; same class as the checkout finding).
# The venv rebuild is ~25s warm — acceptable without cache; pip's own
# HTTP cache is cold but the LAN is fast. Revisit only if the lane
# slows materially (volume-mounted store per R-12, or a pip download
# cache directory via container options).
# bootstrap.sh is idempotent: creates .venv (with the --without-pip +
# get-pip fallback for Debian-without-ensurepip) and pip-installs
# the project with [dev] extras (ruff, mypy, pytest).
- name: Bootstrap ai-service venv
run: bash apps/ai-service/scripts/bootstrap.sh
- name: Lint (ruff)
run: bash apps/ai-service/scripts/lint.sh
- name: Typecheck (mypy, D-058 baseline)
run: bash apps/ai-service/scripts/typecheck.sh
# Fast pytest lane per D-063: -m "not real_server and not userns"
# (scripts/test.sh FAST=1). real_server/userns tiers stay local-only
# — job containers genuinely cannot run them (docker default seccomp
# denies the nested `unshare --user` the backend needs; R-8).
- name: Tests (fast lane)
run: FAST=1 bash apps/ai-service/scripts/test.sh