patchcov 0.2.0

Patch coverage for git diffs: attribute lcov, llvm-cov, Cobertura, Go and JaCoCo reports to a diff and gate on it.
Documentation
name: Release

# Every push to main (a merge, including a merged release PR):
#   - `release`  publishes and tags any version not yet released, then
#   - `binaries` builds the CLI for it and attaches the archives to the release;
#   - `pr`       opens or updates the release PR for the next version.
# See docs/RELEASE.md for the one-time setup and the release procedure.

on:
  push:
    branches: [main]

env:
  CARGO_TERM_COLOR: always

jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    if: ${{ github.repository_owner == 'rust-works' }}
    permissions:
      # Push tags and create releases.
      contents: write
      # Detect the release PR and its commits.
      pull-requests: read
      # crates.io Trusted Publishing: no CARGO_REGISTRY_TOKEN is stored.
      id-token: write
    outputs:
      releases: ${{ steps.release-plz.outputs.releases }}
      releases_created: ${{ steps.release-plz.outputs.releases_created }}
    steps:
      - uses: actions/checkout@v7
        with:
          # The full history is needed to release from the latest commit.
          fetch-depth: 0
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@stable
      - id: release-plz
        uses: release-plz/action@v0.5
        with:
          command: release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  binaries:
    name: Binary (${{ matrix.target }})
    needs: release
    if: ${{ needs.release.outputs.releases_created == 'true' }}
    runs-on: ${{ matrix.os }}
    permissions:
      contents: write
    strategy:
      fail-fast: false
      matrix:
        include:
          # The Linux legs build on 22.04, never a moving label, so the binaries
          # need glibc 2.35 at most; the "Check glibc floor" step enforces it.
          - { os: ubuntu-22.04, target: x86_64-unknown-linux-gnu }
          - { os: ubuntu-22.04-arm, target: aarch64-unknown-linux-gnu }
          - { os: macos-latest, target: aarch64-apple-darwin }
          - { os: macos-latest, target: x86_64-apple-darwin }
          - { os: windows-latest, target: x86_64-pc-windows-msvc }
    env:
      GLIBC_FLOOR: GLIBC_2.35
      TAG: ${{ fromJSON(needs.release.outputs.releases)[0].tag }}
      ARCHIVE_EXT: ${{ matrix.target == 'x86_64-pc-windows-msvc' && 'zip' || 'tar.gz' }}
    steps:
      - uses: actions/checkout@v7
        with:
          ref: ${{ env.TAG }}
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}
      - uses: Swatinem/rust-cache@v2
        with:
          key: ${{ matrix.target }}
      - name: Build
        run: cargo build --release --locked --target ${{ matrix.target }}
      - name: Check glibc floor
        if: ${{ endsWith(matrix.target, '-linux-gnu') }}
        run: |
          bin=target/${{ matrix.target }}/release/patchcov
          highest=$(objdump -T "$bin" | grep -oE 'GLIBC_[0-9]+(\.[0-9]+)*' | sort -uV | tail -1)
          echo "highest glibc symbol version: ${highest:-none}"
          if [ -n "$highest" ] && [ "$(printf '%s\n%s\n' "$highest" "$GLIBC_FLOOR" | sort -V | tail -1)" != "$GLIBC_FLOOR" ]; then
            echo "::error::$bin needs $highest, above the floor $GLIBC_FLOOR"
            exit 1
          fi
      - name: Package Unix
        if: ${{ runner.os != 'Windows' }}
        shell: bash
        run: |
          name=patchcov-${TAG}-${{ matrix.target }}
          mkdir "$name"
          cp target/${{ matrix.target }}/release/patchcov LICENSE README.md "$name"/
          tar -czf "$name.tar.gz" "$name"
          shasum -a 256 "$name.tar.gz" > "$name.tar.gz.sha256"
      - name: Package Windows
        if: ${{ runner.os == 'Windows' }}
        shell: pwsh
        run: |
          $name = "patchcov-$env:TAG-${{ matrix.target }}"
          New-Item -ItemType Directory -Path $name | Out-Null
          Copy-Item "target/${{ matrix.target }}/release/patchcov.exe", LICENSE, README.md -Destination $name
          $archive = "$name.zip"
          Compress-Archive -Path $name -DestinationPath $archive
          $hash = (Get-FileHash -Algorithm SHA256 $archive).Hash.ToLowerInvariant()
          "$hash  $archive" | Set-Content -Encoding ascii "$archive.sha256"
          Expand-Archive -Path $archive -DestinationPath package-check
          & "./package-check/$name/patchcov.exe" --version
          if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
      - name: Upload to the release
        shell: bash
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          archive="patchcov-${TAG}-${{ matrix.target }}.${ARCHIVE_EXT}"
          gh release upload "$TAG" "$archive" "$archive.sha256" --clobber

  pr:
    name: Release PR
    runs-on: ubuntu-latest
    if: ${{ github.repository_owner == 'rust-works' }}
    permissions:
      # Push to the release PR branch, and create and update the PR.
      contents: write
      pull-requests: write
    concurrency:
      group: release-plz-${{ github.ref }}
      cancel-in-progress: false
    steps:
      - uses: actions/checkout@v7
        with:
          fetch-depth: 0
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@stable
      - uses: release-plz/action@v0.5
        with:
          command: release-pr
        env:
          # A PR opened with the default token does not trigger the CI checks.
          # Set RELEASE_PLZ_TOKEN (a PAT or app token) to have them run; see
          # docs/RELEASE.md.
          GITHUB_TOKEN: ${{ secrets.RELEASE_PLZ_TOKEN || secrets.GITHUB_TOKEN }}