dig-pex 0.2.0

Peer Exchange (PEX) for the DIG Node peer network — delta-based first-hand known-peer exchange over already-authenticated links (node<->node dig-nat mux, relay->node RLY-008 WebSocket), in the spirit of BitTorrent PEX: periodic added/dropped deltas, hard per-message caps, receiver-enforced minimum interval anti-flood floor, and no third-party re-flooding. Ships a transport-agnostic sans-IO PexEngine embedded by dig-node and dig-relay.
Documentation
name: Publish to crates.io

# Tag-driven release: pushing a version tag `vX.Y.Z` builds, packages, and publishes to crates.io,
# then cuts a GitHub Release. It does NOT re-run the test/coverage gate — that already ran (and
# gated the merge) on the PR via ci.yml against the exact tree this tag points at (#488: a
# full-suite re-run here only slows/duplicates the release with no new signal). A normal push to
# `main` runs the gates only (see ci.yml) — it does NOT publish. Mirrors the sibling DIG crates
# (dig-dht / dig-download / dig-nat / dig-constants) so the same org secrets apply.
#
# dig-pex is standalone (no DIG git dependencies — the peer entry is mirrored, not imported, to keep
# the tree minimal), so there is no release-ordering dependency on other DIG crates: the published
# build resolves entirely from crates.io.

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

permissions:
  contents: write

env:
  CARGO_TERM_COLOR: always

jobs:
  # No test/coverage re-run here (#488): the merged tree that produced this tag already passed the
  # full ci.yml gate set (fmt/clippy/nextest/coverage>=80%) on its PR. Deploy = build + package +
  # publish only.
  publish:
    name: Publish to crates.io
    runs-on: ubuntu-latest
    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 the package builds
        run: cargo build --release

      - name: Verify the package can be packaged
        run: cargo package --locked

      - name: Check CARGO_REGISTRY_TOKEN is set
        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 --locked --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
    if: 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: softprops/action-gh-release@v2
        with:
          tag_name: ${{ github.ref_name }}
          name: "dig-pex v${{ steps.extract_version.outputs.VERSION }}"
          body: |
            ## dig-pex v${{ steps.extract_version.outputs.VERSION }}

            Peer Exchange (PEX) for the DIG Node peer network — delta-based first-hand known-peer
            exchange over already-authenticated links (node<->node dig-nat mux, relay->node RLY-008
            WebSocket), in the spirit of BitTorrent PEX: periodic `added`/`dropped` deltas, hard
            per-message caps, a receiver-enforced minimum-interval anti-flood floor, and no
            third-party re-flooding. Ships a transport-agnostic, sans-IO `PexEngine` embedded by
            dig-node and dig-relay.

            ### Installation
            ```toml
            [dependencies]
            dig-pex = "${{ steps.extract_version.outputs.VERSION }}"
            ```
          draft: false
          prerelease: false