name: Release

on:
  push:
    tags:
      - 'v[0-9]+.[0-9]+.[0-9]+'

permissions:
  contents: write

jobs:
  build:
    name: Build ${{ matrix.target }}
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - target: x86_64-unknown-linux-gnu
            os: ubuntu-22.04
            bin: remit
            archive: tar.gz
          - target: aarch64-unknown-linux-gnu
            os: ubuntu-22.04
            bin: remit
            archive: tar.gz
          - target: x86_64-unknown-linux-musl
            os: ubuntu-22.04
            bin: remit
            archive: tar.gz
            musl: true
          - target: aarch64-unknown-linux-musl
            os: ubuntu-22.04
            bin: remit
            archive: tar.gz
            musl: true
            cross_arch: true
          - target: x86_64-apple-darwin
            os: macos-latest
            bin: remit
            archive: tar.gz
          - target: aarch64-apple-darwin
            os: macos-latest
            bin: remit
            archive: tar.gz
          - target: x86_64-pc-windows-msvc
            os: windows-latest
            bin: remit.exe
            archive: zip

    steps:
      - uses: actions/checkout@v4

      - name: Install Rust stable
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}

      - name: Install cross-compilation tools (Linux aarch64 glibc)
        if: matrix.target == 'aarch64-unknown-linux-gnu'
        run: |
          sudo apt-get update
          sudo apt-get install -y gcc-aarch64-linux-gnu

      - name: Configure cross-linker (Linux aarch64 glibc)
        if: matrix.target == 'aarch64-unknown-linux-gnu'
        run: |
          echo '[target.aarch64-unknown-linux-gnu]' >> ~/.cargo/config.toml
          echo 'linker = "aarch64-linux-gnu-gcc"' >> ~/.cargo/config.toml

      - name: Install musl tools (x86_64)
        if: matrix.target == 'x86_64-unknown-linux-musl'
        run: sudo apt-get update && sudo apt-get install -y musl-tools

      - name: Install cross (aarch64 musl)
        if: matrix.target == 'aarch64-unknown-linux-musl'
        run: cargo install cross --git https://github.com/cross-rs/cross

      - name: Cache Cargo
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ${{ runner.os }}-${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }}

      - name: Build release binary (with keychain)
        if: "!matrix.musl"
        run: cargo build --release --target ${{ matrix.target }}

      - name: Build release binary (musl x86_64 — no keychain)
        if: matrix.musl && !matrix.cross_arch
        run: cargo build --release --target ${{ matrix.target }} --no-default-features
        env:
          RUSTFLAGS: "-C target-feature=+crt-static"

      - name: Build release binary (musl aarch64 via cross — no keychain)
        if: matrix.musl && matrix.cross_arch
        run: cross build --release --target ${{ matrix.target }} --no-default-features

      - name: Package archive (tar.gz)
        if: matrix.archive == 'tar.gz'
        shell: bash
        run: |
          tar czf remit-${{ matrix.target }}.tar.gz -C target/${{ matrix.target }}/release ${{ matrix.bin }}

      - name: Package archive (zip)
        if: matrix.archive == 'zip'
        shell: bash
        run: |
          cd target/${{ matrix.target }}/release
          7z a ../../../remit-${{ matrix.target }}.zip ${{ matrix.bin }}

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: remit-${{ matrix.target }}
          path: remit-${{ matrix.target }}.${{ matrix.archive }}

  publish-crate:
    name: Publish to crates.io
    needs: [build]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - run: cargo publish --allow-dirty
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}

  release:
    name: Create GitHub Release
    needs: [build]
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

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

      - name: Create release
        uses: softprops/action-gh-release@v2
        with:
          files: artifacts/*
          generate_release_notes: true
          draft: false
          prerelease: ${{ contains(github.ref_name, '-') }}

      - name: Compute SHA256 checksums
        id: checksums
        run: |
          cd artifacts
          for f in *; do
            name=$(echo "$f" | sed 's/[^a-zA-Z0-9]/_/g')
            sha=$(sha256sum "$f" | cut -d' ' -f1)
            echo "${name}=${sha}" >> "$GITHUB_OUTPUT"
          done

      - name: Update Homebrew tap
        if: "!contains(github.ref_name, '-')"
        continue-on-error: true
        uses: peter-evans/repository-dispatch@v3
        with:
          token: ${{ secrets.TAP_GITHUB_TOKEN }}
          repository: remit-md/homebrew-tap
          event-type: release-published
          client-payload: |
            {
              "version": "${{ github.ref_name }}",
              "sha_linux_x86": "${{ steps.checksums.outputs.remit_x86_64_unknown_linux_gnu_tar_gz }}",
              "sha_linux_arm": "${{ steps.checksums.outputs.remit_aarch64_unknown_linux_gnu_tar_gz }}",
              "sha_linux_musl_x86": "${{ steps.checksums.outputs.remit_x86_64_unknown_linux_musl_tar_gz }}",
              "sha_linux_musl_arm": "${{ steps.checksums.outputs.remit_aarch64_unknown_linux_musl_tar_gz }}",
              "sha_macos_x86": "${{ steps.checksums.outputs.remit_x86_64_apple_darwin_tar_gz }}",
              "sha_macos_arm": "${{ steps.checksums.outputs.remit_aarch64_apple_darwin_tar_gz }}",
              "sha_windows_x86": "${{ steps.checksums.outputs.remit_x86_64_pc_windows_msvc_zip }}"
            }

      - name: Update Scoop bucket
        if: "!contains(github.ref_name, '-')"
        continue-on-error: true
        uses: peter-evans/repository-dispatch@v3
        with:
          token: ${{ secrets.TAP_GITHUB_TOKEN }}
          repository: remit-md/scoop-bucket
          event-type: release-published
          client-payload: |
            {
              "version": "${{ github.ref_name }}",
              "sha_windows_x86": "${{ steps.checksums.outputs.remit_x86_64_pc_windows_msvc_zip }}"
            }

  publish-npm:
    name: Publish to npm
    needs: [release]
    if: "!contains(github.ref_name, '-')"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: "22"
          registry-url: "https://registry.npmjs.org"

      - name: Patch version from tag
        run: |
          VERSION="${GITHUB_REF_NAME#v}"
          cd npm
          node -e "
            const pkg = require('./package.json');
            pkg.version = '${VERSION}';
            require('fs').writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');
          "

      - name: Publish
        run: cd npm && npm publish --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

  publish-pypi:
    name: Publish to PyPI
    needs: [release]
    if: "!contains(github.ref_name, '-')"
    runs-on: ubuntu-latest
    permissions:
      id-token: write
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Patch version from tag
        run: |
          VERSION="${GITHUB_REF_NAME#v}"
          cd pypi
          sed -i "s/^version = .*/version = \"${VERSION}\"/" pyproject.toml
          sed -i "s/^__version__ = .*/__version__ = \"${VERSION}\"/" remit_cli/__init__.py

      - name: Build sdist
        run: cd pypi && pip install build && python -m build --sdist

      - uses: pypa/gh-action-pypi-publish@release/v1
        with:
          packages-dir: pypi/dist/
          skip-existing: true

  publish-snap:
    name: Publish to Snap Store
    needs: [release]
    if: "!contains(github.ref_name, '-')"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Patch version from tag
        run: |
          VERSION="${GITHUB_REF_NAME#v}"
          sed -i "s/^version: .*/version: '${VERSION}'/" snap/snapcraft.yaml

      - uses: snapcore/action-build@v1
        id: build

      - uses: snapcore/action-publish@v1
        env:
          SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_TOKEN }}
        with:
          snap: ${{ steps.build.outputs.snap }}
          release: stable
