mirror of
https://github.com/willchen96/mike.git
synced 2026-07-24 23:41:04 +02:00
PR #233's CI failed with "npm ci can only install with an existing package-lock.json" even though the file existed: a "Merge branch 'main'" commit had auto-merged backend/package.json and package-lock.json into invalid JSON with no conflict raised, and npm reports an unparseable lockfile as if it were missing. Two guards: .gitattributes marks package-lock.json/bun.lock merge=binary so concurrent lockfile changes surface as explicit conflicts (resolve by regenerating, never hand-merging), and CI parse-checks package.json and the lockfile before npm ci so any corruption that still lands fails with the real reason. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
112 lines
4 KiB
YAML
112 lines
4 KiB
YAML
# CI: build and test.
|
|
#
|
|
# Adapted from the amal66/mike fork's .github/workflows/ci.yml (monorepo
|
|
# layout) to this repository's backend/ + frontend/ layout. Test steps use
|
|
# `npm test --if-present`, and the eval job checks for evals/run.mjs, so this
|
|
# workflow is safe to merge before or after the test-harness and evals PRs:
|
|
# on a tree without those pieces the test steps no-op and the build still
|
|
# gates the merge. Beyond the fork version this also builds the frontend
|
|
# (placeholder NEXT_PUBLIC_* env — verified sufficient for `next build`) and
|
|
# runs eslint as a blocking gate (the error backlog is at zero).
|
|
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
|
|
jobs:
|
|
backend:
|
|
name: Backend build and tests
|
|
runs-on: ubuntu-latest
|
|
defaults:
|
|
run:
|
|
working-directory: backend
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 22
|
|
cache: npm
|
|
cache-dependency-path: backend/package-lock.json
|
|
|
|
# Git's line-level merge can splice both sides of package(-lock).json
|
|
# into invalid JSON without a conflict (bit PR #233). npm's own error
|
|
# for an unparseable lockfile is the misleading "npm ci can only
|
|
# install with an existing package-lock.json" — fail fast with the real
|
|
# reason instead.
|
|
- name: Validate package.json and lockfile parse
|
|
run: node -e "for (const f of ['package.json','package-lock.json']) JSON.parse(require('fs').readFileSync(f, 'utf8'))"
|
|
|
|
- run: npm ci
|
|
|
|
# No-ops on a tree without a "test" script (e.g. before the vitest
|
|
# harness PR merges); runs the suite once it exists.
|
|
- run: npm test --if-present
|
|
|
|
- run: npm run build
|
|
|
|
frontend:
|
|
name: Frontend build and tests
|
|
runs-on: ubuntu-latest
|
|
defaults:
|
|
run:
|
|
working-directory: frontend
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 22
|
|
cache: npm
|
|
cache-dependency-path: frontend/package-lock.json
|
|
|
|
# Same silent-merge-corruption guard as the backend job.
|
|
- name: Validate package.json and lockfile parse
|
|
run: node -e "for (const f of ['package.json','package-lock.json']) JSON.parse(require('fs').readFileSync(f, 'utf8'))"
|
|
|
|
- run: npm ci
|
|
|
|
# No-ops on a tree without a "test" script (e.g. before the vitest
|
|
# harness PR merges); runs the suite once it exists.
|
|
- run: npm test --if-present
|
|
|
|
# Blocking gate: the eslint error backlog was burned down in this PR
|
|
# (0 errors; warnings do not fail the step), so any new error fails CI.
|
|
- run: npm run lint
|
|
|
|
# Production build. NEXT_PUBLIC_* values are inlined at build time and
|
|
# only need to be well-formed here — nothing is contacted during build.
|
|
# This catches type errors (next build runs tsc) and broken routes/imports.
|
|
- run: npm run build
|
|
env:
|
|
NEXT_PUBLIC_SUPABASE_URL: https://placeholder.supabase.co
|
|
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY: sb_publishable_placeholder
|
|
NEXT_PUBLIC_API_BASE_URL: http://localhost:3001
|
|
|
|
# -----------------------------------------------------------------------
|
|
# Offline eval harness: deterministic scorecard for citation accuracy,
|
|
# prompt-injection resistance, and privilege/PII leakage. Runs against
|
|
# committed fixtures (no network, no LLM calls, no secrets), so it is cheap
|
|
# enough to gate every PR. --threshold 1.0 = every case must pass.
|
|
# Skips gracefully until the evals PR merges.
|
|
# -----------------------------------------------------------------------
|
|
evals:
|
|
name: Eval harness
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 22
|
|
|
|
- name: Run eval harness (skips if evals/ not present)
|
|
run: |
|
|
if [ -f evals/run.mjs ]; then
|
|
node evals/run.mjs --threshold 1.0
|
|
else
|
|
echo "evals/run.mjs not present on this tree; skipping"
|
|
fi
|