diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 45d6af9..c0d3c20 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ concurrency: cancel-in-progress: true jobs: - check: + build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 @@ -25,11 +25,47 @@ jobs: - run: bun run typecheck # The npm package's dist/: the compiled plugin, the wallpaper API and its declarations. - run: bun run build + + # Lists the registered wallpapers, so the jobs below run one per wallpaper in parallel and pick up new ones. + wallpapers: + runs-on: ubuntu-latest + outputs: + ids: ${{ steps.list.outputs.ids }} + steps: + - uses: actions/checkout@v7 + - uses: oven-sh/setup-bun@v2 + with: + bun-version: 1.3.14 + - id: list + run: echo "ids=$(bun -e 'import { WALLPAPERS } from "./wallpapers"; console.log(JSON.stringify(WALLPAPERS.map((w) => w.id)))')" >> "$GITHUB_OUTPUT" + + check: + needs: wallpapers + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + wallpaper: ${{ fromJSON(needs.wallpapers.outputs.ids) }} + steps: + - uses: actions/checkout@v7 + - uses: oven-sh/setup-bun@v2 + with: + bun-version: 1.3.14 + - uses: actions/cache@v6 + with: + path: ~/.bun/install/cache + key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }} + - run: bun install --frozen-lockfile # Fails on errors and flicker; the frame budget is generous because CI machines are slower and noisier. - - run: bun dev/check.ts --quiet --max-ms=60 + - run: bun dev/check.ts --quiet --max-ms=60 ${{ matrix.wallpaper }} screenshots: + needs: wallpapers runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + wallpaper: ${{ fromJSON(needs.wallpapers.outputs.ids) }} steps: - uses: actions/checkout@v7 - uses: oven-sh/setup-bun@v2 @@ -40,9 +76,9 @@ jobs: path: ~/.bun/install/cache key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }} - run: bun install --frozen-lockfile - - run: bun run screenshots + - run: bun dev/screenshots.ts ${{ matrix.wallpaper }} - if: failure() uses: actions/upload-artifact@v7 with: - name: fresh-screenshots - path: dev/out/*-45s.png + name: fresh-screenshots-${{ matrix.wallpaper }} + path: dev/out/${{ matrix.wallpaper }}-*-45s.png diff --git a/dev/screenshots.ts b/dev/screenshots.ts index 1494e68..3ff7d4e 100644 --- a/dev/screenshots.ts +++ b/dev/screenshots.ts @@ -1,12 +1,16 @@ // Re-renders the README gallery (teeming at 45 s via dev/snap.ts) and fails if any screenshot differs from the -// committed one beyond a tiny tolerance; --update writes the fresh renders instead: bun dev/screenshots.ts [--update] +// committed one beyond a tiny tolerance; --update writes the fresh renders instead. Naming wallpapers limits it to them: +// bun dev/screenshots.ts [--update] [wallpaper...] import { availableParallelism } from "node:os" import { TIMES } from "../src/engine" import { WALLPAPERS } from "../wallpapers" import { decodePng } from "./png" const update = process.argv.includes("--update") -const shots = WALLPAPERS.flatMap((w) => TIMES.map((time) => ({ id: w.id, time, file: `screenshots/${w.id}${time === "day" ? "" : `-${time}`}.png` }))) +const ids = process.argv.slice(2).filter((arg) => !arg.startsWith("--")) +const unknown = ids.filter((id) => !WALLPAPERS.some((w) => w.id === id)) +if (unknown.length) throw new Error(`unknown wallpaper ${unknown.join(", ")}`) +const shots = (ids.length ? WALLPAPERS.filter((w) => ids.includes(w.id)) : WALLPAPERS).flatMap((w) => TIMES.map((time) => ({ id: w.id, time, file: `screenshots/${w.id}${time === "day" ? "" : `-${time}`}.png` }))) const queue = [...shots] const stale: string[] = [] await Promise.all(