From 6237af935f2be9979a7d1ca42dff782cfa233899 Mon Sep 17 00:00:00 2001 From: "Jiaxiao (mossaka) Zhou" Date: Thu, 19 Feb 2026 21:20:08 +0000 Subject: [PATCH] Add macOS (Darwin) binary support for x64 and arm64 - Add node18-macos-x64 and node18-macos-arm64 pkg targets - Build awf-darwin-x64 and awf-darwin-arm64 in release workflow - Add Mach-O validation step for macOS binaries - Update install.sh: detect Darwin, use shasum, validate Mach-O - Update release template with macOS installation instructions - Include macOS binaries in GitHub Release artifacts Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/release.yml | 23 +++++++++- docs/RELEASE_TEMPLATE.md | 32 ++++++++------ install.sh | 79 ++++++++++++++++++++++++++--------- package.json | 4 +- 4 files changed, 105 insertions(+), 33 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7d20a665..9ef4a7f8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -345,11 +345,20 @@ jobs: --targets node18-linux-arm64 \ --output release/awf-linux-arm64 + # Create standalone executables for macOS (x64 and arm64) + pkg . \ + --targets node18-macos-x64 \ + --output release/awf-darwin-x64 + + pkg . \ + --targets node18-macos-arm64 \ + --output release/awf-darwin-arm64 + # Verify the binaries were created echo "=== Contents of release directory ===" ls -lh release/ echo "=== Verifying binaries ===" - for bin in awf-linux-x64 awf-linux-arm64; do + for bin in awf-linux-x64 awf-linux-arm64 awf-darwin-x64 awf-darwin-arm64; do test -f "release/$bin" && echo "✓ Binary exists at release/$bin" || echo "✗ Binary NOT found: $bin" file "release/$bin" done @@ -366,6 +375,16 @@ jobs: file release/awf-linux-arm64 | grep -qi "aarch64\|arm" || { echo "ERROR: arm64 binary is not for ARM architecture"; exit 1; } echo "✓ arm64 binary is a valid ELF for ARM64" + - name: Verify macOS binaries are valid Mach-O + run: | + file release/awf-darwin-x64 | grep -q "Mach-O 64-bit" || { echo "ERROR: macOS x64 binary is not a valid Mach-O"; exit 1; } + file release/awf-darwin-x64 | grep -qi "x86_64" || { echo "ERROR: macOS x64 binary is not for x86_64 architecture"; exit 1; } + echo "✓ macOS x64 binary is a valid Mach-O for x86_64" + + file release/awf-darwin-arm64 | grep -q "Mach-O 64-bit" || { echo "ERROR: macOS arm64 binary is not a valid Mach-O"; exit 1; } + file release/awf-darwin-arm64 | grep -qi "arm64" || { echo "ERROR: macOS arm64 binary is not for ARM64 architecture"; exit 1; } + echo "✓ macOS arm64 binary is a valid Mach-O for ARM64" + - name: Create tarball for npm package run: | npm pack @@ -491,6 +510,8 @@ jobs: files: | release/awf-linux-x64 release/awf-linux-arm64 + release/awf-darwin-x64 + release/awf-darwin-arm64 release/awf.tgz release/checksums.txt env: diff --git a/docs/RELEASE_TEMPLATE.md b/docs/RELEASE_TEMPLATE.md index a35e6454..0808d7ab 100644 --- a/docs/RELEASE_TEMPLATE.md +++ b/docs/RELEASE_TEMPLATE.md @@ -31,44 +31,52 @@ Everything below the `---` separator becomes the release notes. ### One-Line Installer (Recommended) -**Linux (x64 and ARM64) with automatic SHA verification:** +**Linux and macOS (x64 and ARM64) with automatic SHA verification:** ```bash curl -sSL https://raw.githubusercontent.com/{{REPOSITORY}}/main/install.sh | sudo bash ``` This installer: -- Automatically detects your architecture (x86_64 or aarch64) +- Automatically detects your OS (Linux or macOS) and architecture (x86_64/aarch64/arm64) - Downloads the correct release binary - Verifies SHA256 checksum against `checksums.txt` -- Validates the file is a valid ELF executable +- Validates the file is a valid executable (ELF on Linux, Mach-O on macOS) - Installs to `/usr/local/bin/awf` ### Manual Binary Installation (Alternative) **Linux (x64):** ```bash -# Download binary and checksums curl -fL https://github.com/{{REPOSITORY}}/releases/download/{{VERSION}}/awf-linux-x64 -o awf curl -fL https://github.com/{{REPOSITORY}}/releases/download/{{VERSION}}/checksums.txt -o checksums.txt - -# Verify checksum sha256sum -c checksums.txt --ignore-missing - -# Install chmod +x awf sudo mv awf /usr/local/bin/ ``` **Linux (ARM64):** ```bash -# Download binary and checksums curl -fL https://github.com/{{REPOSITORY}}/releases/download/{{VERSION}}/awf-linux-arm64 -o awf curl -fL https://github.com/{{REPOSITORY}}/releases/download/{{VERSION}}/checksums.txt -o checksums.txt - -# Verify checksum sha256sum -c checksums.txt --ignore-missing +chmod +x awf +sudo mv awf /usr/local/bin/ +``` + +**macOS (Apple Silicon / ARM64):** +```bash +curl -fL https://github.com/{{REPOSITORY}}/releases/download/{{VERSION}}/awf-darwin-arm64 -o awf +curl -fL https://github.com/{{REPOSITORY}}/releases/download/{{VERSION}}/checksums.txt -o checksums.txt +shasum -a 256 -c checksums.txt --ignore-missing +chmod +x awf +sudo mv awf /usr/local/bin/ +``` -# Install +**macOS (Intel / x64):** +```bash +curl -fL https://github.com/{{REPOSITORY}}/releases/download/{{VERSION}}/awf-darwin-x64 -o awf +curl -fL https://github.com/{{REPOSITORY}}/releases/download/{{VERSION}}/checksums.txt -o checksums.txt +shasum -a 256 -c checksums.txt --ignore-missing chmod +x awf sudo mv awf /usr/local/bin/ ``` diff --git a/install.sh b/install.sh index 57f3e388..4cef846a 100755 --- a/install.sh +++ b/install.sh @@ -63,16 +63,34 @@ check_sudo() { fi } +# Compute SHA256 hash portably (Linux uses sha256sum, macOS uses shasum) +sha256_portable() { + local file="$1" + if command -v sha256sum &> /dev/null; then + sha256sum "$file" | awk '{print $1}' + elif command -v shasum &> /dev/null; then + shasum -a 256 "$file" | awk '{print $1}' + else + error "Neither sha256sum nor shasum found" + exit 1 + fi +} + # Check required commands check_requirements() { local missing=() - - for cmd in curl sha256sum file; do + + for cmd in curl file; do if ! command -v "$cmd" &> /dev/null; then missing+=("$cmd") fi done - + + # Need at least one SHA256 tool + if ! command -v sha256sum &> /dev/null && ! command -v shasum &> /dev/null; then + missing+=("sha256sum or shasum") + fi + if [ ${#missing[@]} -ne 0 ]; then error "Missing required commands: ${missing[*]}" error "Please install them and try again" @@ -86,25 +104,42 @@ check_platform() { os=$(uname -s) arch=$(uname -m) - if [ "$os" != "Linux" ]; then - error "Unsupported OS: $os (this installer supports Linux only)" - exit 1 - fi - - case "$arch" in - x86_64|amd64) - BINARY_NAME="awf-linux-x64" + case "$os" in + Linux) + case "$arch" in + x86_64|amd64) + BINARY_NAME="awf-linux-x64" + ;; + aarch64|arm64) + BINARY_NAME="awf-linux-arm64" + ;; + *) + error "Unsupported architecture: $arch (supported: x86_64, aarch64)" + exit 1 + ;; + esac ;; - aarch64|arm64) - BINARY_NAME="awf-linux-arm64" + Darwin) + case "$arch" in + x86_64) + BINARY_NAME="awf-darwin-x64" + ;; + arm64) + BINARY_NAME="awf-darwin-arm64" + ;; + *) + error "Unsupported architecture: $arch (supported: x86_64, arm64)" + exit 1 + ;; + esac ;; *) - error "Unsupported architecture: $arch (supported: x86_64, aarch64)" + error "Unsupported OS: $os (supported: Linux, macOS)" exit 1 ;; esac - info "Detected architecture: $arch (binary: $BINARY_NAME)" + info "Detected platform: $os $arch (binary: $BINARY_NAME)" } # Validate version format (should be like v1.0.0, v1.2.3, etc.) @@ -207,7 +242,7 @@ verify_checksum() { # Calculate actual checksum local actual_sum - actual_sum=$(sha256sum "$file" | awk '{print $1}' | tr 'A-F' 'a-f') + actual_sum=$(sha256_portable "$file" | tr 'A-F' 'a-f') if [ "$expected_sum" != "$actual_sum" ]; then error "Checksum verification failed!" @@ -260,9 +295,15 @@ main() { # Make binary executable chmod +x "$TEMP_DIR/$BINARY_NAME" - # Test if it's a valid ELF executable - if ! file "$TEMP_DIR/$BINARY_NAME" | grep -q "ELF.*executable"; then - error "Downloaded file is not a valid Linux executable" + # Test if it's a valid executable (ELF on Linux, Mach-O on macOS) + local file_type + file_type=$(file "$TEMP_DIR/$BINARY_NAME") + if echo "$file_type" | grep -q "ELF.*executable"; then + info "Valid Linux ELF executable" + elif echo "$file_type" | grep -q "Mach-O 64-bit"; then + info "Valid macOS Mach-O executable" + else + error "Downloaded file is not a valid executable: $file_type" exit 1 fi diff --git a/package.json b/package.json index 822bbe32..faf6ce45 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,9 @@ ], "targets": [ "node18-linux-x64", - "node18-linux-arm64" + "node18-linux-arm64", + "node18-macos-x64", + "node18-macos-arm64" ] } }