go 0.1.2

A runtime-agnostic Go-style concurrency library for Rust
Documentation
name: Release

# Manually triggered release: enter the target version and the workflow bumps
# the crate version, runs the test gate, tags the commit, publishes to
# crates.io, and creates a GitHub release.
on:
  workflow_dispatch:
    inputs:
      version:
        description: Release version without the leading v (e.g. 0.2.0)
        required: true
        type: string

permissions:
  contents: write

concurrency:
  group: release
  cancel-in-progress: false

env:
  CARGO_TERM_COLOR: always

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: dtolnay/rust-toolchain@stable

      - uses: Swatinem/rust-cache@v2

      - name: Normalize version
        id: meta
        shell: bash
        env:
          INPUT_VERSION: ${{ github.event.inputs.version }}
        run: |
          version="${INPUT_VERSION#v}"
          if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then
            echo "::error::Invalid version '$version' (expected semver like 1.2.3)"
            exit 1
          fi
          echo "version=$version" >> "$GITHUB_OUTPUT"
          echo "tag=v$version" >> "$GITHUB_OUTPUT"

      - name: Fail if tag already exists
        shell: bash
        env:
          TAG: ${{ steps.meta.outputs.tag }}
        run: |
          if git rev-parse "$TAG" >/dev/null 2>&1; then
            echo "::error::Tag $TAG already exists"
            exit 1
          fi

      - name: Set crate version
        shell: bash
        env:
          VERSION: ${{ steps.meta.outputs.version }}
        run: |
          # Replace only the package version (the first `version = "..."` line,
          # in the [package] table) — dependency versions are left untouched.
          awk -v v="$VERSION" '
            !done && /^version = "/ { sub(/"[^"]*"/, "\"" v "\""); done = 1 }
            { print }
          ' Cargo.toml > Cargo.toml.tmp && mv Cargo.toml.tmp Cargo.toml
          grep -m1 '^version = ' Cargo.toml

      - name: Refresh lockfile
        run: cargo check

      - name: Run tests
        run: cargo test

      - name: Verify the package is publishable
        run: cargo publish --dry-run --allow-dirty

      - name: Commit, tag, and push
        shell: bash
        env:
          VERSION: ${{ steps.meta.outputs.version }}
          TAG: ${{ steps.meta.outputs.tag }}
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
          git add Cargo.toml Cargo.lock
          git commit -m "release: $TAG"
          git tag -a "$TAG" -m "Release $TAG"
          git push origin HEAD
          git push origin "$TAG"

      - name: Publish to crates.io
        run: cargo publish
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}

      - name: Create GitHub release
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ steps.meta.outputs.tag }}
          name: ${{ steps.meta.outputs.tag }}
          generate_release_notes: true