character-wizard-cli 0.6.0

Native level-1 SRD character creation CLI
Documentation
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}"