sqlitegis 0.1.4

SQLiteGIS: PostGIS-style spatial functions for SQLite in pure Rust.
Documentation
name: Release

on:
  push:
    tags:
      - "v*"

permissions:
  contents: read

env:
  CARGO_TERM_COLOR: always

jobs:
  verify-version:
    name: Verify tag matches version
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v5

      - name: Check tag against Cargo.toml version
        run: |
          tag="${GITHUB_REF_NAME#v}"
          manifest="$(grep -m1 '^version = ' Cargo.toml | sed -E 's/version = "(.*)"/\1/')"
          echo "tag version: $tag"
          echo "manifest version: $manifest"
          if [ "$tag" != "$manifest" ]; then
            echo "::error::tag $tag does not match Cargo.toml version $manifest"
            exit 1
          fi

  ci-green:
    name: CI is green on tagged commit
    runs-on: ubuntu-latest
    needs: verify-version
    permissions:
      contents: read
      actions: read

    steps:
      - name: Wait for CI to finish on the tagged commit
        env:
          GH_TOKEN: ${{ github.token }}
          SHA: ${{ github.sha }}
        run: |
          # `github.sha` for a tag push is the commit the tag points at, which
          # is the same commit CI runs against on `push: branches: [main]`.
          # Poll `workflow_runs?head_sha=$SHA` until the run for this commit is
          # complete, then require its conclusion to be `success`. Using a URL
          # query string keeps this a GET. Passing the same keys via
          # `gh api --field` turns it into a POST, which the endpoint answers
          # with 404.
          attempts=0
          max_attempts=60          # 60 * 30s = 30 minutes
          sleep_seconds=30
          while :; do
            run="$(gh api \
              "repos/${GITHUB_REPOSITORY}/actions/workflows/ci.yml/runs?head_sha=${SHA}&per_page=10" \
              --jq '[.workflow_runs[] | select(.event == "push" or .event == "workflow_dispatch")][0] // {}')"
            status="$(printf '%s' "$run" | jq -r '.status // "missing"')"
            conclusion="$(printf '%s' "$run" | jq -r '.conclusion // "null"')"
            echo "CI run for ${SHA}: status='${status}' conclusion='${conclusion}'"
            if [ "$status" = "completed" ]; then
              break
            fi
            attempts=$((attempts + 1))
            if [ "$attempts" -ge "$max_attempts" ]; then
              echo "::error::Timed out waiting for CI on ${SHA} to finish (status='${status}')."
              exit 1
            fi
            sleep "$sleep_seconds"
          done
          if [ "$conclusion" != "success" ]; then
            echo "::error::CI for ${SHA} has conclusion '${conclusion}'. CI must be green before releasing."
            exit 1
          fi
          echo "CI for ${SHA} is green."

  publish:
    name: Publish to crates.io
    needs: ci-green
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write

    steps:
      - name: Checkout
        uses: actions/checkout@v5

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

      - name: Authenticate to crates.io
        id: auth
        uses: rust-lang/crates-io-auth-action@v1

      - name: Publish crate
        run: cargo publish --locked
        env:
          CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}