Skip to content

fix: fflush stdout and stderr before restoring them #82

fix: fflush stdout and stderr before restoring them

fix: fflush stdout and stderr before restoring them #82

Workflow file for this run

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