axonflow-sdk-rust 0.6.0

Rust SDK for the AxonFlow AI governance platform
Documentation
name: Release

on:
  push:
    tags:
      - 'v*'

permissions:
  contents: write

env:
  AXONFLOW_TELEMETRY: 'off'
  CARGO_TERM_COLOR: always

jobs:
  preflight:
    name: Preflight (CHANGELOG)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Extract CHANGELOG section for tag
        run: |
          VERSION="${GITHUB_REF#refs/tags/v}"
          awk -v ver="$VERSION" '$0 ~ "^## \\["ver"\\]" {p=1; next} p && /^## \[/ {exit} p {print}' CHANGELOG.md > /tmp/release-body.md
          if [ ! -s /tmp/release-body.md ]; then
            echo "::error::No CHANGELOG.md section found for version $VERSION — refusing to publish."
            echo "::error::Add a '## [$VERSION] - YYYY-MM-DD' section to CHANGELOG.md and re-tag."
            exit 1
          fi
          {
            echo "## AxonFlow Rust SDK v${VERSION}"
            echo ""
            echo "### Installation"
            echo ""
            echo '```toml'
            echo "[dependencies]"
            echo "axonflow-sdk-rust = \"${VERSION}\""
            echo '```'
            echo ""
            echo "### Documentation"
            echo ""
            echo "- [docs.rs](https://docs.rs/axonflow-sdk-rust/${VERSION})"
            echo "- [README](https://github.com/getaxonflow/axonflow-sdk-rust#readme)"
            echo "- [Examples](https://github.com/getaxonflow/axonflow-sdk-rust/tree/main/examples)"
            echo ""
            cat /tmp/release-body.md
          } > /tmp/release-body-final.md
          echo "Release body: $(wc -l < /tmp/release-body-final.md) lines"

      - name: Verify Cargo.toml version matches tag
        run: |
          VERSION="${GITHUB_REF#refs/tags/v}"
          CARGO_VERSION=$(awk -F'"' '/^version *=/ {print $2; exit}' Cargo.toml)
          if [ "$VERSION" != "$CARGO_VERSION" ]; then
            echo "::error::Tag v${VERSION} does not match Cargo.toml version ${CARGO_VERSION}."
            echo "::error::Bump Cargo.toml to ${VERSION} and re-tag."
            exit 1
          fi

      - uses: actions/upload-artifact@v7
        with:
          name: release-body
          path: /tmp/release-body-final.md
          retention-days: 1

  test:
    name: Test (release)
    needs: preflight
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - run: cargo test --all-features
      - run: cargo build --examples

  release:
    name: Create GitHub Release
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - uses: actions/download-artifact@v8
        with:
          name: release-body
          path: /tmp/release-body

      - name: Create Release
        uses: softprops/action-gh-release@v3
        with:
          name: Release ${{ github.ref_name }}
          body_path: /tmp/release-body/release-body-final.md
          generate_release_notes: false
          draft: false
          prerelease: false
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  # Publish to crates.io. Mirrors the PyPI / npm / Maven Central publish-on-tag
  # pattern from the established four SDKs. Requires CARGO_REGISTRY_TOKEN repo
  # secret (https://crates.io/me — generate a publish token, save as a secret).
  #
  # Runs AFTER the GitHub release is created, so a transient crates.io failure
  # does not erase the GH release. If publish fails, fix the underlying issue
  # and run `cargo publish` locally one time, OR cut a patch tag (vX.Y.Z+1).
  publish-cratesio:
    name: Publish to crates.io
    needs: release
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2

      - name: Verify CARGO_REGISTRY_TOKEN secret is configured
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
        run: |
          if [ -z "$CARGO_REGISTRY_TOKEN" ]; then
            echo "::error::CARGO_REGISTRY_TOKEN secret is not set."
            echo "::error::Generate a publish token at https://crates.io/me and add it as a repo secret."
            exit 1
          fi

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

      - name: Verify version is live on crates.io
        # Poll the API up to ~7.5 minutes (30 × 15s). v0.1.0 needed >30s; v0.2.0
        # took ~3-5 minutes (workflow run 25604826136 polled 3 min and false-failed
        # while the version was already created in the crates.io DB but the public
        # API endpoint was still serving a cached 404). 7.5 min covers the
        # observed propagation envelope with headroom; polling instead of sleeping
        # gives the fastest exit once it's live.
        run: |
          VERSION="${GITHUB_REF#refs/tags/v}"
          for i in $(seq 1 30); do
            if curl -sf "https://crates.io/api/v1/crates/axonflow-sdk-rust/${VERSION}" > /dev/null; then
              echo "✅ axonflow-sdk-rust@${VERSION} is live on crates.io (after ${i} attempt(s))"
              exit 0
            fi
            echo "Waiting for crates.io propagation… (attempt ${i}/30)"
            sleep 15
          done
          echo "::error::axonflow-sdk-rust@${VERSION} not found on crates.io after 7.5 minutes."
          echo "::error::cargo publish succeeded earlier in this job — check https://crates.io/crates/axonflow-sdk-rust manually before re-running."
          exit 1