rust-args-parser 2.0.0

Tiny, fast, callback-based CLI argument parser for Rust
Documentation
---
name: Publish to crates.io (manual, protected)
on:
  workflow_dispatch:
    inputs:
      dry_run:
        description: Do a dry run (no publish)?
        required: true
        type: boolean
        default: true
      run_tests:
        description: Run cargo test before packaging/publish
        required: true
        type: boolean
        default: true
      crate_path:
        description: Path to crate ('.' for root, or subcrate path in a workspace)
        required: true
        type: string
        default: .
      require_tag:
        description: Require a git tag matching version (e.g., vX.Y.Z) and pointing
          to HEAD
        required: true
        type: boolean
        default: true
      tag_prefix:
        description: Tag prefix used for version tags
        required: true
        type: string
        default: v
      upload_artifact:
        description: Upload built .crate as a workflow artifact
        required: true
        type: boolean
        default: false
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: false
permissions:
  contents: read
jobs:
  publish:
    name: Cargo publish (${{ inputs.dry_run && 'dry-run' || 'live' }})
    runs-on: ubuntu-latest
    environment: crates-io
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0  # needed for tags
      - name: Install Rust (stable)
        uses: dtolnay/rust-toolchain@stable
      - name: Cache cargo registry + build
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            ${{ runner.os }}-cargo-
      - name: Show toolchain
        run: |
          rustc -Vv
          cargo -Vv
      - name: (optional) Run tests
        if: ${{ inputs.run_tests == true }}
        env:
          RUSTFLAGS: -D warnings
        run: |
          cargo test --locked --workspace --verbose
      - name: Read crate name & version
        id: meta
        run: |
          JSON=$(cargo metadata --no-deps --format-version=1 --manifest-path "${{ inputs.crate_path }}/Cargo.toml")
          NAME=$(echo "$JSON" | jq -r '.packages[0].name')
          VER=$(echo "$JSON" | jq -r '.packages[0].version')
          echo "name=$NAME" >> $GITHUB_OUTPUT
          echo "version=$VER" >> $GITHUB_OUTPUT
          echo "Crate: $NAME@$VER"
      - name: Verify tag matches version (optional)
        if: ${{ inputs.require_tag == true }}
        run: |
          set -euo pipefail
          TAG="${{ inputs.tag_prefix }}${{ steps.meta.outputs.version }}"
          echo "Expecting tag: $TAG"
          git fetch --tags --quiet
          if ! git rev-parse -q --verify "refs/tags/$TAG" >/dev/null; then
            echo "::error::Required tag '$TAG' does not exist."; exit 1; fi
          HEAD=$(git rev-parse HEAD)
          TAG_SHA=$(git rev-list -n 1 "$TAG")
          if [ "$HEAD" != "$TAG_SHA" ]; then
            echo "::error::Tag '$TAG' does not point to HEAD ($HEAD != $TAG_SHA)."; exit 1; fi
          echo "Tag check OK."
      - name: Ensure version not already published
        run: |
          set -euo pipefail
          NAME='${{ steps.meta.outputs.name }}'
          VER='${{ steps.meta.outputs.version }}'
          # jq should be present; install if missing
          if ! command -v jq >/dev/null; then sudo apt-get update && sudo apt-get install -y jq; fi
          EXIST=$(curl -fsSL "https://crates.io/api/v1/crates/$NAME" | jq -r --arg v "$VER" '.versions[].num | select(.==$v)')
          if [ -n "$EXIST" ]; then
            echo "::error::Version $NAME@$VER already exists on crates.io"; exit 1; fi
          echo "Version availability OK."
      - name: Verify clean working tree
        run: |
          git update-index -q --refresh
          if ! git diff --quiet -- .; then
            echo "::error::Working tree is dirty. Commit or stash changes before publishing."; exit 1; fi
          echo "Working tree clean."
      - name: Package crate
        run: |
          cargo package --locked --manifest-path "${{ inputs.crate_path }}/Cargo.toml"
      - name: Upload .crate artifact (optional)
        if: ${{ inputs.upload_artifact == true }}
        uses: actions/upload-artifact@v4
        with:
          name: ${{ steps.meta.outputs.name }}-${{ steps.meta.outputs.version }}.crate
          path: target/package/*.crate
          if-no-files-found: error
      - name: Dry run publish
        if: ${{ inputs.dry_run == true }}
        run: |
          cargo publish --locked --manifest-path "${{ inputs.crate_path }}/Cargo.toml" --dry-run
      - name: Publish to crates.io
        if: ${{ inputs.dry_run == false }}
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
        run: |
          cargo publish --locked --manifest-path "${{ inputs.crate_path }}/Cargo.toml"
      - name: Guidance
        run: |-
          echo "If publishing failed due to existing version, bump 'version' in Cargo.toml and re-run."
          echo "Ensure you have set the repository secret CARGO_REGISTRY_TOKEN (from crates.io)."
          echo "Environment 'crates-io' can be configured to require reviewer approval before this job runs."