ping-rust 0.1.4

Menu-driven installer and manager for the shoes proxy server
name: Release

on:
  push:
    tags:
      - "v[0-9]+.[0-9]+.[0-9]+"
  workflow_dispatch:

permissions:
  contents: read

concurrency:
  group: release-${{ github.ref }}
  cancel-in-progress: false

jobs:
  build:
    name: Build ${{ matrix.target }}
    runs-on: ubuntu-24.04
    strategy:
      fail-fast: false
      matrix:
        target:
          - x86_64-unknown-linux-musl
          - aarch64-unknown-linux-musl
    steps:
      - uses: actions/checkout@v5
      - uses: dtolnay/rust-toolchain@stable
      - uses: taiki-e/install-action@v2
        with:
          tool: cross
      - uses: Swatinem/rust-cache@v2
        with:
          key: release-${{ matrix.target }}

      - name: Build static binary
        run: cross build --locked --release --target "${{ matrix.target }}"

      - name: Install ARM64 runtime emulator
        if: matrix.target == 'aarch64-unknown-linux-musl'
        run: |
          sudo apt-get update
          sudo apt-get install -y --no-install-recommends qemu-user-static

      - name: Verify and package binary
        env:
          TARGET: ${{ matrix.target }}
        shell: bash
        run: |
          set -euo pipefail
          binary="target/${TARGET}/release/ping-rust"
          test -x "${binary}"

          file "${binary}"
          if readelf -l "${binary}" | grep -q "Requesting program interpreter"; then
            echo "error: ${TARGET} binary contains a dynamic program interpreter" >&2
            exit 1
          fi
          if readelf -d "${binary}" 2>/dev/null | grep -q "(NEEDED)"; then
            echo "error: ${TARGET} binary contains dynamic library dependencies" >&2
            exit 1
          fi

          if [ "${TARGET}" = "aarch64-unknown-linux-musl" ]; then
            version_output="$(qemu-aarch64-static "${binary}" --version)"
          else
            version_output="$("${binary}" --version)"
          fi
          printf '%s\n' "${version_output}"
          printf '%s\n' "${version_output}" \
            | grep -Eq '^ping-rust [0-9]+\.[0-9]+\.[0-9]+([.+-][0-9A-Za-z.-]+)?$'

          package_dir="dist/${TARGET}"
          mkdir -p "${package_dir}"
          install -m 0755 "${binary}" "${package_dir}/ping-rust"
          tar --sort=name --owner=0 --group=0 --numeric-owner \
            --mtime='UTC 1970-01-01' -C "${package_dir}" -cf - ping-rust \
            | gzip -9n > "dist/ping-rust-${TARGET}.tar.gz"
          sha256sum "dist/ping-rust-${TARGET}.tar.gz"

      - uses: actions/upload-artifact@v7
        with:
          name: ping-rust-${{ matrix.target }}
          path: dist/ping-rust-${{ matrix.target }}.tar.gz
          if-no-files-found: error

  release:
    name: Publish GitHub Release
    if: startsWith(github.ref, 'refs/tags/v')
    needs: build
    runs-on: ubuntu-24.04
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v5

      - name: Verify tag matches Cargo version
        shell: bash
        run: |
          set -euo pipefail
          manifest_version="$(python3 -c 'import tomllib; print(tomllib.load(open("Cargo.toml", "rb"))["package"]["version"])')"
          tag_version="${GITHUB_REF_NAME#v}"
          if [ "${manifest_version}" != "${tag_version}" ]; then
            echo "error: tag ${GITHUB_REF_NAME} does not match Cargo.toml version ${manifest_version}" >&2
            exit 1
          fi

      - uses: actions/download-artifact@v8
        with:
          path: dist
          merge-multiple: true

      - name: Generate checksums
        shell: bash
        run: |
          set -euo pipefail
          cd dist
          sha256sum ping-rust-*.tar.gz | sort -k 2 > SHA256SUMS
          sha256sum --check SHA256SUMS
          cat SHA256SUMS

      - name: Create GitHub Release
        env:
          GH_TOKEN: ${{ github.token }}
        shell: bash
        run: |
          set -euo pipefail
          if gh release view "${GITHUB_REF_NAME}" >/dev/null 2>&1; then
            gh release upload "${GITHUB_REF_NAME}" dist/* --clobber
          else
            gh release create "${GITHUB_REF_NAME}" dist/* \
              --verify-tag \
              --title "ping-rust ${GITHUB_REF_NAME}" \
              --generate-notes
          fi

      - name: Verify published one-click installer
        shell: bash
        run: |
          set -euo pipefail
          install_dir="${RUNNER_TEMP}/ping-rust-bin"
          bash scripts/install.sh \
            --version "${GITHUB_REF_NAME}" \
            --install-dir "${install_dir}" \
            --quiet
          "${install_dir}/ping-rust" --version \
            | grep -Fx "ping-rust ${GITHUB_REF_NAME#v}"
          "${install_dir}/ping-rust" self-update \
            --version "${GITHUB_REF_NAME}" \
            --force
          "${install_dir}/ping-rust" --version \
            | grep -Fx "ping-rust ${GITHUB_REF_NAME#v}"