name: Native binaries
on:
push:
branches:
- "**"
tags:
- "v*"
pull_request:
workflow_dispatch:
inputs:
release_tag:
description: Existing version tag to publish after successful builds
required: false
type: string
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.sha }}
cancel-in-progress: true
jobs:
build:
name: ${{ matrix.artifact }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
artifact: character-wizard-linux-x86_64
binary: target/release/character-wizard
archive: character-wizard-linux-x86_64.tar.gz
- os: windows-latest
artifact: character-wizard-windows-x86_64
binary: target/release/character-wizard.exe
archive: character-wizard-windows-x86_64.zip
- os: macos-15
artifact: character-wizard-macos-arm64
binary: target/release/character-wizard
archive: character-wizard-macos-arm64.tar.gz
- os: macos-15-intel
artifact: character-wizard-macos-x86_64
binary: target/release/character-wizard
archive: character-wizard-macos-x86_64.tar.gz
steps:
- name: Check out repository
uses: actions/checkout@v5
- name: Install pinned Rust toolchain
run: rustup toolchain install 1.88.0 --profile minimal
- name: Build native executable
run: cargo +1.88.0 build --release --locked --package character-wizard-cli
- name: Smoke-test executable (Unix)
if: runner.os != 'Windows'
shell: bash
run: |
"${{ matrix.binary }}" --help
"${{ matrix.binary }}" --version
"${{ matrix.binary }}" validate fixtures/complete-character.json
"${{ matrix.binary }}" show fixtures/complete-character.json
"${{ matrix.binary }}" create --template assets/character-sheet.pdf --from-json fixtures/complete-character.json --json "${RUNNER_TEMP}/character.json" --output "${RUNNER_TEMP}/character.pdf" --force
test -s "${RUNNER_TEMP}/character.json"
test -s "${RUNNER_TEMP}/character.pdf"
- name: Smoke-test executable (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
& "${{ matrix.binary }}" --help
& "${{ matrix.binary }}" --version
& "${{ matrix.binary }}" validate fixtures/complete-character.json
& "${{ matrix.binary }}" show fixtures/complete-character.json
& "${{ matrix.binary }}" create --template assets/character-sheet.pdf --from-json fixtures/complete-character.json --json "$env:RUNNER_TEMP/character.json" --output "$env:RUNNER_TEMP/character.pdf" --force
if (-not (Test-Path "$env:RUNNER_TEMP/character.json" -PathType Leaf)) { throw "JSON output missing" }
if (-not (Test-Path "$env:RUNNER_TEMP/character.pdf" -PathType Leaf)) { throw "PDF output missing" }
- name: Package executable and checksum (Unix)
if: runner.os != 'Windows'
shell: bash
run: |
mkdir -p dist/packages
tar -czf "dist/packages/${{ matrix.archive }}" -C target/release character-wizard
if command -v sha256sum >/dev/null; then
(cd dist/packages && sha256sum "${{ matrix.archive }}" > "${{ matrix.archive }}.sha256")
else
(cd dist/packages && shasum -a 256 "${{ matrix.archive }}" > "${{ matrix.archive }}.sha256")
fi
- name: Package executable and checksum (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
New-Item -ItemType Directory -Force dist/packages | Out-Null
Compress-Archive -Path "${{ matrix.binary }}" -DestinationPath "dist/packages/${{ matrix.archive }}"
$hash = (Get-FileHash "dist/packages/${{ matrix.archive }}" -Algorithm SHA256).Hash.ToLowerInvariant()
"$hash ${{ matrix.archive }}" | Set-Content "dist/packages/${{ matrix.archive }}.sha256" -Encoding ascii
- name: Upload packaged executable
uses: actions/upload-artifact@v4
with:
name: package-${{ matrix.artifact }}
path: dist/packages/${{ matrix.artifact }}*
if-no-files-found: error
release:
name: Publish GitHub Release
if: startsWith(github.ref, 'refs/tags/v') || inputs.release_tag != ''
needs: build
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Download packaged executables
uses: actions/download-artifact@v5
with:
path: release-assets
merge-multiple: true
pattern: package-*
- name: Publish release
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
RELEASE_TAG: ${{ inputs.release_tag || github.ref_name }}
run: >-
gh release create "${RELEASE_TAG}" release-assets/*
--verify-tag --generate-notes --title "character-wizard ${RELEASE_TAG}"