Bump actions/checkout from 4 to 7 #46
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # The single source of truth for "is master shippable" and the only automated | |
| # path to production. On every push to master and every PR it lints, tests, and | |
| # runs the full build from a clean checkout (so `tsc -b` is never cache-masked, | |
| # the way a stale local .tsbuildinfo once hid a broken vite.config). On a push | |
| # to master, and only after lint + test + build pass, it deploys to gh-pages. | |
| # That keeps the live site equal to a pushed, green commit instead of whatever | |
| # happened to be in someone's working tree. `npm run deploy` stays as a manual | |
| # break-glass fallback. (The daily rankings Action deploys its own data commit | |
| # separately: its push uses GITHUB_TOKEN, which by design does not trigger this | |
| # workflow, so ci.yml never sees that commit.) | |
| name: CI | |
| on: | |
| push: | |
| branches: [master] | |
| pull_request: | |
| branches: [master] | |
| # Cancel superseded PR runs, but never interrupt a master run mid-deploy. | |
| # Master pushes share the deploy-pages group with the daily rankings workflow | |
| # so the two gh-pages publishes serialize instead of interleaving. | |
| concurrency: | |
| group: ${{ github.event_name == 'push' && 'deploy-pages' || format('ci-{0}', github.ref) }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| jobs: | |
| ci: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| permissions: | |
| contents: write # the deploy step pushes the build to the gh-pages branch | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 # the stale-pool guard diffs against the pre-push tip, which can be many commits back | |
| # Guard against the clobber that bit us once (af2bb49): a human commit that | |
| # carries a stale, locally-built draft pool and silently reverts the bot's | |
| # daily data. The bot and any fresh rebuild only move generatedAt forward; | |
| # an untouched commit leaves it equal. So if this push moves any | |
| # draftPool.<season>.json generatedAt BACKWARD versus the pre-push master | |
| # tip, stop before deploying. Compared against github.event.before, not | |
| # HEAD~1: a multi-commit push can bury the stale pool one commit deep, | |
| # where a parent-only check never sees it. ISO-8601 timestamps compare | |
| # correctly as strings. | |
| # Deliberately rolling data back? Rebuild fresh (npm run update:rankings) | |
| # so it moves forward, or use the npm run deploy break-glass. | |
| - name: Guard against stale draft-pool clobber | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/master' | |
| run: | | |
| base="${{ github.event.before }}" | |
| # Force push or missing before-SHA (also the all-zeros SHA): fall | |
| # back to the parent commit rather than skipping the guard entirely. | |
| if [ -z "$base" ] || ! git cat-file -e "$base^{commit}" 2>/dev/null; then | |
| base=$(git rev-parse HEAD~1 2>/dev/null || true) | |
| fi | |
| [ -n "$base" ] || { echo "No base commit to compare against; skipping guard."; exit 0; } | |
| for f in src/data/draftPool.*.json; do | |
| [ -f "$f" ] || continue | |
| cur=$(grep -m1 '"generatedAt"' "$f" | sed -E 's/.*"generatedAt": *"([^"]+)".*/\1/' || true) | |
| prev=$(git show "$base:$f" 2>/dev/null | grep -m1 '"generatedAt"' | sed -E 's/.*"generatedAt": *"([^"]+)".*/\1/' || true) | |
| if [ -n "$prev" ] && [ -n "$cur" ] && [[ "$cur" < "$prev" ]]; then | |
| echo "::error::$f generatedAt moved backward ($prev -> $cur). This looks like a stale local pool clobbering the bot's update. Run 'git checkout origin/master -- src/data' or 'npm run update:rankings', then recommit." | |
| exit 1 | |
| fi | |
| done | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| cache: npm | |
| - run: npm ci | |
| - name: Lint | |
| run: npm run lint | |
| - name: Typecheck | |
| run: npm run typecheck | |
| - name: Test | |
| run: npm run test:run | |
| - name: Build | |
| run: npm run build | |
| # Present only on master pushes (PRs from forks can't read secrets), so | |
| # source maps upload to Sentry on real deploys and are skipped otherwise. | |
| env: | |
| SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} | |
| SENTRY_ORG: ${{ secrets.SENTRY_ORG }} | |
| SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} | |
| # The prerender step degrades to an empty SPA on failure (exit 0) so the | |
| # unattended rankings deploy never breaks. That makes a broken prerender | |
| # silent. CI is attended, so surface it as a warning when dist/index.html | |
| # ships an empty #root - visible in the run, without blocking the deploy. | |
| - name: Verify homepage prerender | |
| run: | | |
| if grep -q '<div id="root"></div>' dist/index.html; then | |
| echo "::warning::Homepage prerender did not inject markup; dist/index.html ships an empty #root (SEO/unfurl copy missing)." | |
| else | |
| echo "::notice::Homepage prerender injected static markup into dist/index.html." | |
| fi | |
| # If master moved while this run was building (e.g. the daily rankings | |
| # job rebased our commit in, deployed, and pushed its data commit), | |
| # deploying our older tree now would overwrite that newer deploy and | |
| # drop the fresh data from production until the next run. The newer | |
| # commit's own deploy already includes this commit, so skip ours. | |
| - name: Check this commit is still the master tip | |
| id: tip | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/master' | |
| run: | | |
| git fetch origin master | |
| if [ "$(git rev-parse origin/master)" = "${{ github.sha }}" ]; then | |
| echo "deploy=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "deploy=false" >> "$GITHUB_OUTPUT" | |
| echo "::notice::master moved past ${{ github.sha }} while this run built; skipping deploy (the newer commit's deploy includes this one)." | |
| fi | |
| - name: Deploy to GitHub Pages | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/master' && steps.tip.outputs.deploy == 'true' | |
| uses: peaceiris/actions-gh-pages@v4 | |
| with: | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| publish_dir: ./dist |