pingall 2.1.4

Ping everything you can reach.
Documentation
name: Release

on:
  push:
    tags:
      - "v*"

permissions:
  contents: write

env:
  CARGO_TERM_COLOR: always

jobs:
  publish-crate:
    name: Publish crate
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

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

      - name: Load release config
        run: cat packaging/aur/config.env >> "$GITHUB_ENV"

      - name: Verify tag matches crate version
        run: |
          version="$(cargo metadata --no-deps --format-version=1 | jq -r --arg crate "$CRATE_NAME" '.packages[] | select(.name == $crate) | .version')"
          tag="${GITHUB_REF_NAME#v}"
          test "$version" = "$tag"
          echo "VERSION=$version" >> "$GITHUB_ENV"

      - name: Publish crate if needed
        run: |
          locked=()
          if [ -f Cargo.lock ]; then
            locked=(--locked)
          fi
          cargo package "${locked[@]}"
          if curl -fsS "https://crates.io/api/v1/crates/${CRATE_NAME}/${VERSION}" >/dev/null; then
            echo "${CRATE_NAME} ${VERSION} is already published"
          else
            cargo publish "${locked[@]}" --token "$CARGO_REGISTRY_TOKEN"
          fi
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}

  release-binaries:
    name: Build release binaries
    runs-on: ubuntu-latest
    needs: publish-crate
    strategy:
      fail-fast: false
      matrix:
        target:
          - x86_64-unknown-linux-gnu
          - aarch64-unknown-linux-gnu
    steps:
      - name: Checkout
        uses: actions/checkout@v4

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

      - name: Install cross
        if: matrix.target != 'x86_64-unknown-linux-gnu'
        uses: taiki-e/install-action@cross

      - name: Load release config
        run: cat packaging/aur/config.env >> "$GITHUB_ENV"

      - name: Build binary
        run: |
          locked=()
          if [ -f Cargo.lock ]; then
            locked=(--locked)
          fi
          if [ "${{ matrix.target }}" = "x86_64-unknown-linux-gnu" ]; then
            cargo build "${locked[@]}" --release --target "${{ matrix.target }}" ${CARGO_BUILD_FLAGS:-}
          else
            cross build "${locked[@]}" --release --target "${{ matrix.target }}" ${CARGO_BUILD_FLAGS:-}
          fi

      - name: Package binary
        run: |
          version="${GITHUB_REF_NAME#v}"
          target="${{ matrix.target }}"
          archive_dir="${AUR_NAME}-${version}-${target}"
          mkdir -p "dist/${archive_dir}"
          install -Dm755 "target/${target}/release/${BIN_NAME}" "dist/${archive_dir}/${INSTALL_NAME}"
          cp README* LICENSE* CHANGELOG* NOTICE* "dist/${archive_dir}/" 2>/dev/null || true
          tar -C dist -czf "dist/${archive_dir}.tar.gz" "${archive_dir}"
          sha256sum "dist/${archive_dir}.tar.gz" > "dist/${archive_dir}.tar.gz.sha256"

      - name: Upload binary artifact
        uses: actions/upload-artifact@v4
        with:
          name: ${{ matrix.target }}-release
          path: dist/*
          if-no-files-found: error

  github-release:
    name: Upload GitHub Release assets
    runs-on: ubuntu-latest
    needs: release-binaries
    steps:
      - name: Download release artifacts
        uses: actions/download-artifact@v4
        with:
          path: dist
          merge-multiple: true

      - name: Publish GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          files: dist/*

  publish-aur:
    name: Publish AUR packages
    runs-on: ubuntu-latest
    needs: github-release
    container:
      image: archlinux:latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Install Arch packaging tools
        run: |
          pacman -Syu --noconfirm --needed base-devel git openssh pacman-contrib sudo curl jq
          useradd -m builder
          printf 'builder ALL=(ALL:ALL) NOPASSWD: ALL\n' > /etc/sudoers.d/builder
          chmod 0440 /etc/sudoers.d/builder

      - name: Configure AUR SSH
        run: |
          install -dm700 "$HOME/.ssh"
          printf '%s\n' "$AUR_SSH_PRIVATE_KEY" > "$HOME/.ssh/aur_github_actions"
          chmod 600 "$HOME/.ssh/aur_github_actions"
          ssh-keyscan -t rsa,ecdsa,ed25519 aur.archlinux.org > "$HOME/.ssh/known_hosts"
          chmod 600 "$HOME/.ssh/known_hosts"
          ssh-keygen -F aur.archlinux.org -f "$HOME/.ssh/known_hosts" >/dev/null
          cat > "$HOME/.ssh/config" <<EOF
          Host aur.archlinux.org
            HostName aur.archlinux.org
            User aur
            IdentityFile $HOME/.ssh/aur_github_actions
            IdentitiesOnly yes
            UserKnownHostsFile $HOME/.ssh/known_hosts
            StrictHostKeyChecking yes
          EOF
        env:
          AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}

      - name: Generate and push AUR packages
        run: |
          set -euo pipefail
          export GIT_SSH_COMMAND="ssh -F $HOME/.ssh/config"
          source packaging/aur/config.env
          version="${GITHUB_REF_NAME#v}"
          short_sha="${GITHUB_SHA::7}"
          packages=("${AUR_NAME}" "${AUR_NAME}-bin" "${AUR_NAME}-git")

          generate_srcinfo() {
            local pkg="$1"
            local dir="$GITHUB_WORKSPACE/packaging/aur/$pkg"
            chown -R builder:builder "$dir"
            if [[ "$pkg" == *-git ]]; then
              sudo -u builder bash -lc "cd '$dir' && makepkg --printsrcinfo > .SRCINFO"
              return 0
            fi

            sudo -u builder bash -lc "
              set -euo pipefail
              cd '$dir'
              for attempt in 1 2 3 4 5 6; do
                if updpkgsums && makepkg --printsrcinfo > .SRCINFO; then
                  exit 0
                fi
                sleep 15
              done
              exit 1
            "
          }

          publish_pkg() {
            local pkg="$1"
            local dir="$GITHUB_WORKSPACE/packaging/aur/$pkg"
            local clone="/tmp/aur-$pkg"

            sed -i "s/^pkgver=.*/pkgver=${version}/" "$dir/PKGBUILD"
            sed -i "s/^pkgrel=.*/pkgrel=1/" "$dir/PKGBUILD"
            if [[ "$pkg" == *-git ]]; then
              sed -i "s/^pkgver=.*/pkgver=${version}.r0.g${short_sha}/" "$dir/PKGBUILD"
            fi

            generate_srcinfo "$pkg"

            git clone "ssh://aur@aur.archlinux.org/${pkg}.git" "$clone"
            cp "$dir/PKGBUILD" "$dir/.SRCINFO" "$clone/"
            git -C "$clone" config user.name "GitHub Actions"
            git -C "$clone" config user.email "actions@github.com"
            git -C "$clone" add PKGBUILD .SRCINFO
            if git -C "$clone" diff --cached --quiet; then
              echo "$pkg is already up to date"
              return 0
            fi
            git -C "$clone" commit -m "$pkg: update to ${version}"
            git -C "$clone" push origin master
          }

          for pkg in "${packages[@]}"; do
            publish_pkg "$pkg"
          done