Files
netris-nestri/.github/workflows/web.yml
Wanjohi f27ea3a132 ci: run each half only when that half changes
Both jobs ran on every pull request, so a change to a Rust binary waited on a
Postgres service and a full TypeScript test run, and a change to a TypeScript
route spent a runner compiling Rust. Neither told anyone anything.

A `paths` filter belongs to a workflow rather than to a job, so the two jobs
become two workflows. That is the whole cost of the change: both job bodies are
carried over unchanged, and only the triggers differ.

The filters are written from what each job actually reads. `packages/` is
entirely TypeScript so it is taken whole, and the two TypeScript apps are named
because the rest of `apps/` is Rust. The Rust job takes its own directory plus
the workspace root and lockfile, which pin every version it builds against, and
nothing else — it depends on no other member of the workspace.

The failure mode of a path filter is silence: a job that does not run leaves a
green pull request. So the one thing a future change has to remember is written
where it will be read — adding a TypeScript app means adding it to that list.
2026-09-06 14:05:37 +03:00

68 lines
2.4 KiB
YAML

# The TypeScript half: the control-plane apps and the packages they share.
#
# Split from the Rust half rather than being two jobs in one workflow, because
# a job cannot carry its own `paths` filter — only a workflow can. Two files is
# what "run this only when its own code changes" costs, and the alternative
# spends a runner on every pull request deciding it has nothing to do.
name: web
on:
push:
branches: [main]
pull_request:
paths:
# Every TypeScript workspace member. `packages/` is entirely TypeScript
# so it is taken whole; `apps/` is mostly Rust, so its two members are
# named. **Adding a TypeScript app means adding it here** — nothing
# detects that on its own, and the failure is silent: the tests do not
# run and the pull request goes green.
- "apps/api/**"
- "apps/auth/**"
- "packages/**"
# The workspace itself. A lockfile change reaches every member, and the
# linter and compiler settings decide whether any of it passes.
- "package.json"
- "bun.lock"
- "tsconfig.json"
- "oxlintrc.json"
# This file. A change to how the tests run is a change worth running.
- ".github/workflows/web.yml"
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:18-alpine
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: nestri
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U postgres"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.11
- name: Install
run: bun install --frozen-lockfile
# Apply the committed migrations rather than `drizzle-kit push`. Two
# reasons: `push` diffs the schema against whatever is in the database and
# is a development tool, whereas CI wants exactly what is in
# `packages/core/migrations`; and `push` under `strict: true` asks for
# confirmation, which on a runner is a hang rather than a failure.
- name: Apply migrations
run: bun run db:migrate
env:
DATABASE_URL: postgres://postgres:postgres@localhost:5432/nestri
- name: Test
run: bun test
env:
TEST_DATABASE_URL: postgres://postgres:postgres@localhost:5432/nestri