Files
thptqg2017/.github/workflows/deploy-pages.yml
T
tiennm99 3fd137a233 refactor(web): rebuild the frontend on SvelteKit, TypeScript and Tailwind
The app was a single-entry React SPA: one index.html that the assembler
copied to every dataset path, with a hand-rolled router resolving the
dataset from window.location and the title patched in at runtime because
one file had to serve every route.

SvelteKit prerenders a real page per route instead. The entry generator
in routes/[dataset]/+page.ts reads the same datasets.json the assembler
does, so the set of pages and the set of databases cannot drift apart,
and each dataset page ships its own <title> and description.

Everything framework-free moved across unchanged in behaviour and became
typed: the admission blocks, subject list, query classifier and SQL
presets. `Student` now mirrors the 22-column table, so a mistyped column
name fails the build rather than rendering blank.

Tailwind replaces the stylesheet. Theme tokens are CSS variables, which
keeps dark mode a single block of overrides rather than a `dark:` variant
on every class. The score tiers stay hand-written CSS: the class is
chosen at runtime from a score, and no utility generator can see that.

Adds the tests the frontend never had, over the three modules where a
silent wrong answer is possible — most importantly that toAscii here
folds exactly as ToAscii does in the parser, which is what makes
accent-insensitive search find anything.

The assembler stops copying index.html per dataset and checks that the
build prerendered each one instead. The database presence, raw-artifact
and idempotence guards are untouched.

Verified: 25 tests, ESLint and svelte-check clean, and a full
`assemble site` producing /thptqg/, /thptqg/2016/, /thptqg/2017/ and
404.html with absolute asset URLs. Not verified in a browser — this
machine has none.
2026-08-14 11:38:29 +07:00

112 lines
3.7 KiB
YAML

name: Deploy to GitHub Pages
on:
push:
branches: [main]
# Pull requests run the build job only: the deploy job is guarded to main, so
# a branch can be verified end to end without touching the live site.
pull_request:
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
env:
# Every Go module here is cgo-free — grate, excelize, yaml.v3, x/net,
# x/text and modernc.org/sqlite — so no C toolchain is needed. Set
# explicitly rather than relying on the default.
CGO_ENABLED: '0'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.26'
cache-dependency-path: |
parser/go.sum
crawler/go.sum
assembler/go.sum
# web/ is the only npm project in the repository; the other stages are Go.
- uses: actions/setup-node@v4
with:
node-version: '24'
cache: 'npm'
cache-dependency-path: web/package-lock.json
- name: Install web dependencies
working-directory: web
run: npm ci
# The reader-fidelity suite compares every real input file against a
# committed hash oracle, so it is the regression guard for the whole
# reader. Runs before anything is built.
- name: Test parser
run: go -C parser test ./...
# The crawler is not part of the build — it only refreshes data/ by hand.
# It is still tested here so it cannot rot unnoticed, and because its
# fixture test guards the parser: input filenames decide which row
# survives a duplicate exam number.
- name: Test crawler
run: go -C crawler test ./...
# The assembler owns every guard between a built database and the
# published site, so its tests are the ones that prove a short or missing
# database cannot ship.
- name: Test assembler
run: go -C assembler test ./...
# Lint covers ESLint and svelte-check; the tests cover the framework-free
# modules, including the ASCII fold that has to match the Go parser.
- name: Test web
working-directory: web
run: npm test
- name: Lint web
working-directory: web
run: npm run lint
# excelize carries an open advisory, and the 2017 refresh runbook feeds
# network-downloaded spreadsheets straight into the parser.
- name: Vulnerability scan
run: |
go install golang.org/x/vuln/cmd/govulncheck@latest
GOVULNCHECK="$(go env GOPATH)/bin/govulncheck"
for m in parser crawler assembler; do (cd "$m" && "$GOVULNCHECK" ./...); done
# One command runs the whole pipeline: compile the parser, build and
# verify each database against its registry row count, compress it, build
# the web app, and assemble _site — refusing to continue if a database is
# short, an artifact looks truncated, or one is missing entirely.
- name: Build site
run: go -C assembler run ./cmd/assemble
- uses: actions/upload-pages-artifact@v3
with:
path: _site
deploy:
# Deploy only from main. pull_request and workflow_dispatch both run on
# other branches, and publishing one would put that branch's output on the
# live site while concurrency cancel-in-progress killed an in-flight good
# deploy on the way.
if: github.ref == 'refs/heads/main'
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4