forge-guard 0.2.0

Pre-deployment smart contract auditing framework for Foundry
Documentation
# ═══════════════════════════════════════════════════════════════════════
#  Release — binary build & upload
# ═══════════════════════════════════════════════════════════════════════
#
# Builds pre-compiled binaries for Linux, macOS (x86_64 + ARM), and
# Windows after CI completes, then uploads them to the GitHub Release
# created by the Publish workflow.
#
# Trigger: after CI completes successfully on a tag commit
#
name: Release

on:
  workflow_run:
    workflows: ["CI"]
    types:
      - completed

env:
  CARGO_TERM_COLOR: always

jobs:
  # ── Check tag ─────────────────────────────────────────────────────
  # Verify CI passed and the commit has a version tag
  check:
    name: Check tag
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    runs-on: ubuntu-latest
    outputs:
      tag: ${{ steps.tag.outputs.tag }}
      skip: ${{ steps.tag.outputs.skip }}
    steps:
      - uses: actions/checkout@v7
        with:
          ref: ${{ github.event.workflow_run.head_sha }}
          fetch-tags: true

      - name: Check that commit has a version tag
        id: tag
        run: |
          COMMIT_SHA="${{ github.event.workflow_run.head_sha }}"
          TAG_NAME=$(git tag --points-at "$COMMIT_SHA" | grep -E '^v[0-9]' | head -1)

          if [ -z "$TAG_NAME" ]; then
            echo "ℹ️ Commit $COMMIT_SHA has no version tag — skipping binary build"
            echo "skip=true" >> "$GITHUB_OUTPUT"
            exit 0
          fi

          echo "Found tag: $TAG_NAME"
          echo "tag=$TAG_NAME" >> "$GITHUB_OUTPUT"
          echo "skip=false" >> "$GITHUB_OUTPUT"

  # ── Build ─────────────────────────────────────────────────────────
  # Native build for each target platform, archive binary, upload to
  # the GitHub Release (created by publish.yml).
  #
  build:
    name: ${{ matrix.target }}
    needs: [check]
    if: needs.check.outputs.skip != 'true'
    strategy:
      fail-fast: false
      matrix:
        include:
          - target: x86_64-unknown-linux-gnu
            os: ubuntu-latest
            ext: ""
            archive: tar.gz
          - target: x86_64-apple-darwin
            os: macos-13
            ext: ""
            archive: tar.gz
          - target: aarch64-apple-darwin
            os: macos-latest
            ext: ""
            archive: tar.gz
          - target: x86_64-pc-windows-msvc
            os: windows-latest
            ext: .exe
            archive: zip

    runs-on: ${{ matrix.os }}
    permissions:
      contents: write

    steps:
      - uses: actions/checkout@v7
        with:
          ref: ${{ github.event.workflow_run.head_sha }}
          fetch-depth: 0
          fetch-tags: true

      - name: Lookup version tag
        id: lookup
        run: |
          COMMIT_SHA="${{ github.event.workflow_run.head_sha }}"
          TAG_NAME=$(git tag --points-at "$COMMIT_SHA" | grep -E '^v[0-9]' | head -1)
          echo "tag=$TAG_NAME" >> "$GITHUB_OUTPUT"
          echo "Building binaries for $TAG_NAME"

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}

      - name: Build release binary
        run: cargo build --release --target ${{ matrix.target }}

      - name: Prepare archive
        shell: bash
        run: |
          BINARY="forge-guard${{ matrix.ext }}"
          SRC="target/${{ matrix.target }}/release/$BINARY"
          STAGING="forge-guard-${{ matrix.target }}"
          mkdir -p "$STAGING"
          cp "$SRC" "$STAGING/"
          cp README.md LICENSE "$STAGING/" 2>/dev/null || true

          if [ "${{ matrix.archive }}" = "zip" ]; then
            if command -v 7z &>/dev/null; then
              7z a -tzip "${STAGING}.zip" "$STAGING/"
            else
              zip -r "${STAGING}.zip" "$STAGING/"
            fi
            echo "artifact=${STAGING}.zip" >> "$GITHUB_ENV"
          else
            tar czf "${STAGING}.tar.gz" "$STAGING/"
            echo "artifact=${STAGING}.tar.gz" >> "$GITHUB_ENV"
          fi

      - name: Upload binary to GitHub Release
        env:
          GH_TOKEN: ${{ github.token }}
        shell: bash
        run: |
          ARCHIVE="${{ env.artifact }}"
          TAG="${{ steps.lookup.outputs.tag }}"

          echo "Uploading $ARCHIVE to release $TAG ..."
          gh release upload "$TAG" "$ARCHIVE" --clobber
          echo "✅ Uploaded $ARCHIVE"

      - name: Upload raw binary artifact (for CI reuse)
        uses: actions/upload-artifact@v7
        with:
          name: forge-guard-${{ matrix.target }}
          path: target/${{ matrix.target }}/release/forge-guard${{ matrix.ext }}
          retention-days: 7