Files
runicgateway.com/.gitea/workflows/pr-checks.yml
wtclaude c29ec94f46
All checks were successful
PR checks / checks (pull_request) Successful in 1m25s
feat(screens): phase 9 — real screenshots, from a real shard
D4 asked for screenshots of the review stack rather than placeholders. Seventeen
of them: eleven of the site in a browser, six of the app on a phone, all from one
demo deployment wired to a running ServUO shard over a real sidecar, captured on
one day (D42).

The deployment is branded "Runic Gateway Demo" rather than a real community (D43),
and the captures sit beside the claims they support — the homepage, /features/, and
five of the administration pages phase 7 could describe but not show (D44).

The rig is committed rather than remembered (D45):

  scripts/seedDemo.mjs        content, by driving the site's own API — never SQL,
                              because a row the product could not have produced is
                              a screenshot of a product that does not exist
  src/data/screens.mjs        every capture: route, viewport, scroll, alt, caption
  scripts/captureScreens.mjs  npm run screens:capture
  scripts/checkScreens.mjs    the ninth check script, in CI

Shard-side dressing is servuo-plugins' scaffolding (D46), never deployed.

The rig found five things nothing else had. One is fixed upstream — a fresh
module-uo install pinned wire protocol 3 against a sidecar speaking 4, released as
v1.0.2, which this repo's own facts check then caught in platform.json. Four are
raised as product observations and worked around in the rig: a renamed guild
member never reaches the site, a guild deleted while the shard is down is a ghost
row forever, "Houses in danger" cannot show a house that was already collapsing,
and the app's news list prints raw ISO timestamps.

Players online reads 0. Logging a character in needs a UO client driven by hand,
and that is where this stopped — PLAN.md §10 says exactly why, and how to retake
the two frames that would change.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-25 09:55:55 -05:00

161 lines
7.7 KiB
YAML

name: PR checks
# Gitea Actions caution, learned elsewhere in this org: never leave an empty
# template expression anywhere in a `run:` script, not even inside a comment.
# The runner silently SKIPS the whole step without failing the job, and the
# problem is invisible in the workflow list.
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
checks:
runs-on: ubuntu-latest
steps:
- name: Check out
uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: '22'
cache: npm
- name: Install
run: npm ci
- name: Design tokens
# PLAN.md §7 — no colour literal outside src/styles/tokens.css.
run: npm run check:tokens
- name: Branding pipeline
# PLAN.md §7 — brand-default is complete, every /brand/* URL the source asks for
# resolves against the route's own allowlist, and every brand string the boot
# rewrite replaces is distinctive enough to replace blindly.
run: npm run check:brand
- name: Play Data Safety declaration
# PLAN.md §9 / D33 — PLAY_DATA_SAFETY.md is generated from the same
# src/data/collection.mjs rows that /privacy section 2 renders, so the published
# policy and the answers given to Google cannot drift apart. This re-runs the
# generator and fails if the committed copy differs.
#
# It runs before the build because it needs neither one: it is the cheapest check
# here and the one whose failure is easiest to act on.
run: npm run check:datasafety
- name: Types
run: npm run check
- name: Unit tests
# PLAN.md §8 — the beta signup's decision path: honeypot, form token, timing, rate
# limit, cap, validation, duplicate, removal.
#
# The first thing in this repository that the other checks cannot see. They all read
# the built output, and none of this appears there: a honeypot that has stopped
# working produces a build that is identical in every way to one where it works.
#
# The test file is NAMED rather than the directory passed. `node --test test/` fails
# on Node 22 with MODULE_NOT_FOUND — directory mode is not portable across the
# versions this org runs, and this workflow pins 22 while developers are on 24, so
# the shorter form would pass locally and break only here.
run: npm test
- name: Sidebar
# PLAN.md §12, phase 8. src/config/sidebar.mjs holds two trees — the one Starlight
# renders and the one §10 planned — and they must agree on groups, labels and
# ORDER. Order because the order of "Getting started" IS the installation path.
#
# While pages were being written the planned tree was a checklist; now that every
# page exists it is a hand-maintained second copy, and it had already drifted
# unnoticed (phase 7 added Content under D37 and never updated it). Nothing caught
# that because nothing read it.
#
# No token, no network, no build — so it runs early and fails fast.
run: npm run check:sidebar
- name: Screenshots
# PLAN.md §12, phase 9 (D45). src/data/screens.mjs is the one list of what the site
# shows of itself: every entry must have a file, at the size the markup declares, and
# every file must have an entry. The size half is the one that repays the check —
# a re-capture taken at the wrong viewport looks perfectly fine on its own and only
# reveals itself as a page that reflows while it decodes.
#
# No browser and no game server: the capture tool is an authoring script whose output
# is committed, exactly like the brand assets, so CI only reads what it produced.
run: npm run check:screens
- name: Production build
run: npm run build
- name: Links
# PLAN.md §12 — every internal link resolves, and every outbound link into a
# RunicGateway repository points at a branch path rather than a commit permalink.
#
# It runs AFTER the build, and that ordering is the design rather than a
# convenience: it reads the built HTML, so links assembled from data files and
# template literals are checked as the strings they actually become. A source scan
# would see an expression and skip most of what phase 4 added.
#
# No network: the outbound rule is about the shape of a URL, and a build that
# fails because some other host is slow is a check people learn to ignore.
run: npm run check:links
- name: Platform facts
# PLAN.md §12 — every version, protocol number and bundle tag is re-read from
# its authority over the Gitea API and must agree with src/data/platform.json.
#
# This needs a token that can read the OTHER repositories in the org: link,
# servuo-plugins, website and installer. The automatic per-run token is scoped
# to this repository alone and 404s on all four, so the job uses the org-level
# REGISTRY_TOKEN, which already exists and already carries the right scope.
#
# The secret is named for the registry; the script reads GITEA_TOKEN. Mapping it
# here rather than renaming either side keeps the script's interface honest — it
# wants a Gitea token, not this org's particular secret.
#
# It runs last, and it is the only step that touches the network, so a Gitea
# outage cannot mask a real failure in the build.
env:
GITEA_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
run: npm run check:facts
- name: Quickstart against website main
# PLAN.md §12, phase 7 (D35). /docs/getting-started/install-the-site/ prints a
# Compose file and an environment file the reader copies without leaving the page,
# which is the one place this site knowingly keeps a copy of another repo's file.
#
# So the copy is checked in BOTH directions: every value it states must match
# website's own docker-compose.yml and .env.example on main, and every service and
# variable THEY have must be either included or listed as deliberately omitted with
# a reason. A new variable upstream turns this repo red until someone decides
# whether a first install needs it — the same intent as the facts check above.
#
# Same token, and for the same reason: it reads another repository in the org.
env:
GITEA_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
run: npm run check:quickstart
- name: Reference enumerations against their sources
# PLAN.md §12, phase 8. The Reference section names things — every environment
# variable, config key, installer command, visibility rung and canonical document.
# §1 forbids re-specifying a contract, and this is what makes writing the NAMES
# down safe anyway: each list is a SET comparison against the repository that owns
# it, in both directions.
#
# The second direction is the one that earns its keep. A reference page does not
# usually rot by describing something that vanished — it rots by quietly not
# mentioning the three things added since it was written.
#
# Descriptions are deliberately NOT checked; nothing here can know whether a
# one-line summary is still true, so it does not pretend to.
#
# Same token, and for the same reason: it reads five other repositories in the org.
env:
GITEA_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
run: npm run check:reference