Skip to content

ci: turnkey Mac .app + Linux Steam Sniper builds (additive)#324

Open
darkshade9 wants to merge 4 commits into
aqtionfrom
ci/turnkey-mac-linux
Open

ci: turnkey Mac .app + Linux Steam Sniper builds (additive)#324
darkshade9 wants to merge 4 commits into
aqtionfrom
ci/turnkey-mac-linux

Conversation

@darkshade9
Copy link
Copy Markdown

Summary

Adds three new build jobs to produce turnkey (no-install-required) artifacts for Mac and Linux Steam players, alongside the existing builds. Existing jobs untouched.

Job Output Why
darwin-arm64-turnkey AQtion-darwin-arm64.zip containing AQtion.app with all dylibs bundled Player no longer needs to brew install SDL2, libpng, libjpeg, libcurl, etc.
darwin-x86_64-turnkey AQtion-darwin-x86_64.zip (same shape) Same, Intel side
linux-steam-sniper Linux binary built inside Steam Runtime "Sniper" container Steam launches game inside Sniper container — no apt/dnf/yum needed by player

Mac bundle layout

AQtion.app keeps baseaq/ and action/ outside the bundle (sibling to the .app, not inside it). A launcher script in Contents/MacOS/ cd's to the .app's parent directory before exec'ing q2pro, so the engine resolves game data relative to CWD = install dir. Preserves the current "data sits next to binary" filesystem expectation.

Gatekeeper / signing

  • Ad-hoc codesign included (codesign --sign -) — free, no Apple Developer cert required, produces a stable signature.
  • No new Gatekeeper warning vs current state: bare binaries today already trigger "developer cannot be verified" when downloaded via browser. The .app shows "Apple cannot check" — same workaround (right-click → Open), same friction.
  • Steam-delivered installs skip the warning entirely on both paths (Steam doesn't set quarantine).

Verification

Each Mac job runs otool -L after dylibbundler and fails the build if any /opt/homebrew, /usr/local, or /opt/local path leaks into the bundle. Silent bad bundles are not possible.

Files

  • .ci/mac/AQtion-launcher.sh — 15-line launcher, sets CWD then execs q2pro
  • .ci/mac/Info.plist — bundle metadata, CFBundleExecutable points at the launcher
  • .github/workflows/build.yml — 3 new jobs appended after existing darwin-arm64
  • .github/workflows/release.yml — 3 new download steps + 3 new files in release upload

Optional follow-ups (not in this PR)

  • Drop AQtion.icns into .ci/mac/ (build works without it — Finder uses generic icon).
  • Update Steam Pipe app_build_<APPID>.vdf to set linux_runtime to sniper for the Linux depot.
  • Add a Mac lipo job to produce a single universal .app from the two per-arch artifacts.
  • Drop bare darwin / fedora jobs once turnkey is proven in production.

Test plan

  • First CI run succeeds for all three new jobs
  • Download q2pro-darwin-arm64-turnkey artifact, unzip next to a real baseaq/ + action/, double-click AQtion.app, verify it launches and finds game data
  • otool -L AQtion.app/Contents/MacOS/q2pro shows only /System/... and @executable_path/... entries
  • Linux Sniper build artifact's ldd q2pro resolves all libs inside the Sniper runtime when extracted into a Sniper container

🤖 Generated with Claude Code

Three new build jobs (additive — existing builds untouched):

- darwin-arm64-turnkey: produces AQtion.app for Apple Silicon with all
  dylib deps bundled via dylibbundler. Player needs zero brew installs.
  Includes ad-hoc codesign (no Apple Developer cert required, no new
  Gatekeeper warning vs current bare-binary distribution).

- darwin-x86_64-turnkey: same as above for Intel Macs.

- linux-steam-sniper: builds inside the official Steam Linux Runtime
  Sniper SDK container. Binary links only against libs Steam ships with
  every install. Player hits Play in Steam, game launches, no apt/dnf.

Mac bundle layout intentionally keeps baseaq/ and action/ OUTSIDE the
.app. A launcher script (.ci/mac/AQtion-launcher.sh) cd's to the .app's
parent directory before exec'ing the q2pro binary, so the engine
resolves game data relative to CWD = install dir. This preserves the
current "data lives next to binary" filesystem layout.

Verification step in each Mac job runs otool -L and fails the build if
any /opt/homebrew or /usr/local path leaks into the bundle.

Release workflow updated to download and upload the three new artifacts
alongside existing ones.

Next steps after merge:
1. Drop AQtion.icns into .ci/mac/ when ready (build works without it).
2. Update Steam Pipe app_build.vdf to set linux_runtime to sniper.
3. Validate first build run, iterate on container path tweaks if needed.
4. Eventually drop the bare darwin/fedora jobs once turnkey is proven.
Two fixes for the .app launcher:

1. Rename launcher AQtion-launcher.sh -> AQtion-launcher (no extension).
   macOS Launch Services is more reliable with no-extension binaries as
   CFBundleExecutable; .sh extension can cause silent launch failure.

2. Drop the manual `zip` step in both Mac jobs. actions/upload-artifact
   already zips its input, so the previous output was double-zipped
   (q2pro-darwin-arm64-turnkey.zip -> AQtion-darwin-arm64.zip ->
   AQtion.app). Now upload the .app directly; user downloads
   AQtion-darwin-arm64.zip and extracts straight to AQtion.app.

Added a diagnostic step that prints the bundle layout and launcher exec
bit before upload, so if modes get stripped somewhere it shows in CI.

release.yml updated to reference the new artifact names.
actions/upload-artifact strips the parent directory prefix when given a
directory path. Result: the previous artifact had files at root
(Contents/Frameworks/...) instead of the proper AQtion.app/Contents/...
layout — broken bundle.

Switch to ditto's --keepParent which preserves the AQtion.app wrapper
AND preserves codesign metadata, extended attrs, and exec bits that
plain zip strips. macOS opens ditto archives transparently via
double-click.

Tradeoff: two extract steps for the user (outer zip from upload-artifact,
inner zip from ditto), but each is a single double-click and the .app
survives intact.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant