snortal 1.0.18

Detect captive portal URLs on a Linux network
name: Release

on:
  push:
    tags:
      - "v*"

permissions: {}

env:
  CARGO_TERM_COLOR: always
  BINARY_NAME: snortal

jobs:
  build:
    name: Build ${{ matrix.target }}
    runs-on: ${{ matrix.runner }}
    permissions:
      contents: read
    strategy:
      matrix:
        include:
          - target: x86_64-unknown-linux-gnu
            artifact_suffix: linux-x86_64
            runner: ubuntu-latest
            use_cross: true
            package: true
          - target: x86_64-unknown-linux-musl
            artifact_suffix: linux-x86_64-musl
            runner: ubuntu-latest
            use_cross: true
          - target: i686-unknown-linux-gnu
            artifact_suffix: linux-x86
            runner: ubuntu-latest
            use_cross: true
            package: true
          - target: i686-unknown-linux-musl
            artifact_suffix: linux-x86-musl
            runner: ubuntu-latest
            use_cross: true
          - target: aarch64-unknown-linux-gnu
            artifact_suffix: linux-aarch64
            runner: ubuntu-latest
            use_cross: true
            package: true
          - target: aarch64-unknown-linux-musl
            artifact_suffix: linux-aarch64-musl
            runner: ubuntu-latest
            use_cross: true
          - target: armv7-unknown-linux-gnueabihf
            artifact_suffix: linux-armv7
            runner: ubuntu-latest
            use_cross: true
            package: true
          - target: armv7-unknown-linux-musleabihf
            artifact_suffix: linux-armv7-musl
            runner: ubuntu-latest
            use_cross: true
          - target: arm-unknown-linux-gnueabihf
            artifact_suffix: linux-armv6-hf
            runner: ubuntu-latest
            use_cross: true
          - target: arm-unknown-linux-musleabihf
            artifact_suffix: linux-armv6-musl
            runner: ubuntu-latest
            use_cross: true
          - target: arm-unknown-linux-gnueabi
            artifact_suffix: linux-armv6
            runner: ubuntu-latest
            use_cross: true
          - target: armv5te-unknown-linux-gnueabi
            artifact_suffix: linux-armv5
            runner: ubuntu-latest
            use_cross: true
          - target: riscv64gc-unknown-linux-gnu
            artifact_suffix: linux-riscv64
            runner: ubuntu-latest
            use_cross: true
          - target: x86_64-apple-darwin
            artifact_suffix: macos-x86_64
            runner: macos-latest
            use_cross: false
          - target: aarch64-apple-darwin
            artifact_suffix: macos-aarch64
            runner: macos-latest
            use_cross: false

    steps:
      - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

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

      - name: Install cross
        if: matrix.use_cross
        uses: taiki-e/install-action@6887963ccf37a9ddcd8c5fa4baeb3e1e5fd61fa1 # v2
        with:
          tool: cross

      - name: Cache cargo registry
        uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ${{ runner.os }}-${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: ${{ runner.os }}-${{ matrix.target }}-cargo-

      - name: Build
        env:
          USE_CROSS: ${{ matrix.use_cross }}
          TARGET: ${{ matrix.target }}
        run: |
          if [ "$USE_CROSS" = "true" ]; then
            cross build --release --locked --target "$TARGET"
          else
            cargo build --release --locked --target "$TARGET"
          fi

      - name: Rename binary
        env:
          TARGET: ${{ matrix.target }}
          SUFFIX: ${{ matrix.artifact_suffix }}
        run: |
          cp "target/${TARGET}/release/${BINARY_NAME}" "${BINARY_NAME}-${SUFFIX}"

      - name: Upload binary artifact
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
        with:
          name: ${{ env.BINARY_NAME }}-${{ matrix.artifact_suffix }}
          path: ${{ env.BINARY_NAME }}-${{ matrix.artifact_suffix }}
          retention-days: 1

      - name: Install packaging tools
        if: matrix.package
        uses: taiki-e/install-action@6887963ccf37a9ddcd8c5fa4baeb3e1e5fd61fa1 # v2
        with:
          tool: cargo-deb,cargo-generate-rpm

      - name: Build .deb
        if: matrix.package
        env:
          TARGET: ${{ matrix.target }}
        run: cargo deb --no-build --no-strip --target "$TARGET"

      - name: Upload .deb artifact
        if: matrix.package
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
        with:
          name: ${{ env.BINARY_NAME }}-${{ matrix.artifact_suffix }}-deb
          path: target/${{ matrix.target }}/debian/*.deb
          retention-days: 1

      - name: Build .rpm
        if: matrix.package
        env:
          TARGET: ${{ matrix.target }}
        run: cargo generate-rpm --target "$TARGET"

      - name: Upload .rpm artifact
        if: matrix.package
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
        with:
          name: ${{ env.BINARY_NAME }}-${{ matrix.artifact_suffix }}-rpm
          path: target/${{ matrix.target }}/generate-rpm/*.rpm
          retention-days: 1

  publish:
    name: Publish to crates.io
    needs: build
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

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

      - name: Cache cargo registry
        uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ${{ runner.os }}-publish-cargo-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: ${{ runner.os }}-publish-cargo-

      - name: Publish
        run: cargo publish --locked
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}

  release:
    name: Create release
    needs: build
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - name: Download all artifacts
        uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
        with:
          path: artifacts
          merge-multiple: true

      - name: Generate PKGBUILD and .SRCINFO
        env:
          TAG: ${{ github.ref_name }}
        run: |
          if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
            echo "ERROR: Invalid tag format: '$TAG'" >&2
            exit 1
          fi
          VERSION="${TAG#v}"
          URL="https://github.com/goastler/snortal/archive/refs/tags/${TAG}.tar.gz"
          SHA256=$(curl --max-time 120 -sL "$URL" | sha256sum | cut -d' ' -f1)
          cat > artifacts/PKGBUILD-src << EOF
          # Maintainer: George Oastler <goastler4 at gmail dot com>
          # SPDX-License-Identifier: 0BSD
          pkgname=snortal
          pkgver=${VERSION}
          pkgrel=1
          pkgdesc='Detect captive portal URLs on a Linux network'
          arch=('x86_64' 'aarch64' 'armv7h' 'i686')
          url='https://github.com/goastler/snortal'
          license=('AGPL-3.0-or-later')
          makedepends=('cargo')
          source=("\$pkgname-\$pkgver.tar.gz::https://github.com/goastler/snortal/archive/refs/tags/v\${pkgver}.tar.gz")
          sha256sums=('${SHA256}')

          prepare() {
              cd "\$pkgname-\$pkgver"
              cargo fetch --locked --target "\$CARCH-unknown-linux-gnu"
          }

          build() {
              cd "\$pkgname-\$pkgver"
              export RUSTUP_TOOLCHAIN=stable
              export CARGO_TARGET_DIR=target
              cargo build --frozen --release
          }

          check() {
              cd "\$pkgname-\$pkgver"
              cargo test --frozen
          }

          package() {
              cd "\$pkgname-\$pkgver"
              install -Dm0755 -t "\$pkgdir/usr/bin/" "target/release/\$pkgname"
          }
          EOF
          cat > artifacts/SRCINFO-src << EOF
          pkgbase = snortal
          	pkgdesc = Detect captive portal URLs on a Linux network
          	pkgver = ${VERSION}
          	pkgrel = 1
          	url = https://github.com/goastler/snortal
          	arch = x86_64
          	arch = aarch64
          	arch = armv7h
          	arch = i686
          	license = AGPL-3.0-or-later
          	makedepends = cargo
          	source = snortal-${VERSION}.tar.gz::https://github.com/goastler/snortal/archive/refs/tags/v${VERSION}.tar.gz
          	sha256sums = ${SHA256}

          pkgname = snortal
          EOF

      - name: Create GitHub Release
        uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2
        with:
          files: artifacts/*
          generate_release_notes: true

  aur-publish:
    name: Publish to AUR
    needs: release
    runs-on: ubuntu-latest
    permissions: {}
    steps:
      - name: Set up AUR SSH
        env:
          AUR_SSH_KEY: ${{ secrets.AUR_SSH_KEY }}
        run: |
          mkdir -p ~/.ssh
          chmod 700 ~/.ssh
          printf '%s\n' "$AUR_SSH_KEY" > ~/.ssh/aur
          chmod 600 ~/.ssh/aur

          ssh-keyscan -H aur.archlinux.org >> ~/.ssh/known_hosts

      - name: Push to AUR
        env:
          TAG: ${{ github.ref_name }}
        run: |
          if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
            echo "ERROR: Invalid tag format: '$TAG'" >&2
            exit 1
          fi
          VERSION="${TAG#v}"
          BASE="https://github.com/goastler/snortal/releases/download/${TAG}"

          SHA_X86_64=$(curl --max-time 120 -sL "${BASE}/snortal-linux-x86_64"   | sha256sum | cut -d' ' -f1)
          SHA_AARCH64=$(curl --max-time 120 -sL "${BASE}/snortal-linux-aarch64" | sha256sum | cut -d' ' -f1)
          SHA_ARMV7H=$(curl  --max-time 120 -sL "${BASE}/snortal-linux-armv7"   | sha256sum | cut -d' ' -f1)
          SHA_ARMV6H=$(curl  --max-time 120 -sL "${BASE}/snortal-linux-armv6-hf" | sha256sum | cut -d' ' -f1)
          SHA_I686=$(curl    --max-time 120 -sL "${BASE}/snortal-linux-x86"     | sha256sum | cut -d' ' -f1)
          SHA_RISCV64=$(curl --max-time 120 -sL "${BASE}/snortal-linux-riscv64" | sha256sum | cut -d' ' -f1)

          export GIT_SSH_COMMAND="ssh -i ~/.ssh/aur -o StrictHostKeyChecking=yes"
          git clone ssh://aur@aur.archlinux.org/snortal.git aur-repo || {
            git init aur-repo
            git -C aur-repo remote add origin ssh://aur@aur.archlinux.org/snortal.git
          }

          cat > aur-repo/PKGBUILD << EOF
          # Maintainer: George Oastler <goastler4 at gmail dot com>
          # SPDX-License-Identifier: 0BSD
          pkgname=snortal
          pkgver=${VERSION}
          pkgrel=1
          pkgdesc='Detect captive portal URLs on a Linux network'
          arch=('x86_64' 'aarch64' 'armv7h' 'armv6h' 'i686' 'riscv64')
          url='https://github.com/goastler/snortal'
          license=('AGPL-3.0-or-later')
          source_x86_64=("snortal::${BASE}/snortal-linux-x86_64")
          source_aarch64=("snortal::${BASE}/snortal-linux-aarch64")
          source_armv7h=("snortal::${BASE}/snortal-linux-armv7")
          source_armv6h=("snortal::${BASE}/snortal-linux-armv6-hf")
          source_i686=("snortal::${BASE}/snortal-linux-x86")
          source_riscv64=("snortal::${BASE}/snortal-linux-riscv64")
          sha256sums_x86_64=('${SHA_X86_64}')
          sha256sums_aarch64=('${SHA_AARCH64}')
          sha256sums_armv7h=('${SHA_ARMV7H}')
          sha256sums_armv6h=('${SHA_ARMV6H}')
          sha256sums_i686=('${SHA_I686}')
          sha256sums_riscv64=('${SHA_RISCV64}')

          package() {
              install -Dm0755 snortal "\$pkgdir/usr/bin/snortal"
          }
          EOF

          cat > aur-repo/.SRCINFO << EOF
          pkgbase = snortal
          	pkgdesc = Detect captive portal URLs on a Linux network
          	pkgver = ${VERSION}
          	pkgrel = 1
          	url = https://github.com/goastler/snortal
          	arch = x86_64
          	arch = aarch64
          	arch = armv7h
          	arch = armv6h
          	arch = i686
          	arch = riscv64
          	license = AGPL-3.0-or-later
          	source_x86_64 = snortal::${BASE}/snortal-linux-x86_64
          	sha256sums_x86_64 = ${SHA_X86_64}
          	source_aarch64 = snortal::${BASE}/snortal-linux-aarch64
          	sha256sums_aarch64 = ${SHA_AARCH64}
          	source_armv7h = snortal::${BASE}/snortal-linux-armv7
          	sha256sums_armv7h = ${SHA_ARMV7H}
          	source_armv6h = snortal::${BASE}/snortal-linux-armv6-hf
          	sha256sums_armv6h = ${SHA_ARMV6H}
          	source_i686 = snortal::${BASE}/snortal-linux-x86
          	sha256sums_i686 = ${SHA_I686}
          	source_riscv64 = snortal::${BASE}/snortal-linux-riscv64
          	sha256sums_riscv64 = ${SHA_RISCV64}

          pkgname = snortal
          EOF

          cd aur-repo
          git config user.name "George Oastler"
          git config user.email "goastler4@gmail.com"
          git add PKGBUILD .SRCINFO
          if ! git diff --cached --quiet; then
            git commit -m "Update to ${TAG}"
            git push origin HEAD:master
          fi