Skip to content

docs(website): move Essential Primer before Language Guide #1107

docs(website): move Essential Primer before Language Guide

docs(website): move Essential Primer before Language Guide #1107

Workflow file for this run

# =============================================================================
# ARO Programming Language - Multi-Platform Build Pipeline
# =============================================================================
# Builds and tests ARO on Linux, macOS, and Windows using Swift 6.2
# =============================================================================
name: Build
permissions:
contents: read
on:
push:
branches:
- main
- 'release/**'
tags:
- '*' # Accept all tag formats (v1.0.0, 0.1.0-alpha.1, etc.)
pull_request:
branches:
- main
- 'release/**'
concurrency:
group: build-${{ github.ref }}
cancel-in-progress: true
env:
SWIFT_VERSION: '6.2.1'
jobs:
# ===========================================================================
# Run Tests (Gate for all builds)
# ===========================================================================
test:
name: Test
runs-on: ubuntu-latest
container:
image: swift:6.2-jammy
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Cache Swift packages
uses: actions/cache@v5
with:
path: .build
key: linux-swift-${{ env.SWIFT_VERSION }}-test-${{ hashFiles('Package.resolved') }}
- name: Install LLVM 20 and dependencies
run: |
apt-get update -qq
apt-get install -y -qq wget gnupg software-properties-common libgit2-dev
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | gpg --dearmor -o /usr/share/keyrings/llvm-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/llvm-archive-keyring.gpg] http://apt.llvm.org/jammy/ llvm-toolchain-jammy-20 main" > /etc/apt/sources.list.d/llvm.list
apt-get update -qq
apt-get install -y -qq llvm-20-dev libzstd-dev
cat > /usr/lib/pkgconfig/llvm.pc << 'PKGCONFIG'
prefix=/usr/lib/llvm-20
exec_prefix=${prefix}
libdir=${prefix}/lib
includedir=${prefix}/include
Name: LLVM
Description: Low-level Virtual Machine compiler framework
Version: 20.1
Libs: -L${libdir} -lLLVM-20
Cflags: -I${includedir}
PKGCONFIG
- name: Run tests
run: swift test --parallel
# ===========================================================================
# Linux Build & Test
# ===========================================================================
linux:
needs: test
name: Linux
runs-on: ubuntu-latest
container:
image: swift:6.2-jammy
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Cache Swift packages
uses: actions/cache@v5
with:
path: .build
key: linux-swift-${{ env.SWIFT_VERSION }}-v3-${{ hashFiles('Package.resolved') }}
- name: Install LLVM 20 and dependencies
run: |
apt-get update -qq
apt-get install -y -qq wget gnupg software-properties-common libgit2-dev
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | gpg --dearmor -o /usr/share/keyrings/llvm-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/llvm-archive-keyring.gpg] http://apt.llvm.org/jammy/ llvm-toolchain-jammy-20 main" > /etc/apt/sources.list.d/llvm.list
apt-get update -qq
apt-get install -y -qq llvm-20-dev libzstd-dev
cat > /usr/lib/pkgconfig/llvm.pc << 'PKGCONFIG'
prefix=/usr/lib/llvm-20
exec_prefix=${prefix}
libdir=${prefix}/lib
includedir=${prefix}/include
Name: LLVM
Description: Low-level Virtual Machine compiler framework
Version: 20.1
Libs: -L${libdir} -lLLVM-20
Cflags: -I${includedir}
PKGCONFIG
- name: Build
run: swift build -c debug
- name: Run tests
run: swift test --parallel
- name: Generate version file
run: |
VERSION=$(git describe --tags --always --dirty 2>/dev/null || echo "dev")
COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
cat > Sources/AROVersion/Version.swift << 'EOF'
// ============================================================
// Version.swift
// ARO Version Information
// ============================================================
// This file is auto-generated during build
import Foundation
public enum AROVersion {
/// Version from git tag (embedded at build time)
public static let version: String = "VERSION_PLACEHOLDER"
/// Short commit hash (embedded at build time)
public static let commit: String = "COMMIT_PLACEHOLDER"
/// Build date in ISO 8601 format (embedded at build time)
public static let buildDate: String = "BUILD_DATE_PLACEHOLDER"
/// Whether this is a release build
public static let isRelease: Bool = {
!version.contains("-dirty") && !version.hasPrefix("unknown") && !version.hasPrefix("dev")
}()
/// Full version string with commit and build date
public static var fullVersion: String {
"\(version) (\(commit)) built on \(buildDate)"
}
/// Short version string (just the version)
public static var shortVersion: String {
version
}
}
EOF
# Replace placeholders with actual values (Linux uses sed without -i '')
sed -i "s|VERSION_PLACEHOLDER|$VERSION|g" Sources/AROVersion/Version.swift
sed -i "s|COMMIT_PLACEHOLDER|$COMMIT|g" Sources/AROVersion/Version.swift
sed -i "s|BUILD_DATE_PLACEHOLDER|$BUILD_DATE|g" Sources/AROVersion/Version.swift
echo "Generated version file with:"
echo " Version: $VERSION"
echo " Commit: $COMMIT"
echo " Build Date: $BUILD_DATE"
- name: Build release
run: |
swift build -c release --static-swift-stdlib
swift build -c release --product ARORuntime
- name: Verify CLI
run: |
.build/release/aro --help
.build/release/aro check ./Examples/HelloWorldAPI
.build/release/aro check ./Examples/UserService
- name: Prepare artifact directory
run: |
mkdir -p aro-dist
cp .build/release/aro aro-dist/
cp .build/x86_64-unknown-linux-gnu/release/libARORuntime.a aro-dist/
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: aro-linux-amd64
path: aro-dist/
retention-days: 30
# ===========================================================================
# macOS Build & Test
# ===========================================================================
macos:
needs: test
name: macOS
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Setup Swift
uses: swift-actions/setup-swift@364295d9c23900ce04d4e5cc708387921b4e50f9 # v3
with:
swift-version: ${{ env.SWIFT_VERSION }}
- name: Verify Swift version
run: |
swift --version
- name: Cache Swift packages
uses: actions/cache@v5
with:
path: .build
key: macos-swift-${{ env.SWIFT_VERSION }}-v1-${{ hashFiles('Package.resolved') }}
- name: Install LLVM 20 and dependencies
run: |
brew install llvm@20 libgit2
# Detect LLVM path (ARM64 vs Intel)
if [ -d "/opt/homebrew/opt/llvm@20" ]; then
LLVM_PREFIX="/opt/homebrew/opt/llvm@20"
# Ensure the default 'llvm' symlink points to llvm@20 for Linker.swift
sudo rm -f /opt/homebrew/opt/llvm 2>/dev/null || true
sudo ln -sf /opt/homebrew/opt/llvm@20 /opt/homebrew/opt/llvm
else
LLVM_PREFIX="/usr/local/opt/llvm@20"
sudo rm -f /usr/local/opt/llvm 2>/dev/null || true
sudo ln -sf /usr/local/opt/llvm@20 /usr/local/opt/llvm
fi
echo "LLVM_PATH=$LLVM_PREFIX" >> $GITHUB_ENV
echo "$LLVM_PREFIX/bin" >> $GITHUB_PATH
# Set include paths for Swifty-LLVM C shims
echo "C_INCLUDE_PATH=$LLVM_PREFIX/include" >> $GITHUB_ENV
echo "CPLUS_INCLUDE_PATH=$LLVM_PREFIX/include" >> $GITHUB_ENV
echo "LIBRARY_PATH=$LLVM_PREFIX/lib" >> $GITHUB_ENV
# Set runtime library path
echo "DYLD_LIBRARY_PATH=$LLVM_PREFIX/lib" >> $GITHUB_ENV
echo "DYLD_FALLBACK_LIBRARY_PATH=$LLVM_PREFIX/lib" >> $GITHUB_ENV
# Create pkg-config file for Swifty-LLVM
mkdir -p $HOME/.pkgconfig
cat > $HOME/.pkgconfig/llvm.pc << PKGCONFIG
prefix=$LLVM_PREFIX
exec_prefix=\${prefix}
libdir=\${prefix}/lib
includedir=\${prefix}/include
Name: LLVM
Description: Low-level Virtual Machine compiler framework
Version: 20.1
Libs: -L\${libdir} -lLLVM
Cflags: -I\${includedir}
PKGCONFIG
echo "PKG_CONFIG_PATH=$HOME/.pkgconfig" >> $GITHUB_ENV
- name: Build
run: swift build -c debug
- name: Run tests
run: swift test --parallel
- name: Generate version file
run: |
VERSION=$(git describe --tags --always --dirty 2>/dev/null || echo "dev")
COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
cat > Sources/AROVersion/Version.swift << 'EOF'
// ============================================================
// Version.swift
// ARO Version Information
// ============================================================
// This file is auto-generated during build
import Foundation
public enum AROVersion {
/// Version from git tag (embedded at build time)
public static let version: String = "VERSION_PLACEHOLDER"
/// Short commit hash (embedded at build time)
public static let commit: String = "COMMIT_PLACEHOLDER"
/// Build date in ISO 8601 format (embedded at build time)
public static let buildDate: String = "BUILD_DATE_PLACEHOLDER"
/// Whether this is a release build
public static let isRelease: Bool = {
!version.contains("-dirty") && !version.hasPrefix("unknown") && !version.hasPrefix("dev")
}()
/// Full version string with commit and build date
public static var fullVersion: String {
"\(version) (\(commit)) built on \(buildDate)"
}
/// Short version string (just the version)
public static var shortVersion: String {
version
}
}
EOF
# Replace placeholders with actual values
sed -i '' "s|VERSION_PLACEHOLDER|$VERSION|g" Sources/AROVersion/Version.swift
sed -i '' "s|COMMIT_PLACEHOLDER|$COMMIT|g" Sources/AROVersion/Version.swift
sed -i '' "s|BUILD_DATE_PLACEHOLDER|$BUILD_DATE|g" Sources/AROVersion/Version.swift
echo "Generated version file with:"
echo " Version: $VERSION"
echo " Commit: $COMMIT"
echo " Build Date: $BUILD_DATE"
- name: Build release
run: |
swift build -c release
swift build -c release --product ARORuntime
- name: Verify CLI
run: |
.build/release/aro --help
.build/release/aro check ./Examples/HelloWorldAPI
.build/release/aro check ./Examples/UserService
# ========================================================================
# Code Signing and Notarization (only for tagged releases)
# ========================================================================
- name: Import Code Signing Certificate
if: github.ref_type == 'tag'
env:
APPLE_CERTIFICATE_BASE64: ${{ secrets.APPLE_CERTIFICATE_BASE64 }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
run: |
# Create temporary keychain
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
KEYCHAIN_PASSWORD=$(openssl rand -base64 32)
# Decode certificate
echo "$APPLE_CERTIFICATE_BASE64" | base64 --decode > certificate.p12
# Create keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
# Import certificate
security import certificate.p12 \
-P "$APPLE_CERTIFICATE_PASSWORD" \
-A \
-t cert \
-f pkcs12 \
-k $KEYCHAIN_PATH
# Set keychain search list
security list-keychain -d user -s $KEYCHAIN_PATH
# Allow codesign to access keychain
security set-key-partition-list \
-S apple-tool:,apple: \
-s \
-k "$KEYCHAIN_PASSWORD" \
$KEYCHAIN_PATH
# Clean up certificate file
rm certificate.p12
- name: Sign Binary
if: github.ref_type == 'tag'
run: |
# Create entitlements that allow loading third-party libraries
# (e.g. Homebrew's llvm@20). Without this, the hardened runtime
# rejects dylibs signed by a different Team ID.
cat > /tmp/aro-entitlements.plist << 'PLIST'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>
PLIST
# Sign the binary with entitlements
codesign --sign "Developer ID Application" \
--timestamp \
--options runtime \
--entitlements /tmp/aro-entitlements.plist \
--verbose \
.build/release/aro
# Verify signature (codesign only - spctl requires notarization)
codesign --verify --verbose .build/release/aro
- name: Create ZIP for Notarization
if: github.ref_type == 'tag'
run: |
# Notarization requires .zip, .dmg, or .pkg
cd .build/release
zip -r aro.zip aro
cd ../..
- name: Notarize Binary
if: github.ref_type == 'tag'
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
run: |
# Submit for notarization
xcrun notarytool submit .build/release/aro.zip \
--apple-id "$APPLE_ID" \
--team-id "$APPLE_TEAM_ID" \
--password "$APPLE_APP_PASSWORD" \
--wait
# Unzip to get the notarized binary
cd .build/release
unzip -o aro.zip
cd ../..
# Try to staple the notarization ticket
# Note: Stapling may not work for standalone executables distributed as tarballs.
# The binary is still notarized - macOS will verify online when users run it.
echo "Attempting to staple notarization ticket..."
if xcrun stapler staple .build/release/aro 2>&1; then
echo "Stapling successful!"
xcrun stapler validate .build/release/aro
else
echo "Stapling not supported for this binary format (this is normal for CLI tools)."
echo "Binary is still notarized - macOS will verify online."
fi
# Verify the binary signature is valid
codesign --verify --verbose .build/release/aro
echo "Binary is signed and notarized successfully!"
- name: Clean Up Keychain
if: always() && github.ref_type == 'tag'
run: |
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
if [ -f "$KEYCHAIN_PATH" ]; then
security delete-keychain $KEYCHAIN_PATH
fi
# ========================================================================
# Upload Artifact
# ========================================================================
- name: Prepare artifact directory
run: |
mkdir -p aro-dist
cp .build/release/aro aro-dist/
cp .build/arm64-apple-macosx/release/libARORuntime.a aro-dist/
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: aro-macos-arm64
path: aro-dist/
retention-days: 30
# ===========================================================================
# Windows Build & Test (temporarily disabled)
# ===========================================================================
windows:
if: false
needs: test
name: Windows
permissions:
contents: read
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Setup Swift
uses: compnerd/gha-setup-swift@c8363f1001fbb4b12d127c432f9eaadec5f56e8c # main
with:
swift-version: swift-6.2.1-release
swift-build: 6.2.1-RELEASE
- name: Build
run: swift build -c debug
- name: Run tests
run: swift test --parallel
- name: Generate version file
shell: bash
run: |
VERSION=$(git describe --tags --always --dirty 2>/dev/null || echo "dev")
COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
cat > Sources/AROVersion/Version.swift << 'EOF'
// ============================================================
// Version.swift
// ARO Version Information
// ============================================================
// This file is auto-generated during build
import Foundation
public enum AROVersion {
/// Version from git tag (embedded at build time)
public static let version: String = "VERSION_PLACEHOLDER"
/// Short commit hash (embedded at build time)
public static let commit: String = "COMMIT_PLACEHOLDER"
/// Build date in ISO 8601 format (embedded at build time)
public static let buildDate: String = "BUILD_DATE_PLACEHOLDER"
/// Whether this is a release build
public static let isRelease: Bool = {
!version.contains("-dirty") && !version.hasPrefix("unknown") && !version.hasPrefix("dev")
}()
/// Full version string with commit and build date
public static var fullVersion: String {
"\(version) (\(commit)) built on \(buildDate)"
}
/// Short version string (just the version)
public static var shortVersion: String {
version
}
}
EOF
# Replace placeholders (Windows bash shell)
sed -i "s|VERSION_PLACEHOLDER|$VERSION|g" Sources/AROVersion/Version.swift
sed -i "s|COMMIT_PLACEHOLDER|$COMMIT|g" Sources/AROVersion/Version.swift
sed -i "s|BUILD_DATE_PLACEHOLDER|$BUILD_DATE|g" Sources/AROVersion/Version.swift
echo "Generated version file with:"
echo " Version: $VERSION"
echo " Commit: $COMMIT"
echo " Build Date: $BUILD_DATE"
- name: Build release
run: |
swift build -c release
swift build -c release --product ARORuntime
- name: Verify CLI
run: |
.build\release\aro.exe --help
- name: Find runtime library
shell: bash
run: |
echo "Looking for runtime library..."
echo "=== Searching for ARORuntime library files ==="
find .build -name "*ARORuntime*.a" -o -name "*ARORuntime*.lib" 2>/dev/null || true
echo "=== Searching for all .a and .lib files ==="
find .build \( -name "*.a" -o -name "*.lib" \) -type f 2>/dev/null | head -30 || true
echo "=== Contents of .build/release/ ==="
ls -la .build/release/ 2>/dev/null || true
echo "=== Contents of .build/x86_64-unknown-windows-msvc/release/ ==="
ls -la .build/x86_64-unknown-windows-msvc/release/ 2>/dev/null || true
- name: Prepare artifact directory
shell: bash
run: |
mkdir -p aro-dist
cp .build/release/aro.exe aro-dist/
# Search for runtime library in multiple locations
# Swift on Windows may place it in different locations
# Library names on Windows: libARORuntime.a (Swift default) or ARORuntime.lib (MSVC style)
RUNTIME_FOUND=0
# Standard locations with explicit library names
for path in \
".build/release/libARORuntime.a" \
".build/x86_64-unknown-windows-msvc/release/libARORuntime.a" \
".build/release/ARORuntime.lib" \
".build/x86_64-unknown-windows-msvc/release/ARORuntime.lib" \
".build/release/ARORuntime.a" \
".build/x86_64-unknown-windows-msvc/release/ARORuntime.a"; do
if [ -f "$path" ]; then
echo "Found runtime library at: $path"
cp "$path" aro-dist/libARORuntime.a
RUNTIME_FOUND=1
break
fi
done
# If not found in standard locations, search for library files only
# Be specific: only .a or .lib files with ARORuntime in the name
if [ "$RUNTIME_FOUND" = "0" ]; then
echo "Searching for runtime library..."
# Search for .a files first (more common for Swift)
FOUND_LIB=$(find .build -name "*ARORuntime*.a" -type f 2>/dev/null | head -1)
if [ -z "$FOUND_LIB" ]; then
# Try .lib files (MSVC style)
FOUND_LIB=$(find .build -name "*ARORuntime*.lib" -type f 2>/dev/null | head -1)
fi
if [ -n "$FOUND_LIB" ]; then
echo "Found runtime library at: $FOUND_LIB"
# Verify it looks like a valid library (has some minimum size)
LIB_SIZE=$(stat -c%s "$FOUND_LIB" 2>/dev/null || stat -f%z "$FOUND_LIB" 2>/dev/null || echo "0")
echo "Library size: $LIB_SIZE bytes"
if [ "$LIB_SIZE" -gt 1000 ]; then
cp "$FOUND_LIB" aro-dist/libARORuntime.a
RUNTIME_FOUND=1
else
echo "WARNING: Found file is too small to be a valid library"
fi
fi
fi
if [ "$RUNTIME_FOUND" = "0" ]; then
echo "ERROR: Runtime library not found!"
echo "Native compilation tests will fail without libARORuntime.a"
echo ""
echo "=== All .a and .lib files in .build ==="
find .build \( -name "*.a" -o -name "*.lib" \) -type f 2>/dev/null || true
exit 1
fi
echo "=== Artifact contents ==="
ls -la aro-dist/
# Verify the library file
echo "=== Library file info ==="
file aro-dist/libARORuntime.a 2>/dev/null || true
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: aro-windows-amd64
path: aro-dist/
retention-days: 30
# ===========================================================================
# Integration Tests - Linux
# ===========================================================================
integration-tests-linux:
needs: [linux]
name: Integration Tests - Linux
runs-on: ubuntu-latest
container:
image: swift:6.2-jammy
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install LLVM 20 and dependencies
run: |
# Running inside container as root (no sudo needed)
apt-get update -qq
apt-get install -y -qq wget gnupg software-properties-common libgit2-dev
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | gpg --dearmor -o /usr/share/keyrings/llvm-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/llvm-archive-keyring.gpg] http://apt.llvm.org/jammy/ llvm-toolchain-jammy-20 main" > /etc/apt/sources.list.d/llvm.list
apt-get update -qq
apt-get install -y -qq llvm-20-dev libzstd-dev libxml2-dev
ln -sf /usr/bin/llc-20 /usr/bin/llc
# Create pkg-config file for LLVM
mkdir -p /usr/lib/pkgconfig
cat > /usr/lib/pkgconfig/llvm.pc << 'PKGCONFIG'
prefix=/usr/lib/llvm-20
exec_prefix=${prefix}
libdir=${prefix}/lib
includedir=${prefix}/include
Name: LLVM
Description: Low-level Virtual Machine compiler framework
Version: 20.1
Libs: -L${libdir} -lLLVM-20
Cflags: -I${includedir}
PKGCONFIG
- name: Install dependencies and Perl modules
run: |
export DEBIAN_FRONTEND=noninteractive
# Install runtime libraries for plugin tests (SQLiteExample, ZipService)
# and Perl modules from apt (faster and more reliable)
apt-get install -y -qq \
libsqlite3-dev \
zlib1g-dev \
git \
libipc-run-perl \
libyaml-libyaml-perl \
libhttp-tiny-perl \
cpanminus || true
# Install remaining modules via cpan
cpanm -q --notest Net::EmptyPort Term::ANSIColor 2>/dev/null || true
- name: Download ARO artifact
uses: actions/download-artifact@v4
with:
name: aro-linux-amd64
path: ./aro-bin
- name: Prepare ARO binary
run: |
chmod +x ./aro-bin/aro
echo "ARO_BIN=$GITHUB_WORKSPACE/aro-bin/aro" >> $GITHUB_ENV
# Copy libARORuntime.a to system location for native compilation tests
mkdir -p /usr/local/lib
cp ./aro-bin/libARORuntime.a /usr/local/lib/libARORuntime.a
./aro-bin/aro --version
# Verify Swift version
echo "Swift binary: $(which swift)"
swift --version
- name: Install Rust for plugin compilation
run: |
apt-get install -y -qq curl build-essential
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
export PATH="$HOME/.cargo/bin:$PATH"
# Create symlink so ARO runtime can find cargo at known paths
ln -sf "$HOME/.cargo/bin/cargo" /usr/local/bin/cargo
ln -sf "$HOME/.cargo/bin/rustc" /usr/local/bin/rustc
rustc --version
cargo --version
- name: Clean plugin build directories
run: |
# Remove any cached plugin builds from previous runs with different Swift versions
find Examples -name ".build" -type d -exec rm -rf {} + 2>/dev/null || true
echo "Plugin build directories cleaned"
- name: Run integration tests
run: |
export PATH="$HOME/.cargo/bin:$PATH"
chmod +x test-examples.pl
perl test-examples.pl --verbose
- name: Upload test results on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: test-failures-Linux
path: |
Examples/**/expected.*
Examples/**/testrun.*
retention-days: 7
# ===========================================================================
# REPL Integration Tests - Linux
# ===========================================================================
integration-tests-repl:
needs: [linux]
name: REPL Tests - Linux
runs-on: ubuntu-latest
container:
image: ubuntu:22.04
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
run: |
apt-get update -qq
export DEBIAN_FRONTEND=noninteractive
apt-get install -y -qq wget gnupg software-properties-common perl libgit2-dev libcurl4
# Add LLVM APT repository for LLVM 20 (required for aro binary which links against libLLVM-20)
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | gpg --dearmor -o /usr/share/keyrings/llvm-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/llvm-archive-keyring.gpg] http://apt.llvm.org/jammy/ llvm-toolchain-jammy-20 main" > /etc/apt/sources.list.d/llvm.list
apt-get update -qq
apt-get install -y -qq libllvm20
# Install Perl modules for REPL tests
apt-get install -y -qq cpanminus
cpanm -q --notest Term::ANSIColor 2>/dev/null || true
- name: Download ARO artifact
uses: actions/download-artifact@v4
with:
name: aro-linux-amd64
path: ./aro-bin
- name: Prepare ARO binary
run: |
chmod +x ./aro-bin/aro
echo "ARO_BIN=$GITHUB_WORKSPACE/aro-bin/aro" >> $GITHUB_ENV
./aro-bin/aro --version
- name: Run REPL tests
run: |
export LD_LIBRARY_PATH="/usr/lib/llvm-20/lib:$LD_LIBRARY_PATH"
chmod +x test_repl.pl
perl test_repl.pl
# ===========================================================================
# REPL Integration Tests - macOS
# ===========================================================================
integration-tests-repl-macos:
needs: [macos]
name: REPL Tests - macOS
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Swift
uses: swift-actions/setup-swift@364295d9c23900ce04d4e5cc708387921b4e50f9 # v3
with:
swift-version: ${{ env.SWIFT_VERSION }}
- name: Install LLVM 20 and dependencies
run: |
brew install llvm@20 libgit2
if [ -d "/opt/homebrew/opt/llvm@20" ]; then
LLVM_PREFIX="/opt/homebrew/opt/llvm@20"
else
LLVM_PREFIX="/usr/local/opt/llvm@20"
fi
echo "DYLD_LIBRARY_PATH=$LLVM_PREFIX/lib" >> $GITHUB_ENV
- name: Download ARO artifact
uses: actions/download-artifact@v4
with:
name: aro-macos-arm64
path: ./aro-bin
- name: Prepare ARO binary
run: |
chmod +x ./aro-bin/aro
echo "ARO_BIN=$GITHUB_WORKSPACE/aro-bin/aro" >> $GITHUB_ENV
./aro-bin/aro --version
- name: Run REPL tests
run: |
chmod +x test_repl.pl
perl test_repl.pl
# ===========================================================================
# Integration Tests - macOS
# ===========================================================================
integration-tests-macos:
needs: [macos]
name: Integration Tests - macOS
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Swift
uses: swift-actions/setup-swift@364295d9c23900ce04d4e5cc708387921b4e50f9 # v3
with:
swift-version: ${{ env.SWIFT_VERSION }}
- name: Verify Swift version and set library path
run: |
swift --version
# Get the runtime library path from swift itself
# The runtimeLibraryPaths array contains the actual path to Swift libraries
SWIFT_LIB=$(swift -print-target-info 2>/dev/null | python3 -c "
import sys, json
info = json.load(sys.stdin)
paths = info.get('paths', {}).get('runtimeLibraryPaths', [])
# Use the first path that exists and contains the toolchain
for p in paths:
if 'xctoolchain' in p or 'swift' in p.lower():
print(p)
break
")
echo "Swift lib path from target-info: $SWIFT_LIB"
if [ -n "$SWIFT_LIB" ] && [ -d "$SWIFT_LIB" ]; then
echo "SWIFT_LIB_PATH=$SWIFT_LIB" >> $GITHUB_ENV
echo "Found Swift lib path: $SWIFT_LIB"
ls -la "$SWIFT_LIB" | head -5
else
echo "ERROR: Could not find Swift library path!"
echo "Target info output:"
swift -print-target-info
exit 1
fi
# Set SWIFTC for plugin compilation to use the same Swift version
# This ensures plugins are compiled with the same ABI as the runtime
SWIFTC_PATH=$(which swiftc)
echo "SWIFTC=$SWIFTC_PATH" >> $GITHUB_ENV
echo "Swift compiler for plugins: $SWIFTC_PATH"
- name: Install LLVM 20 and dependencies
run: |
brew install llvm@20 libgit2
# Detect LLVM path (ARM64 vs Intel)
if [ -d "/opt/homebrew/opt/llvm@20" ]; then
LLVM_PREFIX="/opt/homebrew/opt/llvm@20"
# Ensure the default 'llvm' symlink points to llvm@20 for Linker.swift
sudo rm -f /opt/homebrew/opt/llvm 2>/dev/null || true
sudo ln -sf /opt/homebrew/opt/llvm@20 /opt/homebrew/opt/llvm
else
LLVM_PREFIX="/usr/local/opt/llvm@20"
sudo rm -f /usr/local/opt/llvm 2>/dev/null || true
sudo ln -sf /usr/local/opt/llvm@20 /usr/local/opt/llvm
fi
echo "LLVM_PATH=$LLVM_PREFIX" >> $GITHUB_ENV
echo "$LLVM_PREFIX/bin" >> $GITHUB_PATH
# Set runtime library path for LLVM and Swift (SWIFT_LIB_PATH set in previous step)
# This ensures plugins loaded at runtime use the correct Swift runtime
echo "DYLD_LIBRARY_PATH=$SWIFT_LIB_PATH:$LLVM_PREFIX/lib" >> $GITHUB_ENV
echo "DYLD_FALLBACK_LIBRARY_PATH=$SWIFT_LIB_PATH:$LLVM_PREFIX/lib" >> $GITHUB_ENV
- name: Install Perl modules
run: |
cpan -T IPC::Run YAML::XS HTTP::Tiny Net::EmptyPort Term::ANSIColor Time::HiRes 2>&1 || true
- name: Install Rust for plugin compilation
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
source "$HOME/.cargo/env"
rustc --version
cargo --version
- name: Verify LLVM setup
run: |
echo "=== Checking LLVM symlink ==="
ls -la /opt/homebrew/opt/llvm || echo "No /opt/homebrew/opt/llvm"
ls -la /opt/homebrew/opt/llvm/bin/llc || echo "No llc at symlink path"
echo "=== Checking llc in PATH ==="
which llc || echo "llc not in PATH"
llc --version | head -3 || echo "llc --version failed"
echo "=== Checking LLVM_PATH ==="
echo "LLVM_PATH=$LLVM_PATH"
echo "=== Environment ==="
echo "DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH"
- name: Download ARO artifact
uses: actions/download-artifact@v4
with:
name: aro-macos-arm64
path: ./aro-bin
- name: Prepare ARO binary
run: |
chmod +x ./aro-bin/aro
echo "ARO_BIN=$GITHUB_WORKSPACE/aro-bin/aro" >> $GITHUB_ENV
# Copy libARORuntime.a to system location for native compilation tests
sudo mkdir -p /usr/local/lib
sudo cp ./aro-bin/libARORuntime.a /usr/local/lib/libARORuntime.a
./aro-bin/aro --version
- name: Test binary compilation
run: |
echo "=== Swift version ==="
swift --version
echo "=== Swift library path ==="
echo "SWIFT_LIB_PATH=$SWIFT_LIB_PATH"
if [ -n "$SWIFT_LIB_PATH" ]; then
ls -la "$SWIFT_LIB_PATH" | head -20
fi
echo "=== Git version and config ==="
git --version
git config --list 2>/dev/null || true
echo "=== Testing aro build ==="
./aro-bin/aro build Examples/HelloWorld --verbose 2>&1 || echo "Build failed with exit code $?"
echo "=== Checking for binary ==="
ls -la Examples/HelloWorld/HelloWorld 2>/dev/null || echo "Binary not found"
ls -la Examples/HelloWorld/.build/ 2>/dev/null || echo "No .build directory"
- name: Run integration tests
run: |
chmod +x test-examples.pl
# Run tests with timeout to prevent hanging
perl test-examples.pl --verbose 2>&1 || {
echo "=== Integration tests failed ==="
echo "=== Checking testrun.log files for errors ==="
find Examples -name "testrun.log" -exec echo "--- {} ---" \; -exec cat {} \; 2>/dev/null | head -500
exit 1
}
- name: Upload test results on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: test-failures-macOS
path: |
Examples/**/expected.*
Examples/**/testrun.*
retention-days: 7
# ===========================================================================
# Integration Tests - Windows (temporarily disabled)
# ===========================================================================
integration-tests-windows:
if: false
needs: [windows]
name: Integration Tests - Windows
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Swift
uses: compnerd/gha-setup-swift@c8363f1001fbb4b12d127c432f9eaadec5f56e8c # main
with:
swift-version: swift-6.2.1-release
swift-build: 6.2.1-RELEASE
# Note: LLVM is not installed for Windows integration tests because
# native compilation (aro build) is not supported on Windows yet.
# Windows uses interpreter mode (aro run) only.
- name: Setup Perl Build Environment
shell: pwsh
run: |
# Ensure Strawberry Perl's build tools are available
Write-Host "Setting up Perl build environment..."
# Get Perl installation directory
$perlExe = (Get-Command perl).Source
$perlRoot = Split-Path (Split-Path $perlExe)
Write-Host "Perl root: $perlRoot"
# Add C compiler and build tools to PATH
$pathsToAdd = @(
"$perlRoot\c\bin", # gcc, gmake
"$perlRoot\perl\bin" # perl tools
)
foreach ($path in $pathsToAdd) {
if (Test-Path $path) {
echo $path | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
$env:PATH = "$path;$env:PATH"
Write-Host "Added to PATH: $path"
} else {
Write-Host "Path not found: $path"
}
}
# Verify build tools
Write-Host "`nVerifying build tools:"
perl -v
gcc --version
gmake --version
- name: Install Perl modules
shell: pwsh
run: |
Write-Host "Installing Perl modules..."
# Configure CPAN for non-interactive mode
$env:PERL_MM_USE_DEFAULT = "1"
# Install all modules with cpan
# Note: cpan may show errors for optional dependencies (like IO::Pty)
# but the main modules will install successfully
Write-Host "`nInstalling all modules..."
cpan -T IPC::Run YAML::XS HTTP::Tiny Net::EmptyPort Term::ANSIColor Time::HiRes
Write-Host "`nVerifying module installation..."
perl -e "use IPC::Run; print 'IPC::Run OK\n'" 2>&1
perl -e "use YAML::XS; print 'YAML::XS OK\n'" 2>&1
perl -e "use HTTP::Tiny; print 'HTTP::Tiny OK\n'" 2>&1
Write-Host "`nPerl module installation complete"
exit 0 # Always succeed - test script has fallback handling
- name: Download ARO artifact
uses: actions/download-artifact@v4
with:
name: aro-windows-amd64
path: ./aro-bin
- name: Prepare ARO binary
shell: pwsh
run: |
# Set environment variable for subsequent steps
echo "ARO_BIN=$env:GITHUB_WORKSPACE\aro-bin\aro.exe" >> $env:GITHUB_ENV
# Verify the binary works
& .\aro-bin\aro.exe --version
# Verify runtime library exists (required for native compilation)
Write-Host "`n=== Checking artifact contents ==="
Get-ChildItem -Path .\aro-bin\ | Format-Table -AutoSize
if (Test-Path ".\aro-bin\libARORuntime.a") {
Write-Host "Runtime library found: libARORuntime.a"
$size = (Get-Item ".\aro-bin\libARORuntime.a").Length
Write-Host "Size: $size bytes"
} else {
Write-Host "WARNING: Runtime library (libARORuntime.a) not found!"
Write-Host "Native compilation tests may fail."
}
- name: Test interpreter mode
shell: pwsh
run: |
Write-Host "=== Testing interpreter mode (aro run) ==="
Write-Host "Note: Native compilation (aro build) is not supported on Windows yet."
Write-Host ""
# Test aro check
Write-Host "Testing aro check..."
& $env:ARO_BIN check Examples/HelloWorld
if ($LASTEXITCODE -ne 0) {
Write-Host "ERROR: aro check failed!"
exit 1
}
Write-Host "aro check passed!"
# Test aro run with HelloWorld
Write-Host "`nTesting aro run Examples/HelloWorld..."
& $env:ARO_BIN run Examples/HelloWorld 2>&1 | Tee-Object -Variable runOutput
$runExitCode = $LASTEXITCODE
Write-Host "Exit code: $runExitCode"
if ($runExitCode -ne 0) {
Write-Host "ERROR: aro run failed!"
exit 1
}
Write-Host "`n=== Interpreter test completed successfully ==="
- name: Run integration tests
shell: pwsh
run: |
# Show current directory and binary location for debugging
Write-Host "Current directory: $(Get-Location)"
Write-Host "ARO_BIN: $env:ARO_BIN"
perl test-examples.pl --verbose
- name: Upload test results on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: test-failures-Windows
path: |
Examples/**/expected.*
Examples/**/testrun.*
retention-days: 7
# ===========================================================================
# Generate Documentation PDFs
# ===========================================================================
documentation:
needs: test
name: Documentation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y weasyprint fonts-ibm-plex \
texlive-xetex texlive-latex-extra texlive-fonts-recommended texlive-fonts-extra \
inkscape librsvg2-bin
# Install pandoc 3.9 from official releases (Ubuntu Noble ships 3.1.3 which has YAML parse bugs)
wget -q https://github.com/jgm/pandoc/releases/download/3.9/pandoc-3.9-1-amd64.deb
sudo dpkg -i pandoc-3.9-1-amd64.deb
- name: Build Language Guide PDF
run: |
cd Book/TheLanguageGuide
chmod +x build-pdf.sh
./build-pdf.sh
- name: Build Construction Studies PDF
run: |
cd Book/TheConstructionStudies
chmod +x build-pdf.sh
./build-pdf.sh
- name: Build ARO By Example PDF
run: |
cd Book/AROByExample
chmod +x build-pdf.sh
./build-pdf.sh
- name: Build Plugin Guide PDF
run: |
cd Book/ThePluginGuide
chmod +x build-pdf.sh
./build-pdf.sh
- name: Upload Language Guide PDF
uses: actions/upload-artifact@v4
with:
name: aro-language-guide
path: Book/TheLanguageGuide/output/ARO-Language-Guide.pdf
retention-days: 30
- name: Upload Construction Studies PDF
uses: actions/upload-artifact@v4
with:
name: aro-construction-studies
path: Book/TheConstructionStudies/output/ARO-Construction-Studies.pdf
retention-days: 30
- name: Upload ARO By Example PDF
uses: actions/upload-artifact@v4
with:
name: aro-by-example
path: Book/AROByExample/output/ARO-By-Example.pdf
retention-days: 30
- name: Upload Plugin Guide PDF
uses: actions/upload-artifact@v4
with:
name: aro-plugin-guide
path: Book/ThePluginGuide/output/ARO-Plugin-Guide.pdf
retention-days: 30
- name: Build Essential Primer PDF
run: |
cd Book/TheEssentialPrimer
chmod +x build-pdf.sh
./build-pdf.sh
- name: Upload Essential Primer PDF
uses: actions/upload-artifact@v4
with:
name: aro-essential-primer
path: Book/TheEssentialPrimer/output/ARO-Essential-Primer.pdf
retention-days: 30
# ===========================================================================
# Create Release (only on tags)
# ===========================================================================
release:
name: Create Release
needs: [integration-tests-linux, integration-tests-repl, integration-tests-macos, integration-tests-repl-macos, documentation]
runs-on: ubuntu-latest
if: github.ref_type == 'tag'
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Package release assets
run: |
# Linux
cd artifacts/aro-linux-amd64
chmod +x aro
tar -czvf ../aro-linux-amd64.tar.gz aro libARORuntime.a
cd ../..
# macOS
cd artifacts/aro-macos-arm64
chmod +x aro
tar -czvf ../aro-macos-arm64.tar.gz aro libARORuntime.a
cd ../..
# Windows (optional — only if the build was enabled)
if [ -d "artifacts/aro-windows-amd64" ]; then
cd artifacts/aro-windows-amd64
zip ../aro-windows-amd64.zip aro.exe libARORuntime.a
cd ../..
else
echo "Windows artifact not present — skipping"
fi
- name: Extract version from tag
id: version
run: |
VERSION="${{ github.ref_name }}"
VERSION="${VERSION#v}"
echo "version=${VERSION}" >> $GITHUB_OUTPUT
- name: Collect release assets
id: assets
run: |
# Build the file list dynamically — only include assets that exist
FILES=""
for f in \
artifacts/aro-linux-amd64.tar.gz \
artifacts/aro-macos-arm64.tar.gz \
artifacts/aro-windows-amd64.zip \
artifacts/aro-language-guide/ARO-Language-Guide.pdf \
artifacts/aro-plugin-guide/ARO-Plugin-Guide.pdf \
artifacts/aro-construction-studies/ARO-Construction-Studies.pdf \
artifacts/aro-by-example/ARO-By-Example.pdf \
artifacts/aro-essential-primer/ARO-Essential-Primer.pdf; do
if [ -f "$f" ]; then
FILES="${FILES}${f}\n"
else
echo "Skipping missing asset: $f"
fi
done
echo -e "$FILES" > /tmp/release-files.txt
cat /tmp/release-files.txt
# Build downloads table — only include platforms that were built
DOWNLOADS="| Platform | Architecture | Download |\n|----------|--------------|----------|\n"
DOWNLOADS="${DOWNLOADS}| Linux | x86_64 | [aro-linux-amd64.tar.gz](https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/aro-linux-amd64.tar.gz) |\n"
DOWNLOADS="${DOWNLOADS}| macOS | Apple Silicon | [aro-macos-arm64.tar.gz](https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/aro-macos-arm64.tar.gz) |\n"
if [ -f "artifacts/aro-windows-amd64.zip" ]; then
DOWNLOADS="${DOWNLOADS}| Windows | x86_64 | [aro-windows-amd64.zip](https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/aro-windows-amd64.zip) |\n"
fi
# Store for the next step
{
echo "downloads<<ENDOFDOWNLOADS"
echo -e "$DOWNLOADS"
echo "ENDOFDOWNLOADS"
} >> $GITHUB_OUTPUT
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
name: ARO ${{ steps.version.outputs.version }}
draft: false
prerelease: ${{ contains(github.ref_name, '-') }}
generate_release_notes: true
files: |
artifacts/aro-linux-amd64.tar.gz
artifacts/aro-macos-arm64.tar.gz
artifacts/aro-windows-amd64.zip
artifacts/aro-language-guide/ARO-Language-Guide.pdf
artifacts/aro-plugin-guide/ARO-Plugin-Guide.pdf
artifacts/aro-construction-studies/ARO-Construction-Studies.pdf
artifacts/aro-by-example/ARO-By-Example.pdf
artifacts/aro-essential-primer/ARO-Essential-Primer.pdf
fail_on_unmatched_files: false
body: |
## ARO Programming Language ${{ steps.version.outputs.version }}
### Downloads
${{ steps.assets.outputs.downloads }}
### Documentation
| Document | Download |
|----------|----------|
| ARO Language Guide | [ARO-Language-Guide.pdf](https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/ARO-Language-Guide.pdf) |
| ARO Plugin Guide | [ARO-Plugin-Guide.pdf](https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/ARO-Plugin-Guide.pdf) |
| ARO Construction Studies | [ARO-Construction-Studies.pdf](https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/ARO-Construction-Studies.pdf) |
| ARO By Example | [ARO-By-Example.pdf](https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/ARO-By-Example.pdf) |
| ARO Essential Primer | [ARO-Essential-Primer.pdf](https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/ARO-Essential-Primer.pdf) |
### Installation
**macOS (Homebrew)** — Recommended
```bash
brew tap arolang/aro
brew install aro
```
**macOS (Manual)**
```bash
curl -L https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/aro-macos-arm64.tar.gz | tar xz
sudo mv aro /usr/local/bin/
sudo mv libARORuntime.a /usr/local/lib/
```
**Linux**
```bash
curl -L https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/aro-linux-amd64.tar.gz | tar xz
sudo mv aro /usr/local/bin/
sudo mv libARORuntime.a /usr/local/lib/
```
**Windows**
Download and extract the zip file, then add the directory to your PATH.
Keep `aro.exe` and `libARORuntime.a` in the same directory.
# ========================================================================
# Update Homebrew Formula
# ========================================================================
- name: Update Homebrew Formula
continue-on-error: true
run: |
# Calculate SHA256 of the macOS release
SHA256=$(shasum -a 256 artifacts/aro-macos-arm64.tar.gz | awk '{print $1}')
VERSION="${{ steps.version.outputs.version }}"
echo "Version: $VERSION"
echo "SHA256: $SHA256"
# Clone homebrew-aro repository
git clone https://github.com/arolang/homebrew-aro.git
cd homebrew-aro
# Update the formula - write directly with proper Ruby formatting
{
echo 'class Aro < Formula'
echo ' desc "ARO programming language - Natural language DSL for business logic"'
echo ' homepage "https://github.com/arolang/aro"'
echo " url \"https://github.com/arolang/aro/releases/download/${{ github.ref_name }}/aro-macos-arm64.tar.gz\""
echo " sha256 \"$SHA256\""
echo " version \"$VERSION\""
echo ' license "MIT"'
echo ''
echo ' # Only support macOS for now (ARM64 binary)'
echo ' depends_on :macos'
echo ' depends_on arch: :arm64'
echo ''
echo ' def install'
echo ' bin.install "aro"'
echo ' lib.install "libARORuntime.a"'
echo ' end'
echo ''
echo ' test do'
echo ' assert_match version.to_s, shell_output("#{bin}/aro --version")'
echo ' end'
echo 'end'
} > Formula/aro.rb
# Configure git
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
# Commit and push if there are changes
git add Formula/aro.rb
if git diff --staged --quiet; then
echo "No changes to formula"
else
git commit -m "chore: update formula to version $VERSION
Auto-update from release workflow
- Version: $VERSION
- SHA256: $SHA256
- Release: https://github.com/${{ github.repository }}/releases/tag/${{ github.ref_name }}"
# Push using PAT (requires HOMEBREW_TAP_TOKEN secret with repo permissions)
git push https://x-access-token:${{ secrets.HOMEBREW_TAP_TOKEN }}@github.com/arolang/homebrew-aro.git main
fi