troy 0.1.1

Superfast primitives and data structures for high frequency trading
Documentation
name: release

# Triggered by `v*` tags (push one with `make release`). Checks the tag matches
# the version in Cargo.toml, runs lint, tests and the doc build, and extracts
# the matching section from docs/release-notes.md - every step that can fail
# runs before the crates.io publish, which cannot be taken back for a version.
# It then publishes the crate and the extracted notes as the GitHub Release
# body. Re-runs idempotently update an existing release rather than failing.

on:
  push:
    tags:
      - "v*"

permissions:
  contents: write

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1

jobs:
  release:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}

    steps:
      - name: checkout code
        uses: actions/checkout@v5
        with:
          fetch-depth: 0

      - name: Install rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt, clippy

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

      - name: Check tag matches Cargo.toml version
        run: |
          TAG="${GITHUB_REF_NAME}"
          VERSION="$(cargo pkgid | sed 's/.*[#@]//')"
          if [ "$TAG" != "v${VERSION}" ]; then
            echo "Tag ${TAG} does not match Cargo.toml version ${VERSION}" >&2
            exit 1
          fi

      - name: run lint
        run: .dev/rs-lint

      - name: tests
        run: make rs-test

      - name: build docs
        # a rustdoc warning is a broken page on docs.rs, which cannot be
        # rebuilt for a version once it is published
        env:
          RUSTDOCFLAGS: -Dwarnings
        run: make docs

      - name: Extract release notes
        run: |
          TAG="${GITHUB_REF_NAME}"
          awk -v tag="## ${TAG}" '
            $0 == tag { in_section = 1; next }
            /^## / && in_section { exit }
            in_section { print }
          ' docs/release-notes.md > /tmp/notes.md
          if [ ! -s /tmp/notes.md ]; then
            echo "No section '## ${TAG}' found in docs/release-notes.md" >&2
            exit 1
          fi
          echo "--- extracted notes for ${TAG} ---"
          cat /tmp/notes.md

      - name: publish to crates.io
        run: make rs-publish

      - name: Publish GitHub Release
        run: |
          TAG="${GITHUB_REF_NAME}"
          if gh release view "$TAG" >/dev/null 2>&1; then
            gh release edit "$TAG" --notes-file /tmp/notes.md
          else
            gh release create "$TAG" --title "$TAG" --notes-file /tmp/notes.md
          fi