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

  1. Bump version in CMakeLists.txt.
  2. Regenerate the SPDX source SBOM after the version bump, then verify it:

    python3 tools/generate_spdx_sbom.py
    python3 tests/test_generate_spdx_sbom.py
    

    Commit 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.

  3. 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.

  4. Update active TODO and DONE ledgers as needed: TODO.md for cross-game work, TODO-<game>.md for active game work, and the matching DONE*.md only after evidence-backed completion. Then run scripts/sync_wiki.sh in the release workflow to publish docs/wiki/.
  5. Commit the version bump, SBOM and documentation.
  6. Tag with v prefix only when a release is explicitly requested.
  7. 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:

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:

  1. Preflight — validates the version against CMakeLists.txt and verifies that the selected release-notes section names added, changed and removed functions/features before extracting it
  2. 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
  3. Windows — builds x86_64 via MSYS2 UCRT64
    • Produces: portable .zip, Inno Setup installer .exe
    • Bundles: Artpack Studio, Dungeon Studio, Savegame Editor
  4. Linux — builds x86_64 and arm64 in parallel
    • Produces: .deb, .rpm
    • x86_64 also produces Steam Deck pacman .pkg.tar.zst and AppImage
    • SDL3 built from source (pinned to release-3.2.14)
  5. 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)
  6. 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)
  7. 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:

Manual Dispatch

The release workflow can also be triggered manually via workflow_dispatch with optional inputs: