Skip to content

Commit 926e1eb

Browse files
committed
feat(release): add macOS arm64 build and installer support
- bundle.sh: parameterize output via BUNDLE_TARGET env var (default: linux-x64), produces safeclaw-${BUNDLE_TARGET}.tar.gz - release.yml: matrix build for ubuntu-latest (linux-x64) and macos-15 (darwin-arm64); native sandbox helper built on Linux only - install.sh: remove Linux-only restriction; detect OS/arch and map to correct release asset (linux-x64, linux-arm64, darwin-arm64, darwin-x64); skip sandbox helper on macOS; add ~/.zprofile for macOS login shells; Homebrew Node.js install hint on macOS
1 parent be309c9 commit 926e1eb

3 files changed

Lines changed: 112 additions & 59 deletions

File tree

.github/workflows/release.yml

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,15 @@ permissions:
1010

1111
jobs:
1212
build-and-release:
13-
runs-on: ubuntu-latest
13+
strategy:
14+
matrix:
15+
include:
16+
- os: ubuntu-latest
17+
bundle_target: linux-x64
18+
- os: macos-15
19+
bundle_target: darwin-arm64
20+
21+
runs-on: ${{ matrix.os }}
1422

1523
steps:
1624
- name: Checkout code
@@ -35,24 +43,39 @@ jobs:
3543

3644
- name: Build and bundle
3745
run: pnpm bundle
46+
env:
47+
BUNDLE_TARGET: ${{ matrix.bundle_target }}
3848

3949
- name: Install musl-tools
50+
if: runner.os == 'Linux'
4051
run: sudo apt-get update && sudo apt-get install -y musl-tools
4152

4253
- name: Build native sandbox helper
54+
if: runner.os == 'Linux'
4355
run: make -C native
4456

45-
- name: Prepare native release assets
57+
- name: Prepare release assets (Linux)
58+
if: runner.os == 'Linux'
4659
run: |
4760
cp native/safeclaw-sandbox-helper safeclaw-sandbox-helper-linux-x86_64
48-
sha256sum safeclaw-sandbox-helper-linux-x86_64 > SHA256SUMS
61+
sha256sum safeclaw-${{ matrix.bundle_target }}.tar.gz safeclaw-sandbox-helper-linux-x86_64 > SHA256SUMS
4962
50-
- name: Create GitHub release
63+
- name: Upload release assets (Linux)
64+
if: runner.os == 'Linux'
5165
uses: softprops/action-gh-release@v2
5266
with:
5367
name: ${{ github.ref_name }}
5468
files: |
55-
safeclaw-linux-x64.tar.gz
69+
safeclaw-${{ matrix.bundle_target }}.tar.gz
5670
safeclaw-sandbox-helper-linux-x86_64
5771
SHA256SUMS
5872
generate_release_notes: true
73+
74+
- name: Upload release assets (macOS)
75+
if: runner.os == 'macOS'
76+
uses: softprops/action-gh-release@v2
77+
with:
78+
name: ${{ github.ref_name }}
79+
files: |
80+
safeclaw-${{ matrix.bundle_target }}.tar.gz
81+
generate_release_notes: false

install.sh

Lines changed: 77 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -44,30 +44,41 @@ for arg in "$@"; do
4444
done
4545

4646
# ---------------------------------------------------------------------------
47-
# OS check — Linux only for v1
47+
# OS and architecture detection
4848
# ---------------------------------------------------------------------------
4949
OS="$(uname -s)"
50-
if [ "$OS" != "Linux" ]; then
51-
error "Error: SafeClaw currently supports Linux only."
52-
error "Detected OS: $OS"
53-
error "macOS and Windows support is planned for a future release."
54-
exit 1
55-
fi
56-
57-
# ---------------------------------------------------------------------------
58-
# Architecture detection
59-
# ---------------------------------------------------------------------------
6050
RAW_ARCH="$(uname -m)"
61-
case "$RAW_ARCH" in
62-
x86_64) ARCH="x64" ;;
63-
aarch64) ARCH="arm64" ;;
51+
52+
case "$OS" in
53+
Linux)
54+
case "$RAW_ARCH" in
55+
x86_64) PLATFORM="linux-x64" ;;
56+
aarch64) PLATFORM="linux-arm64" ;;
57+
*)
58+
error "Error: Unsupported architecture: $RAW_ARCH"
59+
error "SafeClaw supports x86_64 and aarch64 on Linux."
60+
exit 1
61+
;;
62+
esac
63+
;;
64+
Darwin)
65+
case "$RAW_ARCH" in
66+
arm64) PLATFORM="darwin-arm64" ;;
67+
x86_64) PLATFORM="darwin-x64" ;;
68+
*)
69+
error "Error: Unsupported architecture: $RAW_ARCH"
70+
error "SafeClaw supports arm64 and x86_64 on macOS."
71+
exit 1
72+
;;
73+
esac
74+
;;
6475
*)
65-
error "Error: Unsupported architecture: $RAW_ARCH"
66-
error "SafeClaw supports x86_64 (x64) and aarch64 (arm64)."
76+
error "Error: Unsupported OS: $OS"
77+
error "SafeClaw supports Linux and macOS."
6778
exit 1
6879
;;
6980
esac
70-
info "Detected architecture: $RAW_ARCH (mapped to $ARCH)"
81+
info "Detected platform: $OS/$RAW_ARCH (mapped to $PLATFORM)"
7182

