Skip to content

fix(): release prep #58

fix(): release prep

fix(): release prep #58

Workflow file for this run

name: CI
on:
workflow_call:
inputs:
run_cross_platform:
description: Build every supported host and mobile target family
required: false
default: true
type: boolean
push:
branches:
- master
- dev
- 'jwerle/**'
- 'feature/**'
- 'fix/**'
pull_request:
workflow_dispatch:
permissions:
contents: read
pull-requests: read
env:
CI: true
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
PUPPETEER_SKIP_DOWNLOAD: 'true'
concurrency:
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
changes:
name: Determine required coverage
runs-on: ubuntu-24.04
timeout-minutes: 5
outputs:
run_ci: ${{ steps.scope.outputs.run_ci }}
runtime_changed: ${{ steps.scope.outputs.runtime_changed }}
steps:
- name: Classify changed files
id: scope
shell: bash
env:
GH_TOKEN: ${{ github.token }}
EVENT_NAME: ${{ github.event_name }}
BEFORE_SHA: ${{ github.event.before }}
CURRENT_SHA: ${{ github.sha }}
REF_NAME: ${{ github.ref_name }}
PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}
run: |
run_ci=true
if [[ "$EVENT_NAME" == 'push' && "$REF_NAME" != 'master' && "$REF_NAME" != 'dev' ]]; then
if pull_count="$(gh api "/repos/$GITHUB_REPOSITORY/commits/$CURRENT_SHA/pulls" --jq '[.[] | select(.state == "open")] | length')" && (( pull_count > 0 )); then
run_ci=false
fi
fi
echo "run_ci=$run_ci" >> "$GITHUB_OUTPUT"
if [[ "$run_ci" != 'true' ]]; then
echo 'An open pull-request run already covers this branch commit; skipping the duplicate push run.' >> "$GITHUB_STEP_SUMMARY"
echo 'runtime_changed=false' >> "$GITHUB_OUTPUT"
exit 0
fi
changed_files="$RUNNER_TEMP/changed-files.txt"
case "$EVENT_NAME" in
pull_request)
if ! gh api --paginate \
"/repos/$GITHUB_REPOSITORY/pulls/$PULL_REQUEST_NUMBER/files?per_page=100" \
--jq '.[].filename' > "$changed_files"; then
printf '*\n' > "$changed_files"
fi
;;
push)
if [[ -z "$BEFORE_SHA" || "$BEFORE_SHA" =~ ^0+$ ]]; then
printf '*\n' > "$changed_files"
else
if comparison="$(gh api "/repos/$GITHUB_REPOSITORY/compare/$BEFORE_SHA...$CURRENT_SHA")"; then
jq -r '.files[].filename' <<< "$comparison" > "$changed_files"
else
printf '*\n' >> "$changed_files"
fi
if (( $(wc -l < "$changed_files") >= 300 )); then
printf '*\n' >> "$changed_files"
fi
fi
;;
*)
printf '*\n' > "$changed_files"
;;
esac
runtime_changed=false
while IFS= read -r file; do
case "$file" in
'') ;;
*.md|LICENSE*|share/man/*) ;;
*) runtime_changed=true ;;
esac
done < "$changed_files"
echo "runtime_changed=$runtime_changed" >> "$GITHUB_OUTPUT"
if [[ "$runtime_changed" == "true" ]]; then
echo 'Runtime, tooling, or workflow changes require build coverage.' >> "$GITHUB_STEP_SUMMARY"
else
echo 'Documentation-only changes skip native builds and integration tests.' >> "$GITHUB_STEP_SUMMARY"
fi
lint:
name: Lint
needs: changes
if: needs.changes.outputs.run_ci == 'true'
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
- name: Setup pnpm and Node.js
uses: pnpm/setup@84cb39b217b10273981911c288cd62326dc7c6d2 # v2.0.2
with:
runtime: node@24
cache: true
cache-dependency-path: pnpm-lock.yaml
install: false
- name: Setup Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
with:
python-version: '3.x'
cache: pip
cache-dependency-path: .github/requirements-lint.txt
- name: Install actionlint
shell: bash
env:
ACTIONLINT_VERSION: 1.7.11
ACTIONLINT_SHA256: 900919a84f2229bac68ca9cd4103ea297abc35e9689ebb842c6e34a3d1b01b0a
run: |
archive="$RUNNER_TEMP/actionlint.tar.gz"
bin_dir="$RUNNER_TEMP/actionlint-bin"
curl --fail --location --retry 3 --silent --show-error \
--output "$archive" \
"https://github.com/rhysd/actionlint/releases/download/v$ACTIONLINT_VERSION/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz"
echo "$ACTIONLINT_SHA256 $archive" | sha256sum --check --status
mkdir -p "$bin_dir"
tar -xzf "$archive" -C "$bin_dir" actionlint
echo "$bin_dir" >> "$GITHUB_PATH"
- name: Install cpplint
run: python -m pip install --requirement .github/requirements-lint.txt
- name: Install dependencies
run: pnpm install --frozen-lockfile --prefer-offline
- name: Lint GitHub Actions workflows
run: actionlint .github/workflows/*.yml
- name: Run tooling unit tests
run: npm run test:unit
- name: Lint
run: npm run test:lint:ci
- name: Validate generated documentation and declarations are committed
run: |
npm run gen:docs
git diff --exit-code
node-compatibility:
name: Tooling unit tests / Node 22
needs: [changes, lint]
if: needs.changes.outputs.runtime_changed == 'true'
runs-on: ubuntu-24.04
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
- name: Setup Node.js
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: 22.x
- name: Run tooling unit tests
run: npm run test:unit
linux-integration:
name: Linux x64 integration / Node 24
needs: [changes, lint]
if: needs.changes.outputs.runtime_changed == 'true'
runs-on: ubuntu-24.04
timeout-minutes: 90
env:
CCACHE_BASEDIR: ${{ github.workspace }}
CCACHE_COMPILERCHECK: content
CCACHE_DIR: ${{ github.workspace }}/.cache/ccache
CCACHE_TEMPDIR: ${{ github.workspace }}/.cache/ccache-tmp
DEBUG: '1'
GDK_BACKEND: x11
GSK_RENDERER: cairo
LIBGL_ALWAYS_SOFTWARE: '1'
NO_ANDROID: '1'
NO_IOS: '1'
ORO_CI_FAST_COMPILE: '1'
ORO_CI_ID: linux-x64-node24
ORO_SKIP_PATH_PROMPT: '1'
ORO_TEST_HEADLESS: '1'
ORO_TEST_SKIP_DESKTOP_EXTENSION: '1'
ORO_TEST_SKIP_TEST_EXTENSIONS: '1'
WEBKIT_DISABLE_COMPOSITING_MODE: '1'
XDG_RUNTIME_DIR: /tmp/oro-xdg-runtime
steps:
- name: Checkout
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
- name: Setup Node.js
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: 24.x
- name: Setup Go for libipfs
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: '1.23.2'
cache: false
- name: Setup Unix Rust compiler cache
uses: mozilla-actions/sccache-action@fc920bf0ec8de6ee65d409111f7ec508035751ba # v0.0.11
with:
version: v0.17.0
- name: Configure Unix Rust compiler cache
shell: bash
run: |
{
echo 'SCCACHE_GHA_ENABLED=true'
echo 'RUSTC_WRAPPER=sccache'
} >> "$GITHUB_ENV"
- name: Restore native compiler cache
id: native-cache
uses: actions/cache/restore@caa296126883cff596d87d8935842f9db880ef25 # v5
with:
path: ${{ env.CCACHE_DIR }}
key: ccache-v1-${{ runner.os }}-${{ runner.arch }}-linux-x64-${{ github.sha }}-${{ github.run_attempt }}
restore-keys: |
ccache-v1-${{ runner.os }}-${{ runner.arch }}-linux-x64-${{ github.sha }}-
ccache-v1-${{ runner.os }}-${{ runner.arch }}-linux-x64-
ccache-v1-${{ runner.os }}-${{ runner.arch }}-
- name: Restore Rust dependency cache
uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5
with:
path: |
~/.cargo/git
~/.cargo/registry
~/.rustup/toolchains/nightly-2023-10-05-*
~/.rustup/update-hashes/nightly-2023-10-05-*
key: cargo-v2-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('rust/**/Cargo.lock', 'rust/**/Cargo.toml') }}
restore-keys: |
cargo-v2-${{ runner.os }}-${{ runner.arch }}-
cargo-v1-${{ runner.os }}-${{ runner.arch }}-
- name: Restore Go build cache
uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5
with:
path: |
.cache/go-build
.cache/go-mod
key: go-v1-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('bin/install.sh') }}
restore-keys: |
go-v1-${{ runner.os }}-${{ runner.arch }}-
- name: Restore test dependency cache
uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5
with:
path: ~/.npm
key: npm-test-v1-${{ runner.os }}-${{ runner.arch }}-node24-${{ hashFiles('test/package-lock.json') }}
restore-keys: |
npm-test-v1-${{ runner.os }}-${{ runner.arch }}-node24-
- name: Install Linux system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
autoconf \
automake \
build-essential \
ccache \
clang-18 \
curl \
dbus-daemon \
git \
libdbus-1-dev \
libgtk-3-dev \
libsoup-3.0-dev \
libsystemd-dev \
libtool \
libwebkit2gtk-4.1-dev \
pkg-config
- name: Configure native compiler cache and headless runtime
shell: bash
run: |
echo /usr/lib/ccache >> "$GITHUB_PATH"
{
echo "ORO_HOME=$RUNNER_TEMP/oro-ci-linux-x64-node24"
echo "PREFIX=$RUNNER_TEMP/oro-ci-linux-x64-node24"
echo 'CMAKE_C_COMPILER_LAUNCHER=ccache'
echo 'CMAKE_CXX_COMPILER_LAUNCHER=ccache'
} >> "$GITHUB_ENV"
mkdir -p "$CCACHE_TEMPDIR"
ccache --max-size 1536M
ccache --zero-stats
mkdir -p "$XDG_RUNTIME_DIR"
chmod 700 "$XDG_RUNTIME_DIR"
- name: Install test harness dependencies
run: npm ci --prefix test --no-audit --prefer-offline
- name: Build Oro Runtime CLI
id: build-runtime
timeout-minutes: 20
shell: bash
run: ./bin/install.sh --yes-deps
- name: Save native compiler cache
if: ${{ always() && steps.native-cache.outcome == 'success' && steps.native-cache.outputs.cache-hit != 'true' }}
uses: actions/cache/save@caa296126883cff596d87d8935842f9db880ef25 # v5
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ steps.native-cache.outputs.cache-primary-key }}
- name: Validate desktop-only target families
id: validate-targets
if: ${{ always() && steps.build-runtime.outcome == 'success' }}
shell: bash
run: |
shopt -s nullglob
mobile_targets=(
"$ORO_HOME"/lib/*-android
"$ORO_HOME"/lib/*-iPhoneOS
"$ORO_HOME"/lib/*-iPhoneSimulator
"$ORO_HOME"/lib/*-ios
"$ORO_HOME"/lib/*-ios-simulator
)
if (( ${#mobile_targets[@]} != 0 )); then
echo >&2 'Linux desktop CI unexpectedly contains a mobile target directory'
exit 1
fi
- name: Smoke test staged CLI
id: smoke-test
if: ${{ always() && steps.validate-targets.outcome == 'success' }}
run: |
node -e "const { spawnSync } = require('node:child_process'); const path = require('node:path'); const cli = path.join(process.env.ORO_HOME, 'bin', 'oroc'); const result = spawnSync(cli, ['--version'], { stdio: 'inherit' }); process.exit(result.status ?? 1)"
node -e "const { spawnSync } = require('node:child_process'); const path = require('node:path'); const cli = path.join(process.env.ORO_HOME, 'bin', 'oroc'); const result = spawnSync(cli, ['help'], { stdio: 'inherit' }); process.exit(result.status ?? 1)"
- name: Run desktop tests
if: ${{ always() && steps.smoke-test.outcome == 'success' }}
timeout-minutes: 20
run: dbus-run-session -- npm test
- name: Run child process integration tests
if: ${{ always() && steps.smoke-test.outcome == 'success' }}
timeout-minutes: 15
run: dbus-run-session -- npm run test:child-process
- name: Run MCP integration tests
if: ${{ always() && steps.smoke-test.outcome == 'success' }}
timeout-minutes: 15
run: dbus-run-session -- npm run test:mcp
- name: Run runtime-core tests
if: ${{ always() && steps.smoke-test.outcome == 'success' }}
timeout-minutes: 15
run: dbus-run-session -- npm run test:runtime-core
- name: Report native compiler cache
if: always()
run: ccache --show-stats || true
test-platform:
name: Build and test ${{ matrix.name }}
needs: [changes, lint]
if: >-
needs.changes.outputs.runtime_changed == 'true' &&
(github.event_name != 'workflow_call' || inputs.run_cross_platform)
runs-on: ${{ matrix.runs_on }}
timeout-minutes: 120
strategy:
fail-fast: false
matrix:
include:
- name: Linux arm64
id: linux-arm64
runs_on: ubuntu-24.04-arm
release_support: desktop
build_android: false
exclude_android: true
exclude_ios: true
install_tests: false
test_desktop: false
test_child_process: false
test_android: false
test_ios: false
windows: false
- name: Android x86_64
id: android-x86_64
runs_on: ubuntu-24.04
release_support: android
android_supported_abis: x86_64
build_android: true
exclude_android: false
exclude_ios: true
install_tests: true
test_desktop: false
test_child_process: false
test_android: true
test_ios: false
windows: false
- name: Android arm64-v8a
id: android-arm64-v8a
runs_on: ubuntu-24.04
release_support: android
android_supported_abis: arm64-v8a
build_android: true
exclude_android: false
exclude_ios: true
install_tests: false
test_desktop: false
test_child_process: false
test_android: false
test_ios: false
windows: false
- name: macOS x64
id: macos-x64
runs_on: macos-15-intel
compile_only: true
release_support: desktop
build_android: false
exclude_android: true
exclude_ios: true
install_tests: false
test_desktop: false
test_child_process: false
test_android: false
test_ios: false
windows: false
- name: macOS + iOS arm64
id: macos-ios-arm64
runs_on: macos-14
release_support: ios
apple_mobile_targets: arm64-iPhoneSimulator
build_android: false
exclude_android: true
exclude_ios: false
install_tests: true
test_desktop: true
test_child_process: false
test_android: false
test_ios: true
windows: false
- name: Windows x64
id: windows-x64
runs_on: windows-2022
release_support: desktop
build_android: false
exclude_android: true
exclude_ios: true
install_tests: true
test_desktop: true
test_child_process: true
test_android: false
test_ios: false
windows: true
env:
ANDROID_SUPPORTED_ABIS: ${{ matrix.android_supported_abis }}
BUILD_ANDROID: ${{ matrix.build_android }}
CCACHE_BASEDIR: ${{ github.workspace }}
CCACHE_COMPILERCHECK: content
CCACHE_DIR: ${{ github.workspace }}/.cache/ccache
CCACHE_TEMPDIR: ${{ github.workspace }}/.cache/ccache-tmp
DEBUG: '1'
EXCLUDE_ANDROID: ${{ matrix.exclude_android }}
EXCLUDE_IOS: ${{ matrix.exclude_ios }}
GDK_BACKEND: x11
GSK_RENDERER: cairo
LIBGL_ALWAYS_SOFTWARE: '1'
ORO_CI_APPLE_MOBILE_TARGETS: ${{ matrix.apple_mobile_targets }}
ORO_CI_FAST_COMPILE: '1'
ORO_CI_ID: ${{ matrix.id }}
ORO_RUNTIME_COMPILE_ONLY: ${{ matrix.compile_only }}
ORO_PRUNE_BUILD_OUTPUTS_AFTER_INSTALL: ${{ matrix.test_android }}
ORO_PRUNE_IROH_BUILD_OUTPUTS: ${{ matrix.build_android }}
ORO_PRUNE_TRANSIENT_BUILD_OUTPUTS: ${{ matrix.build_android }}
ORO_SKIP_PATH_PROMPT: '1'
ORO_TEST_HEADLESS: '1'
ORO_TEST_SKIP_DESKTOP_EXTENSION: '1'
ORO_TEST_SKIP_TEST_EXTENSIONS: '1'
RELEASE_SUPPORT: ${{ matrix.release_support }}
WEBKIT_DISABLE_COMPOSITING_MODE: '1'
XDG_RUNTIME_DIR: /tmp/oro-xdg-runtime
steps:
- name: Checkout
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
- name: Setup Node.js
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6
with:
node-version: 24.x
- name: Setup Go for libipfs
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: '1.23.2'
cache: false
- name: Setup Windows native compiler cache
if: matrix.windows
uses: mozilla-actions/sccache-action@fc920bf0ec8de6ee65d409111f7ec508035751ba # v0.0.11
with:
version: v0.17.0
- name: Setup Unix Rust compiler cache
if: runner.os != 'Windows'
uses: mozilla-actions/sccache-action@fc920bf0ec8de6ee65d409111f7ec508035751ba # v0.0.11
with:
version: v0.17.0
- name: Configure Windows native compiler cache
if: matrix.windows
shell: bash
run: |
{
echo 'SCCACHE_GHA_ENABLED=true'
echo 'RUSTC_WRAPPER=sccache'
echo 'CMAKE_C_COMPILER_LAUNCHER=sccache'
echo 'CMAKE_CXX_COMPILER_LAUNCHER=sccache'
} >> "$GITHUB_ENV"
- name: Configure Unix Rust compiler cache
if: runner.os != 'Windows'
shell: bash
run: |
{
echo 'SCCACHE_GHA_ENABLED=true'
echo 'RUSTC_WRAPPER=sccache'
} >> "$GITHUB_ENV"
- name: Setup Java for Android
if: matrix.build_android
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5
with:
distribution: temurin
java-version: '17'
cache: gradle
cache-dependency-path: |
bin/android-functions.sh
bin/generate-gradle-files.sh
- name: Resolve Android SDK cache root
if: matrix.build_android
id: android-sdk
shell: bash
run: echo "root=$ANDROID_HOME" >> "$GITHUB_OUTPUT"
- name: Reclaim Android build disk
if: matrix.build_android && runner.os == 'Linux'
shell: bash
run: |
for directory in \
/usr/share/dotnet \
/opt/ghc \
/usr/local/.ghcup \
/opt/hostedtoolcache/CodeQL \
"$ANDROID_HOME/system-images"
do
if [[ -e "$directory" ]]; then
sudo rm -rf -- "$directory"
fi
done
android_group="$(id -gn)"
for directory in \
"$ANDROID_HOME" \
"$ANDROID_HOME/build-tools" \
"$ANDROID_HOME/cmdline-tools" \
"$ANDROID_HOME/ndk" \
"$ANDROID_HOME/platforms"
do
if [[ -e "$directory" ]]; then
sudo chown "$USER":"$android_group" "$directory"
else
sudo install -d -o "$USER" -g "$android_group" "$directory"
fi
done
shopt -s nullglob
cache_directories=(
"$ANDROID_HOME/build-tools/36.0.0"
"$ANDROID_HOME/cmdline-tools/23.0"
"$ANDROID_HOME/ndk/29.0.14206865"
"$ANDROID_HOME/platform-tools"
"$ANDROID_HOME"/platforms/android-37*
)
for directory in "${cache_directories[@]}"; do
if [[ -e "$directory" ]]; then
sudo chown -R "$USER":"$android_group" "$directory"
fi
done
sudo apt-get clean
df -h .
- name: Restore Android build SDK cache
if: matrix.build_android
uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5
with:
path: |
${{ steps.android-sdk.outputs.root }}/build-tools/36.0.0
${{ steps.android-sdk.outputs.root }}/cmdline-tools/23.0
${{ steps.android-sdk.outputs.root }}/ndk/29.0.14206865
${{ steps.android-sdk.outputs.root }}/platform-tools
${{ steps.android-sdk.outputs.root }}/platforms/android-37*
key: android-build-sdk-v1-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('bin/android-functions.sh') }}
- name: Restore native compiler cache
if: runner.os != 'Windows'
id: native-cache
uses: actions/cache/restore@caa296126883cff596d87d8935842f9db880ef25 # v5
with:
path: ${{ env.CCACHE_DIR }}
key: ccache-v1-${{ runner.os }}-${{ runner.arch }}-${{ matrix.id }}-${{ github.sha }}-${{ github.run_attempt }}
restore-keys: |
ccache-v1-${{ runner.os }}-${{ runner.arch }}-${{ matrix.id }}-${{ github.sha }}-
ccache-v1-${{ runner.os }}-${{ runner.arch }}-${{ matrix.id }}-
ccache-v1-${{ runner.os }}-${{ runner.arch }}-
- name: Restore Rust dependency cache
uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5
with:
path: |
~/.cargo/git
~/.cargo/registry
~/.rustup/toolchains/nightly-2023-10-05-*
~/.rustup/update-hashes/nightly-2023-10-05-*
key: cargo-v2-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('rust/**/Cargo.lock', 'rust/**/Cargo.toml') }}
restore-keys: |
cargo-v2-${{ runner.os }}-${{ runner.arch }}-
cargo-v1-${{ runner.os }}-${{ runner.arch }}-
- name: Restore Go build cache
uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5
with:
path: |
.cache/go-build
.cache/go-mod
key: go-v1-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('bin/install.sh') }}
restore-keys: |
go-v1-${{ runner.os }}-${{ runner.arch }}-
- name: Restore test dependency cache
if: matrix.install_tests
uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5
with:
path: ~/.npm
key: npm-test-v1-${{ runner.os }}-${{ runner.arch }}-node24-${{ hashFiles('test/package-lock.json') }}
restore-keys: |
npm-test-v1-${{ runner.os }}-${{ runner.arch }}-node24-
- name: Install Linux system dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y \
autoconf \
automake \
build-essential \
ccache \
clang-18 \
curl \
git \
libdbus-1-dev \
libgtk-3-dev \
libsoup-3.0-dev \
libsystemd-dev \
libtool \
libwebkit2gtk-4.1-dev \
pkg-config
- name: Install macOS system dependencies
if: runner.os == 'macOS'
shell: bash
env:
HOMEBREW_NO_AUTO_UPDATE: '1'
run: brew install automake ccache libomp libtool pkg-config
- name: Configure native compiler cache
if: runner.os != 'Windows'
shell: bash
run: |
if [[ "$RUNNER_OS" == 'Linux' ]]; then
echo /usr/lib/ccache >> "$GITHUB_PATH"
else
echo "$(brew --prefix ccache)/libexec" >> "$GITHUB_PATH"
fi
echo 'CMAKE_C_COMPILER_LAUNCHER=ccache' >> "$GITHUB_ENV"
echo 'CMAKE_CXX_COMPILER_LAUNCHER=ccache' >> "$GITHUB_ENV"
mkdir -p "$CCACHE_TEMPDIR"
if [[ "$RUNNER_OS" == 'macOS' ]]; then
ccache --max-size 3G
else
ccache --max-size 1536M
fi
ccache --zero-stats
- name: Prepare Linux headless runtime directory
if: runner.os == 'Linux'
shell: bash
run: |
mkdir -p "$XDG_RUNTIME_DIR"
chmod 700 "$XDG_RUNTIME_DIR"
- name: Configure source-build target families
shell: bash
run: |
{
echo "ORO_HOME=$RUNNER_TEMP/oro-ci-$ORO_CI_ID"
echo "PREFIX=$RUNNER_TEMP/oro-ci-$ORO_CI_ID"
if [[ "$ORO_RUNTIME_COMPILE_ONLY" == "true" ]]; then
# The Intel macOS lane validates every host translation unit.
# Apple Silicon performs the complete archive, link, and tests.
echo "ORO_RUNTIME_SOURCE_PREFLIGHT=1"
else
# Archive builds compile the complete source surface. Do not
# syntax-compile every translation unit a second time first.
echo "ORO_RUNTIME_SOURCE_PREFLIGHT=0"
fi
if [[ "$EXCLUDE_ANDROID" == "true" ]]; then
echo "NO_ANDROID=1"
else
echo "NO_ANDROID="
fi
if [[ "$EXCLUDE_IOS" == "true" ]]; then
echo "NO_IOS=1"
else
echo "NO_IOS="
fi
# The Linux integration lane exercises the desktop networking FFI.
# Cross-platform lanes focus on their platform runtime and tests.
echo "ORO_SKIP_IROH=1"
echo "ORO_SKIP_LIBIPFS=1"
if [[ "$RELEASE_SUPPORT" != "desktop" ]]; then
echo "ORO_RUNTIME_SEQUENTIAL_TARGET_BUILDS=1"
fi
if [[ "$BUILD_ANDROID" == "true" ]]; then
echo "ORO_ANDROID_CI=1"
echo "ORO_RUNTIME_DESKTOP_CLI_ONLY=1"
echo "ANDROID_SDK_MANAGER_ACCEPT_LICENSES=yes"
fi
} >> "$GITHUB_ENV"
- name: Report host toolchain and disk
shell: bash
run: |
uname -a || true
node --version
df -h . || true
if [[ "$RUNNER_OS" == "macOS" ]]; then
xcodebuild -version
xcrun --sdk iphoneos --show-sdk-path
xcrun --sdk iphonesimulator --show-sdk-path
fi
if [[ "$RUNNER_OS" == "Windows" ]]; then
cmd.exe /c ver
fi
- name: Install test harness dependencies
if: matrix.install_tests
run: npm ci --prefix test --no-audit --prefer-offline
- name: Build Oro Runtime CLI (Unix)
id: build-runtime-unix
if: runner.os != 'Windows'
timeout-minutes: 45
shell: bash
run: ./bin/install.sh --yes-deps
- name: Quiesce native compiler cache
if: ${{ always() && runner.os != 'Windows' && steps.native-cache.outcome == 'success' && steps.native-cache.outputs.cache-hit != 'true' }}
shell: bash
run: |
native_compiler_pids() {
ps -Ao pid=,command= | awk -v workspace="$GITHUB_WORKSPACE" '
index($0, workspace) &&
$0 ~ /(^|[\/ ])(ccache|clang|clang\+\+)( |$)/ { print $1 }
'
}
for native_signal in TERM KILL; do
native_pids="$(native_compiler_pids)"
if [[ -z "$native_pids" ]]; then
break
fi
while IFS= read -r native_pid; do
if [[ -n "$native_pid" ]]; then
kill -"$native_signal" "$native_pid" 2>/dev/null || true
fi
done <<< "$native_pids"
if [[ "$native_signal" == "TERM" ]]; then
sleep 2
fi
done
ccache --cleanup
- name: Save native compiler cache
if: ${{ always() && runner.os != 'Windows' && steps.native-cache.outcome == 'success' && steps.native-cache.outputs.cache-hit != 'true' }}
uses: actions/cache/save@caa296126883cff596d87d8935842f9db880ef25 # v5
with:
path: ${{ env.CCACHE_DIR }}
key: ${{ steps.native-cache.outputs.cache-primary-key }}
- name: Build Oro Runtime CLI (Windows)
id: build-runtime-windows
if: matrix.windows
timeout-minutes: 20
shell: pwsh
run: .\bin\install.ps1 -yesdeps -debug
- name: Validate staged target families
id: validate-targets-unix
if: ${{ always() && runner.os != 'Windows' && matrix.compile_only != true && steps.build-runtime-unix.outcome == 'success' }}
shell: bash
run: |
shopt -s nullglob
android_targets=("$ORO_HOME"/lib/*-android)
ios_targets=("$ORO_HOME"/lib/*-iPhoneOS "$ORO_HOME"/lib/*-iPhoneSimulator "$ORO_HOME"/lib/*-ios "$ORO_HOME"/lib/*-ios-simulator)
case "$RELEASE_SUPPORT" in
desktop)
(( ${#android_targets[@]} == 0 && ${#ios_targets[@]} == 0 ))
;;
android)
if (( ${#ios_targets[@]} != 0 )); then
echo >&2 'Android CI unexpectedly contains an Apple-mobile target directory'
exit 1
fi
read -r -a required_android_abis <<< "$ANDROID_SUPPORTED_ABIS"
if (( ${#required_android_abis[@]} == 0 )); then
echo >&2 'Android CI has no assigned ABI target'
exit 1
fi
for abi in "${required_android_abis[@]}"; do
target="$abi-android"
if [[ ! -d "$ORO_HOME/lib/$target" ]]; then
echo >&2 "Android CI is missing required ABI target: $target"
exit 1
fi
done
for path in "${android_targets[@]}"; do
target="$(basename "$path")"
expected=false
for abi in "${required_android_abis[@]}"; do
if [[ "$target" == "$abi-android" ]]; then
expected=true
break
fi
done
if [[ "$expected" != "true" ]]; then
echo >&2 "Android CI built an unassigned ABI target: $target"
exit 1
fi
done
;;
ios)
if (( ${#android_targets[@]} != 0 )); then
echo >&2 'Apple CI unexpectedly contains an Android target directory'
exit 1
fi
read -r -a required_ios_targets <<< "$ORO_CI_APPLE_MOBILE_TARGETS"
if (( ${#required_ios_targets[@]} == 0 )); then
echo >&2 'Apple CI has no assigned iOS targets'
exit 1
fi
for target in "${required_ios_targets[@]}"; do
if [[ ! -d "$ORO_HOME/lib/$target" ]]; then
echo >&2 "Apple CI is missing required iOS target: $target"
exit 1
fi
done
for path in "${ios_targets[@]}"; do
target="$(basename "$path")"
expected=false
for required_target in "${required_ios_targets[@]}"; do
if [[ "$target" == "$required_target" ]]; then
expected=true
break
fi
done
if [[ "$expected" != "true" ]]; then
echo >&2 "Apple CI built an unassigned iOS target: $target"
exit 1
fi
done
;;
*)
echo >&2 "Unknown platform family: $RELEASE_SUPPORT"
exit 1
;;
esac
- name: Validate staged target families (Windows)
id: validate-targets-windows
if: ${{ always() && matrix.windows && steps.build-runtime-windows.outcome == 'success' }}
shell: pwsh
run: |
if ($env:RELEASE_SUPPORT -ne 'desktop') {
throw "Windows CI has unsupported target family: $env:RELEASE_SUPPORT"
}
$libRoot = Join-Path $env:ORO_HOME 'lib'
$targets = if (Test-Path $libRoot) { @(Get-ChildItem -Path $libRoot -Directory) } else { @() }
$mobileTargets = @($targets | Where-Object {
$_.Name -like '*-android' -or $_.Name -match '-(iPhoneOS|iPhoneSimulator|ios|ios-simulator)$'
})
if ($mobileTargets.Count -ne 0) {
throw 'Windows desktop build unexpectedly contains a mobile target directory'
}
- name: Smoke test staged CLI
id: smoke-test
if: >-
${{ always() &&
((runner.os != 'Windows' && steps.validate-targets-unix.outcome == 'success') ||
(runner.os == 'Windows' && steps.validate-targets-windows.outcome == 'success')) }}
run: |
node -e "const { spawnSync } = require('node:child_process'); const path = require('node:path'); const cli = path.join(process.env.ORO_HOME, 'bin', process.platform === 'win32' ? 'oroc.exe' : 'oroc'); const result = spawnSync(cli, ['--version'], { stdio: 'inherit' }); process.exit(result.status ?? 1)"
node -e "const { spawnSync } = require('node:child_process'); const path = require('node:path'); const cli = path.join(process.env.ORO_HOME, 'bin', process.platform === 'win32' ? 'oroc.exe' : 'oroc'); const result = spawnSync(cli, ['help'], { stdio: 'inherit' }); process.exit(result.status ?? 1)"
- name: Run desktop tests
if: ${{ always() && matrix.test_desktop && steps.smoke-test.outcome == 'success' }}
timeout-minutes: 20
run: npm test
- name: Run child process integration tests
if: ${{ always() && matrix.test_child_process && steps.smoke-test.outcome == 'success' }}
timeout-minutes: 15
run: npm run test:child-process
- name: Boot iOS Simulator and run tests
if: ${{ always() && matrix.test_ios && steps.smoke-test.outcome == 'success' }}
timeout-minutes: 20
shell: bash
run: |
simulator_udid="$(python3 - <<'PY'
import json
import subprocess
devices = json.loads(subprocess.check_output([
'xcrun', 'simctl', 'list', 'devices', 'available', '--json'
]))['devices']
for runtime_devices in devices.values():
for device in runtime_devices:
if device.get('isAvailable') and device.get('name', '').startswith('iPhone'):
print(device['udid'])
raise SystemExit(0)
raise SystemExit('No available iPhone simulator was found')
PY
)"
trap 'xcrun simctl shutdown "$simulator_udid" || true' EXIT
xcrun simctl boot "$simulator_udid" || true
xcrun simctl bootstatus "$simulator_udid" -b
export ORO_IOS_SIMULATOR_UDID="$simulator_udid"
export ORO_RC="$RUNNER_TEMP/oro-ios-tests.ororc"
printf '[settings.ios]\nsimulator_uuid = "%s"\n' "$simulator_udid" > "$ORO_RC"
npm run test:ios-simulator
- name: Upload macOS crash reports
if: ${{ failure() && runner.os == 'macOS' }}
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: macos-crash-reports-${{ runner.arch }}
path: |
~/Library/Logs/DiagnosticReports/**/oro-runtime-javascript-tests*
/Library/Logs/DiagnosticReports/**/oro-runtime-javascript-tests*
if-no-files-found: ignore
retention-days: 7
# Restore the multi-gigabyte emulator only after native outputs have been
# staged and pruned so both trees do not consume runner disk together.
- name: Restore Android emulator cache
id: android-emulator-cache
if: ${{ always() && matrix.test_android && steps.smoke-test.outcome == 'success' }}
uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5
with:
path: |
${{ steps.android-sdk.outputs.root }}/emulator
${{ steps.android-sdk.outputs.root }}/system-images/android-37.0/google_apis/x86_64
~/.android/avd
key: android-emulator-v37.1.11-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('test/scripts/bootstrap-android-emulator.sh') }}
- name: Grant Android emulator KVM access
id: android-kvm
if: ${{ always() && matrix.test_android && runner.os == 'Linux' && steps.android-emulator-cache.outcome == 'success' }}
shell: bash
run: |
if [[ ! -e /dev/kvm ]]; then
echo >&2 'Android emulator acceleration is unavailable: /dev/kvm does not exist'
exit 1
fi
sudo chmod a+rw /dev/kvm
- name: Run Android emulator tests
if: ${{ always() && matrix.test_android && steps.android-emulator-cache.outcome == 'success' && steps.android-kvm.outcome == 'success' }}
timeout-minutes: 20
shell: bash
run: npm run test:android-emulator
- name: Capture Android failure logs
if: ${{ failure() && matrix.test_android }}
shell: bash
run: |
mkdir -p "$RUNNER_TEMP/android-failure-logs"
if [[ ! -s "$RUNNER_TEMP/android-failure-logs/logcat.txt" ]]; then
"$ANDROID_HOME/platform-tools/adb" logcat -d -b all > "$RUNNER_TEMP/android-failure-logs/logcat.txt" 2>&1 || true
fi
if [[ ! -s "$RUNNER_TEMP/android-failure-logs/activities.txt" ]]; then
"$ANDROID_HOME/platform-tools/adb" shell dumpsys activity activities > "$RUNNER_TEMP/android-failure-logs/activities.txt" 2>&1 || true
fi
- name: Upload Android failure logs
if: ${{ failure() && matrix.test_android }}
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: android-failure-logs-${{ runner.arch }}
path: ${{ runner.temp }}/android-failure-logs
if-no-files-found: ignore
retention-days: 7
- name: Report native compiler cache
if: always() && runner.os != 'Windows'
shell: bash
run: ccache --show-stats || true
- name: Report final disk usage
if: always()
shell: bash
run: df -h . || true