mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 16:31:05 +02:00
cab62ff7b3
Fix Blue ROM source setup
515 lines
21 KiB
YAML
515 lines
21 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.
|
|
#
|
|
on:
|
|
push:
|
|
# Integration branch + release branch. PRs already run via pull_request
|
|
# (any base); this list is only for post-merge push runs.
|
|
branches: [dev, 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
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
ios-changes:
|
|
name: detect iOS changes
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
changed: ${{ steps.paths.outputs.changed }}
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
- id: paths
|
|
env:
|
|
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
|
|
HEAD_SHA: ${{ github.sha }}
|
|
run: |
|
|
if [ -z "$BASE_SHA" ] || [ "$BASE_SHA" = "0000000000000000000000000000000000000000" ]; then
|
|
echo "changed=true" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
if git diff --name-only "$BASE_SHA" "$HEAD_SHA" | grep -Eq '^(mobile/ios/|scripts/build_ios\.sh$)'; then
|
|
echo "changed=true" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "changed=false" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
ios-build:
|
|
name: iOS build
|
|
needs: ios-changes
|
|
if: needs.ios-changes.outputs.changed == 'true'
|
|
runs-on: ${{ fromJSON(github.repository == 'bryanthaboi/gen1recomp' && '["self-hosted", "macOS"]' || '"macos-latest"') }}
|
|
outputs:
|
|
ipa_url: ${{ steps.upload-ipa.outputs.artifact-url }}
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
- name: import signing certificate
|
|
if: github.repository == 'bryanthaboi/gen1recomp'
|
|
run: |
|
|
keychain_path="$RUNNER_TEMP/gen1recomp-ci-signing.keychain-db"
|
|
ci_dir="${POKEMON_CI_DIR:-$HOME/.config/pokemon-ci}"
|
|
p12="$ci_dir/signing.p12"
|
|
passfile="$ci_dir/signing.pass"
|
|
[ -f "$p12" ] && [ -f "$passfile" ] || exit 1
|
|
p12pw="$(cat "$passfile")"
|
|
kcpw="$(openssl rand -base64 24)"
|
|
echo "::add-mask::$kcpw"
|
|
security delete-keychain "$keychain_path" 2>/dev/null || true
|
|
security create-keychain -p "$kcpw" "$keychain_path"
|
|
security set-keychain-settings "$keychain_path"
|
|
security unlock-keychain -p "$kcpw" "$keychain_path"
|
|
security import "$p12" -P "$p12pw" -k "$keychain_path" -T /usr/bin/codesign -T /usr/bin/security
|
|
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$kcpw" "$keychain_path" >/dev/null
|
|
existing="$(security list-keychains -d user | sed -e 's/^[[:space:]]*//' -e 's/"//g')"
|
|
security list-keychains -d user -s "$keychain_path" $existing
|
|
- name: install xcbeautify
|
|
run: brew list xcbeautify >/dev/null 2>&1 || brew install xcbeautify
|
|
- name: build iOS release
|
|
env:
|
|
CANONICAL_REPOSITORY: ${{ github.repository == 'bryanthaboi/gen1recomp' }}
|
|
run: |
|
|
if [ "$CANONICAL_REPOSITORY" = true ]; then
|
|
scripts/build_ios.sh --fetch --device --release
|
|
else
|
|
scripts/build_ios.sh --fetch --release
|
|
fi
|
|
- name: upload iOS release artifact
|
|
id: upload-ipa
|
|
if: github.repository == 'bryanthaboi/gen1recomp'
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: gen1recomp-ios-ipa
|
|
path: dist/ios/gen1recomp.ipa
|
|
if-no-files-found: error
|
|
retention-days: 7
|
|
- name: clean up signing keychain
|
|
if: ${{ always() && github.repository == 'bryanthaboi/gen1recomp' }}
|
|
run: security delete-keychain "$RUNNER_TEMP/gen1recomp-ci-signing.keychain-db" 2>/dev/null || true
|
|
|
|
switch-changes:
|
|
name: detect Switch changes
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
changed: ${{ steps.paths.outputs.changed }}
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
- id: paths
|
|
env:
|
|
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
|
|
HEAD_SHA: ${{ github.sha }}
|
|
run: |
|
|
if [ -z "$BASE_SHA" ] || [ "$BASE_SHA" = "0000000000000000000000000000000000000000" ]; then
|
|
echo "changed=true" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
if git diff --name-only "$BASE_SHA" "$HEAD_SHA" | grep -Eq '^(scripts/build_switch\.sh$|scripts/switch/|docs/switch-.*\.md$|tests/switch_ci_workflows_test\.lua$|tests/switch_transfer_docs_test\.lua$|\.github/workflows/(ci|release|switch-artifact-comment)\.yml$|src/core/(NxAssetOverlay|Platform|GameVersion)\.lua$|src/import/CacheFs\.lua$|tests/engine/(assets_version_fallback|nx_generated_guard|nx_yellow_boot|switch_diagnostics)_test\.lua$|tests/engine/platform_nx)'; then
|
|
echo "changed=true" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "changed=false" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
switch-selftest:
|
|
name: Switch offline selftest
|
|
needs: switch-changes
|
|
if: needs.switch-changes.outputs.changed == 'true'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
- name: install luajit
|
|
run: sudo apt-get update && sudo apt-get install -y luajit
|
|
- name: Switch offline selftest
|
|
run: bash scripts/switch/selftest_build_switch.sh
|
|
- name: verify_payload self-test
|
|
run: bash scripts/switch/verify_payload.sh --self-test
|
|
- name: Switch CI workflow content gate
|
|
run: luajit tests/switch_ci_workflows_test.lua
|
|
- name: Switch transfer docs content gate
|
|
run: luajit tests/switch_transfer_docs_test.lua
|
|
# NX runtime regressions gate this job via switch-changes; run the NX
|
|
# engine suites here too so a PR touching them gets feedback on the
|
|
# fork-safe ubuntu runner before the self-hosted Mac build.
|
|
- name: NX engine suites (headless)
|
|
run: |
|
|
luajit tests/engine/assets_version_fallback_test.lua
|
|
luajit tests/engine/nx_generated_guard_test.lua
|
|
luajit tests/engine/nx_yellow_boot_test.lua
|
|
|
|
switch-build:
|
|
name: Switch fused build
|
|
needs: [switch-changes, switch-selftest]
|
|
if: |
|
|
always()
|
|
&& needs.switch-changes.outputs.changed == 'true'
|
|
&& needs.switch-selftest.result == 'success'
|
|
&& github.repository == 'bryanthaboi/gen1recomp'
|
|
&& (github.event_name != 'pull_request'
|
|
|| github.event.pull_request.head.repo.full_name == github.repository)
|
|
runs-on: ["self-hosted", "macOS"]
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
- name: Build Switch fused NRO
|
|
run: |
|
|
set -euo pipefail
|
|
VER="$(printf '%s' "$GITHUB_SHA" | cut -c1-7)"
|
|
scripts/build_switch.sh --fetch --fused --version "$VER"
|
|
echo "SWITCH_VER=$VER" >> "$GITHUB_ENV"
|
|
- name: upload Switch NRO artifact
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: gen1recomp-switch-nro
|
|
path: |
|
|
dist/switch/gen1recomp-${{ env.SWITCH_VER }}-switch.nro
|
|
dist/switch/gen1recomp-${{ env.SWITCH_VER }}-switch.nro.sha256
|
|
if-no-files-found: error
|
|
retention-days: 7
|
|
|
|
xbox-uwp-changes:
|
|
name: detect Xbox UWP changes
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
changed: ${{ steps.paths.outputs.changed }}
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
- id: paths
|
|
env:
|
|
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
|
|
HEAD_SHA: ${{ github.sha }}
|
|
run: |
|
|
if [ -z "$BASE_SHA" ] || [ "$BASE_SHA" = "0000000000000000000000000000000000000000" ]; then
|
|
echo "changed=true" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
if git diff --name-only "$BASE_SHA" "$HEAD_SHA" | grep -Eq '^(ports/uwp/|scripts/build_xbox_uwp\.sh$|scripts/xbox-uwp/|scripts/pack_love\.sh$|\.github/workflows/(ci|release)\.yml$|src/core/Platform\.lua$|src/import/(CacheFs|LauncherView|RomImporter)\.lua$|src/update/Check\.lua$|tests/engine/(platform_nx|uwp_baseroms|uwp_native_picker)_test\.lua$|tests/rom_importer_double_pick_test\.lua$)'; then
|
|
echo "changed=true" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "changed=false" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
xbox-uwp-selftest:
|
|
name: Xbox UWP offline selftest
|
|
needs: xbox-uwp-changes
|
|
if: needs.xbox-uwp-changes.outputs.changed == 'true'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
- name: Xbox UWP offline selftest
|
|
run: bash scripts/xbox-uwp/selftest_build_xbox_uwp.sh
|
|
- name: Build shared payload
|
|
run: |
|
|
scripts/pack_love.sh \
|
|
--output .bazinga/work/ci-game.love \
|
|
--listing .bazinga/work/ci-love-listing.txt \
|
|
--version 0.0.0
|
|
- name: Upload shared payload
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: gen1recomp-xbox-uwp-payload
|
|
path: .bazinga/work/ci-game.love
|
|
if-no-files-found: error
|
|
retention-days: 1
|
|
|
|
xbox-uwp-build:
|
|
name: Xbox UWP build
|
|
needs: [xbox-uwp-changes, xbox-uwp-selftest]
|
|
if: |
|
|
always()
|
|
&& needs.xbox-uwp-changes.outputs.changed == 'true'
|
|
&& needs.xbox-uwp-selftest.result == 'success'
|
|
runs-on: windows-2022
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
- name: Download shared payload
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
name: gen1recomp-xbox-uwp-payload
|
|
path: .bazinga/work
|
|
- name: Build Xbox UWP package
|
|
shell: bash
|
|
run: |
|
|
bash scripts/build_xbox_uwp.sh \
|
|
--release \
|
|
--version 0.0.0 \
|
|
--game-love .bazinga/work/ci-game.love
|
|
- name: Upload Xbox UWP package
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: gen1recomp-xbox-uwp
|
|
path: |
|
|
dist/xbox-uwp/gen1recomp-0.0.0-xbox-uwp.zip
|
|
dist/xbox-uwp/gen1recomp-0.0.0-xbox-uwp.zip.sha256
|
|
if-no-files-found: error
|
|
retention-days: 7
|
|
|
|
linux-arm64-changes:
|
|
name: detect Linux arm64 changes
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
changed: ${{ steps.paths.outputs.changed }}
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
- id: paths
|
|
env:
|
|
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
|
|
HEAD_SHA: ${{ github.sha }}
|
|
run: |
|
|
if [ -z "$BASE_SHA" ] || [ "$BASE_SHA" = "0000000000000000000000000000000000000000" ]; then
|
|
echo "changed=true" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
if git diff --name-only "$BASE_SHA" "$HEAD_SHA" | grep -Eq '^(scripts/build_linux_arm64\.sh$|scripts/linux-arm64/|scripts/pack_love\.sh$|docs/linux-arm64-build\.md$|\.github/workflows/(ci|release)\.yml$)'; then
|
|
echo "changed=true" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "changed=false" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
linux-arm64-selftest:
|
|
name: Linux arm64 offline selftest
|
|
needs: linux-arm64-changes
|
|
if: needs.linux-arm64-changes.outputs.changed == 'true'
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
# Deliberately on x86_64: everything this gate checks (pins, the
|
|
# host-arch guard, the dependency exclude list, the AppRun fusion
|
|
# contract) is answerable without a container or an aarch64 machine,
|
|
# so the slow native job below only ever starts on a sane tree.
|
|
- name: Linux arm64 offline selftest
|
|
run: bash scripts/linux-arm64/selftest_build_linux_arm64.sh
|
|
|
|
linux-arm64-build:
|
|
name: Linux arm64 AppImage build
|
|
needs: [linux-arm64-changes, linux-arm64-selftest]
|
|
if: |
|
|
always()
|
|
&& needs.linux-arm64-changes.outputs.changed == 'true'
|
|
&& needs.linux-arm64-selftest.result == 'success'
|
|
# No fork restriction, unlike switch-build: this needs no secrets and no
|
|
# self-hosted hardware, just GitHub's free arm64 runner for public repos,
|
|
# so contributors get the same coverage on their own PRs.
|
|
runs-on: ubuntu-24.04-arm
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
- name: Build the aarch64 AppImage
|
|
run: |
|
|
set -euo pipefail
|
|
scripts/build_linux_arm64.sh --version 0.0.0
|
|
- name: Verify the AppImage is self-contained and bullseye-compatible
|
|
run: |
|
|
set -euo pipefail
|
|
image="dist/linux-arm64/gen1recomp-0.0.0-linux-arm64.AppImage"
|
|
|
|
# --appimage-extract needs no FUSE, so this works on a runner
|
|
# without /dev/fuse and still exercises the real payload.
|
|
"$image" --appimage-extract >/dev/null
|
|
for required in AppRun bin/love game.love lib/liblove-11.5.so; do
|
|
[ -e "squashfs-root/$required" ] \
|
|
|| { echo "::error::AppImage is missing $required"; exit 1; }
|
|
done
|
|
|
|
# Every bundled object must resolve once AppRun's LD_LIBRARY_PATH is
|
|
# applied; an unresolved soname here is a user-visible launch crash.
|
|
#
|
|
# This runs on a HEADLESS runner on purpose, and that is the point.
|
|
# The first version of this build bundled Debian's SDL2, which
|
|
# hard-links libpulse/libasound/libX11/libwayland, so it only ever
|
|
# started on a full desktop -- a bare runner is what exposed it.
|
|
missing="$(LD_LIBRARY_PATH="$PWD/squashfs-root/lib" \
|
|
ldd squashfs-root/bin/love squashfs-root/lib/*.so* 2>/dev/null \
|
|
| grep 'not found' || true)"
|
|
[ -z "$missing" ] || { echo "::error::unresolved deps:"; echo "$missing"; exit 1; }
|
|
|
|
# Nothing may hard-link a driver, session or audio-stack library:
|
|
# those must be reached through dlopen so the AppImage runs on a box
|
|
# with only ALSA, only Wayland, or only KMSDRM.
|
|
linked="$(for f in squashfs-root/bin/love squashfs-root/lib/*.so*; do
|
|
objdump -p "$f" 2>/dev/null | awk '/NEEDED/{print $2}'
|
|
done | sort -u | grep -E '^lib(pulse|asound|X11|wayland|GL|EGL|drm|gbm|xcb|cairo|sndio|dbus)' || true)"
|
|
[ -z "$linked" ] \
|
|
|| { echo "::error::these must be dlopened, not linked:"; echo "$linked"; exit 1; }
|
|
|
|
# The whole point of compiling on bullseye. If a future change moves
|
|
# the builder to a newer base, the glibc floor silently rises and
|
|
# every user on an older distro gets "GLIBC_2.xx not found" -- catch
|
|
# it here instead of in a release.
|
|
floor="$(objdump -T squashfs-root/bin/love squashfs-root/lib/*.so* 2>/dev/null \
|
|
| grep -o 'GLIBC_[0-9.]*' | sort -V | tail -1)"
|
|
echo "highest required glibc symbol version: $floor"
|
|
[ -n "$floor" ] \
|
|
|| { echo "::error::found no versioned glibc symbols -- objdump read nothing"; exit 1; }
|
|
highest="$(printf '%s\n' "$floor" "GLIBC_2.31" | sort -V | tail -1)"
|
|
[ "$highest" = "GLIBC_2.31" ] \
|
|
|| { echo "::error::AppImage requires $floor, above the bullseye 2.31 floor"; exit 1; }
|
|
- name: Upload the AppImage
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: gen1recomp-linux-arm64
|
|
path: |
|
|
dist/linux-arm64/gen1recomp-0.0.0-linux-arm64.AppImage
|
|
dist/linux-arm64/gen1recomp-0.0.0-linux-arm64.AppImage.sha256
|
|
if-no-files-found: error
|
|
retention-days: 7
|
|
|
|
headless:
|
|
name: headless suites (no ROM)
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
|
|
# 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: install Pillow
|
|
run: python3 -m pip install --upgrade pillow
|
|
|
|
- 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@v7
|
|
- 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@v7
|
|
- 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@v7
|
|
|
|
# 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
|