netspeed-cli 0.5.0

Command-line interface for testing internet bandwidth using speedtest.net
name: Release

on:
  push:
    tags:
      - 'v*'

env:
  CARGO_TERM_COLOR: always

jobs:
  verify-tag-on-main:
    name: Verify Tag is on Main
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 0
      - name: Verify tag points to main branch
        run: |
          if ! git branch -r --contains "${{ github.ref_name }}" | grep -q 'origin/master'; then
            echo "::error::Tag ${{ github.ref_name }} is not on the 'main' branch."
            echo "::error::Releases must be created from main. Merge develop → main first."
            echo "::error::See RELEASE.md for the release process."
            exit 1
          fi
          echo "Tag ${{ github.ref_name }} is on main branch"

  build-binaries:
    name: Build Binary (${{ matrix.target }})
    runs-on: ${{ matrix.os }}
    needs: [verify-tag-on-main]
    strategy:
      matrix:
        include:
          # Linux GNU (glibc)
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            artifact_name: netspeed-cli
            asset_name: netspeed-cli-x86_64-linux-gnu
          - os: ubuntu-latest
            target: aarch64-unknown-linux-gnu
            artifact_name: netspeed-cli
            asset_name: netspeed-cli-aarch64-linux-gnu
          # Linux musl (static)
          - os: ubuntu-latest
            target: x86_64-unknown-linux-musl
            artifact_name: netspeed-cli
            asset_name: netspeed-cli-x86_64-linux-musl
          - os: ubuntu-latest
            target: aarch64-unknown-linux-musl
            artifact_name: netspeed-cli
            asset_name: netspeed-cli-aarch64-linux-musl
          # macOS
          - os: macos-latest
            target: x86_64-apple-darwin
            artifact_name: netspeed-cli
            asset_name: netspeed-cli-x86_64-macos
          - os: macos-latest
            target: aarch64-apple-darwin
            artifact_name: netspeed-cli
            asset_name: netspeed-cli-aarch64-macos
          # Windows
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            artifact_name: netspeed-cli.exe
            asset_name: netspeed-cli-x86_64-windows.exe
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}
      - name: Cache dependencies
        uses: Swatinem/rust-cache@v2
      - name: Install cross-compilation tools (aarch64 Linux GNU)
        if: matrix.target == 'aarch64-unknown-linux-gnu'
        run: |
          sudo apt-get update
          sudo apt-get install -y gcc-aarch64-linux-gnu
      - name: Configure aarch64 linker
        if: matrix.target == 'aarch64-unknown-linux-gnu'
        run: |
          mkdir -p .cargo
          cat > .cargo/config.toml << 'EOF'
          [target.aarch64-unknown-linux-gnu]
          linker = "aarch64-linux-gnu-gcc"
          EOF
      - name: Install musl tools (x86_64)
        if: matrix.target == 'x86_64-unknown-linux-musl'
        run: |
          sudo apt-get update
          sudo apt-get install -y musl-tools
      - name: Install cross (aarch64 musl)
        if: matrix.target == 'aarch64-unknown-linux-musl'
        run: cargo install cross --locked
      - name: Build release (cross)
        if: matrix.target == 'aarch64-unknown-linux-musl'
        run: cross build --release --target ${{ matrix.target }}
      - name: Build release (native)
        if: matrix.target != 'aarch64-unknown-linux-musl'
        run: cargo build --release --target ${{ matrix.target }}
      - name: Prepare artifact
        shell: bash
        run: |
          mkdir -p dist
          cp "target/${{ matrix.target }}/release/${{ matrix.artifact_name }}" dist/
      - name: Upload artifact
        uses: actions/upload-artifact@v6
        with:
          name: ${{ matrix.asset_name }}
          path: dist/${{ matrix.artifact_name }}

  publish-github-release:
    name: Create GitHub Release
    runs-on: ubuntu-latest
    needs: [build-binaries]
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v6
      - uses: actions/download-artifact@v7
        with:
          path: release-assets
          merge-multiple: true
      - name: Generate SHA256 checksums
        run: |
          cd release-assets
          sha256sum * > SHA256SUMS.txt
          cat SHA256SUMS.txt
      - name: Generate SBOM
        uses: anchore/sbom-action@v0
        with:
          path: .
          artifact-name: sbom.spdx.json
          output-file: release-assets/sbom.spdx.json
          format: spdx-json
      - name: Create GitHub Release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          gh release delete "${{ github.ref_name }}" --yes --repo "${{ github.repository }}" 2>/dev/null || true
          gh release create "${{ github.ref_name }}" \
            --title "${{ github.ref_name }}" \
            --generate-notes \
            --repo "${{ github.repository }}"
      - name: Upload assets to release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          gh release upload "${{ github.ref_name }}" \
            release-assets/* \
            --repo "${{ github.repository }}" \
            --clobber
      - name: Update Homebrew formula
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          VERSION="${{ github.ref_name }}"
          VERSION_NO_V="${VERSION#v}"
          SHA256=$(curl -sL "https://github.com/${{ github.repository }}/archive/refs/tags/${VERSION}.tar.gz" | shasum -a 256 | awk '{print $1}')
          
          # Update formula file
          sed -i "s/version \".*\"/version \"${VERSION_NO_V}\"/" netspeed-cli.rb
          sed -i "s|url \".*\"|url \"https://github.com/${{ github.repository }}/releases/download/${VERSION}/netspeed-cli-${VERSION_NO_V}.tar.gz\"|" netspeed-cli.rb
          sed -i "s/sha256 \".*\"/sha256 \"${SHA256}\"/" netspeed-cli.rb
          
          # Commit and push to master branch
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git add netspeed-cli.rb
          git commit -m "chore: update formula to ${VERSION}"
          git push origin HEAD:master

  publish-crates-io:
    name: Publish to crates.io
    runs-on: ubuntu-latest
    needs: [publish-github-release]
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@stable
      - name: Cache dependencies
        uses: Swatinem/rust-cache@v2
      - name: Verify tests pass
        run: cargo test --verbose
      - name: Publish to crates.io
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
        run: cargo publish --allow-dirty