zipatch-rs 1.0.1

Parser for FFXIV ZiPatch patch files
Documentation
name: Release

on:
  push:
    branches: [main]
  workflow_dispatch:

permissions:
  contents: write

concurrency:
  group: release
  cancel-in-progress: false

jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6.0.2
        with:
          fetch-depth: 0

      - name: Extract version from Cargo.toml
        id: version
        run: |
          version=$(grep '^version' Cargo.toml | head -1 | sed -E 's/version = "(.*)"/\1/')
          echo "version=$version" >> "$GITHUB_OUTPUT"
          echo "tag=v$version" >> "$GITHUB_OUTPUT"

      - name: Check if tag already exists
        id: tag-check
        run: |
          tag="v${{ steps.version.outputs.version }}"
          if git rev-parse "$tag" >/dev/null 2>&1; then
            echo "exists=true" >> "$GITHUB_OUTPUT"
            echo "Tag $tag already exists, skipping release."
          else
            echo "exists=false" >> "$GITHUB_OUTPUT"
          fi

      - name: Set up Rust
        if: steps.tag-check.outputs.exists == 'false'
        uses: dtolnay/rust-toolchain@stable

      - name: Cache Rust
        if: steps.tag-check.outputs.exists == 'false'
        uses: Swatinem/rust-cache@v2.9.1

      - name: Verify build with dry-run
        if: steps.tag-check.outputs.exists == 'false'
        run: cargo publish --dry-run --all-features

      - name: Extract changelog section
        if: steps.tag-check.outputs.exists == 'false'
        id: changelog
        run: |
          version="${{ steps.version.outputs.version }}"

          # Find the line number of this version and the next version header
          start=$(grep -n "^## \[$version\]" CHANGELOG.md | head -1 | cut -d: -f1)
          if [ -z "$start" ]; then
            echo "Error: Could not find version $version in CHANGELOG.md"
            exit 1
          fi

          # Find the next "## [" after the start line
          end=$(tail -n +$((start + 1)) CHANGELOG.md | grep -n "^## \[" | head -1 | cut -d: -f1)

          if [ -z "$end" ]; then
            # No next section, extract to end of file
            sed -n "${start},\$p" CHANGELOG.md > /tmp/release_notes.txt
          else
            # Extract from start to before the next section
            end=$((start + end - 1))
            sed -n "${start},$((end - 1))p" CHANGELOG.md > /tmp/release_notes.txt
          fi

          # Validate that we got content
          if [ ! -s /tmp/release_notes.txt ]; then
            echo "Error: Could not extract changelog section for version $version"
            exit 1
          fi
          echo "notes_file=/tmp/release_notes.txt" >> "$GITHUB_OUTPUT"

      - name: Create git tag
        if: steps.tag-check.outputs.exists == 'false'
        run: |
          git tag "${{ steps.version.outputs.tag }}"
          git push origin "${{ steps.version.outputs.tag }}"

      - name: Create GitHub release
        if: steps.tag-check.outputs.exists == 'false'
        run: |
          gh release create \
            "${{ steps.version.outputs.tag }}" \
            --notes-file "${{ steps.changelog.outputs.notes_file }}"
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Publish to crates.io
        if: steps.tag-check.outputs.exists == 'false'
        run: cargo publish --all-features
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}