PR 4 of the in-place admin router split (docs/website/API_V2_PLAN.md § Phase 2),
and the last admin one: it moves the entire residual 33 and DELETES
admin.routes.js. Every one of the 110 admin routes is now declared in a
capability router. No URL, gate or handler changes.
shard.router.js (16) /admin/shard
uoLink.router.js ( 5) /admin/uo-link
email.router.js ( 6) /admin/email
discordBot.router.js ( 2) /admin/discord-bot
settings.router.js ( 2) /admin/settings
dashboard.router.js ( 2) GET /dashboard + PUT /site-mode, at the group root
admin.routes.js deleted, was 33
No gate moved to router level. Every adminOnly in the residual file was
per-route, and modAccess on /shard must stay per-route because half that router
must not have it — which keeps the per-route handler count intact, the one
number routes.guards.json can actually check.
/shard is the first prefix where two tiers share one router: 7 self-service
account-linking routes (no extra gate, served by the same player/shard
controller handlers, tagged `Admin · Account`) alongside 9 in-game staff ops on
modAccess. Prefix ownership beats tag grouping — splitting by tag would put two
routers under one prefix for no gain. The tag mismatch stays; retagging is a
real spec diff and belongs in a PR about tags.
dashboard.router.js is the one router mounted at the group root rather than a
prefix: GET /dashboard and PUT /site-mode share no path segment. That is safe
only because the file declares no router-level middleware — a bare use(gate) in
a root-mounted router would run for every request passing through toward
another mount. The file carries a comment saying so.
Acceptance — all four gates zero-diff:
routes.manifest.json unchanged (200 public + 2 internal)
routes.guards.json unchanged (no route lost or gained a gate)
swagger-output.json unchanged (198 operations)
api-route-inventory.json already in sync
plus 434 server tests green.
Verified separately, because no gate can catch it: introspecting the built
stack, all 59 literal admin paths still dispatch to their own layer — nothing
is captured first by a /:param sibling. The manifest sorts its entries, so
declaration order is invisible to it.
Also repoints the comments that referenced admin.routes.js by name
(botActivity/moderation controllers, the town-crier cap mirror in
announceJobs.logic.js) and generalizes the "the path is on the line after
router.get(" rationale in routeManifest.js, README.md and pr-checks.yml, which
was never about that one file.
Co-Authored-By: Claude <noreply@anthropic.com>
81 lines
2.9 KiB
YAML
81 lines
2.9 KiB
YAML
# Gate every pull request into `main` on a fast, DB-free check suite so a broken
|
|
# build or failing test can't reach the deployable branch. Complements
|
|
# build-images.yml, which runs only AFTER merge (on push to main) to publish
|
|
# images — this one runs BEFORE merge.
|
|
#
|
|
# 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.
|
|
#
|
|
# Runner: reuses the existing self-hosted `ubuntu-latest` runner. These jobs need
|
|
# only Node (no Docker socket), and the server tests stub their models + point the
|
|
# DB pool at a dead port, so no MariaDB service is required.
|
|
|
|
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
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 20
|
|
cache: npm
|
|
cache-dependency-path: server/package-lock.json
|
|
- name: Install server deps
|
|
run: npm ci --prefix server
|
|
- name: Run server tests
|
|
run: npm test --prefix server
|
|
- name: Check the route manifest is current
|
|
# The URL surface is frozen while the routers are carved up by capability
|
|
# (docs/website/API_V2_PLAN.md § Phase 2). Regenerating from the live Express
|
|
# stack and diffing proves a "mechanical" refactor moved no URL. A PR that
|
|
# really does change one has to commit the new manifest, putting it in front
|
|
# of a reviewer instead of letting it pass silently.
|
|
run: npm run routes:manifest --prefix server -- --check
|
|
|
|
client-build:
|
|
runs-on: ubuntu-latest
|
|
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
|
|
# Pure-logic unit tests on Node's built-in runner (no browser/DOM).
|
|
run: npm test --prefix client
|
|
- name: Build client
|
|
run: npm run build --prefix client
|
|
|
|
bot-install:
|
|
# No tests/build to run; a clean install still catches a broken or
|
|
# out-of-sync lockfile before it ships in the bot image.
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 20
|
|
cache: npm
|
|
cache-dependency-path: bot/package-lock.json
|
|
- name: Install bot deps
|
|
run: npm ci --prefix bot
|