dig-clvm 0.2.2

DIG L2 CLVM consensus engine — validates spend bundles, computes coin additions and removals
Documentation
name: Publish to crates.io

on:
  push:
    branches:
      - main
    tags:
      - 'v*'
  pull_request:
    branches:
      - main
  workflow_dispatch:
    inputs:
      version:
        description: 'Version to publish (e.g., v0.1.0)'
        required: true
        type: string

env:
  CARGO_TERM_COLOR: always

jobs:
  test:
    name: Test Suite
    runs-on: ubuntu-latest
    # The release-gate PR run already tested this exact merged tree before it was
    # allowed to merge/tag (CLAUDE.md §2.4a). Re-running the full suite again on the
    # tag push is redundant and a pure flake-exposure surface (#488 — a re-run flake
    # blocked a release). Skip on tag pushes; still run for PRs, main pushes, and
    # workflow_dispatch.
    if: "!startsWith(github.ref, 'refs/tags/')"
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          toolchain: stable
          components: llvm-tools-preview

      - name: Cache dependencies
        uses: Swatinem/rust-cache@v2

      - name: Install cargo-nextest
        uses: taiki-e/install-action@nextest

      - name: Install cargo-llvm-cov
        uses: taiki-e/install-action@cargo-llvm-cov

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

      - name: Check clippy
        run: cargo clippy --all-targets --all-features -- -D warnings

      # Run the full test suite under nextest (retries: a test that fails then
      # passes on retry is reported as flaky, not hidden) with coverage
      # instrumentation, gated at >=80% line coverage. --test-threads=1 is required
      # because the Simulator-based tests are not parallel-safe.
      - name: Run tests with coverage (nextest, retries=2, gate >=80% lines)
        run: cargo llvm-cov nextest --all-features --fail-under-lines 80 --retries 2 --test-threads 1

      - name: Check documentation
        run: cargo doc --no-deps --all-features

  publish:
    name: Publish to crates.io
    runs-on: ubuntu-latest
    needs: test
    # Tag pushes skip the `test` job above (already gated on the PR) — treat that
    # skip as success so publish still runs on the tag; only a real failure blocks it.
    # Without an explicit status-check function, GitHub inserts an implicit success(),
    # which is false when a needed job is skipped, so the tolerance clause never runs.
    # !cancelled() makes the condition actually reachable.
    if: |
      !cancelled() &&
      (startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch') &&
      (needs.test.result == 'success' || needs.test.result == 'skipped')
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

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

      - name: Cache dependencies
        uses: Swatinem/rust-cache@v2

      - name: Verify package can be built
        run: cargo build --release

      - name: Verify package can be packaged
        run: cargo package --allow-dirty

      - name: Check if CARGO_REGISTRY_TOKEN is available
        run: |
          if [ -z "${{ secrets.CARGO_REGISTRY_TOKEN }}" ]; then
            echo "CARGO_REGISTRY_TOKEN secret is not set in repository settings"
            exit 1
          fi

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

  create-release:
    name: Create GitHub Release
    runs-on: ubuntu-latest
    needs: publish
    # A skip propagates down the whole needs chain: `test` is skipped on tag
    # pushes, so without a status function this job is unreachable even when
    # `publish` succeeds. !cancelled() makes it reachable; the explicit
    # needs.publish.result check is what keeps a release from ever being cut
    # for a version that failed to publish.
    if: |
      !cancelled() &&
      needs.publish.result == 'success' &&
      startsWith(github.ref, 'refs/tags/v')
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Extract version from tag
        id: extract_version
        run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT

      - name: Create GitHub Release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GH_ACCESS_TOKEN }}
        with:
          tag_name: ${{ github.ref }}
          release_name: "dig-clvm v${{ steps.extract_version.outputs.VERSION }}"
          body: |
            ## dig-clvm v${{ steps.extract_version.outputs.VERSION }}

            DIG L2 CLVM consensus engine — validates spend bundles, computes coin additions and removals.

            ### Installation
            ```toml
            [dependencies]
            dig-clvm = "${{ steps.extract_version.outputs.VERSION }}"
            ```

            See the [README](https://github.com/DIG-Network/dig-clvm/blob/main/README.md) for usage instructions.
          draft: false
          prerelease: false