name: release

on:
  push:
    tags:
      - "v*.*.*"

env:
  TOOLCHAIN_VERSION: 1.95.0
  CARGO_PROFILE_RELEASE_LTO: "fat"
  CARGO_PROFILE_RELEASE_CODEGEN_UNITS: "1"
  PNPM_OFFLINE: "TRUE"

jobs:
  changelog:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Get release notes from changelog
        id: release_notes
        run: |
          export VERSION=$(echo ${{  github.ref_name }} | sed 's/^v//')
          echo "VERSION = ${VERSION}"
          awk "/## v${VERSION}.*/{include=1; next} /## v.*/{include=0} include && NF" CHANGELOG.md > ./CHANGELOG-release.md
          cat ./CHANGELOG-release.md

      - name: Release Changelog
        uses: softprops/action-gh-release@v2
        with:
          generate_release_notes: true
          body_path: ./CHANGELOG-release.md

  # NOTE: We use Docker. Otherwise getting compatible versions for
  # musl-gcc, g++ (GEOS is C++) and rustc is borderline impossible.
  release-x86_64-linux-musl:
    needs: changelog
    runs-on: ubuntu-latest
    env:
      RUST_TARGET: x86_64-unknown-linux-musl
      BINARY_PATH: target/$RUST_TARGET/release/trail
      ARCHIVE_NAME: trailbase_${{  github.ref_name }}_x86_64_linux.zip
      DOCKER_WORKSPACE: /workspace

    steps:
      - uses: actions/checkout@v6
        with:
          submodules: 'recursive'
          # No shallow checkout, i.e. fetch all tags (used for versioning the binary).
          fetch-depth: 0
      - name: Inspect Checkout
        run: git describe --tags
      - uses: actions/setup-node@v6
        with:
          node-version: 22
      - uses: pnpm/action-setup@v4
        with:
          version: 10
      - name: PNPM install
        run: pnpm install
      - name: Build a Builder Image
        run: |
          docker build -f Dockerfile.ci \
            --build-arg BASE_IMAGE_TAG=x86_64-musl \
            --build-arg RUST_TARGET=${{ env.RUST_TARGET }} \
            --build-arg RUST_TOOLCHAIN_VERSION=${{ env.TOOLCHAIN_VERSION }} \
            --build-arg WORKSPACE=${{ env.DOCKER_WORKSPACE }} \
            -t builder:latest .

      - name: Rust Build using the Builder
        run: |
          env && \
          docker run --rm \
            -v ${{ github.workspace }}:${{ env.DOCKER_WORKSPACE }} \
            -e CARGO_PROFILE_RELEASE_LTO=${{ env.CARGO_PROFILE_RELEASE_LTO }} \
            -e CARGO_PROFILE_RELEASE_CODEGEN_UNITS=${{ env.CARGO_PROFILE_RELEASE_CODEGEN_UNITS }} \
            -e PNPM_OFFLINE=FALSE \
            builder:latest \
              sh -c "git describe --tags && /root/.cargo/bin/cargo build --target ${{ env.RUST_TARGET }} --release --features=geos-static --bin trail"

      - name: Package Artifacts
        run: |
          ${{ env.BINARY_PATH }} --version && \
          zip -r -j ${{ env.ARCHIVE_NAME }} ${{ env.BINARY_PATH }} CHANGELOG.md LICENSE
      - name: Release binaries
        uses: softprops/action-gh-release@v2
        with:
          fail_on_unmatched_files: true
          files: ${{ env.ARCHIVE_NAME }}

  release-aarch64-linux-musl:
    needs: changelog
    runs-on: ubuntu-24.04-arm
    env:
      RUST_TARGET: aarch64-unknown-linux-musl
      BINARY_PATH: target/$RUST_TARGET/release/trail
      ARCHIVE_NAME: trailbase_${{  github.ref_name }}_arm64_linux.zip
      DOCKER_WORKSPACE: /workspace

    steps:
      - uses: actions/checkout@v6
        with:
          submodules: 'recursive'
          # No shallow checkout, i.e. fetch all tags (used for versioning the binary).
          fetch-depth: 0
      - name: Inspect Checkout
        run: git describe --tags
      - uses: actions/setup-node@v6
        with:
          node-version: 22
      - uses: pnpm/action-setup@v4
        with:
          version: 10
      - name: PNPM install
        run: pnpm install
      - name: Build a Builder Image
        run: |
          docker build -f Dockerfile.ci \
            --build-arg BASE_IMAGE_TAG=aarch64-musl \
            --build-arg RUST_TARGET=${{ env.RUST_TARGET }} \
            --build-arg RUST_TOOLCHAIN_VERSION=${{ env.TOOLCHAIN_VERSION }} \
            --build-arg WORKSPACE=${{ env.DOCKER_WORKSPACE }} \
            -t builder:latest .

      - name: Rust Build using the Builder
        run: |
          env && \
          docker run --rm \
            -v ${{ github.workspace }}:${{ env.DOCKER_WORKSPACE }} \
            -e CARGO_PROFILE_RELEASE_LTO=${{ env.CARGO_PROFILE_RELEASE_LTO }} \
            -e CARGO_PROFILE_RELEASE_CODEGEN_UNITS=${{ env.CARGO_PROFILE_RELEASE_CODEGEN_UNITS }} \
            -e PNPM_OFFLINE=FALSE \
            builder:latest \
              sh -c "git describe --tags && /root/.cargo/bin/cargo build --target ${{ env.RUST_TARGET }} --release --features=geos-static --bin trail"

      - name: Package Artifacts
        run: |
          ${{ env.BINARY_PATH }} --version && \
          zip -r -j ${{ env.ARCHIVE_NAME }} ${{ env.BINARY_PATH }} CHANGELOG.md LICENSE
      - name: Release binaries
        uses: softprops/action-gh-release@v2
        with:
          fail_on_unmatched_files: true
          files: ${{ env.ARCHIVE_NAME }}

  release-aarch64-apple-darwin:
    needs: changelog
    runs-on: macos-15
    env:
      RUST_TARGET: aarch64-apple-darwin
      BINARY_PATH: target/$RUST_TARGET/release/trail
      ARCHIVE_NAME: trailbase_${{  github.ref_name }}_arm64_apple_darwin.zip
    steps:
      - uses: actions/checkout@v6
        with:
          submodules: 'recursive'
          # No shallow checkout, i.e. fetch all tags (used for versioning the binary).
          fetch-depth: 0
      - name: Inspect Checkout
        run: git describe --tags
      - name: Install Dependencies
        run: brew update && brew install protobuf pnpm
      - name: PNPM install
        run: pnpm install --dangerously-allow-all-builds
      # CMake v4 is too new: https://github.com/georust/geos/issues/194
      - name: Downgrade CMake
        run: pipx install --force cmake==3.31.10
      - uses: actions-rs/toolchain@v1
        with:
          toolchain: ${{ env.TOOLCHAIN_VERSION }}
          target: ${{ env.RUST_TARGET }}
          default: true
      - name: Rust Build
        run: |
          env && \
            cargo build --target ${{ env.RUST_TARGET }} --release --features=geos-static --bin trail

      - name: Package Artifacts
        run: |
          ${{ env.BINARY_PATH }} --version && \
          zip -r -j ${{ env.ARCHIVE_NAME }} ${{ env.BINARY_PATH }} CHANGELOG.md LICENSE
      - name: Release binaries
        uses: softprops/action-gh-release@v2
        with:
          fail_on_unmatched_files: true
          files: ${{ env.ARCHIVE_NAME }}

  release-x86_64-apple-darwin:
    needs: changelog
    runs-on: macos-15
    env:
      RUST_TARGET: x86_64-apple-darwin
      BINARY_PATH: target/$RUST_TARGET/release/trail
      ARCHIVE_NAME: trailbase_${{  github.ref_name }}_x86_64_apple_darwin.zip
    steps:
      - uses: actions/checkout@v6
        with:
          submodules: 'recursive'
          # No shallow checkout, i.e. fetch all tags (used for versioning the binary).
          fetch-depth: 0
      - name: Inspect Checkout
        run: git describe --tags
      - name: Install Dependencies
        run: brew update && brew install protobuf pnpm
      - name: PNPM install
        run: pnpm install --dangerously-allow-all-builds
      # CMake v4 is too new: https://github.com/georust/geos/issues/194
      - name: Downgrade CMake
        run: pipx install --force cmake==3.31.10
      - uses: actions-rs/toolchain@v1
        with:
          toolchain: ${{ env.TOOLCHAIN_VERSION }}
          target: ${{ env.RUST_TARGET }}
          default: true
      - name: Rust Build
        run: |
          env && \
            cargo build --target ${{ env.RUST_TARGET }} --release --features=geos-static --bin trail

      - name: Package Artifacts
        run: |
          ${{ env.BINARY_PATH }} --version && \
          zip -r -j ${{ env.ARCHIVE_NAME }} ${{ env.BINARY_PATH }} CHANGELOG.md LICENSE
      - name: Release binaries
        uses: softprops/action-gh-release@v2
        with:
          fail_on_unmatched_files: true
          files: ${{ env.ARCHIVE_NAME }}

  release-x86_64-windows:
    needs: changelog
    runs-on: windows-latest
    env:
      RUST_TARGET: x86_64-pc-windows-msvc
      BINARY_PATH: target/x86_64-pc-windows-msvc/release/trail.exe
      ARCHIVE_NAME: trailbase_${{  github.ref_name }}_x86_64_windows.zip
    steps:
      - uses: actions/checkout@v6
        with:
          submodules: 'recursive'
          # No shallow checkout, i.e. fetch all tags (used for versioning the binary).
          fetch-depth: 0
      - name: Inspect Checkout
        run: git describe --tags
      - uses: MinoruSekine/setup-scoop@v4.0.1
        with:
          buckets: extras
          apps: nodejs pnpm protobuf zip
      - name: PNPM install
        shell: bash
        run: pnpm install --dangerously-allow-all-builds
      - uses: actions-rs/toolchain@v1
        with:
          toolchain: ${{ env.TOOLCHAIN_VERSION }}
          target: ${{ env.RUST_TARGET }}
          default: true
      - name: Rust Build
        shell: bash
        run: |
          env && \
            cargo build --target ${{ env.RUST_TARGET }} --release --features=geos-static --bin trail

      - name: Package Artifacts
        run: |
          ${{ env.BINARY_PATH }} --version &&
            zip -r -j ${{ env.ARCHIVE_NAME }} ${{ env.BINARY_PATH }} CHANGELOG.md LICENSE
      - name: Release binaries
        uses: softprops/action-gh-release@v2
        with:
          fail_on_unmatched_files: true
          files: ${{ env.ARCHIVE_NAME }}

  release-wasm-auth-ui:
    needs: changelog
    runs-on: ubuntu-latest
    env:
      RUST_TARGET: wasm32-wasip2
      BINARY_PATH: target/$RUST_TARGET/release/auth_ui_component.wasm
      ARCHIVE_NAME: trailbase_${{  github.ref_name }}_wasm_auth_ui.zip
    steps:
      - uses: actions/checkout@v6
        with:
          submodules: 'recursive'
          # No shallow checkout, i.e. fetch all tags (used for versioning the binary).
          fetch-depth: 0
      - name: Inspect Checkout
        run: git describe --tags
      - name: Install Dependencies
        run: |
          sudo apt-get update && \
            sudo apt-get install -y --no-install-recommends curl libssl-dev pkg-config libclang-dev protobuf-compiler libprotobuf-dev zip
      - uses: actions/setup-node@v6
        with:
          node-version: 22
      - uses: pnpm/action-setup@v4
        with:
          version: 10
      - name: PNPM install
        run: pnpm install
      - uses: actions-rs/toolchain@v1
        with:
          toolchain: ${{ env.TOOLCHAIN_VERSION }}
          target: ${{ env.RUST_TARGET }}
          default: true
      - name: Rust Build
        run: |
          env && cd crates/auth-ui && \
            cargo build --target ${{ env.RUST_TARGET }} --release

      - name: Package Artifacts
        run: |
          zip -r -j ${{ env.ARCHIVE_NAME }} ${{ env.BINARY_PATH }} CHANGELOG.md LICENSE
      - name: Release binaries
        uses: softprops/action-gh-release@v2
        with:
          fail_on_unmatched_files: true
          files: ${{ env.ARCHIVE_NAME }}