7283
# ---------------------------------------------------------------------------
7384
# Node.js version check (>= 22)
@@ -82,10 +93,16 @@ if ! command -v node &>/dev/null; then
8293
error " curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash"
8394
error " nvm install $MIN_NODE_VERSION"
8495
error ""
85-
error " # Using NodeSource:"
86-
error " curl -fsSL https://deb.nodesource.com/setup_${MIN_NODE_VERSION}.x | sudo -E bash -"
87-
error " sudo apt-get install -y nodejs"
88-
error ""
96+
if [ "$OS" = "Darwin" ]; then
97+
error " # Using Homebrew:"
98+
error " brew install node@$MIN_NODE_VERSION"
99+
error ""
100+
else
101+
error " # Using NodeSource (Linux):"
102+
error " curl -fsSL https://deb.nodesource.com/setup_${MIN_NODE_VERSION}.x | sudo -E bash -"
103+
error " sudo apt-get install -y nodejs"
104+
error ""
105+
fi
89106
error " # Using fnm:"
90107
error " curl -fsSL https://fnm.vercel.app/install | bash"
91108
error " fnm install $MIN_NODE_VERSION"
@@ -173,7 +190,7 @@ info "Latest release: $TAG"
173190
# ---------------------------------------------------------------------------
174191
# Download tarball
175192
# ---------------------------------------------------------------------------
176-
ASSET_NAME="safeclaw-linux-${ARCH}.tar.gz"
193+
ASSET_NAME="safeclaw-${PLATFORM}.tar.gz"
177194
DOWNLOAD_URL="https://github.com/$REPO/releases/download/$TAG/$ASSET_NAME"
178195
TMPDIR="$(mktemp -d)"
179196
TARBALL="$TMPDIR/$ASSET_NAME"
@@ -197,36 +214,39 @@ mkdir -p "$INSTALL_DIR"
197214
tar xzf "$TARBALL" -C "$INSTALL_DIR" --strip-components=1
198215

