name: Release

on:
  workflow_dispatch:
    inputs:
      version:
        description: "Version to release (e.g. 0.1.0 or 0.1.0-pre1)"
        required: true
        type: string

permissions:
  contents: write
  packages: write

env:
  CARGO_TERM_COLOR: always

jobs:
  prepare:
    runs-on: ubuntu-24.04
    timeout-minutes: 5
    outputs:
      version: ${{ steps.version.outputs.version }}
      tag: ${{ steps.version.outputs.tag }}
      prerelease: ${{ steps.version.outputs.prerelease }}
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-tags: true

      - name: Validate and normalize version
        id: version
        run: |
          INPUT="${{ inputs.version }}"
          if ! echo "$INPUT" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$'; then
            echo "::error::Invalid version format. Use semver like 0.1.0 or 0.1.0-pre1"
            exit 1
          fi
          TAG="v${INPUT}"
          if git rev-parse "$TAG" >/dev/null 2>&1; then
            echo "::error::Tag $TAG already exists"
            exit 1
          fi
          if echo "$INPUT" | grep -q '-'; then
            echo "prerelease=true" >> "$GITHUB_OUTPUT"
          else
            echo "prerelease=false" >> "$GITHUB_OUTPUT"
          fi
          echo "version=${INPUT}" >> "$GITHUB_OUTPUT"
          echo "tag=${TAG}" >> "$GITHUB_OUTPUT"

      - name: Bump version and tag
        run: |
          sed -i 's/^version = ".*"/version = "${{ steps.version.outputs.version }}"/' Cargo.toml
          cargo update -p kap
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git add Cargo.toml Cargo.lock
          git commit -m "Release ${{ steps.version.outputs.tag }}"
          git tag "${{ steps.version.outputs.tag }}"
          git push origin main --tags

  build:
    needs: prepare
    strategy:
      matrix:
        include:
          - target: x86_64-apple-darwin
            os: macos-26
            cross: false
          - target: aarch64-apple-darwin
            os: macos-26
            cross: false
          - target: x86_64-unknown-linux-gnu
            os: ubuntu-24.04
            cross: false
          - target: x86_64-unknown-linux-musl
            os: ubuntu-24.04
            cross: false
          - target: aarch64-unknown-linux-gnu
            os: ubuntu-24.04
            cross: true
    runs-on: ${{ matrix.os }}
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ needs.prepare.outputs.tag }}

      - uses: jdx/mise-action@v2

      - name: Add Rust target
        if: "!matrix.cross"
        run: rustup target add ${{ matrix.target }}

      - uses: Swatinem/rust-cache@v2
        with:
          key: ${{ matrix.target }}

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

      - name: Install cross
        if: matrix.cross
        run: cargo install cross --git https://github.com/cross-rs/cross

      - name: Build with cargo
        if: "!matrix.cross"
        run: cargo build --release --target ${{ matrix.target }}

      - name: Build with cross
        if: matrix.cross
        run: cross build --release --target ${{ matrix.target }}

      - name: Package tarball
        run: |
          cd target/${{ matrix.target }}/release
          tar czf ../../../kap-${{ matrix.target }}.tar.gz kap

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: kap-${{ matrix.target }}
          path: kap-${{ matrix.target }}.tar.gz

  release:
    needs: [build, prepare]
    runs-on: ubuntu-24.04
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ needs.prepare.outputs.tag }}

      - uses: actions/download-artifact@v4
        with:
          pattern: kap-*
          merge-multiple: true

      - name: Create GitHub release
        run: |
          FLAGS="--generate-notes"
          if [ "${{ needs.prepare.outputs.prerelease }}" = "true" ]; then
            FLAGS="$FLAGS --prerelease"
          fi
          gh release create "${{ needs.prepare.outputs.tag }}" kap-*.tar.gz $FLAGS
        env:
          GH_TOKEN: ${{ github.token }}

  publish:
    needs: [build, prepare]
    runs-on: ubuntu-24.04
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ needs.prepare.outputs.tag }}

      - uses: jdx/mise-action@v2

      - uses: Swatinem/rust-cache@v2

      - name: Publish to crates.io
        run: cargo publish
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}

  docker:
    needs: prepare
    runs-on: ubuntu-24.04
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ needs.prepare.outputs.tag }}

      - uses: docker/setup-qemu-action@v3

      - uses: docker/setup-buildx-action@v3

      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and push multi-arch image
        uses: docker/build-push-action@v6
        with:
          context: .
          file: .devcontainer/Dockerfile
          target: proxy
          platforms: linux/amd64,linux/arm64
          push: true
          tags: |
            ghcr.io/${{ github.repository }}:latest
            ghcr.io/${{ github.repository }}:${{ needs.prepare.outputs.tag }}
