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

name: "Release"

jobs:
  crate-info:
    name: "Extract crate info"
    runs-on: "ubuntu-latest"
    outputs:
      version: ${{ steps.derive.outputs.version }}

    steps:
      - id: "derive"
        name: "Derive crate info from Git tag"
        run: |
          FULL_REF="${{ github.ref }}"
          REGEX="^refs\/tags\/v(.*)$"
          [[ $FULL_REF =~ $REGEX ]];

          echo "version=${BASH_REMATCH[1]}" >> $GITHUB_OUTPUT

  # Just in case we accidentally release something not on master.
  commit-branch-check:
    name: "Check commit branch"
    runs-on: "ubuntu-latest"
    needs: ["crate-info"]

    steps:
      - name: "Checkout source code"
        uses: "actions/checkout@v4"
        with:
          fetch-depth: 0

      - name: "Check if commit is on master"
        run: |
          COMMIT_HASH=$(git log -1 --format=%H ${{ github.ref }})
          GREP_OUTPUT=$(git log origin/master --format=%H | grep "$COMMIT_HASH")

          if [ -z "$GREP_OUTPUT" ]; then
            echo "Cannot release commits not on the master branch"
            exit 1
          fi

  crate-version-check:
    name: "Check crate version"
    runs-on: "ubuntu-latest"
    needs: ["crate-info"]

    steps:
      - name: "Checkout source code"
        uses: "actions/checkout@v4"

      - name: "Check against Cargo.toml"
        run: |
          GREP_OUTPUT=$(cat Cargo.toml | grep "^version = \"${{ needs.crate-info.outputs.version }}\"$")

          if [ -z "$GREP_OUTPUT" ]; then
            echo "Crate version mismatch"
            exit 1
          fi

  build:
    name: "Build for ${{ matrix.os }}"
    runs-on: "${{ matrix.os }}"
    needs: ["crate-info"]

    strategy:
      matrix:
        os:
          - "ubuntu-latest"
          - "windows-latest"
          - "macos-latest"

    steps:
      - name: "Checkout source code"
        uses: "actions/checkout@v4"

      - name: "Setup stable toolchain"
        uses: "actions-rs/toolchain@v1"
        with:
          toolchain: "stable"
          profile: "minimal"
          override: true

      - name: "Build crate"
        run: |
          cargo build --all --all-targets

  crates-io-release:
    name: "Release to crates.io"
    runs-on: "ubuntu-latest"

    needs:
      - "crate-info"
      - "commit-branch-check"
      - "crate-version-check"
      - "build"

    steps:
      - name: "Checkout source code"
        uses: "actions/checkout@v4"

      - name: "Login to crates.io"
        run: |
          cargo login ${{ secrets.CRATES_IO_API_TOKEN }}

      - name: "Publish crate"
        run: |
          cargo publish
