Skip to content

feat: declared extra controls in GameMeta (wire revision 6) #99

feat: declared extra controls in GameMeta (wire revision 6)

feat: declared extra controls in GameMeta (wire revision 6) #99

Workflow file for this run

name: CI
on:
push:
branches: [main]
tags: ["v*"]
pull_request:
schedule:
# Nightly (07:00 UTC): keep the slow release-profile artifact path honest.
- cron: "0 7 * * *"
# Pinned shellcade-kit toolchain: the author binary the arcade ships, attached
# to this repo's matching release. Bump the version AND the linux/amd64 sha
# (from that release's checksums.txt) together when adopting a new toolchain.
# The kit-pin job below fails CI when this pin falls behind the newest
# published binary release, so drift can't accumulate silently again.
env:
SHELLCADE_KIT_VERSION: "2.9.0"
SHELLCADE_KIT_SHA256: "9db05e285fb0d9ea41c1f2e772d1658814d9048bc9bee0e18e89d3b2a2be203d"
jobs:
# Toolchain pin lockstep: the SHELLCADE_KIT_VERSION pin above is a manual
# mirror of the newest published shellcade-kit binary release, and it has
# drifted before (2.2.0 lingered after v2.3.0 shipped). Two mechanical
# checks keep it honest:
# 1. the binary fetched at tag vX must EMBED kit vX — parse the `kit`
# line of `shellcade-kit version` (the kit module version baked in via
# debug.ReadBuildInfo, NOT the binary's own version line);
# 2. the pin must equal the newest release that actually carries
# shellcade-kit binaries (binaries attach to existing kit releases, so
# bare module tags without assets don't count).
# Runs on the nightly schedule too: staleness appears without a push.
kit-pin:
runs-on: ubuntu-latest
steps:
- name: fetch pinned shellcade-kit (sha256-verified)
run: |
set -euo pipefail
ver="${SHELLCADE_KIT_VERSION}"
asset="shellcade-kit_${ver}_linux_amd64.tar.gz"
base="https://github.com/shellcade/kit/releases/download/v${ver}"
curl -fsSL -o "${asset}" "${base}/${asset}"
echo "${SHELLCADE_KIT_SHA256} ${asset}" | sha256sum -c -
tar -xzf "${asset}" shellcade-kit
sudo install shellcade-kit /usr/local/bin/shellcade-kit
- name: pinned binary embeds the pinned kit version (lockstep)
run: |
set -euo pipefail
shellcade-kit version
embedded="$(shellcade-kit version | awk '$1 == "kit" { print $2 }')"
if [ "${embedded}" != "v${SHELLCADE_KIT_VERSION}" ]; then
echo "::error::lockstep violation: the v${SHELLCADE_KIT_VERSION} shellcade-kit binary embeds kit ${embedded}."
echo "A binary released at tag vX must be built against kit vX (see CLAUDE.md 'Lockstep')."
echo "Bump SHELLCADE_KIT_VERSION and SHELLCADE_KIT_SHA256 in ci.yml to a release whose binary matches its tag."
exit 1
fi
- name: pin is the newest published binary release
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
# Newest release carrying shellcade-kit binaries — NOT releases/latest
# blindly, and not bare module tags: the private repo attaches the
# binaries to this repo's existing releases after a kit tag, so only
# releases with a shellcade-kit linux/amd64 asset are candidates.
newest="$(gh api "repos/${GITHUB_REPOSITORY}/releases?per_page=30" --jq \
'[.[] | select(.draft or .prerelease | not)
| select(any(.assets[].name; startswith("shellcade-kit_") and endswith("_linux_amd64.tar.gz")))
][0].tag_name')"
echo "pin: v${SHELLCADE_KIT_VERSION} newest binary release: ${newest}"
if [ -z "${newest}" ] || [ "${newest}" = "null" ]; then
echo "::error::could not determine the newest shellcade-kit binary release"
exit 1
fi
if [ "${newest}" != "v${SHELLCADE_KIT_VERSION}" ] && \
[ "$(printf '%s\n' "v${SHELLCADE_KIT_VERSION}" "${newest}" | sort -V | tail -n1)" = "${newest}" ]; then
echo "::error::SHELLCADE_KIT_VERSION (${SHELLCADE_KIT_VERSION}) is stale: the newest published shellcade-kit binary release is ${newest}."
echo "Bump SHELLCADE_KIT_VERSION to ${newest#v} and SHELLCADE_KIT_SHA256 to the"
echo "linux/amd64 entry of that release's checksums.txt in .github/workflows/ci.yml."
exit 1
fi
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with: { go-version-file: go.mod }
- run: go build ./...
- run: go vet ./...
- run: go test ./...
# The committed crossverify .dgld vectors are a snapshot of the Go
# reference encoder; without this gate a Go-side byte-output change
# leaves them silently representing a HISTORICAL encoder (the rust job's
# golden step keeps passing against the stale bytes). Re-emit from the
# current encoder and require an exact match. Emission is deterministic
# (no RNG; committed .fseq inputs), so this is non-flaky.
- name: crossverify golden vectors are fresh (byte-identity vs the CURRENT Go reference)
run: |
set -euo pipefail
out="$(mktemp -d)"
DIFFBENCH_GOLDEN_DIR="$out" go test -run TestEmitGolden ./internal/diffbench/
if ! diff -r "$out" crossverify/tests/golden; then
echo "::error::committed crossverify golden vectors are STALE: the Go reference encoder's byte output changed."
echo "Review the change (it is wire-visible), then regenerate and commit:"
echo " DIFFBENCH_GOLDEN_DIR=crossverify/tests/golden go test -run TestEmitGolden ./internal/diffbench/"
exit 1
fi
- name: no private imports (the module must build from ABI.md alone)
run: |
! grep -rn "shellcade/shellcade" --include="*.go" . || (echo "FORBIDDEN private import" && exit 1)
# Author journey: prove the experience an author actually has — scaffold a
# fresh game with the pinned shellcade-kit, build the dev-profile wasm, and
# run the arcade's acceptance check on it. The scaffold pins a kit version, so
# we replace it with the PR's checkout to gate THIS repo's code, not a release.
wasm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { path: kit }
- uses: actions/setup-go@v5
with: { go-version-file: kit/go.mod }
- uses: acifani/setup-tinygo@v2
with: { tinygo-version: "0.41.1" }
- run: sudo apt-get update && sudo apt-get install -y binaryen
- name: fetch pinned shellcade-kit (sha256-verified)
run: |
set -euo pipefail
ver="${SHELLCADE_KIT_VERSION}"
asset="shellcade-kit_${ver}_linux_amd64.tar.gz"
base="https://github.com/shellcade/kit/releases/download/v${ver}"
curl -fsSL -o "${asset}" "${base}/${asset}"
# Verify against the exact sha we pin, then cross-check the release's
# own checksums.txt agrees (defence in depth against a swapped asset).
echo "${SHELLCADE_KIT_SHA256} ${asset}" | sha256sum -c -
curl -fsSL -o checksums.txt "${base}/checksums.txt"
grep " ${asset}\$" checksums.txt | sha256sum -c -
tar -xzf "${asset}" shellcade-kit
sudo install shellcade-kit /usr/local/bin/shellcade-kit
shellcade-kit version
- name: scaffold a fresh game
run: shellcade-kit new cigame
- name: build against this PR's kit (dev profile) and check
run: |
set -euo pipefail
cd cigame
# The scaffold pins a released kit; point it at the PR's checkout so
# the gate exercises THIS repo's SDK, then tidy and build.
go mod edit -replace github.com/shellcade/kit/v2=../kit
go mod tidy
go build ./...
tinygo build -opt=1 -no-debug -gc=conservative -o cigame.wasm \
-target wasip1 -buildmode=c-shared .
ls -la cigame.wasm
shellcade-kit check cigame.wasm
# Rust author journey: the Rust mirror of the wasm job above — scaffold with
# the pinned shellcade-kit (`new --rust`), point the scaffold's crate dep at
# the PR's checkout (the cargo equivalent of `go mod edit -replace`), build
# the release artifact, and run the arcade's acceptance check on it. This is
# the gate that catches scaffolder/crate drift at PR time.
wasm-rust:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { path: kit }
- uses: dtolnay/rust-toolchain@stable
with: { targets: wasm32-wasip1 }
- name: fetch pinned shellcade-kit (sha256-verified)
run: |
set -euo pipefail
ver="${SHELLCADE_KIT_VERSION}"
asset="shellcade-kit_${ver}_linux_amd64.tar.gz"
base="https://github.com/shellcade/kit/releases/download/v${ver}"
curl -fsSL -o "${asset}" "${base}/${asset}"
echo "${SHELLCADE_KIT_SHA256} ${asset}" | sha256sum -c -
curl -fsSL -o checksums.txt "${base}/checksums.txt"
grep " ${asset}\$" checksums.txt | sha256sum -c -
tar -xzf "${asset}" shellcade-kit
sudo install shellcade-kit /usr/local/bin/shellcade-kit
shellcade-kit version
- name: scaffold a fresh Rust game
run: shellcade-kit new --rust cigame
- name: build against this PR's crate (release profile) and check
run: |
set -euo pipefail
cd cigame
# The scaffold pins a released kit tag; point it at the PR's checkout
# so the gate exercises THIS repo's crate.
sed -i 's|^shellcade-kit = .*|shellcade-kit = { path = "../kit/rust" }|' Cargo.toml
cargo build --release --target wasm32-wasip1
ls -la target/wasm32-wasip1/release/cigame.wasm
shellcade-kit check target/wasm32-wasip1/release/cigame.wasm
# Rust SDK: the shellcade-kit crate (rust/) and its golden-vector harness
# (crossverify/). Gates: unit tests, byte-identity with the Go reference
# encoder, a wasm32-wasip1 release build smoke of the crate, and the
# version lockstep (crate version == package.json version, kept in sync by
# scripts/sync-crate-version.mjs at `changeset version` time).
rust:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with: { targets: wasm32-wasip1 }
- name: crate version == kit version (lockstep)
run: |
set -euo pipefail
kit_ver="$(node -p 'require("./package.json").version')"
crate_ver="$(grep -m1 '^version = ' rust/Cargo.toml | cut -d'"' -f2)"
if [ "${kit_ver}" != "${crate_ver}" ]; then
echo "version drift: package.json=${kit_ver} rust/Cargo.toml=${crate_ver}" >&2
echo "run: node scripts/sync-crate-version.mjs" >&2
exit 1
fi
- name: SDK tests
run: cargo test --manifest-path rust/Cargo.toml
- name: golden vectors (byte-identity vs the Go reference encoder)
run: cargo test --release --manifest-path crossverify/Cargo.toml
- name: wasm32-wasip1 release build smoke
run: cargo build --release --target wasm32-wasip1 --manifest-path rust/Cargo.toml
# Slow path: the release profile (-opt=2) that ships. Only nightly and on
# tags — it's the artifact authors submit, so keep it building, but don't
# pay its cost on every PR. Mirrors the author journey, release build.
release-wasm:
if: github.event_name == 'schedule' || startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { path: kit }
- uses: actions/setup-go@v5
with: { go-version-file: kit/go.mod }
- uses: acifani/setup-tinygo@v2
with: { tinygo-version: "0.41.1" }
- run: sudo apt-get update && sudo apt-get install -y binaryen
- name: fetch pinned shellcade-kit (sha256-verified)
run: |
set -euo pipefail
ver="${SHELLCADE_KIT_VERSION}"
asset="shellcade-kit_${ver}_linux_amd64.tar.gz"
base="https://github.com/shellcade/kit/releases/download/v${ver}"
curl -fsSL -o "${asset}" "${base}/${asset}"
echo "${SHELLCADE_KIT_SHA256} ${asset}" | sha256sum -c -
curl -fsSL -o checksums.txt "${base}/checksums.txt"
grep " ${asset}\$" checksums.txt | sha256sum -c -
tar -xzf "${asset}" shellcade-kit
sudo install shellcade-kit /usr/local/bin/shellcade-kit
- name: scaffold and release-build (-opt=2) against this PR's kit
run: |
set -euo pipefail
shellcade-kit new cigame
cd cigame
go mod edit -replace github.com/shellcade/kit/v2=../kit
go mod tidy
tinygo build -opt=2 -no-debug -gc=conservative -o cigame.wasm \
-target wasip1 -buildmode=c-shared .
ls -la cigame.wasm
shellcade-kit check cigame.wasm