Implement file-backed repositories via .store files #1113
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # ============================================================================= | |
| # 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 | |