mirror of
https://github.com/tiennm99/thptqg2017.git
synced 2026-10-03 07:13:38 +00:00
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.
112 lines
3.7 KiB
YAML
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
|