All checks were successful
PR checks / checks (pull_request) Successful in 1m13s
Twenty pages completing the tree section 10 planned: Modules (8), Architecture
(5) and Reference (7). Four decisions, D38-D41, recorded in PLAN.md section 10.
D39 is the one that shaped the phase. Section 1 forbids re-specifying a
contract, and a Reference section is exactly where that rule is most tempting to
break, so the line is drawn at names: every environment variable, config key,
installer command, visibility rung and canonical document is listed with one
terse line saying what it is FOR, while shapes, semantics and every "why" stay
in the canonical document.
That is only safe because the names are checked. checkReference.mjs compares six
enumerations against the repositories that own them, over the Gitea API, as set
comparisons in BOTH directions -- and the second direction is the one that earns
its keep, because a reference page does not usually rot by describing something
that vanished, it rots by quietly not mentioning what was added since.
The check went green on its first run, which is the least trustworthy possible
outcome, so it was verified by breaking it: seven mutations, all caught. The one
worth keeping is the visibility ladder REORDERED with its membership unchanged
-- it is a security boundary, and a set comparison alone would have passed it.
D41 turns plannedSidebar from a checklist into a checked invariant, and finding
out why was the phase's first defect: it had already drifted, because phase 7
added the Content page under D37 and never updated the list. Nothing failed,
because nothing read it. checkSidebar.mjs now asserts the two trees agree on
groups, labels and order -- order because the order of Getting started IS the
installation path.
Two more things the writing found. PLAN.md's page count was wrong and had been
since section 10 was written ("roughly 38, 37 planned" for a tree of forty).
And module.json's `mounts` and the SPA's paths are different mechanisms that no
single document stated plainly -- module-uo declares admin: ["/shard",
"/uo-link"] while its screen lives at /admin/uo/link, because API routes are
deliberately NOT namespaced while SPA routes are. That is precisely the
distinction the installer got wrong in v0.1.0, and it now has a named home.
D40: the docs link to /architecture/'s drawn diagrams rather than importing
them. Those components carry marketing chrome and depend on diagram.css, which
Starlight does not load; the docs use text diagrams, which paste into an issue.
npm run verify green: 40 pages across 5 groups agree with plannedSidebar, 2390
internal links resolve, 123 repository links point at a branch, 19 facts, 59
quickstart checks, 22 reference enumerations, astro check 0 errors, 36 tests.
Co-Authored-By: Claude <noreply@anthropic.com>
150 lines
7.0 KiB
YAML
150 lines
7.0 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: 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
|