Release Process
Version Scheme
Firestaff uses semantic versioning: MAJOR.MINOR.PATCH (for example,
3.0.315). The version is set in CMakeLists.txt:
project(Firestaff VERSION 3.0.315 LANGUAGES C)
Release notes format
Each published version block in RELEASE_NOTES.md is the complete public
record of user- and developer-relevant changes for that release. It must have
at least one of User-facing changes or Developer changes (both when both
audiences are affected). Do not use a generic summary to hide individual
changes: each bullet names the affected feature, subsystem, command or screen
in backticks and states the concrete delta. Empty categories are omitted—
None. is rejected by the release validator.
Game headings (DM1, DM2, CSB, Nexus, and Theron) and release-wide
headings (Added, Changed, Removed, and Fixed) may organize the detailed
record. Historical entries retain their original documented structure; a new
release must use the audience sections so a reader can immediately separate
what changes in the product from implementation, packaging, API, tooling and
verification changes.
Creating a release
- Bump version in
CMakeLists.txt. -
Regenerate the SPDX source SBOM after the version bump, then verify it:
python3 tools/generate_spdx_sbom.py python3 tests/test_generate_spdx_sbom.pyCommit the resulting
sbom/firestaff.spdx.json. The SBOM embeds the release version, so a version bump without this step is deliberately rejected by the verify workflow. -
Write release notes in
RELEASE_NOTES.md(add a section headed# Firestaff vX.Y.Z). Include only the relevant game and release-wide audience sections, each with concrete bullets:# Firestaff vX.Y.Z ## User-facing changes - `CSB entrance`: restores mouse activation of the selected door control. ## Developer changes - `csb_input_router`: maps the entrance pointer region to the native command.Include every relevant change for either audience. Name the affected function, subsystem, command, screen or feature in every bullet. Do not use aggregate wording such as “various updates” or generic release summaries. The release workflow rejects notes that do not meet this contract.
- Update active TODO and DONE ledgers as needed:
TODO.mdfor cross-game work,TODO-<game>.mdfor active game work, and the matchingDONE*.mdonly after evidence-backed completion. Then runscripts/sync_wiki.shin the release workflow to publishdocs/wiki/. - Commit the version bump, SBOM and documentation.
- Tag with
vprefix only when a release is explicitly requested. - Push the tag only for that release.
The GitHub Actions release workflow triggers automatically on v* tags.
GitHub Actions limits publication to one Firestaff release in each rolling 12-hour window. The workflow serializes release runs and checks the cooldown both before platform builds and immediately before publishing. Updating an already-published release with the same tag does not count as a second release; a draft does not consume the cooldown until it is published.
Ordinary documentation and code work is pushed to main without creating a
tag or GitHub Release.
CI/CD Pipeline
Verify Workflow (verify.yml)
Runs on every push and PR. Tests on:
- Ubuntu 24.04
- macOS 14
- Windows 2022
Checks: build, test suite, compiler warnings, asset hygiene (no game data committed).
Release Workflow (release.yml)
Triggers on v* tags or manual workflow_dispatch. Jobs:
- Preflight — validates the version against
CMakeLists.txtand verifies that the selected release-notes section names added, changed and removed functions/features before extracting it - macOS — builds x86_64 (Intel) and arm64 (Apple Silicon) in parallel
- Produces:
.dmg,.zip - Bundles: Artpack Studio, Dungeon Studio, Savegame Editor
- Runs Phase A and Audio smoke probes
- Produces:
- Windows — builds x86_64 via MSYS2 UCRT64
- Produces: portable
.zip, Inno Setup installer.exe - Bundles: Artpack Studio, Dungeon Studio, Savegame Editor
- Produces: portable
- Linux — builds x86_64 and arm64 in parallel
- Produces:
.deb,.rpm - x86_64 also produces Steam Deck pacman
.pkg.tar.zstand AppImage - SDL3 built from source (pinned to
release-3.2.14)
- Produces:
- iOS — builds arm64 on macOS 14
- Cross-compiles with iOS toolchain (deployment target iOS 14.0)
- SDL3 built as static library for iOS
- Produces:
.ipa(ad-hoc signed, AltStore Classic sideloadable)
- Android — builds arm64 on Ubuntu 24.04
- Cross-compiles with Android NDK 27 (API 24, arm64-v8a)
- SDL3 built as shared library for Android
- Produces:
.apk(debug-signed)
- Publish — creates/updates the GitHub Release
- Downloads all platform artifacts
- Generates release notes from
RELEASE_NOTES.md - Validates the committed SPDX source SBOM against the release version and attaches it as
Firestaff-X.Y.Z-sbom.spdx.json - Creates combined SHA-256 checksum manifest
- Uploads all artifacts to the GitHub Release
SDL3 Version
All platform builds pin SDL3 to release-3.2.14 via the SDL3_TAG environment variable.
Release Artifacts
| Platform | Artifacts | Architecture |
|---|---|---|
| macOS | .dmg, .zip |
x86_64, arm64 |
| Windows | .zip, .exe (installer) |
x86_64 |
| Linux | .deb, .rpm |
x86_64, arm64 |
| Steam Deck | .pkg.tar.zst, .AppImage |
x86_64 |
| iOS | .ipa |
arm64 |
| Android | .apk |
arm64 |
Each platform artifact set includes a .sha256 checksum file. The release also includes the version-matched SPDX source SBOM. A combined all-assets.sha256 manifest covers every artifact in the release, including the SBOM.
Pre-commit Hooks (Lefthook)
Three checks run on every commit:
- newline_eof: all committed files must end with a newline
- trailing_whitespace: no trailing whitespace allowed
- no_game_data_payloads: original game data files (DUNGEON.DAT, GRAPHICS.DAT, etc.) must never be tracked by git
Manual Dispatch
The release workflow can also be triggered manually via workflow_dispatch with optional inputs:
- version: override release version (defaults to
CMakeLists.txtversion) - draft: create as draft release
- prerelease: mark as prerelease