sopsy 1.3.0

Public/private individual key encryption for repo secrets with biometrics support and explicit approval of who can decrypt. In other words — the missing good UX for SOPS
Documentation
name: release

# Build prebuilt sopsy binaries and attach them to the GitHub Release for a tag,
# so users can install via Homebrew (kigster/tap) without a Rust toolchain.
on:
  push:
    tags:
      - "v*"
  workflow_dispatch:
    inputs:
      tag:
        description: "Existing tag to build and attach binaries to (e.g. v1.0.2)"
        required: true

permissions:
  contents: write

jobs:
  # Pushing a tag does not create a GitHub Release object, and
  # upload-rust-binary-action attaches to an existing release rather than
  # creating one — so create (or reuse) the release first, once.
  create-release:
    runs-on: ubuntu-latest
    steps:
      - name: Ensure the GitHub release exists
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GH_REPO: ${{ github.repository }}
          TAG: ${{ github.event.inputs.tag || github.ref_name }}
        run: |
          set -euo pipefail
          if gh release view "$TAG" >/dev/null 2>&1; then
            echo "Release $TAG already exists; reusing it."
          else
            gh release create "$TAG" --title "$TAG" --generate-notes
          fi

  upload:
    name: ${{ matrix.target }}
    needs: create-release
    strategy:
      fail-fast: false
      matrix:
        include:
          - target: aarch64-apple-darwin
            os: macos-14
          # Cross-compiled on the Apple Silicon runner: GitHub is sunsetting the
          # Intel macos-13 runners (they can queue indefinitely), and macos-14
          # builds the x86_64 target reliably via rustup.
          - target: x86_64-apple-darwin
            os: macos-14
          - target: x86_64-unknown-linux-gnu
            os: ubuntu-latest
          - target: aarch64-unknown-linux-gnu
            os: ubuntu-24.04-arm
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
        with:
          ref: ${{ github.event.inputs.tag || github.ref }}

      # Builds (cross-compiling where needed), tars the binary as
      # sopsy-<target>.tar.gz, generates a .sha256, and uploads to the release.
      # Pinned to a full commit SHA (supply-chain hardening); bump deliberately.
      - uses: taiki-e/upload-rust-binary-action@f0d45ae91ee7b8ee928de7a9d04d893a08bcbec6 # v1
        with:
          bin: sopsy
          target: ${{ matrix.target }}
          archive: sopsy-$target
          checksum: sha256
          ref: refs/tags/${{ github.event.inputs.tag || github.ref_name }}
          token: ${{ secrets.GITHUB_TOKEN }}

  notify-tap:
    name: refresh Homebrew formula
    needs: upload
    runs-on: ubuntu-latest
    steps:
      - name: Trigger tap update-formula workflow
        env:
          TAG: ${{ github.event.inputs.tag || github.ref_name }}
          # Optional: a PAT with `repo` scope on kigster/homebrew-tap. Without it
          # the tap is updated by running its update-formula workflow manually.
          GH_TOKEN: ${{ secrets.TAP_DISPATCH_TOKEN }}
        run: |
          set -euo pipefail
          if [ -z "${GH_TOKEN:-}" ]; then
            echo "TAP_DISPATCH_TOKEN not set — skipping auto-update."
            echo "Run the tap's update-formula workflow manually:"
            echo "  gh workflow run update-formula.yml -R kigster/homebrew-tap -f tag=$TAG"
            exit 0
          fi
          gh api "repos/kigster/homebrew-tap/dispatches" \
            -f "event_type=sopsy-release" \
            -f "client_payload[tag]=$TAG"