mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 08:21:02 +02:00
164 lines
6.1 KiB
YAML
164 lines
6.1 KiB
YAML
name: ci
|
|
|
|
# The ROM-free test run (21-testing-and-ci §CI).
|
|
#
|
|
# CI has no ROM and never will: data/generated/ is produced by a SHA-1
|
|
# verified import of a cartridge dump, and no ROM bytes are ever committed.
|
|
# That is why the suite is tiered -- T1 (primitives), T2 (engine invariants)
|
|
# and T4 (mod SDK) run against the committed tests/fixture_data dataset, so
|
|
# they need no ROM, no display and no assets beyond what is in the repo.
|
|
# The T3 content tier asserts Pokemon Red facts; scripts/test.sh detects
|
|
# data/generated/ is absent and skips it rather than failing.
|
|
#
|
|
# Runs alongside release.yml, which is untouched by this file.
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
|
|
# a force-push while CI is mid-run should cancel the stale run, not queue
|
|
concurrency:
|
|
group: ci-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
headless:
|
|
name: headless suites (no ROM)
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
# LuaJIT, not lua5.4: LOVE 11.x embeds LuaJIT 2.1 and the engine is
|
|
# written to Lua 5.1 semantics, so CI must run the interpreter the
|
|
# game actually ships with or it would green-light 5.4-only syntax.
|
|
- name: install luajit
|
|
run: sudo apt-get update && sudo apt-get install -y luajit
|
|
|
|
- name: interpreter version
|
|
run: luajit -v
|
|
|
|
- name: run every ROM-free tier
|
|
run: ./scripts/test.sh
|
|
|
|
fixture-dataset:
|
|
name: fixture dataset integrity
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- run: sudo apt-get update && sudo apt-get install -y luajit
|
|
- run: python3 -m pip install --upgrade pillow
|
|
|
|
# the fixture PNGs are committed (they are 8x8 placeholders, not
|
|
# ROM-derived); assert they are still readable 4-shade images rather
|
|
# than regenerating them, so a corrupted commit is caught
|
|
- name: fixture assets are valid PNGs
|
|
run: |
|
|
python3 - <<'PY'
|
|
import glob, sys
|
|
from PIL import Image
|
|
paths = sorted(glob.glob("tests/fixture_data/assets/*.png"))
|
|
if not paths:
|
|
sys.exit("no fixture assets found")
|
|
for path in paths:
|
|
with Image.open(path) as image:
|
|
image.load()
|
|
print(f"ok {path} {image.size} {image.mode}")
|
|
print(f"\n{len(paths)} fixture assets valid")
|
|
PY
|
|
|
|
# the fingerprint golden is the parity tripwire; prove it still
|
|
# matches the dataset on a clean checkout
|
|
- name: fingerprint gate
|
|
run: luajit tests/engine/gate_fingerprint.lua
|
|
|
|
- name: parity-guarantee meta-test
|
|
run: luajit tests/engine/gate_meta_coverage.lua
|
|
|
|
# Only the differ is under test here, and the job is named for that. The
|
|
# capture half of the golden pipeline does not exist: a POKEPORT_DRIVER
|
|
# chunk runs after main.lua has already booted the game, and
|
|
# src/core/Data.lua has no POKEPORT_DATA_DIR branch, so no LOVE process
|
|
# can be pointed at tests/fixture_data. There is deliberately no step
|
|
# here that runs scripts/test.sh with WITH_SHOTS: it would have nothing
|
|
# to capture and nothing to diff, and a job that green-lights on skipped
|
|
# work is worse than an absent one.
|
|
shot-differ:
|
|
name: screenshot differ (capture not yet wired)
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- run: python3 -m pip install --upgrade pillow
|
|
|
|
# 21-testing-and-ci §"Testing & acceptance criteria": compare_shots
|
|
# flags a deliberately corrupted golden and passes the clean one.
|
|
# That is the half of the pipeline this repo can actually prove.
|
|
- name: compare_shots self-test
|
|
run: |
|
|
set -e
|
|
python3 - <<'PY'
|
|
import os
|
|
from PIL import Image
|
|
os.makedirs("/tmp/g", exist_ok=True)
|
|
os.makedirs("/tmp/s", exist_ok=True)
|
|
base = Image.new("RGB", (160, 144), (255, 255, 255))
|
|
for x in range(0, 160, 8):
|
|
for y in range(0, 144, 8):
|
|
base.putpixel((x, y), (0, 0, 0))
|
|
base.save("/tmp/g/clean.png")
|
|
base.save("/tmp/s/clean.png")
|
|
base.save("/tmp/g/broken.png")
|
|
bad = base.copy()
|
|
for x in range(40, 60):
|
|
for y in range(40, 60):
|
|
bad.putpixel((x, y), (255, 0, 0))
|
|
bad.save("/tmp/s/broken.png")
|
|
PY
|
|
if python3 tools/compare_shots.py /tmp/g /tmp/s; then
|
|
echo "compare_shots passed a corrupted golden -- differ is broken"
|
|
exit 1
|
|
fi
|
|
rm /tmp/g/broken.png /tmp/s/broken.png
|
|
python3 tools/compare_shots.py /tmp/g /tmp/s
|
|
|
|
# an empty golden directory must not read as success
|
|
- name: differ refuses to pass vacuously
|
|
run: |
|
|
set -e
|
|
mkdir -p /tmp/empty-goldens /tmp/empty-shots
|
|
if python3 tools/compare_shots.py /tmp/empty-goldens /tmp/empty-shots; then
|
|
echo "compare_shots passed with no goldens"
|
|
exit 1
|
|
fi
|
|
|
|
lint:
|
|
name: mod lint (no ROM-derived content)
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
# the MK305 dump check key-diffs shipped tables through luajit, and
|
|
# modkit treats a missing interpreter as a fatal MK100 -- without
|
|
# this install the gate would fail instead of failing open
|
|
- run: sudo apt-get update && sudo apt-get install -y luajit
|
|
- run: python3 -m pip install --upgrade pillow
|
|
|
|
# constraint 1, enforced automatically: a committed mod that ships
|
|
# ROM-derived bytes fails the build. `lint` is the no-ROM-content
|
|
# check; `validate` is deliberately not run here because it resolves
|
|
# a mod against the fixture dataset, and a Red-content mod such as
|
|
# example_mew_starter legitimately does not resolve against it.
|
|
- name: lint every committed mod
|
|
run: |
|
|
set -e
|
|
found=0
|
|
for mod in mods/*/; do
|
|
[ -f "$mod/manifest.json" ] || continue
|
|
found=1
|
|
echo "== $mod"
|
|
python3 tools/modkit.py lint "${mod%/}"
|
|
done
|
|
if [ "$found" = "0" ]; then
|
|
echo "no committed mods to lint"
|
|
fi
|