Files
TREK/.github/workflows/test.yml
T

297 lines
9.0 KiB
YAML

name: Tests
permissions:
contents: read
on:
pull_request:
branches: [main, dev]
paths:
- 'server/**'
- 'client/**'
- 'shared/**'
- 'nest-mcp/**'
- 'plugin-sdk/**'
- '.github/workflows/test.yml'
jobs:
plugin-facts:
name: Plugin Permission Facts
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- name: Install dependencies
run: npm ci --workspace server
# The plugin permission facts live once, in
# server/src/nest/plugins/protocol/envelope.ts. Every other copy - the SDK's
# generated/host-facts.ts and shared's plugin-permissions.ts - is generated from it
# and checked in, because publish-plugin-sdk builds from a standalone checkout with
# no server present. This fails the PR if a copy drifts, if a new permission has no
# admin.plugins.perm.* translation, or if the CLI has no hint for it.
- name: Check the generated plugin facts are in sync
run: cd server && npm run check:plugin-facts
i18n-parity:
name: i18n Key Parity
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24
- name: Check i18n key parity
run: node shared/scripts/i18n-parity.mjs --strict
shared-contracts:
name: Shared Contracts (Zod)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24
cache: npm
cache-dependency-path: package-lock.json
- name: Install dependencies
run: npm ci --workspace shared
- name: Typecheck
run: cd shared && npm run typecheck
- name: Run tests
run: cd shared && npm test
nest-mcp-package:
name: nest-mcp Package
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24
cache: npm
cache-dependency-path: package-lock.json
- name: Install dependencies
run: npm ci --workspace nest-mcp
- name: Ensure @swc/core's Linux binary for unplugin-swc
# Same lockfile quirk as server-tests: the Linux native binary is
# omitted, and nest-mcp's vitest config uses the SWC transform too.
run: |
SWC_VERSION=$(node -p "require('@swc/core/package.json').version")
npm install --no-save --legacy-peer-deps "@swc/core-linux-x64-gnu@$SWC_VERSION"
- name: Build
run: npm run build --workspace=nest-mcp
- name: Typecheck
run: cd nest-mcp && npm run typecheck
- name: Lint
run: cd nest-mcp && npm run lint:check
- name: Run tests
run: cd nest-mcp && npm test
server-tests:
name: Server Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24
cache: npm
cache-dependency-path: package-lock.json
- name: Install dependencies
run: npm ci
- name: Ensure @swc/core's Linux binary for unplugin-swc
# The lockfile was generated on Windows and omits @swc/core's Linux
# optional native binary, so npm ci/install skips it on the runner.
# Install the matching version explicitly so the server's SWC transform
# (server/vitest.config.ts) can load.
run: |
SWC_VERSION=$(node -p "require('@swc/core/package.json').version")
npm install --no-save --legacy-peer-deps "@swc/core-linux-x64-gnu@$SWC_VERSION"
- name: Build shared
run: npm run build --workspace=shared
- name: Build nest-mcp
# Server typecheck/build resolve @trek/nest-mcp's types from its dist
# (tests alias the package source, but tsc does not).
run: npm run build --workspace=nest-mcp
- name: Build server (tsc -> dist)
run: cd server && npm run build
- name: Smoke production require chain
# Vitest aliases @trek/nest-mcp to its source, so only this exercises
# what production runs: nest-mcp's built dist resolving the MCP SDK's
# subpath exports through the tsconfig-paths/register runtime hook.
run: cd server && node --require tsconfig-paths/register -e "require('@trek/nest-mcp')"
- name: Typecheck
run: cd server && npm run typecheck
- name: Typecheck tests
# tests/ is outside the build tsconfig, so a service that grows a
# constructor parameter does not break its hand-wired call sites at
# compile time: the argument arrives as undefined and throws at runtime,
# if anything reads it at all. This is the step that catches it.
run: cd server && npm run typecheck:tests
- name: Lint
run: cd server && npm run lint:check
- name: Run tests
run: cd server && npm run test:coverage
- name: Upload coverage
if: success()
uses: actions/upload-artifact@v6
with:
name: backend-coverage
path: server/coverage/
retention-days: 7
s3-contract:
name: S3 Driver Contract (MinIO)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24
cache: npm
cache-dependency-path: package-lock.json
- name: Install dependencies
run: npm ci
- name: Ensure @swc/core's Linux binary for unplugin-swc
# The lockfile was generated on Windows and omits @swc/core's Linux
# optional native binary, so npm ci/install skips it on the runner.
# Install the matching version explicitly so the server's SWC transform
# (server/vitest.config.ts) can load.
run: |
SWC_VERSION=$(node -p "require('@swc/core/package.json').version")
npm install --no-save --legacy-peer-deps "@swc/core-linux-x64-gnu@$SWC_VERSION"
- name: Build shared
run: npm run build --workspace=shared
- name: Start MinIO
# `services:` can't pass the `server /data` command to minio/minio, so
# the container starts via docker run. Tag pinned — quay.io is the
# maintained registry (Docker Hub minio/minio is archived). 127.0.0.1
# endpoint is load-bearing: aws-lite picks path-style only for IP/localhost
# hosts, which is all stock MinIO speaks.
run: |
docker run -d --name minio -p 127.0.0.1:9000:9000 \
-e MINIO_ROOT_USER=trekci -e MINIO_ROOT_PASSWORD=trekci-secret \
quay.io/minio/minio:RELEASE.2025-09-07T16-13-09Z.hotfix.7aa24e772 server /data
- name: Wait for MinIO
# curl was removed from the MinIO image — poll from the runner instead.
run: |
for i in $(seq 1 30); do
curl -sf http://127.0.0.1:9000/minio/health/live && exit 0
sleep 1
done
echo "MinIO never became healthy" >&2
docker logs minio >&2
exit 1
- name: Run the S3 driver contract suite
env:
TREK_TEST_S3_ENDPOINT: http://127.0.0.1:9000
TREK_TEST_S3_BUCKET: trek-test
TREK_TEST_S3_ACCESS_KEY_ID: trekci
TREK_TEST_S3_SECRET_ACCESS_KEY: trekci-secret
run: cd server && npx vitest run tests/unit/nest/storage/s3.driver.contract.test.ts
client-quality:
# Split out of client-tests: the suite takes ~11 minutes, and having the
# gates in front of it meant a single lint finding threw away the whole test
# signal for that run. Both jobs pay the install/build, which is cheap next
# to running the two in series.
name: Client Types & Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24
cache: npm
cache-dependency-path: package-lock.json
- name: Install dependencies
run: npm ci --workspace shared && npm ci --workspace client
- name: Build shared
run: npm run build --workspace=shared
- name: Typecheck
run: cd client && npm run typecheck
- name: Lint
run: cd client && npm run lint:check
- name: Page pattern check
run: cd client && npm run lint:pages
client-tests:
name: Client Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24
cache: npm
cache-dependency-path: package-lock.json
- name: Install dependencies
run: npm ci --workspace shared && npm ci --workspace client
- name: Build shared
run: npm run build --workspace=shared
- name: Run tests
run: cd client && npm run test:coverage
- name: Upload coverage
if: success()
uses: actions/upload-artifact@v6
with:
name: frontend-coverage
path: client/coverage/
retention-days: 7