# 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. # # ── Package guard ──────────────────────────────────────────────────────────── # This repo is in the planning phase and has no module code yet: the API contract # is settled in Phase 1 and Phase 3 is what extracts the UO half of `website/` # into this repo (docs/website/MODULE_SYSTEM.md §2.7). Rather than leave the repo # ungated until then — or land a workflow that red-Xes every governance/docs PR — # each half's gates are conditional on its package.json existing. Before the code # lands, the job reports green with a notice saying so. The moment a package.json # appears the gates arm themselves; nothing here has to change. # # The same trick guards the client build, which is the higher-risk half: it must # build with Vite in library mode with react/react-dom/react-router-dom EXTERNAL, # because there is exactly one React instance in the page and core owns it. A # module that bundles its own React loads and then breaks hooks at runtime, which # is precisely the kind of failure worth catching before merge. # # Not here yet, deliberately, because there is nothing for them to act on until # Phase 3: a release workflow (the `module-uo-.tar.gz` artifact and its # sha256 manifest), the zero-internal-imports check, and the module's own frozen # route manifest. Each lands with the code 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 - name: Detect whether the server half exists yet id: detect run: | set -euo pipefail if [ -f server/package.json ]; then echo "pkg=true" >> "$GITHUB_OUTPUT" echo "==> server/package.json found - running the server gates." else echo "pkg=false" >> "$GITHUB_OUTPUT" echo "==> No server/package.json yet (planning phase)." echo " Skipping install/test. These gates arm themselves as soon" echo " as Phase 3 lands the server half - see MODULE_SYSTEM.md." fi - uses: actions/setup-node@v4 if: ${{ steps.detect.outputs.pkg == 'true' }} 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 if: ${{ steps.detect.outputs.pkg == 'true' }} run: npm ci --prefix server - name: Run server tests if: ${{ steps.detect.outputs.pkg == 'true' }} run: npm test --prefix server client-build: runs-on: ubuntu-latest timeout-minutes: 20 steps: - uses: actions/checkout@v4 - name: Detect whether the client half exists yet id: detect run: | set -euo pipefail if [ -f client/package.json ]; then echo "pkg=true" >> "$GITHUB_OUTPUT" echo "==> client/package.json found - running the client gates." else echo "pkg=false" >> "$GITHUB_OUTPUT" echo "==> No client/package.json yet (planning phase)." echo " Skipping install/test/build. These gates arm themselves as" echo " soon as Phase 3 lands the client half." fi - uses: actions/setup-node@v4 if: ${{ steps.detect.outputs.pkg == 'true' }} with: node-version: 20 cache: npm cache-dependency-path: client/package-lock.json - name: Install client deps if: ${{ steps.detect.outputs.pkg == 'true' }} run: npm ci --prefix client - name: Run client tests if: ${{ steps.detect.outputs.pkg == 'true' }} run: npm test --prefix client # Building the ESM chunk in CI is not just a check: it is how the chunk # that ships in the release is produced, since an operator never builds. - name: Build the client chunk if: ${{ steps.detect.outputs.pkg == 'true' }} run: npm run build --prefix client