diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f592837..b7c27b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -84,6 +84,17 @@ jobs: persist-credentials: false - run: bash packaging/apt/test-build-deb.sh + homebrew-script: + name: Homebrew release script + # release.sh runs by hand after a release, so it is exercised here + # against stand-in assets. + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - run: bash packaging/homebrew/test-release.sh + test-macos: name: Test (macOS) runs-on: macos-latest diff --git a/CHANGELOG.md b/CHANGELOG.md index 6247141..10fde3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -94,7 +94,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 `GLIBC_2.39' not found``. Each release now also ships statically linked `x86_64-unknown-linux-musl` and `aarch64-unknown-linux-musl` archives, which start on any distribution. CI runs both on Ubuntu - 22.04 and Debian 12 and fails on any loader message. + 22.04 and Debian 12 and fails on any loader message. The Homebrew + tap installs the musl archives on Linux. - **bash, zsh, nu: a line that starts with `-` expands (#50).** The templates passed the buffer as `--line `, so `runex hook` read a leading `-` as an option, failed, and the shell inserted a plain diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9f7450a..b151ced 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -407,7 +407,7 @@ https://github.com/ShortArrow/runex/releases/tag/vX.Y.Z. The second argument is the tap clone (`git clone https://github.com/ShortArrow/homebrew-runex.git` anywhere; the path above is where it lives on the Windows workstation). The - script fetches the macOS arm64/x86_64 and Linux arm64/x86_64 + script fetches the macOS arm64/x86_64 and Linux musl arm64/x86_64 tarball sha256s, rewrites `Formula/runex.rb`, and stages a commit in the tap clone. Push manually: diff --git a/packaging/homebrew/release.sh b/packaging/homebrew/release.sh index f60eeea..b11beab 100755 --- a/packaging/homebrew/release.sh +++ b/packaging/homebrew/release.sh @@ -8,7 +8,7 @@ # packaging/homebrew/release.sh 0.1.12 /v/github.com/ShortArrow/homebrew-runex # # What it does: -# 1. Fetches SHA256 of the macOS/Linux (x86_64/aarch64) release tarballs +# 1. Fetches SHA256 of the macOS and Linux musl (x86_64/aarch64) release tarballs # 2. Rewrites version and sha256 values in Formula/runex.rb # 3. Commits the change (push is left to the user) @@ -39,13 +39,15 @@ sha_of() { curl -fsSL "$url" | sha256sum | awk '{print $1}' } -BASE="https://github.com/ShortArrow/runex/releases/download/v${VERSION}" +# RUNEX_RELEASE_BASE points the checksums at other assets, such as a +# file:// directory in a test. +BASE="${RUNEX_RELEASE_BASE:-https://github.com/ShortArrow/runex/releases/download/v${VERSION}}" echo "Fetching SHA256 checksums for v${VERSION}..." SHA_MAC_ARM=$(sha_of "${BASE}/runex-aarch64-apple-darwin.tar.gz") SHA_MAC_X64=$(sha_of "${BASE}/runex-x86_64-apple-darwin.tar.gz") -SHA_LINUX_ARM=$(sha_of "${BASE}/runex-aarch64-unknown-linux-gnu.tar.gz") -SHA_LINUX_X64=$(sha_of "${BASE}/runex-x86_64-unknown-linux-gnu.tar.gz") +SHA_LINUX_ARM=$(sha_of "${BASE}/runex-aarch64-unknown-linux-musl.tar.gz") +SHA_LINUX_X64=$(sha_of "${BASE}/runex-x86_64-unknown-linux-musl.tar.gz") echo " macOS arm64: $SHA_MAC_ARM" echo " macOS x86_64: $SHA_MAC_X64" @@ -72,10 +74,14 @@ def sub_sha(src, url_substr, sha): ) return pattern.sub(rf'\1"{sha}"', src, count=1) +# Linux installs the statically linked musl archives, which start on any +# glibc; a formula still naming the gnu archives is moved over. +src = src.replace("-unknown-linux-gnu.tar.gz", "-unknown-linux-musl.tar.gz") + src = sub_sha(src, "aarch64-apple-darwin", mac_arm) src = sub_sha(src, "x86_64-apple-darwin", mac_x64) -src = sub_sha(src, "aarch64-unknown-linux-gnu", linux_arm) -src = sub_sha(src, "x86_64-unknown-linux-gnu", linux_x64) +src = sub_sha(src, "aarch64-unknown-linux-musl", linux_arm) +src = sub_sha(src, "x86_64-unknown-linux-musl", linux_x64) open(path, "w").write(src) PY diff --git a/packaging/homebrew/test-release.sh b/packaging/homebrew/test-release.sh new file mode 100755 index 0000000..3cad831 --- /dev/null +++ b/packaging/homebrew/test-release.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash +# Behaviour examples for release.sh, run against stand-in release assets +# and a throwaway tap clone. Needs git, curl and python3. +set -euo pipefail + +here="$(cd "$(dirname "$0")" && pwd)" +work="$(mktemp -d)" +trap 'rm -rf "$work"' EXIT +failures=0 + +# check : passes when the command succeeds +check() { + local description="$1" + shift + if "$@" >/dev/null 2>&1; then + echo "ok: $description" + else + echo "FAIL: $description" + failures=$((failures + 1)) + fi +} + +assets="$work/assets" +mkdir "$assets" +for target in aarch64-apple-darwin x86_64-apple-darwin \ + aarch64-unknown-linux-musl x86_64-unknown-linux-musl; do + printf '%s\n' "$target" >"$assets/runex-$target.tar.gz" +done +sha() { sha256sum "$assets/runex-$1.tar.gz" | awk '{print $1}'; } + +tap="$work/tap" +mkdir -p "$tap/Formula" +old="0000000000000000000000000000000000000000000000000000000000000000" +url="https://github.com/ShortArrow/runex/releases/download/v#{version}" +cat >"$tap/Formula/runex.rb" <"$work/out" 2>&1 || status=$? +check "release.sh succeeds when only musl Linux assets exist" test "$status" -eq 0 +[ "$status" -eq 0 ] || sed 's/^/ output: /' "$work/out" + +formula="$tap/Formula/runex.rb" +# pinned : the url naming is followed by +pinned() { + grep -A1 "runex-$1.tar.gz\"" "$formula" | grep -q "sha256 \"$2\"" +} +check "the version is 0.1.21" grep -q '^ version "0.1.21"$' "$formula" +check "no url names a linux-gnu archive" bash -c "! grep -q linux-gnu '$formula'" +for target in aarch64-apple-darwin x86_64-apple-darwin \ + aarch64-unknown-linux-musl x86_64-unknown-linux-musl; do + check "$target carries its checksum" pinned "$target" "$(sha "$target")" +done +check "the Linux arm block names the aarch64 musl archive" \ + bash -c "grep -A2 'on_linux do' '$formula' | grep -q aarch64-unknown-linux-musl" +check "the change is committed in the tap" \ + bash -c "test -z \"\$(git -C '$tap' status --porcelain)\" && git -C '$tap' log -1 --format=%s | grep -q '0.1.21'" + +if [ "$failures" -ne 0 ]; then + echo "$failures check(s) failed" + exit 1 +fi +echo "all checks passed"