foch 0.1.0

Paradox mod static analysis toolkit with CLI and EU4-focused language tooling
Documentation
name: release

on:
  push:
    tags:
      - "v*"
  workflow_dispatch:
    inputs:
      tag:
        description: "Existing tag to package and release"
        required: true
        type: string

permissions:
  contents: read

jobs:
  build-cli-assets:
    name: Build CLI assets (${{ matrix.target }})
    runs-on: ${{ matrix.runner }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - runner: ubuntu-latest
            target: linux-x64
            archive_ext: tar.gz
          - runner: windows-latest
            target: win32-x64
            archive_ext: zip
          - runner: macos-14
            target: darwin-arm64
            archive_ext: tar.gz
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          ref: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }}

      - name: Resolve release metadata
        id: meta
        shell: bash
        run: |
          if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
            tag="${{ inputs.tag }}"
          else
            tag="${GITHUB_REF_NAME}"
          fi
          version="${tag#v}"
          echo "tag=${tag}" >> "$GITHUB_OUTPUT"
          echo "version=${version}" >> "$GITHUB_OUTPUT"

      - name: Setup Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Build release binaries
        run: cargo build --release --locked --bin foch --bin foch_lsp

      - name: Package Unix archive
        if: runner.os != 'Windows'
        shell: bash
        run: |
          mkdir -p dist/bin
          cp target/release/foch dist/bin/
          cp target/release/foch_lsp dist/bin/
          tar -C dist/bin -czf "dist/foch-${{ steps.meta.outputs.version }}-${{ matrix.target }}.${{ matrix.archive_ext }}" foch foch_lsp

      - name: Package Windows archive
        if: runner.os == 'Windows'
        shell: pwsh
        run: |
          New-Item -ItemType Directory -Force dist | Out-Null
          New-Item -ItemType Directory -Force dist/bin | Out-Null
          Copy-Item target/release/foch.exe dist/bin/
          Copy-Item target/release/foch_lsp.exe dist/bin/
          Compress-Archive -Path dist/bin/* -DestinationPath "dist/foch-${{ steps.meta.outputs.version }}-${{ matrix.target }}.${{ matrix.archive_ext }}" -Force

      - name: Upload CLI artifact
        uses: actions/upload-artifact@v4
        with:
          name: cli-${{ matrix.target }}
          path: dist/*

  package-vsix:
    name: Package VSIX (${{ matrix.target }})
    runs-on: ${{ matrix.runner }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - runner: ubuntu-latest
            target: linux-x64
          - runner: windows-latest
            target: win32-x64
          - runner: macos-14
            target: darwin-arm64
    defaults:
      run:
        working-directory: vscode-foch
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          ref: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }}

      - name: Setup Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: "20"

      - name: Install extension dependencies
        run: npm install

      - name: Package VSIX
        run: npm run package:vsix

      - name: Upload VSIX artifact
        uses: actions/upload-artifact@v4
        with:
          name: vsix-${{ matrix.target }}
          path: vscode-foch/*.vsix

  build-source-archive:
    name: Build source archive
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          ref: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }}

      - name: Resolve release metadata
        id: meta
        shell: bash
        run: |
          if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
            tag="${{ inputs.tag }}"
          else
            tag="${GITHUB_REF_NAME}"
          fi
          version="${tag#v}"
          echo "tag=${tag}" >> "$GITHUB_OUTPUT"
          echo "version=${version}" >> "$GITHUB_OUTPUT"

      - name: Create source tarball
        shell: bash
        run: |
          mkdir -p dist
          git archive \
            --format=tar.gz \
            --prefix="foch-${{ steps.meta.outputs.version }}/" \
            -o "dist/foch-${{ steps.meta.outputs.version }}-source.tar.gz" \
            HEAD

      - name: Upload source artifact
        uses: actions/upload-artifact@v4
        with:
          name: source-archive
          path: dist/*

  github-release:
    name: Publish GitHub release
    runs-on: ubuntu-latest
    needs:
      - build-cli-assets
      - package-vsix
      - build-source-archive
    permissions:
      contents: write
    steps:
      - name: Resolve release metadata
        id: meta
        shell: bash
        run: |
          if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
            tag="${{ inputs.tag }}"
          else
            tag="${GITHUB_REF_NAME}"
          fi
          version="${tag#v}"
          echo "tag=${tag}" >> "$GITHUB_OUTPUT"
          echo "version=${version}" >> "$GITHUB_OUTPUT"

      - name: Download build artifacts
        uses: actions/download-artifact@v4
        with:
          path: dist
          merge-multiple: true

      - name: Generate checksums
        shell: bash
        run: |
          cd dist
          sha256sum * > SHA256SUMS.txt

      - name: Create or update GitHub release
        env:
          GH_TOKEN: ${{ github.token }}
        shell: bash
        run: |
          tag="${{ steps.meta.outputs.tag }}"
          version="${{ steps.meta.outputs.version }}"
          extra_args=()
          if [[ "${tag}" == *-* ]]; then
            extra_args+=(--prerelease)
          fi

          if gh release view "${tag}" >/dev/null 2>&1; then
            gh release upload "${tag}" dist/* --clobber
          else
            gh release create "${tag}" dist/* \
              --title "Foch ${version}" \
              --generate-notes \
              "${extra_args[@]}"
          fi