spec-drift 0.1.0

Semantic coherence analysis between specification and implementation for Rust projects.
Documentation
name: 'spec-drift'
description: 'Semantic coherence analysis between specification and Rust implementation'
author: 'spec-drift contributors'
branding:
  icon: 'file-text'
  color: 'blue'

inputs:
  version:
    description: 'spec-drift ref. Accepts a tag (`v0.1.0`) for pre-built binaries, or a branch/SHA to build from source.'
    required: false
    default: 'v0.1.0'
  format:
    description: 'Output format: human, json, or sarif'
    required: false
    default: 'human'
  output:
    description: 'Write output to this path (stdout if empty)'
    required: false
    default: ''
  deny:
    description: 'Fail when any divergence at or above this severity exists: notice | warning | critical'
    required: false
    default: 'notice'
  args:
    description: 'Additional arguments forwarded to spec-drift'
    required: false
    default: ''
  working-directory:
    description: 'Working directory for the scan'
    required: false
    default: '.'
  anthropic-api-key:
    description: 'Anthropic API key for LLM-backed rules. Omit to run without LLM.'
    required: false
    default: ''

runs:
  using: 'composite'
  steps:
    - name: Cache spec-drift binary
      id: cache-spec-drift
      uses: actions/cache@v4
      with:
        path: ~/.cargo/bin/spec-drift
        key: spec-drift-${{ inputs.version }}-${{ runner.os }}-${{ runner.arch }}

    - name: Download pre-built binary
      id: download
      if: steps.cache-spec-drift.outputs.cache-hit != 'true'
      shell: bash
      run: |
        set -euo pipefail
        # Only tagged versions have pre-built binaries.
        case "${{ inputs.version }}" in
          v*.*.*) ;;
          *)
            echo "version `${{ inputs.version }}` is not a semver tag; skipping binary download"
            echo "downloaded=false" >> "$GITHUB_OUTPUT"
            exit 0
          ;;
        esac

        case "${{ runner.os }}-${{ runner.arch }}" in
          Linux-X64)   TARGET=x86_64-unknown-linux-gnu ;;
          macOS-ARM64) TARGET=aarch64-apple-darwin ;;
          macOS-X64)   TARGET=x86_64-apple-darwin ;;
          *)
            echo "no pre-built binary for ${{ runner.os }}-${{ runner.arch }}; will fall back to source install"
            echo "downloaded=false" >> "$GITHUB_OUTPUT"
            exit 0
          ;;
        esac

        URL="https://github.com/asmuelle/spec-drift/releases/download/${{ inputs.version }}/spec-drift-${TARGET}.tar.gz"
        echo "Fetching ${URL}"
        if curl -sfL -o /tmp/spec-drift.tar.gz "$URL"; then
          mkdir -p "$HOME/.cargo/bin"
          tar -xzf /tmp/spec-drift.tar.gz -C "$HOME/.cargo/bin"
          chmod +x "$HOME/.cargo/bin/spec-drift"
          echo "downloaded=true" >> "$GITHUB_OUTPUT"
        else
          echo "release asset not found; falling back to source install"
          echo "downloaded=false" >> "$GITHUB_OUTPUT"
        fi

    - name: Install Rust toolchain (fallback)
      if: steps.cache-spec-drift.outputs.cache-hit != 'true' && steps.download.outputs.downloaded != 'true'
      uses: dtolnay/rust-toolchain@stable
      with:
        toolchain: "1.95"

    - name: Install spec-drift from source (fallback)
      if: steps.cache-spec-drift.outputs.cache-hit != 'true' && steps.download.outputs.downloaded != 'true'
      shell: bash
      run: |
        cargo install --git https://github.com/asmuelle/spec-drift --branch "${{ inputs.version }}" --locked

    - name: Add cargo bin to PATH
      shell: bash
      run: echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"

    - name: Run spec-drift
      shell: bash
      working-directory: ${{ inputs.working-directory }}
      env:
        ANTHROPIC_API_KEY: ${{ inputs.anthropic-api-key }}
      run: |
        set -o pipefail
        ARGS="--format ${{ inputs.format }} --deny ${{ inputs.deny }} ${{ inputs.args }}"
        if [ -n "${{ inputs.output }}" ]; then
          # shellcheck disable=SC2086
          spec-drift $ARGS > "${{ inputs.output }}"
        else
          # shellcheck disable=SC2086
          spec-drift $ARGS
        fi