ajhahn.de
← Theria
YAML 96 lines
name: Release build

# Builds the player-facing launcher binaries (Windows + macOS) and attaches them to the
# GitHub Release for the tag. The launcher is the seed build: a full export with boot.tscn as
# its main scene, so it runs offline out of the box and then self-updates by pulling game.pck
# from the rolling `playtest` pre-release (published by ci.yml). Testers download a launcher
# ONCE; new builds arrive as pck updates. Re-run this only when the launcher contract changes
# (the engine line, the autoload/class set) and min_client is bumped — not every release.
#
# Unlike the pck export, full executable exports need the Godot export templates, so this job
# downloads them. The macOS app is unsigned (codesign disabled in export_presets.cfg); testers
# clear the Gatekeeper quarantine per the README. macOS exports fine from a Linux runner.

on:
  push:
    tags: ["v*"]
  workflow_dispatch:  # allow a manual launcher build without cutting a new tag

jobs:
  launchers:
    name: build launchers
    runs-on: ubuntu-latest
    permissions:
      contents: write
    env:
      GODOT_VERSION: "4.6.3"
    steps:
      - uses: actions/checkout@v5
        with:
          # The .glb models and .png textures are Git LFS objects; without this the
          # launcher seed and its embedded pck ship without art and crash on match start.
          lfs: true
      - name: Download Godot ${{ env.GODOT_VERSION }} + export templates
        run: |
          base="https://github.com/godotengine/godot-builds/releases/download"
          ver="${GODOT_VERSION}-stable"
          wget -q "${base}/${ver}/Godot_v${ver}_linux.x86_64.zip" -O godot.zip
          unzip -q godot.zip
          mv "Godot_v${ver}_linux.x86_64" godot
          chmod +x godot
          wget -q "${base}/${ver}/Godot_v${ver}_export_templates.tpz" -O templates.tpz
          mkdir -p "$HOME/.local/share/godot/export_templates/${GODOT_VERSION}.stable"
          unzip -q templates.tpz
          mv templates/* "$HOME/.local/share/godot/export_templates/${GODOT_VERSION}.stable/"
      - name: Import project
        run: ./godot --headless --import
      - name: Export launchers
        run: |
          mkdir -p build
          ./godot --headless --export-release "Windows Desktop" build/Theria.exe
          ./godot --headless --export-release "macOS" build/Theria-macos.zip
          test -s build/Theria.exe
          test -s build/Theria-macos.zip
          ls -la build
      - name: Export game.pck
        run: |
          # The Stable channel pulls game.pck + manifest.json from the TAGGED release (the Beta
          # channel pulls them from the rolling playtest pre-release, published by ci.yml). A
          # tagged release that carried only launchers would leave Stable with nothing to pull,
          # so it ships the same payload pair the rolling channel does — exported the same way.
          ./godot --headless --export-pack "Windows Desktop" build/game.pck
          test -s build/game.pck
      - name: Write manifest.json
        run: |
          # min_client is the OLDEST launcher that can load this pck. Bump it ONLY when the
          # launcher contract breaks (the engine line or the autoload/class set changes) — never
          # per release — or testers would have to re-download the launcher on every build. Kept
          # in lockstep with the same literal in ci.yml's publish-pck job.
          MIN_CLIENT="0.1.0"
          VERSION="$(cat VERSION)"
          cat > build/manifest.json <<EOF
          {
            "version": "${VERSION#v}",
            "sha": "${GITHUB_SHA}",
            "pck": "game.pck",
            "min_client": "${MIN_CLIENT}"
          }
          EOF
          cat build/manifest.json
      - name: Package the Windows launcher
        run: |
          # embed_pck is on, so Theria.exe is the whole launcher — zip it for a clean download.
          cd build && zip -j Theria-windows.zip Theria.exe
      - name: Attach launchers and the Stable payload to the release
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          tag="${GITHUB_REF_NAME}"
          # workflow_dispatch has no tag ref name; fall back to the latest release tag.
          if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
            tag="$(gh release list --limit 1 --json tagName --jq '.[0].tagName')"
          fi
          gh release upload "$tag" \
            build/Theria-windows.zip build/Theria-macos.zip \
            build/game.pck build/manifest.json --clobber