name: CD

on:
  push:
    tags: ["v*"]

permissions:
  contents: write

env:
  CARGO_TERM_COLOR: always

jobs:
  check:
    name: Check
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Verify version matches tag
        run: |
          tag="${GITHUB_REF#refs/tags/v}"
          version=$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[0].version')
          if [ "$tag" != "$version" ]; then
            echo "::error::Tag v${tag} does not match Cargo.toml version ${version}"
            exit 1
          fi

      - name: Test
        run: cargo test
        env:
          RUSTFLAGS: "-D warnings"

  release:
    name: Release (${{ matrix.target }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: true
      matrix:
        include:
          - target: x86_64-unknown-linux-musl
            os: ubuntu-latest
          - target: aarch64-unknown-linux-musl
            os: ubuntu-latest
          - target: x86_64-apple-darwin
            os: macos-latest
          - target: aarch64-apple-darwin
            os: macos-latest
    steps:
      - uses: actions/checkout@v4

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

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

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

      - name: Install cargo-zigbuild (Linux aarch64)
        if: matrix.target == 'aarch64-unknown-linux-musl'
        run: pip3 install cargo-zigbuild ziglang

      - name: Build
        shell: bash
        run: |
          if [ "${{ matrix.target }}" = "aarch64-unknown-linux-musl" ]; then
            cargo zigbuild --release --target ${{ matrix.target }}
          else
            cargo build --release --target ${{ matrix.target }}
          fi
        env:
          RUSTFLAGS: "-D warnings"

      - name: Package
        shell: bash
        run: |
          tag="${GITHUB_REF#refs/tags/}"
          name="layover-${tag}-${{ matrix.target }}"
          mkdir "$name"
          cp target/${{ matrix.target }}/release/layover "$name/"
          cp LICENSE README.md "$name/"
          tar czf "$name.tar.gz" "$name"
          echo "ASSET=$name.tar.gz" >> "$GITHUB_ENV"

      - name: Upload to release
        uses: softprops/action-gh-release@v2
        with:
          files: ${{ env.ASSET }}
          prerelease: ${{ contains(github.ref, '-rc') || contains(github.ref, '-alpha') || contains(github.ref, '-beta') }}

  publish:
    name: Publish to crates.io
    runs-on: ubuntu-latest
    needs: [check, release]
    if: ${{ !contains(github.ref, '-rc') && !contains(github.ref, '-alpha') && !contains(github.ref, '-beta') }}
    steps:
      - uses: actions/checkout@v4

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Cache cargo
        uses: Swatinem/rust-cache@v2

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

  deploy:
    name: Deploy to server
    runs-on: ubuntu-latest
    needs: [check, release]
    if: ${{ !contains(github.ref, '-rc') && !contains(github.ref, '-alpha') && !contains(github.ref, '-beta') }}
    env:
      AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
      AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      TF_VAR_gandi_api_key: ${{ secrets.GANDI_API_KEY }}
      TF_VAR_certbot_email: ${{ secrets.CERTBOT_EMAIL }}
    steps:
      - uses: actions/checkout@v4

      - name: Write SSH keys
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/layover-sh.pem
          echo "${{ secrets.SSH_PUBLIC_KEY }}" > ~/.ssh/layover-sh.pub
          chmod 600 ~/.ssh/layover-sh.pem
          chmod 644 ~/.ssh/layover-sh.pub

      - name: Download release binary
        env:
          GH_TOKEN: ${{ github.token }}
        run: |
          tag="${GITHUB_REF#refs/tags/}"
          asset="layover-${tag}-x86_64-unknown-linux-musl.tar.gz"
          gh release download "$tag" --pattern "$asset" --dir .
          tar xzf "$asset"
          mkdir -p target/x86_64-unknown-linux-musl/release
          cp "layover-${tag}-x86_64-unknown-linux-musl/layover" target/x86_64-unknown-linux-musl/release/

      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v3

      - name: Terraform Init
        working-directory: deploy
        run: terraform init

      - name: Terraform Apply
        working-directory: deploy
        run: terraform apply -auto-approve -input=false
