feat: add GitHub Actions CI and support hosting under a subpath
Mirrors the GitLab pipeline — typecheck, tests, feed sanity — and adds a Pages deploy. Pages serves from /<repo>/, and the app used absolute asset paths, so that job would have shipped a site that 404s on everything. Assets now resolve against a <base href> the build substitutes, the feed URL resolves against document.baseURI so deep links work too, and the service worker derives its paths from its own registration scope. Root-hosted builds are unchanged. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
517066dc65
commit
b86794a62d
@@ -0,0 +1,132 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
# A new push supersedes the one before it on the same ref.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
# Least privilege by default; jobs opt into more where they need it.
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: Typecheck, test, feed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: "1.3"
|
||||
|
||||
- run: bun install --frozen-lockfile
|
||||
|
||||
- name: Typecheck
|
||||
run: bun run typecheck
|
||||
|
||||
- name: Test
|
||||
# Offline by design: no fixture is re-fetched, so a red run always means
|
||||
# the code changed, never that a source was unreachable.
|
||||
run: bun test
|
||||
|
||||
- name: Build feed
|
||||
run: bun run build:feed
|
||||
|
||||
- name: Feed sanity
|
||||
# A source that quietly stops yielding events is the failure mode a
|
||||
# parser-only pipeline is most prone to, and nothing else surfaces it.
|
||||
run: |
|
||||
bun -e '
|
||||
const feed = await Bun.file("public/data/events.v1.json").json();
|
||||
const games = new Set(feed.events.map((e) => e.game));
|
||||
console.log(`${feed.events.length} events across ${games.size} games`);
|
||||
if (feed.events.length < 20) {
|
||||
throw new Error(`feed collapsed to ${feed.events.length} events`);
|
||||
}
|
||||
if (feed.events.some((e) => !e.startsAt)) {
|
||||
throw new Error("events without a start date");
|
||||
}
|
||||
'
|
||||
|
||||
build:
|
||||
name: Build site
|
||||
runs-on: ubuntu-latest
|
||||
needs: check
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: "1.3"
|
||||
- run: bun install --frozen-lockfile
|
||||
- name: Build
|
||||
# Pages serves from /<repo>/, so the app is built with a matching base
|
||||
# href. Built at the domain root it would 404 on every asset.
|
||||
env:
|
||||
BASE_PATH: /${{ github.event.repository.name }}/
|
||||
run: bun run build
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: site
|
||||
path: public/
|
||||
retention-days: 7
|
||||
|
||||
image:
|
||||
name: Container image
|
||||
runs-on: ubuntu-latest
|
||||
needs: check
|
||||
# Pushing an image for every pull request fills the registry; do it where
|
||||
# the artefact could actually be deployed.
|
||||
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
|
||||
- uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: |
|
||||
ghcr.io/${{ github.repository }}:latest
|
||||
ghcr.io/${{ github.repository }}:${{ github.sha }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
pages:
|
||||
name: Deploy to Pages
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deploy.outputs.page_url }}
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: site
|
||||
path: public
|
||||
- uses: actions/configure-pages@v5
|
||||
- uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: public
|
||||
- id: deploy
|
||||
uses: actions/deploy-pages@v4
|
||||
Reference in New Issue
Block a user