feat: tests #81
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
| name: CI & Release | |
| # Builds static libraries for all supported platforms, runs tests on native | |
| # platforms (Linux, macOS), and creates a GitHub Release when appropriate. | |
| # | |
| # - Push to master → snapshot release (vX.Y.Z-<sha>-snapshot) | |
| # - Tag push (v*) → stable release (vX.Y.Z) | |
| # - Pull requests → build & test only (no release) | |
| on: | |
| push: | |
| branches: [master] | |
| tags: ['v*'] | |
| pull_request: | |
| branches: [master] | |
| workflow_dispatch: | |
| inputs: | |
| ruby_libs_version: | |
| description: "ruby-for-android release tag (e.g. v3.1.1-1). Leave empty to use RUBY_LIBS_VERSION file." | |
| required: false | |
| type: string | |
| tag_name: | |
| description: "Release tag name (e.g. v1.0.0). Leave empty for auto-detection." | |
| required: false | |
| type: string | |
| jobs: | |
| build-linux: | |
| runs-on: ubuntu-latest | |
| name: Build & Test (Linux x86_64) | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install build dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| cmake make gcc g++ pkg-config | |
| - name: Cache Ruby prebuilt libraries | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| external/lib | |
| external/include | |
| assets/files | |
| key: ruby-libs-${{ hashFiles('RUBY_LIBS_VERSION') }}-linux-x86_64 | |
| - name: Download Ruby prebuilt libraries | |
| run: | | |
| if [ -n "${{ inputs.ruby_libs_version }}" ]; then | |
| export RUBY_LIBS_VERSION="${{ inputs.ruby_libs_version }}" | |
| fi | |
| ./scripts/download-ruby-libs.sh linux-x86_64 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Configure | |
| run: | | |
| cmake -B build \ | |
| -DCMAKE_BUILD_TYPE=Release \ | |
| -DBUILD_WRAPPER_SHARED=OFF \ | |
| -DBUILD_SHARED_LIBS=OFF \ | |
| -DBUILD_JNI=OFF \ | |
| -DBUILD_TESTS=ON \ | |
| -DSKIP_RUBY_DOWNLOAD=ON | |
| - name: Build | |
| run: cmake --build build --config Release | |
| - name: Test | |
| run: ctest --test-dir build --output-on-failure | |
| - name: Set up JDK | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: temurin | |
| java-version: '17' | |
| - name: Build Kotlin/Native linuxX64 & Desktop JAR | |
| run: ./gradlew compileKotlinLinuxX64 desktopJar | |
| - name: Run Desktop tests | |
| run: ./gradlew desktopTest | |
| - name: Patch Kotlin/Native linker for glibc compatibility | |
| run: | | |
| # Konan bundles ld.gold with glibc 2.19 sysroot, which cannot verify | |
| # shared library deps built against the system's newer glibc (2.38+). | |
| # Wrap ld.gold to add --allow-shlib-undefined for test linking. | |
| KONAN_DIR="$HOME/.konan/dependencies" | |
| LD_GOLD=$(find "$KONAN_DIR" -name "ld.gold" -type f 2>/dev/null | head -1) | |
| if [ -n "$LD_GOLD" ]; then | |
| mv "$LD_GOLD" "${LD_GOLD}.bin" | |
| printf '#!/bin/sh\nexec "%s.bin" --allow-shlib-undefined "$@"\n' "$LD_GOLD" > "$LD_GOLD" | |
| chmod +x "$LD_GOLD" | |
| echo "Wrapped $LD_GOLD to allow shlib undefined symbols" | |
| else | |
| echo "Warning: konan ld.gold not found, skipping patch" | |
| fi | |
| - name: Verify native libs | |
| run: | | |
| echo "Contents of kmp/libs/linux_x64/:" | |
| ls -la kmp/libs/linux_x64/ || echo "Directory does not exist" | |
| echo "" | |
| echo "Contents of build/lib/:" | |
| ls -la build/lib/ || echo "Directory does not exist" | |
| - name: Prepare native libs for Kotlin/Native tests | |
| run: | | |
| # assets_bootstrap() extracts Ruby stdlib but doesn't create the | |
| # native-libs directory. Pre-copy the .so and .deps there so the | |
| # Ruby VM can load its dependencies at runtime. | |
| NATIVE_LIBS="$HOME/.cache/embedded-ruby-vm/native-libs/x86_64-linux-linux" | |
| mkdir -p "$NATIVE_LIBS" | |
| cp kmp/libs/linux_x64/libembedded-ruby.so "$NATIVE_LIBS/" | |
| cp kmp/libs/linux_x64/libembedded-ruby.deps "$NATIVE_LIBS/" | |
| ls -la "$NATIVE_LIBS/" | |
| - name: Run Linux Native tests | |
| run: ./gradlew linuxX64Test --console=plain --info | |
| timeout-minutes: 10 | |
| env: | |
| LD_LIBRARY_PATH: ${{ github.workspace }}/kmp/libs/linux_x64 | |
| - name: Debug crash with strace | |
| if: failure() | |
| run: | | |
| echo "=== dmesg ===" | |
| sudo dmesg | grep -i -E "segfault|killed|signal|test.kexe" | tail -10 || true | |
| echo "" | |
| echo "=== Extracted assets ===" | |
| find "$HOME/.cache/embedded-ruby-vm" -maxdepth 3 -type d || true | |
| echo "" | |
| echo "=== Re-running test binary under strace ===" | |
| cd kmp | |
| LD_LIBRARY_PATH=${{ github.workspace }}/kmp/libs/linux_x64 \ | |
| strace -f -e trace=process,signal \ | |
| ./build/bin/linuxX64/debugTest/test.kexe \ | |
| --ktest_filter=com.scorbutics.rubyvm.RubyVMSmokeTest.testInterpreterLifecycle \ | |
| 2>&1 | tail -80 || true | |
| - name: Package artifacts | |
| run: | | |
| mkdir -p artifacts/include | |
| cp build/lib/libembedded-ruby.a artifacts/ | |
| cp build/lib/libassets.a artifacts/ | |
| cp build/lib/libminizip.a artifacts/ | |
| cp -r include/public/embedded-ruby-vm artifacts/include/ | |
| tar czf embedded-ruby-vm-linux-x86_64.tar.gz -C artifacts . | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: embedded-ruby-vm-linux-x86_64 | |
| path: embedded-ruby-vm-linux-x86_64.tar.gz | |
| build-android: | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| include: | |
| - abi: arm64-v8a | |
| platform: android-arm64 | |
| arch_label: arm64 | |
| triplet: aarch64-linux-android | |
| - abi: x86_64 | |
| platform: android-x86_64 | |
| arch_label: x86_64 | |
| triplet: x86_64-linux-android | |
| name: Build (Android ${{ matrix.arch_label }}) | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install build dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| cmake make pkg-config | |
| - name: Cache Ruby prebuilt libraries | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| external/lib | |
| external/include | |
| assets/files | |
| key: ruby-libs-${{ hashFiles('RUBY_LIBS_VERSION') }}-${{ matrix.platform }} | |
| - name: Download Ruby prebuilt libraries | |
| run: | | |
| if [ -n "${{ inputs.ruby_libs_version }}" ]; then | |
| export RUBY_LIBS_VERSION="${{ inputs.ruby_libs_version }}" | |
| fi | |
| ./scripts/download-ruby-libs.sh ${{ matrix.platform }} | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Configure | |
| run: | | |
| cmake -B build \ | |
| -DCMAKE_BUILD_TYPE=Release \ | |
| -DCMAKE_SYSTEM_NAME=Android \ | |
| -DCMAKE_ANDROID_ARCH_ABI=${{ matrix.abi }} \ | |
| -DCMAKE_ANDROID_NDK=$ANDROID_NDK_HOME \ | |
| -DCMAKE_SYSTEM_VERSION=24 \ | |
| -DHOST=${{ matrix.triplet }} \ | |
| -DBUILD_WRAPPER_SHARED=OFF \ | |
| -DBUILD_SHARED_LIBS=OFF \ | |
| -DBUILD_JNI=ON \ | |
| -DBUILD_JNI_ANDROID_LOG=ON \ | |
| -DBUILD_TESTS=OFF \ | |
| -DSKIP_RUBY_DOWNLOAD=ON | |
| - name: Build | |
| run: cmake --build build --config Release | |
| - name: Package artifacts | |
| run: | | |
| mkdir -p artifacts/include | |
| cp build/lib/libembedded-ruby.a artifacts/ | |
| cp build/lib/libassets.a artifacts/ | |
| cp build/lib/libminizip.a artifacts/ | |
| cp -r include/public/embedded-ruby-vm artifacts/include/ | |
| tar czf embedded-ruby-vm-android-${{ matrix.arch_label }}.tar.gz -C artifacts . | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: embedded-ruby-vm-android-${{ matrix.arch_label }} | |
| path: embedded-ruby-vm-android-${{ matrix.arch_label }}.tar.gz | |
| build-ios: | |
| runs-on: macos-latest | |
| strategy: | |
| matrix: | |
| include: | |
| - variant: device | |
| sysroot: iphoneos | |
| ruby_libs_platform: ios-device | |
| deployment_target: "13.0" | |
| - variant: simulator | |
| sysroot: iphonesimulator | |
| ruby_libs_platform: ios-simulator | |
| deployment_target: "14.0" | |
| name: Build (iOS ${{ matrix.variant }} arm64) | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Cache Ruby prebuilt libraries | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| external/lib | |
| external/include | |
| assets/files | |
| key: ruby-libs-${{ hashFiles('RUBY_LIBS_VERSION') }}-${{ matrix.ruby_libs_platform }} | |
| - name: Download Ruby prebuilt libraries | |
| run: | | |
| if [ -n "${{ inputs.ruby_libs_version }}" ]; then | |
| export RUBY_LIBS_VERSION="${{ inputs.ruby_libs_version }}" | |
| fi | |
| ./scripts/download-ruby-libs.sh ${{ matrix.ruby_libs_platform }} | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Configure | |
| run: | | |
| cmake -B build \ | |
| -DCMAKE_BUILD_TYPE=Release \ | |
| -DCMAKE_SYSTEM_NAME=iOS \ | |
| -DCMAKE_OSX_SYSROOT=${{ matrix.sysroot }} \ | |
| -DCMAKE_OSX_ARCHITECTURES=arm64 \ | |
| -DCMAKE_OSX_DEPLOYMENT_TARGET=${{ matrix.deployment_target }} \ | |
| -DHOST=aarch64-apple-ios-${{ matrix.variant }} \ | |
| -DBUILD_WRAPPER_SHARED=OFF \ | |
| -DBUILD_SHARED_LIBS=OFF \ | |
| -DBUILD_JNI=OFF \ | |
| -DBUILD_TESTS=OFF \ | |
| -DSKIP_RUBY_DOWNLOAD=ON | |
| - name: Build | |
| run: cmake --build build --config Release | |
| - name: Package artifacts | |
| run: | | |
| mkdir -p artifacts/include | |
| cp build/lib/libembedded-ruby.a artifacts/ | |
| cp build/lib/libassets.a artifacts/ | |
| cp build/lib/libminizip.a artifacts/ | |
| cp -r include/public/embedded-ruby-vm artifacts/include/ | |
| tar czf embedded-ruby-vm-ios-${{ matrix.variant }}-arm64.tar.gz -C artifacts . | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: embedded-ruby-vm-ios-${{ matrix.variant }}-arm64 | |
| path: embedded-ruby-vm-ios-${{ matrix.variant }}-arm64.tar.gz | |
| build-macos: | |
| runs-on: macos-14 | |
| name: Build & Test (macOS arm64) | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install build dependencies | |
| run: brew install autoconf automake libtool cmake | |
| - name: Cache Ruby prebuilt libraries | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| external/lib | |
| external/include | |
| assets/files | |
| key: ruby-libs-${{ hashFiles('RUBY_LIBS_VERSION') }}-macos-arm64 | |
| - name: Download Ruby prebuilt libraries | |
| run: | | |
| if [ -n "${{ inputs.ruby_libs_version }}" ]; then | |
| export RUBY_LIBS_VERSION="${{ inputs.ruby_libs_version }}" | |
| fi | |
| ./scripts/download-ruby-libs.sh macos-arm64 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Configure | |
| run: | | |
| cmake -B build \ | |
| -DCMAKE_BUILD_TYPE=Release \ | |
| -DCMAKE_OSX_ARCHITECTURES=arm64 \ | |
| -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 \ | |
| -DHOST=aarch64-apple-darwin \ | |
| -DBUILD_WRAPPER_SHARED=OFF \ | |
| -DBUILD_SHARED_LIBS=OFF \ | |
| -DBUILD_JNI=OFF \ | |
| -DBUILD_TESTS=ON \ | |
| -DSKIP_RUBY_DOWNLOAD=ON | |
| - name: Build | |
| run: cmake --build build --config Release | |
| - name: Test | |
| run: ctest --test-dir build --output-on-failure | |
| - name: Package artifacts | |
| run: | | |
| mkdir -p artifacts/include | |
| cp build/lib/libembedded-ruby.a artifacts/ | |
| cp build/lib/libassets.a artifacts/ | |
| cp build/lib/libminizip.a artifacts/ | |
| cp -r include/public/embedded-ruby-vm artifacts/include/ | |
| tar czf embedded-ruby-vm-macos-arm64.tar.gz -C artifacts . | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: embedded-ruby-vm-macos-arm64 | |
| path: embedded-ruby-vm-macos-arm64.tar.gz | |
| release: | |
| needs: [build-linux, build-android, build-ios, build-macos] | |
| if: github.event_name != 'pull_request' | |
| runs-on: ubuntu-latest | |
| name: Create Release | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| - name: Determine tag name | |
| id: tag | |
| run: | | |
| if [ -n "${{ inputs.tag_name }}" ]; then | |
| TAG="${{ inputs.tag_name }}" | |
| elif [[ "$GITHUB_REF" == refs/tags/* ]]; then | |
| TAG="${GITHUB_REF#refs/tags/}" | |
| else | |
| BASE_TAG="$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")" | |
| SHORT_SHA="${GITHUB_SHA::7}" | |
| TAG="${BASE_TAG}-${SHORT_SHA}-snapshot" | |
| fi | |
| echo "tag=$TAG" >> "$GITHUB_OUTPUT" | |
| if [[ "$GITHUB_REF" == refs/tags/v* ]]; then | |
| echo "prerelease=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "prerelease=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.tag.outputs.tag }} | |
| name: ${{ steps.tag.outputs.tag }} | |
| prerelease: ${{ steps.tag.outputs.prerelease == 'true' }} | |
| generate_release_notes: true | |
| files: | | |
| artifacts/embedded-ruby-vm-linux-x86_64/embedded-ruby-vm-linux-x86_64.tar.gz | |
| artifacts/embedded-ruby-vm-android-arm64/embedded-ruby-vm-android-arm64.tar.gz | |
| artifacts/embedded-ruby-vm-android-x86_64/embedded-ruby-vm-android-x86_64.tar.gz | |
| artifacts/embedded-ruby-vm-ios-device-arm64/embedded-ruby-vm-ios-device-arm64.tar.gz | |
| artifacts/embedded-ruby-vm-ios-simulator-arm64/embedded-ruby-vm-ios-simulator-arm64.tar.gz | |
| artifacts/embedded-ruby-vm-macos-arm64/embedded-ruby-vm-macos-arm64.tar.gz |