Skip to content

v0.1-garibaldi

v0.1-garibaldi #6

Workflow file for this run

name: Build DSi Wi-Fi Manager release
on:
release:
types: [published]
permissions:
contents: write
jobs:
build:
runs-on: ubuntu-latest
container: skylyrac/blocksds:slim-latest
env:
BLOCKSDS: /opt/wonderful/thirdparty/blocksds/core
name: Build with BlocksDS toolchain using official Docker image
steps:
- name: Checkout repo
uses: actions/checkout@v7
- name: Build app
id: build
# ROM is overridden to the bare name so every release carries an identically-named
# asset, keeping the /releases/latest/download/dsi_wifi_manager.dsi URL permanent.
#
# A release shows its tag on the banner rather than a commit hash: the tag is what a user
# can read back to you, and the release itself already pins the exact commit. Nightlies
# have no tag and keep the hash. Fed through DSIWIFI_COMMIT because that is the field the
# banner prints; a long tag is cut with a '~' rather than overflowing the row.
#
# DSIWIFI_BUILD_KIND=Release also turns DSIWIFI_DEBUG off, which removes the
# flash-layout screen and the ability to force a write that programs nothing.
run: |
# No pipefail: the container's shell is dash, which does not have it, and `make | tee`
# would then report tee's status and a broken build would look clean. Redirecting and
# replaying the log keeps make's own exit status without needing bash.
make ROM=dsi_wifi_manager.dsi DSIWIFI_BUILD_KIND=Release DSIWIFI_COMMIT="${{ github.event.release.tag_name }}" > build.log 2>&1 || { cat build.log; echo "::error::build failed"; exit 1; }
cat build.log
- name: Check the debug affordances are off
# A Release that still offered the forced write would put a developer affordance in front
# of somebody restoring their home network. Checked here rather than by looking for debug
# strings in the ROM: those are compiled into every build, because the view layer takes a
# runtime flag so the offline harness can draw both variants. Only the flag differs.
run: |
grep -q "kind=Release debug=0" build.log || {
echo "::error::release build has debug affordances on"; grep "BUILD kind=" build.log; exit 1; }
echo "debug affordances off"
- name: Fail on any compiler warning
run: |
if grep -qi "warning" build.log; then
echo "::error::compiler warnings in build.log"
grep -i warning build.log
exit 1
fi
echo "no warnings"
- name: Keep the ROM for the verify job
uses: actions/upload-artifact@v7
with:
name: release-rom
path: dsi_wifi_manager.dsi
retention-days: 1
verify:
# A separate job on the runner, not in the build container: the BlocksDS image has no
# python3, and this check has to decode a little-endian offset and a UTF-16 banner. Doing
# that in the container's dash with od and awk would be fragile in a step whose whole job
# is to be trustworthy.
#
# The asset is only attached once this passes, so a ROM that fails verification is never
# published.
needs: build
runs-on: ubuntu-latest
name: Verify the ROM and attach it to the release
steps:
- name: Fetch the ROM
uses: actions/download-artifact@v8
with:
name: release-rom
- name: Check the ROM really is a Release DSi build
# Reads the banner and the unitcode back out of the ROM, which is the only way to know
# DSIWIFI_BUILD_KIND reached the binary -- and DEBUG follows from the kind.
#
# Not checked by looking for debug strings: they are present in every build. The view
# layer takes a runtime flag so the offline harness can draw both variants, so the
# text compiles in either way and only its reachability changes.
env:
TAG: ${{ github.event.release.tag_name }}
run: |
python3 - <<'EOF'
import os, struct, sys
d = open("dsi_wifi_manager.dsi", "rb").read()
off = struct.unpack("<I", d[0x68:0x6C])[0]
banner = d[off+0x240:off+0x240+256].decode("utf-16-le", "replace").split("\x00")[0]
lines = banner.split("\n")
tag = os.environ["TAG"]
print("banner:", lines)
print("unitcode: 0x%02X" % d[0x12])
bad = []
# The version line is the tag alone. Equality rather than a prefix is the point: it
# also catches a build kind leaking back in, since "Release v1.2.3" would slip past
# any test that only asked whether the tag was present.
if lines[-1] != tag:
bad.append(f"version line is {lines[-1]!r}, expected the tag {tag!r}")
if d[0x12] != 0x02:
bad.append("unitcode is not 0x02, DSi-only")
if bad:
print("::error::" + "; ".join(bad)); sys.exit(1)
EOF
- name: Upload dsi_wifi_manager.dsi
uses: AButler/upload-release-assets@v4.0.0
with:
files: dsi_wifi_manager.dsi
repo-token: ${{ secrets.GITHUB_TOKEN }}