199216
# ---------------------------------------------------------------------------
200-
# Download sandbox helper binary (optional — sandboxing works without it)
217+
# Download sandbox helper binary (Linux only)
201218
# ---------------------------------------------------------------------------
202-
HELPER_ASSET="safeclaw-sandbox-helper-linux-${RAW_ARCH}"
203-
HELPER_URL="https://github.com/$REPO/releases/download/$TAG/$HELPER_ASSET"
204-
SHA_URL="https://github.com/$REPO/releases/download/$TAG/SHA256SUMS"
205-
206-
info "Downloading sandbox helper..."
207-
HELPER_DL="$TMPDIR/$HELPER_ASSET"
208-
SHA_DL="$TMPDIR/SHA256SUMS"
209-
210-
if curl -fSL --progress-bar -o "$HELPER_DL" "$HELPER_URL" 2>/dev/null && \
211-
curl -fsSL -o "$SHA_DL" "$SHA_URL" 2>/dev/null; then
212-
213-
# Verify SHA-256 checksum
214-
EXPECTED_HASH="$(grep "$HELPER_ASSET" "$SHA_DL" | awk '{print $1}')"
215-
ACTUAL_HASH="$(sha256sum "$HELPER_DL" | awk '{print $1}')"
216-
217-
if [ -n "$EXPECTED_HASH" ] && [ "$EXPECTED_HASH" = "$ACTUAL_HASH" ]; then
218-
mkdir -p "$BIN_DIR"
219-
install -m755 "$HELPER_DL" "$BIN_DIR/safeclaw-sandbox-helper"
220-
success "Sandbox helper installed (SHA-256 verified)."
221-
else
222-
warn "Warning: Sandbox helper checksum mismatch — skipping."
223-
warn "Expected: $EXPECTED_HASH"
224-
warn "Actual: $ACTUAL_HASH"
225-
warn "SafeClaw will run with namespace-only sandboxing."
226-
fi
219+
if [ "$OS" = "Linux" ]; then
220+
HELPER_ASSET="safeclaw-sandbox-helper-linux-${RAW_ARCH}"
221+
HELPER_URL="https://github.com/$REPO/releases/download/$TAG/$HELPER_ASSET"
222+
SHA_URL="https://github.com/$REPO/releases/download/$TAG/SHA256SUMS"
223+
224+
info "Downloading sandbox helper..."
225+
HELPER_DL="$TMPDIR/$HELPER_ASSET"
226+
SHA_DL="$TMPDIR/SHA256SUMS"
227+
228+
if curl -fSL --progress-bar -o "$HELPER_DL" "$HELPER_URL" 2>/dev/null && \
229+
curl -fsSL -o "$SHA_DL" "$SHA_URL" 2>/dev/null; then
230+
231+
EXPECTED_HASH="$(grep "$HELPER_ASSET" "$SHA_DL" | awk '{print $1}')"
232+
ACTUAL_HASH="$(sha256sum "$HELPER_DL" | awk '{print $1}')"
233+
234+
if [ -n "$EXPECTED_HASH" ] && [ "$EXPECTED_HASH" = "$ACTUAL_HASH" ]; then
235+
mkdir -p "$BIN_DIR"
236+
install -m755 "$HELPER_DL" "$BIN_DIR/safeclaw-sandbox-helper"
237+
success "Sandbox helper installed (SHA-256 verified)."
238+
else
239+
warn "Warning: Sandbox helper checksum mismatch — skipping."
240+
warn "Expected: $EXPECTED_HASH"
241+
warn "Actual: $ACTUAL_HASH"
242+
warn "SafeClaw will run with namespace-only sandboxing."
243+
fi
244+
else
245+
warn "Sandbox helper not available for $RAW_ARCH — skipping."
246+
warn "SafeClaw will run with namespace-only sandboxing."
247+
fi
227248
else
228-
warn "Sandbox helper not available for $RAW_ARCH — skipping."
229-
warn "SafeClaw will run with namespace-only sandboxing."
249+
info "Sandbox helper is Linux-only — skipping on macOS."
230250
fi
231251

232252
# ---------------------------------------------------------------------------
@@ -273,6 +293,13 @@ else
273293
printf '\n# SafeClaw\n%s\n' "$PATH_LINE" >> "$HOME/.zshrc"
274294
MODIFIED_CONFIGS+=("~/.zshrc")
275295
fi
296+
# ~/.zprofile — login shells on macOS (Terminal.app opens login shells)
297+
if [ "$OS" = "Darwin" ]; then
298+
if [ -f "$HOME/.zprofile" ] && ! grep -qF '.safeclaw/bin' "$HOME/.zprofile" 2>/dev/null; then
299+
printf '\n# SafeClaw\n%s\n' "$PATH_LINE" >> "$HOME/.zprofile"
300+
MODIFIED_CONFIGS+=("~/.zprofile")
301+
fi
302+
fi
276303
fi
277304

278305
if [ ${#MODIFIED_CONFIGS[@]} -gt 0 ]; then

scripts/bundle.sh

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ set -euo pipefail
44
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
55
cd "$REPO_ROOT"
66

7+
BUNDLE_TARGET="${BUNDLE_TARGET:-linux-x64}"
8+
TARBALL="safeclaw-${BUNDLE_TARGET}.tar.gz"
9+
710
echo "==> Cleaning previous build artifacts..."
8-
rm -rf bundle/ safeclaw-linux-x64.tar.gz
11+
rm -rf bundle/ safeclaw-*.tar.gz
912
pnpm -r exec rm -rf dist
1013

1114
echo "==> Installing dependencies..."
@@ -51,10 +54,10 @@ echo "==> Installing production dependencies in bundle..."
5154
(cd bundle/safeclaw && pnpm install --prod --frozen-lockfile)
5255

5356
echo "==> Creating tarball..."
54-
tar czf safeclaw-linux-x64.tar.gz -C bundle safeclaw
57+
tar czf "$TARBALL" -C bundle safeclaw
5558

56-
TARBALL_SIZE="$(du -h safeclaw-linux-x64.tar.gz | cut -f1)"
59+
TARBALL_SIZE="$(du -h "$TARBALL" | cut -f1)"
5760
echo ""
5861
echo "Bundle complete:"
59-
echo " Path: $(pwd)/safeclaw-linux-x64.tar.gz"
62+
echo " Path: $(pwd)/$TARBALL"
6063
echo " Size: $TARBALL_SIZE"

0 commit comments

Comments
 (0)