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}"
test -L "${install_dir}/prs"
test "$(readlink "${install_dir}/prs")" = ping-rust
test ! -e "${install_dir}/sb"
"${install_dir}/prs" --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}"
conflict_dir="${RUNNER_TEMP}/ping-rust-conflict"
mkdir -p "${conflict_dir}"
printf 'owned-by-another-program\n' > "${conflict_dir}/prs"
bash scripts/install.sh \
--version "${GITHUB_REF_NAME}" \
--install-dir "${conflict_dir}" \
--quiet
grep -Fx 'owned-by-another-program' "${conflict_dir}/prs"
test -x "${conflict_dir}/ping-rust"
legacy_dir="${RUNNER_TEMP}/ping-rust-legacy-alias"
mkdir -p "${legacy_dir}"
ln -s ping-rust "${legacy_dir}/sb"
bash scripts/install.sh \
--version "${GITHUB_REF_NAME}" \
--install-dir "${legacy_dir}" \
--quiet
test ! -e "${legacy_dir}/sb"
test "$(readlink "${legacy_dir}/prs")" = ping-rust