cheetah-string 3.1.0

An immutable, clone-cheap UTF-8 string with explicit construction and byte interoperability
Documentation
name: Release

on:
  workflow_dispatch:
    inputs:
      version:
        description: "Version to release, for example 3.1.0"
        required: true
        type: string

permissions:
  contents: read

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: full

jobs:
  validate:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    outputs:
      version: ${{ steps.version.outputs.version }}
      tag: ${{ steps.version.outputs.tag }}

    steps:
      - name: Checkout candidate
        uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
        with:
          fetch-depth: 0

      - name: Set up Rust 1.95
        uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c
        with:
          toolchain: 1.95
          components: rustfmt, clippy

      - name: Resolve release version
        id: version
        shell: bash
        env:
          INPUT_VERSION: ${{ inputs.version }}
        run: |
          VERSION="$INPUT_VERSION"

          if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+([+-][0-9A-Za-z.-]+)?$ ]]; then
            echo "Invalid release version" >&2
            exit 1
          fi

          MANIFEST_VERSION="$(cargo metadata --no-deps --format-version 1 |
            python3 -c 'import json, sys; print(json.load(sys.stdin)["packages"][0]["version"])')"
          if [[ "$MANIFEST_VERSION" != "$VERSION" ]]; then
            echo "Cargo.toml version does not match the requested release" >&2
            exit 1
          fi

          echo "version=$VERSION" >> "$GITHUB_OUTPUT"
          echo "tag=v$VERSION" >> "$GITHUB_OUTPUT"

      - name: Check formatting
        run: cargo fmt --all -- --check

      - name: Lint all targets and features
        run: cargo clippy --all-targets --all-features -- -D warnings

      - name: Test all features
        run: cargo test --all-features

      - name: Test no-default feature matrix
        run: cargo test --no-default-features --features serde,bytes,simd

      - name: Verify allocation contracts
        run: cargo test --test allocation_contract --all-features -- --test-threads=1

      - name: Verify layout contracts
        run: cargo test --test layout_snapshot --all-features -- --nocapture

      - name: Check packaged MSRV consumers
        run: bash scripts/check-msrv-package.sh 1.95

      - name: Build default documentation
        run: RUSTDOCFLAGS="-D warnings" cargo doc --lib --no-deps

      - name: Build all-feature documentation
        run: RUSTDOCFLAGS="-D warnings" cargo doc --lib --no-deps --all-features

      - name: Run repository contracts
        run: python -m unittest discover -s scripts/tests -v

      - name: Install dependency auditor
        run: cargo install cargo-audit --version 0.22.2 --locked

      - name: Audit dependencies
        run: cargo audit -D warnings

      - name: Package crate
        run: cargo package

      - name: Create candidate digest
        shell: bash
        env:
          VERSION: ${{ steps.version.outputs.version }}
        run: |
          cd target/package
          sha256sum "cheetah-string-$VERSION.crate" > "cheetah-string-$VERSION.crate.sha256"

      - name: Upload release candidate
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
        with:
          name: cheetah-string-release-candidate
          path: |
            target/package/cheetah-string-${{ steps.version.outputs.version }}.crate
            target/package/cheetah-string-${{ steps.version.outputs.version }}.crate.sha256
          if-no-files-found: error
          retention-days: 7

  publish:
    needs: [validate]
    runs-on: ubuntu-latest
    environment: crates-io
    permissions:
      contents: write

    steps:
      - name: Checkout validated commit
        uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
        with:
          fetch-depth: 0
          ref: ${{ github.sha }}

      - name: Set up Rust
        uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c
        with:
          toolchain: stable

      - name: Download release candidate
        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
        with:
          name: cheetah-string-release-candidate
          path: release-candidate

      - name: Verify candidate digest
        shell: bash
        working-directory: release-candidate
        env:
          VERSION: ${{ needs.validate.outputs.version }}
        run: sha256sum -c "cheetah-string-$VERSION.crate.sha256"

      - name: Create tag for manual release
        shell: bash
        env:
          TAG: ${{ needs.validate.outputs.tag }}
          EXPECTED_SHA: ${{ github.sha }}
        run: |
          git fetch --force --tags origin
          if git rev-parse "$TAG" >/dev/null 2>&1; then
            TAG_SHA="$(git rev-list -n 1 "$TAG")"
            if [[ "$TAG_SHA" != "$EXPECTED_SHA" ]]; then
              echo "Release tag exists at a different commit" >&2
              exit 1
            fi
          else
            git config user.name "github-actions[bot]"
            git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
            git tag -a "$TAG" "$EXPECTED_SHA" -m "cheetah-string $TAG"
            git push origin "$TAG"
          fi

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

      - name: Create GitHub release
        env:
          GH_TOKEN: ${{ github.token }}
          TAG: ${{ needs.validate.outputs.tag }}
          VERSION: ${{ needs.validate.outputs.version }}
        run: |
          gh release create "$TAG" \
            "release-candidate/cheetah-string-$VERSION.crate#cheetah-string-$VERSION.crate" \
            --verify-tag \
            --title "cheetah-string $TAG" \
            --generate-notes