Skip to content

chore: bump miso to 1.13 #166

chore: bump miso to 1.13

chore: bump miso to 1.13 #166

Workflow file for this run

name: CI
# Two build paths, on two toolchains:
# * native-checks — the host-side bundler and the spec/loader tests, built with
# a native GHC (flake devShell .#native). Produces public/game.json.
# * build-and-deploy — the engine, built to wasm via the flake's default shell.
# It pulls in the game.json from native-checks and deploys the combined
# static bundle to GitHub Pages (gh-pages) on push to main. PRs build but do
# not deploy.
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
# Needed for peaceiris/actions-gh-pages to push to the gh-pages branch.
permissions:
contents: write
jobs:
# The native pipeline: run the pure spec/loader tests and bundle the game data.
# Separate from the wasm build because the bundler is native Haskell (it uses
# the yaml package, which the wasm app deliberately avoids); a stock native GHC
# also cannot resolve the wasm-only miso pin, so this builds against
# cabal.project.native.
native-checks:
name: Tests + bundle (native)
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout
uses: actions/checkout@v4
- name: ❄️ Install Nix
uses: nixbuild/nix-quick-install-action@v30
with:
nix_conf: |
experimental-features = nix-command flakes
# Cache the realised nix store for the native shell (GHC 9.8, cabal). A
# separate key prefix from the wasm store so the two do not evict each
# other; it only changes when the flake inputs do.
- name: ❄️ Cache the nix store (native toolchain)
uses: nix-community/cache-nix-action@v6
with:
primary-key: nixnative-${{ runner.os }}-${{ hashFiles('flake.nix', 'flake.lock') }}
restore-prefixes-first-match: nixnative-${{ runner.os }}-
# Cache the native cabal store (built rzk + deps), the Hackage index, and
# the cloned source-repository-package. Keyed on the files that determine
# the native plan.
- name: 💾 Cache the native cabal store, index, and SRP clone
uses: actions/cache@v4
with:
path: |
.cabal-native
dist-newstyle/src
key: cabal-native-${{ runner.os }}-${{ hashFiles('cabal.project.native', 'rzk-game.cabal', 'flake.lock') }}
restore-keys: |
cabal-native-${{ runner.os }}-
- name: 🧪 Test and bundle (in the native dev shell)
# The first run compiles rzk natively from scratch (several minutes); the
# caches make later runs fast. Bundle first, then test, so the spec test's
# bundle check runs against the freshly written public/game.json.
run: |
nix develop .#native --command bash -c '
export CABAL_DIR="$PWD/.cabal-native" &&
cabal --project-file=cabal.project.native update &&
make bundle &&
make test
'
- name: 📤 Upload the game bundle
uses: actions/upload-artifact@v4
with:
name: game-json
path: public/game.json
if-no-files-found: error
# Build the release bundler the way release.yml does — with a stock ghcup GHC,
# not nix — so the portable linux-x64 binary is exercised on every PR (catching
# a break before a tag is cut) and, on main, this run warms the bundler cache.
# release.yml runs only on tags, and tag-scoped caches are not shared between
# tags; caches created on the default branch are visible to all refs, so this
# main run is what makes a release restore the cache instead of recompiling.
# Uses the same cache path and key as release.yml's bundler job.
release-bundler:
name: Build release bundler (ghcup)
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout
uses: actions/checkout@v4
- name: 🎩 Set up GHC and cabal (ghcup)
id: setup
uses: haskell-actions/setup@v2
with:
ghc-version: '9.8.2'
cabal-version: '3.12'
- name: 💾 Cache the cabal store and build outputs
uses: actions/cache@v4
with:
# Same path/key as release.yml's bundler job. Cache the store at the
# path haskell-actions/setup reports (cabal 3.12 uses an XDG dir, not
# ~/.cabal). This job warms the cache on main for release tags to reuse.
path: |
${{ steps.setup.outputs.cabal-store }}
dist-newstyle
key: bundler-cabal-v2-${{ runner.os }}-ghc9.8.2-${{ hashFiles('cabal.project.native', 'rzk-game.cabal') }}
restore-keys: |
bundler-cabal-v2-${{ runner.os }}-ghc9.8.2-
- name: 🔨 Build the bundler
run: |
cabal --project-file=cabal.project.native update
cabal --project-file=cabal.project.native build exe:rzk-game-bundle
build-and-deploy:
name: Build to wasm (nix) and deploy
runs-on: ubuntu-latest
# Wait for the native job so its game.json is available to fold into public/.
needs: native-checks
steps:
- name: 📥 Checkout
uses: actions/checkout@v4
# Install Nix with a single-user, runner-writable /nix store. This is the
# installer cache-nix-action is built to pair with: the DeterminateSystems
# installer uses a daemon and a read-only store, which makes the cache's
# tar restore fail ("Cannot mkdir/Cannot open"), so the toolchain cache
# never actually loads. nix-quick-install avoids that.
- name: ❄️ Install Nix
uses: nixbuild/nix-quick-install-action@v30
with:
nix_conf: |
experimental-features = nix-command flakes
# Cache the realised nix store — the ghc-wasm toolchain (GHC wasm backend,
# wasm-opt, wasm-tools, node). Realising it from scratch is the single
# biggest cost (~3.5 min every run); it only changes when the flake inputs
# do, so key on flake.nix/flake.lock. With a stable key the cache is saved
# once and reused; GitHub's per-repo LRU bounds the overall budget.
#
# The "nix2-" generation: the first cache (saved under the old
# DeterminateSystems installer) was incomplete — it missed the realised
# wasm32-wasi-ghc output, so nix develop rebuilt the toolchain every run
# while still paying to restore the cache. nix-quick-install puts the whole
# closure in a runner-writable store that cache-nix-action can capture;
# bumping the key prefix forces one clean re-save. Bump it again if the
# restored store ever stops containing the realised toolchain.
- name: ❄️ Cache the nix store (wasm toolchain)
uses: nix-community/cache-nix-action@v6
with:
primary-key: nix2-${{ runner.os }}-${{ hashFiles('flake.nix', 'flake.lock') }}
restore-prefixes-first-match: nix2-${{ runner.os }}-
# Cache the wasm cabal store (built rzk/miso/deps), the Hackage index, and
# the cloned source-repository-packages (so rzk's full-history clone, ~40 s,
# is skipped). Keyed on the files that determine the pins; a pin change
# rebuilds only what actually differs, the prefix restore-key reusing the
# rest of the store.
- name: 💾 Cache the wasm cabal store, index, and SRP clones
uses: actions/cache@v4
with:
path: |
.wasm-store
.cabal-wasm
dist-newstyle/src
key: wasm-store-${{ runner.os }}-${{ hashFiles('cabal.project', 'rzk-game.cabal', 'flake.lock') }}
restore-keys: |
wasm-store-${{ runner.os }}-
- name: 🔨 Build and optimise (in the nix dev shell)
# nix supplies the wasm toolchain (flake.nix); cabal does the Haskell
# build against cabal.project (which pins rzk and miso). The pinned repos
# still draw their transitive deps (aeson, with-utf8, …) from Hackage, so
# the index must be fetched first — a fresh runner has none, which makes
# the solver fail with "unknown package". CABAL_DIR is pointed at the
# workspace so the index is cached alongside the store; `cabal update`
# then refreshes it incrementally. The first run compiles rzk + miso under
# wasm from scratch (several minutes); the caches make later runs fast.
# `make build` assembles public/; game.json is folded in below.
run: |
nix develop --command bash -c '
export CABAL_DIR="$PWD/.cabal-wasm" &&
wasm32-wasi-cabal update &&
make build WASM_STORE="$PWD/.wasm-store" &&
make optim
'
# Fold the bundled game data (from native-checks) into public/, after
# `make build` has assembled the fresh directory. Without it the deployed
# app would fall back to the built-in content instead of loading the bundle.
- name: 📥 Add the game bundle to public/
uses: actions/download-artifact@v4
with:
name: game-json
path: public
- name: 🚀 Deploy to GitHub Pages (gh-pages)
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public