Files
gacha-event-tracker/.github/workflows/ci.yml
T
Lucas WintherandClaude Opus 5 b86794a62d 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]>
2026-08-15 01:22:22 +02:00

133 lines
3.7 KiB
YAML

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