ftr 0.7.0

A fast, parallel ICMP traceroute with ASN lookup, reverse DNS, and ISP detection
Documentation
name: Release

on:
  push:
    tags:
      - 'v*'
  release:
    types: [published]  # Trigger when a release is published (not just created)
  workflow_dispatch:

permissions:
  contents: write  # Needed to create releases

jobs:
  # Validate the release tag before building anything
  validate:
    name: Validate Release
    if: startsWith(github.ref, 'refs/tags/v')
    uses: ./.github/workflows/validate-release.yml
    secrets: inherit

  # First, publish to crates.io (only when release is published, not on tag push)
  publish-crate:
    name: Publish to crates.io
    runs-on: ubuntu-latest
    # Only run when a release is published (ensures release notes are ready)
    if: github.event_name == 'release' && github.event.action == 'published'
    steps:
      - uses: actions/checkout@v4

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

      - name: Check version matches tag
        run: |
          TAG_VERSION=${GITHUB_REF#refs/tags/v}
          CARGO_VERSION=$(grep "^version" Cargo.toml | sed 's/.*"\(.*\)".*/\1/')
          if [ "$TAG_VERSION" != "$CARGO_VERSION" ]; then
            echo "Error: Tag version ($TAG_VERSION) does not match Cargo.toml version ($CARGO_VERSION)"
            exit 1
          fi

      - name: Run tests
        run: cargo test --all-features

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

  build-deb:
    name: Build Debian Package
    runs-on: ubuntu-latest
    needs: validate
    # Run on tag push to create draft release with .deb files
    if: startsWith(github.ref, 'refs/tags/v')
    strategy:
      matrix:
        target:
          - x86_64-unknown-linux-gnu
          - aarch64-unknown-linux-gnu
    steps:
      - uses: actions/checkout@v4

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

      - name: Setup Rust cache
        uses: Swatinem/rust-cache@v2
        with:
          key: ${{ matrix.target }}

      - name: Cache cargo-deb
        id: cache-cargo-deb
        uses: actions/cache@v4
        with:
          path: ~/.cargo/bin/cargo-deb
          key: ${{ runner.os }}-cargo-deb-2.7.0

      - name: Install cargo-deb
        if: steps.cache-cargo-deb.outputs.cache-hit != 'true'
        run: cargo install cargo-deb --version 2.7.0

      - name: Install cross-compilation tools for ARM64
        if: matrix.target == 'aarch64-unknown-linux-gnu'
        run: |
          sudo apt-get update
          sudo apt-get install -y gcc-aarch64-linux-gnu pkg-config libssl-dev

      - name: Build release binary
        run: |
          if [ "${{ matrix.target }}" = "aarch64-unknown-linux-gnu" ]; then
            export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc
            export CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc
            export CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++
          fi
          cargo build --release --target ${{ matrix.target }}

      - name: Build .deb package
        run: |
          if [ "${{ matrix.target }}" = "aarch64-unknown-linux-gnu" ]; then
            # For cross-compilation, disable stripping to avoid strip format errors
            cargo deb --target ${{ matrix.target }} --no-build --no-strip
          else
            cargo deb --target ${{ matrix.target }} --no-build
          fi

      - name: Upload .deb artifact
        uses: actions/upload-artifact@v4
        with:
          name: ftr-deb-${{ matrix.target }}
          path: target/${{ matrix.target }}/debian/*.deb

  build-windows:
    name: Build Windows Binary
    runs-on: windows-latest
    needs: validate
    # Run on tag push to create draft release with Windows binaries
    if: startsWith(github.ref, 'refs/tags/v')
    strategy:
      matrix:
        target:
          - x86_64-pc-windows-msvc
          - aarch64-pc-windows-msvc
    steps:
      - uses: actions/checkout@v4

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

      - name: Setup Rust cache
        uses: Swatinem/rust-cache@v2
        with:
          key: ${{ matrix.target }}

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

      - name: Create archive
        shell: pwsh
        run: |
          $target = "${{ matrix.target }}"
          $version = "${env:GITHUB_REF}" -replace "refs/tags/v", ""
          $archiveName = "ftr-${version}-${target}.zip"
          
          # Create a directory for the archive contents
          New-Item -ItemType Directory -Force -Path "archive"
          
          # Copy the binary
          Copy-Item "target\${target}\release\ftr.exe" "archive\"
          
          # Copy README and LICENSE
          Copy-Item "README.md" "archive\"
          Copy-Item "LICENSE" "archive\"
          
          # Create the zip archive
          Compress-Archive -Path "archive\*" -DestinationPath $archiveName
          
          # Output the archive name for the upload step
          echo "ARCHIVE_NAME=$archiveName" >> $env:GITHUB_ENV

      - name: Upload Windows artifact
        uses: actions/upload-artifact@v4
        with:
          name: ftr-windows-${{ matrix.target }}
          path: ${{ env.ARCHIVE_NAME }}

  create-release:
    name: Create Release
    needs: [build-deb, build-windows]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Download all artifacts
        uses: actions/download-artifact@v4
        with:
          pattern: ftr-*
          merge-multiple: true

      - name: Create Release
        uses: softprops/action-gh-release@v1
        with:
          files: |
            *.deb
            *.zip
          draft: true  # Create as draft so release notes can be edited
          prerelease: false
          body: |
            ## Installation

            ### Windows
            Download the appropriate .zip file below for your architecture:
            - `ftr-*-x86_64-pc-windows-msvc.zip` for 64-bit Intel/AMD
            - `ftr-*-aarch64-pc-windows-msvc.zip` for ARM64

            Extract the archive and add the directory to your PATH, or run `ftr.exe` directly.

            ### Debian/Ubuntu packages
            Download the appropriate .deb file below for your architecture:
            - `ftr_*_amd64.deb` for 64-bit Intel/AMD
            - `ftr_*_arm64.deb` for ARM64

            ### Other platforms
            - macOS: `brew tap dweekly/ftr && brew install ftr`
            - Cargo: `cargo install ftr` (available after this release is published)

            ## Release Notes
            Please see [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ github.ref_name }}/CHANGELOG.md) for detailed changes.

            ---
            *Note: This is a draft release. Please edit with proper release notes before publishing.*
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}