clipf 0.5.0

Copy file contents to the clipboard, locally or over SSH via OSC 52
name: release

on:
  push:
    tags:
      - 'v*'

permissions:
  contents: write

jobs:
  build:
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-musl
            archive: tar.gz
          - os: ubuntu-24.04-arm
            target: aarch64-unknown-linux-musl
            archive: tar.gz
          # macos-13 was retired on 2025-12-04; macos-15-intel is the x86_64
          # replacement, so this leg still builds natively.
          - os: macos-15-intel
            target: x86_64-apple-darwin
            archive: tar.gz
          - os: macos-14
            target: aarch64-apple-darwin
            archive: tar.gz
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            archive: zip
    steps:
      - uses: actions/checkout@v4
      - name: Install Rust
        shell: bash
        run: |
          rustup toolchain install stable --profile minimal
          rustup default stable
      - name: Add Target
        run: rustup target add ${{ matrix.target }}
      - name: Install musl tools
        if: runner.os == 'Linux'
        run: |
          sudo apt-get update
          sudo apt-get install -y musl-tools
      - name: Build
        run: cargo build --release --locked --target ${{ matrix.target }}
      - name: Smoke test
        if: runner.os != 'Windows'
        run: ./target/${{ matrix.target }}/release/clipf --version
      - name: Smoke test (Windows)
        if: runner.os == 'Windows'
        run: ./target/${{ matrix.target }}/release/clipf.exe --version
      - name: Package (tar.gz)
        if: matrix.archive == 'tar.gz'
        run: tar -czf clipf-${{ matrix.target }}.tar.gz -C target/${{ matrix.target }}/release clipf
      - name: Package (zip)
        if: matrix.archive == 'zip'
        shell: pwsh
        run: Compress-Archive -Path target/${{ matrix.target }}/release/clipf.exe -DestinationPath clipf-${{ matrix.target }}.zip
      - uses: actions/upload-artifact@v4
        with:
          name: ${{ matrix.target }}
          path: clipf-${{ matrix.target }}.${{ matrix.archive }}

  publish:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/download-artifact@v4
        with:
          merge-multiple: true
          path: dist
      - name: Generate shell completions
        shell: bash
        run: |
          # x86_64-unknown-linux-musl is statically linked, so it runs
          # natively on this ubuntu-latest (x86_64) runner with nothing
          # else installed -- these ship as release assets so users get
          # completions without a compiler or clipf itself.
          tar -xzf dist/clipf-x86_64-unknown-linux-musl.tar.gz -C /tmp
          chmod +x /tmp/clipf
          /tmp/clipf --completions bash > dist/clipf.bash
          /tmp/clipf --completions zsh > dist/clipf.zsh
          /tmp/clipf --completions fish > dist/clipf.fish
      - name: Generate SHA256SUMS
        shell: bash
        run: |
          cd dist
          # clipf* (not clipf-*): also covers clipf.bash/.zsh/.fish, which
          # use a dot, not a hyphen, after the name.
          sha256sum clipf* > SHA256SUMS
      - name: Publish
        run: gh release create "$GITHUB_REF_NAME" dist/* --generate-notes
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          # This job has no checkout, so gh cannot infer the repo from a git
          # remote; name it explicitly.
          GH_REPO: ${{ github.repository }}

  publish-crate:
    needs: build
    runs-on: ubuntu-latest
    # The `secrets` context cannot be referenced in a job-level `if:` --
    # GitHub Actions rejects the whole workflow file at parse time with
    # "Unrecognized named-value: secrets" if you try (confirmed the hard
    # way: this exact mistake produced two silently-failed "invalid
    # workflow file" runs during 0.5.0's release). The documented
    # workaround is to map the secret to a job-level env var and gate an
    # individual step on that instead.
    env:
      CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
    steps:
      - uses: actions/checkout@v4
      - name: Install Rust
        shell: bash
        run: |
          rustup toolchain install stable --profile minimal
          rustup default stable
      - name: Publish to crates.io
        # Skips cleanly (rather than failing the release) when the secret
        # isn't configured -- crates.io publishing needs an API token from
        # https://crates.io/settings/tokens added as a repo secret named
        # CARGO_REGISTRY_TOKEN. Until that's set, this step is a no-op and
        # the GitHub release in the `publish` job above is unaffected.
        if: ${{ env.CARGO_REGISTRY_TOKEN != '' }}
        run: cargo publish --locked