fix(release): restore linux compatibility fallbacks
This commit is contained in:
parent
2b6085b10e
commit
b940c7b641
6
.github/workflows/pub-release.yml
vendored
6
.github/workflows/pub-release.yml
vendored
@ -202,7 +202,7 @@ jobs:
|
||||
include:
|
||||
# Keep GNU Linux release artifacts on Ubuntu 22.04 to preserve
|
||||
# a broadly compatible GLIBC baseline for user distributions.
|
||||
- os: [self-hosted, Linux, X64, blacksmith-2vcpu-ubuntu-2404]
|
||||
- os: ubuntu-22.04
|
||||
target: x86_64-unknown-linux-gnu
|
||||
artifact: zeroclaw
|
||||
archive_ext: tar.gz
|
||||
@ -217,7 +217,7 @@ jobs:
|
||||
linker_env: ""
|
||||
linker: ""
|
||||
use_cross: true
|
||||
- os: [self-hosted, Linux, X64, blacksmith-2vcpu-ubuntu-2404]
|
||||
- os: ubuntu-22.04
|
||||
target: aarch64-unknown-linux-gnu
|
||||
artifact: zeroclaw
|
||||
archive_ext: tar.gz
|
||||
@ -232,7 +232,7 @@ jobs:
|
||||
linker_env: ""
|
||||
linker: ""
|
||||
use_cross: true
|
||||
- os: [self-hosted, Linux, X64, blacksmith-2vcpu-ubuntu-2404]
|
||||
- os: ubuntu-22.04
|
||||
target: armv7-unknown-linux-gnueabihf
|
||||
artifact: zeroclaw
|
||||
archive_ext: tar.gz
|
||||
|
||||
@ -132,29 +132,33 @@ get_available_disk_mb() {
|
||||
fi
|
||||
}
|
||||
|
||||
detect_release_target() {
|
||||
detect_release_targets() {
|
||||
local os arch
|
||||
os="$(uname -s)"
|
||||
arch="$(uname -m)"
|
||||
|
||||
case "$os:$arch" in
|
||||
Linux:x86_64)
|
||||
echo "x86_64-unknown-linux-gnu"
|
||||
printf '%s\n' \
|
||||
"x86_64-unknown-linux-musl" \
|
||||
"x86_64-unknown-linux-gnu"
|
||||
;;
|
||||
Linux:aarch64|Linux:arm64)
|
||||
echo "aarch64-unknown-linux-gnu"
|
||||
printf '%s\n' \
|
||||
"aarch64-unknown-linux-musl" \
|
||||
"aarch64-unknown-linux-gnu"
|
||||
;;
|
||||
Linux:armv7l|Linux:armv6l)
|
||||
echo "armv7-unknown-linux-gnueabihf"
|
||||
printf '%s\n' "armv7-unknown-linux-gnueabihf"
|
||||
;;
|
||||
Darwin:x86_64)
|
||||
echo "x86_64-apple-darwin"
|
||||
printf '%s\n' "x86_64-apple-darwin"
|
||||
;;
|
||||
Darwin:arm64|Darwin:aarch64)
|
||||
echo "aarch64-apple-darwin"
|
||||
printf '%s\n' "aarch64-apple-darwin"
|
||||
;;
|
||||
FreeBSD:amd64|FreeBSD:x86_64)
|
||||
echo "x86_64-unknown-freebsd"
|
||||
printf '%s\n' "x86_64-unknown-freebsd"
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
@ -264,6 +268,7 @@ detect_config_channel_features() {
|
||||
|
||||
install_prebuilt_binary() {
|
||||
local target archive_url temp_dir archive_path extracted_bin install_dir
|
||||
local -a candidate_targets=()
|
||||
|
||||
if ! have_cmd curl; then
|
||||
warn "curl is required for pre-built binary installation."
|
||||
@ -274,19 +279,25 @@ install_prebuilt_binary() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
target="$(detect_release_target || true)"
|
||||
if [[ -z "$target" ]]; then
|
||||
mapfile -t candidate_targets < <(detect_release_targets || true)
|
||||
if [[ "${#candidate_targets[@]}" -eq 0 ]]; then
|
||||
warn "No pre-built binary target mapping for $(uname -s)/$(uname -m)."
|
||||
return 1
|
||||
fi
|
||||
|
||||
archive_url="https://github.com/zeroclaw-labs/zeroclaw/releases/latest/download/zeroclaw-${target}.tar.gz"
|
||||
temp_dir="$(mktemp -d -t zeroclaw-prebuilt-XXXXXX)"
|
||||
archive_path="$temp_dir/zeroclaw-${target}.tar.gz"
|
||||
|
||||
info "Attempting pre-built binary install for target: $target"
|
||||
if ! curl -fsSL "$archive_url" -o "$archive_path"; then
|
||||
warn "Could not download release asset: $archive_url"
|
||||
for target in "${candidate_targets[@]}"; do
|
||||
archive_url="https://github.com/zeroclaw-labs/zeroclaw/releases/latest/download/zeroclaw-${target}.tar.gz"
|
||||
archive_path="$temp_dir/zeroclaw-${target}.tar.gz"
|
||||
info "Attempting pre-built binary install for target: $target"
|
||||
if curl -fsSL "$archive_url" -o "$archive_path"; then
|
||||
break
|
||||
fi
|
||||
rm -f "$archive_path"
|
||||
archive_path=""
|
||||
done
|
||||
if [[ -z "${archive_path:-}" || ! -f "$archive_path" ]]; then
|
||||
warn "Could not download a compatible release asset."
|
||||
rm -rf "$temp_dir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
121
scripts/ci/tests/test_release_installers.py
Normal file
121
scripts/ci/tests/test_release_installers.py
Normal file
@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Behavioral checks for release installer target selection helpers."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import subprocess
|
||||
import textwrap
|
||||
import unittest
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[3]
|
||||
INSTALL_RELEASE = ROOT / "scripts" / "install-release.sh"
|
||||
BOOTSTRAP = ROOT / "scripts" / "bootstrap.sh"
|
||||
PUB_RELEASE = ROOT / ".github" / "workflows" / "pub-release.yml"
|
||||
|
||||
|
||||
def run_cmd(cmd: list[str]) -> subprocess.CompletedProcess[str]:
|
||||
return subprocess.run(
|
||||
cmd,
|
||||
text=True,
|
||||
capture_output=True,
|
||||
check=False,
|
||||
)
|
||||
|
||||
|
||||
def extract_function(function_name: str, script_path: Path) -> str:
|
||||
lines = script_path.read_text(encoding="utf-8").splitlines()
|
||||
start = None
|
||||
for index, line in enumerate(lines):
|
||||
if line == f"{function_name}() {{":
|
||||
start = index
|
||||
break
|
||||
if start is None:
|
||||
raise AssertionError(f"could not find function {function_name} in {script_path}")
|
||||
|
||||
body: list[str] = []
|
||||
for line in lines[start:]:
|
||||
body.append(line)
|
||||
if line == "}":
|
||||
break
|
||||
return "\n".join(body) + "\n"
|
||||
|
||||
|
||||
def run_shell_function(script_path: Path, function_name: str, os_name: str, arch: str) -> list[str]:
|
||||
function_source = extract_function(function_name, script_path)
|
||||
shell = textwrap.dedent(
|
||||
f"""
|
||||
set -euo pipefail
|
||||
{function_source}
|
||||
uname() {{
|
||||
if [[ "${{1:-}}" == "-m" ]]; then
|
||||
printf '%s\\n' "{arch}"
|
||||
else
|
||||
printf '%s\\n' "{os_name}"
|
||||
fi
|
||||
}}
|
||||
{function_name}
|
||||
"""
|
||||
)
|
||||
proc = run_cmd(["bash", "-lc", shell])
|
||||
if proc.returncode != 0:
|
||||
raise AssertionError(proc.stderr or proc.stdout)
|
||||
return [line for line in proc.stdout.splitlines() if line]
|
||||
|
||||
|
||||
def workflow_target_os(target: str) -> str:
|
||||
workflow = PUB_RELEASE.read_text(encoding="utf-8")
|
||||
pattern = re.compile(
|
||||
rf"^\s+- os: (?P<os>.+)\n\s+target: {re.escape(target)}$",
|
||||
re.MULTILINE,
|
||||
)
|
||||
match = pattern.search(workflow)
|
||||
if match is None:
|
||||
raise AssertionError(f"could not find workflow target block for {target}")
|
||||
return match.group("os").strip()
|
||||
|
||||
|
||||
class ReleaseInstallerTargetSelectionTest(unittest.TestCase):
|
||||
def test_install_release_prefers_musl_for_linux_x86_64(self) -> None:
|
||||
self.assertEqual(
|
||||
run_shell_function(INSTALL_RELEASE, "linux_triples", "Linux", "x86_64"),
|
||||
["x86_64-unknown-linux-musl", "x86_64-unknown-linux-gnu"],
|
||||
)
|
||||
|
||||
def test_install_release_prefers_musl_for_linux_aarch64(self) -> None:
|
||||
self.assertEqual(
|
||||
run_shell_function(INSTALL_RELEASE, "linux_triples", "Linux", "aarch64"),
|
||||
["aarch64-unknown-linux-musl", "aarch64-unknown-linux-gnu"],
|
||||
)
|
||||
|
||||
def test_bootstrap_prefers_musl_for_linux_x86_64(self) -> None:
|
||||
self.assertEqual(
|
||||
run_shell_function(BOOTSTRAP, "detect_release_targets", "Linux", "x86_64"),
|
||||
["x86_64-unknown-linux-musl", "x86_64-unknown-linux-gnu"],
|
||||
)
|
||||
|
||||
def test_bootstrap_preserves_non_linux_target_mapping(self) -> None:
|
||||
self.assertEqual(
|
||||
run_shell_function(BOOTSTRAP, "detect_release_targets", "Darwin", "arm64"),
|
||||
["aarch64-apple-darwin"],
|
||||
)
|
||||
|
||||
def test_pub_release_keeps_gnu_linux_targets_on_ubuntu_22_04(self) -> None:
|
||||
self.assertEqual(workflow_target_os("x86_64-unknown-linux-gnu"), "ubuntu-22.04")
|
||||
self.assertEqual(workflow_target_os("aarch64-unknown-linux-gnu"), "ubuntu-22.04")
|
||||
self.assertEqual(workflow_target_os("armv7-unknown-linux-gnueabihf"), "ubuntu-22.04")
|
||||
|
||||
def test_pub_release_keeps_musl_linux_targets_on_self_hosted_runner(self) -> None:
|
||||
expected = "[self-hosted, Linux, X64, blacksmith-2vcpu-ubuntu-2404]"
|
||||
self.assertEqual(workflow_target_os("x86_64-unknown-linux-musl"), expected)
|
||||
self.assertEqual(workflow_target_os("aarch64-unknown-linux-musl"), expected)
|
||||
|
||||
def test_scripts_remain_shell_parseable(self) -> None:
|
||||
proc = run_cmd(["bash", "-n", str(INSTALL_RELEASE), str(BOOTSTRAP)])
|
||||
self.assertEqual(proc.returncode, 0, msg=proc.stderr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@ -23,13 +23,23 @@ run_privileged() {
|
||||
fi
|
||||
}
|
||||
|
||||
linux_triple() {
|
||||
linux_triples() {
|
||||
local arch
|
||||
arch="$(uname -m)"
|
||||
case "$arch" in
|
||||
x86_64|amd64) echo "x86_64-unknown-linux-gnu" ;;
|
||||
aarch64|arm64) echo "aarch64-unknown-linux-gnu" ;;
|
||||
armv7l|armv7) echo "armv7-unknown-linux-gnueabihf" ;;
|
||||
x86_64|amd64)
|
||||
printf '%s\n' \
|
||||
"x86_64-unknown-linux-musl" \
|
||||
"x86_64-unknown-linux-gnu"
|
||||
;;
|
||||
aarch64|arm64)
|
||||
printf '%s\n' \
|
||||
"aarch64-unknown-linux-musl" \
|
||||
"aarch64-unknown-linux-gnu"
|
||||
;;
|
||||
armv7l|armv7)
|
||||
printf '%s\n' "armv7-unknown-linux-gnueabihf"
|
||||
;;
|
||||
*)
|
||||
echo "error: unsupported Linux architecture: $arch" >&2
|
||||
echo "supported: x86_64, aarch64, armv7" >&2
|
||||
@ -90,9 +100,8 @@ need_cmd tar
|
||||
need_cmd mktemp
|
||||
need_cmd install
|
||||
|
||||
TRIPLE="$(linux_triple)"
|
||||
ASSET="zeroclaw-${TRIPLE}.tar.gz"
|
||||
DOWNLOAD_URL="${RELEASE_BASE}/${ASSET}"
|
||||
TRIPLE=""
|
||||
ASSET=""
|
||||
|
||||
TMP_DIR="$(mktemp -d)"
|
||||
cleanup() {
|
||||
@ -106,8 +115,27 @@ if ! curl -fsSL "$API_URL" >/dev/null; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "==> Downloading ${ASSET}"
|
||||
curl -fL "$DOWNLOAD_URL" -o "$TMP_DIR/$ASSET"
|
||||
download_asset() {
|
||||
local triple asset download_url
|
||||
while IFS= read -r triple; do
|
||||
[ -n "$triple" ] || continue
|
||||
asset="zeroclaw-${triple}.tar.gz"
|
||||
download_url="${RELEASE_BASE}/${asset}"
|
||||
echo "==> Attempting ${asset}"
|
||||
if curl -fsSL "$download_url" -o "$TMP_DIR/$asset"; then
|
||||
TRIPLE="$triple"
|
||||
ASSET="$asset"
|
||||
return 0
|
||||
fi
|
||||
done < <(linux_triples)
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
if ! download_asset; then
|
||||
echo "error: unable to download a compatible Linux release artifact" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "==> Extracting release archive"
|
||||
tar -xzf "$TMP_DIR/$ASSET" -C "$TMP_DIR"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user