# Gate every pull request into `main` on a fast, DB-free check suite, so a broken # build or a failing test can't reach the branch that gets released. # # Mirrors RunicGateway/website's pr-checks.yml — this module is two npm packages # shaped like that repo's `server/` and `client/`, and it is loaded into that # repo's process, so it is checked the same way with the same Node version. # # ── What each job is really asking ─────────────────────────────────────────── # # The tests are the ordinary half. The two `check:*` scripts are the interesting # one, because they are the acceptance criteria of the module contract itself # (docs/website/MODULE_API.md Part 5) rather than of this module's behaviour: # # • `server: check:imports` — no relative path escapes the module root, and no # shipped file resolves a bare specifier. A module that reaches into core's # tree works right up until core moves a file, and the whole boundary is # worth exactly as much as this check is (§5.1). # # • `client: check:externals` — the BUILT chunk has no bare imports left. That # failure is invisible in source: `import { useState } from 'react'` is # correct in every file, and whether it becomes core's React or a bare # specifier no browser can resolve is decided by vite.config.js. It has to # be asked of the artifact, so it runs after the build. (The other half — # a shared dependency being BUNDLED — fails the build itself, from a # resolution-time guard inside vite.config.js.) # # Building the chunk in CI is not only a check: it is how the chunk that ships is # produced, since an operator never builds (MODULE_SYSTEM.md §1.14). # # Not here yet, deliberately, because there is nothing for them to act on until # the extraction is further along: the release workflow (the # `module-uo-.tar.gz` artifact and its sha256 manifest) and the module's # own frozen route manifest, which needs core checked out at a pinned ref # (MODULE_API.md §5.3). Each lands with the slice it checks. # # Enforcement (one-time, in the Gitea UI): # Repository Settings → Branches → Branch Protection (rule for `main`) # • Enable Status Check # • Status check patterns: PR Checks / * # Note: Gitea only lists a context in its dropdown after it has reported once, # so let this workflow run on one PR first. The `PR Checks / *` glob matches # without needing the dropdown, and keeps matching as jobs are added. # # Runner: the shared self-hosted `ubuntu-latest` runner. These jobs need only # Node — no Docker socket, no database. name: PR Checks on: pull_request: branches: [main] # A newer push to the same PR cancels the in-flight run. concurrency: group: pr-checks-${{ github.ref }} cancel-in-progress: true jobs: server-tests: runs-on: ubuntu-latest timeout-minutes: 20 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 cache: npm cache-dependency-path: server/package-lock.json # `npm ci` rather than `npm install`: it also proves the lockfile is in # sync with package.json instead of silently updating it. - name: Install server deps run: npm ci --prefix server - name: Run server tests run: npm test --prefix server - name: Check the module boundary (MODULE_API.md §5.1) run: npm run check:imports --prefix server client-build: runs-on: ubuntu-latest timeout-minutes: 20 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 cache: npm cache-dependency-path: client/package-lock.json - name: Install client deps run: npm ci --prefix client - name: Run client tests run: npm test --prefix client - name: Build the client chunk run: npm run build --prefix client - name: Check the built chunk's externals (MODULE_API.md §3.6) run: npm run check:externals --prefix client