Skip to content

Record video on every CI trail run, and keep recordings in sync on older ffmpeg #773

Record video on every CI trail run, and keep recordings in sync on older ffmpeg

Record video on every CI trail run, and keep recordings in sync on older ffmpeg #773

Workflow file for this run

name: Checks
on:
# Runs on PRs targeting the default branch
pull_request:
branches: [ "main" ]
# Runs after merging to the default branch
push:
branches: [ "main" ]
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
# Pre-build the trailblaze uber JAR once, with the WASM report template
# embedded, and publish it as an artifact for the downstream test jobs to
# consume. Mirrors the trailblaze-internal `build-uber-jar` Buildkite step:
# downstream test jobs install the prebuilt JAR via
# `scripts/install-trailblaze-from-artifact.sh` instead of paying their own
# `./gradlew :trailblaze-desktop:jar` (~3–5 min cold) plus a cold daemon
# start via `./gradlew :trailblaze-desktop:run`. The installed `trailblaze`
# binary runs the JAR directly via `java -jar`, skipping Gradle entirely
# for every CLI invocation.
#
# `-Ptrailblaze.wasm=true` (via TRAILBLAZE_GRADLE_EXTRA_ARGS) bundles the
# WASM-rendered report template into the JAR's classpath, so every
# downstream `trailblaze report` invocation finds its template inside the
# uber JAR — no separate template download dance is required.
# (The internal repo keeps the CI JAR wasm-less and downloads the template
# as a sibling artifact; OSS keeps it simple and embeds.)
build-uber-jar:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: zulu
java-version: 17
- name: Setup Gradle
# Persists the Gradle User Home (dependency cache + local build cache)
# across runs. Pushes to main seed the cache; PR runs restore it
# read-only, so warm PR builds pull unchanged task outputs — including
# the ~5-minute Kotlin/WASM compile+optimize chain — from cache.
uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6.3.0
with:
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
- name: Setup Android SDK
# trailblaze-desktop transitively depends on Android-targeted modules,
# so the Android Gradle Plugin needs an SDK to evaluate the build.
uses: android-actions/setup-android@9fc6c4e9069bf8d3d10b2204b1fb8f6ef7065407
with:
# Drop the action's default `tools` package. Google removed the obsolete SDK Tools
# package from the repository, so `sdkmanager tools` fails outright on runner images
# that no longer ship it preinstalled. `platform-tools` is what the build needs.
packages: platform-tools
- name: Setup Bun
# `:trailblaze-desktop:releaseArtifacts` transitively triggers
# `:trailblaze-scripting-subprocess:installTrailblazeScriptingSdk`,
# which runs `bun install` to lay down the scripting SDK's
# node_modules ahead of JAR packaging.
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
- name: Build trailblaze uber JAR (with WASM template embedded)
# `install-trailblaze-source.sh` invokes
# `:trailblaze-desktop:releaseArtifacts`, which runs
# `packageUberJarForCurrentOS` and copies the launcher script
# alongside the JAR into `trailblaze-desktop/build/release/`.
# TRAILBLAZE_GRADLE_EXTRA_ARGS layers in `-Ptrailblaze.wasm=true` so
# the report template gets bundled into the JAR's classpath, and
# `--parallel` so independent modules compile concurrently (the
# `checks` job already runs the same task graph with `--parallel`).
env:
TRAILBLAZE_GRADLE_EXTRA_ARGS: -Ptrailblaze.wasm=true --parallel
run: ./scripts/install-trailblaze-source.sh
- name: Stage artifact contents
# `releaseArtifacts` lays down the JAR + launcher with stable names
# at `trailblaze-desktop/build/release/`. Copy them to a flat
# top-level staging dir so the upload step keeps the layout simple
# — `actions/download-artifact@v4` extracts into a directory whose
# contents match what was uploaded, and the install-from-artifact
# script expects `trailblaze.jar` + `trailblaze` side-by-side.
run: |
mkdir -p trailblaze-uber-jar
cp trailblaze-desktop/build/release/trailblaze.jar trailblaze-uber-jar/
cp trailblaze-desktop/build/release/trailblaze trailblaze-uber-jar/
ls -lh trailblaze-uber-jar/
- name: Upload uber JAR artifact
uses: actions/upload-artifact@v4
with:
name: trailblaze-uber-jar
path: trailblaze-uber-jar/
if-no-files-found: error
retention-days: 7
# Run Tests. Split into two parallel jobs so the slow
# `:trailblaze-scripting-subprocess` test suite (~45min — spawns a `bun`/`tsx`
# subprocess per test) doesn't gate the rest of the build behind a single
# 60-minute timeout. Wall-clock time becomes max(jobs), not sum.
checks:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'
check-latest: true
- name: Setup Gradle
# Dependency + build cache reuse across runs (seeded on main pushes,
# restored read-only on PRs) — unchanged modules restore compiled
# classes and test results metadata from cache instead of rebuilding.
uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6.3.0
with:
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
- name: Setup Bun
# bun is the sole supported JS runtime. `assemble check` triggers
# `:trailblaze-scripting-subprocess:installTrailblazeScriptingSdk`
# (a `bun install` that downstream JAR builds read) and the host
# `CheckCommandTest` suite, which shells out to the bun-test phase.
# Without bun on PATH both fail hard rather than skipping.
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
- name: Install ffmpeg
# The trailblaze-capture video tests encode real recordings; see the script for
# why it is a pinned build.
run: ./.github/install-ffmpeg.sh
- name: Test on Ubuntu (excluding scripting-subprocess)
# `--parallel` lets independent modules compile and test concurrently
# across the daemon's worker pool; combined with carving out the slow
# subprocess suite into its own job this brings the wall-clock down
# from 60+ minutes to roughly 10–15.
run: >-
./gradlew --parallel assemble check
-x :trailblaze-scripting-subprocess:test
-x :trailblaze-scripting-subprocess:check
- name: Verify Documentation is up-to-date
run: ./scripts/generate-docs-and-diff.sh
# Isolated job for the subprocess-spawning tests. Each test forks a
# `bun`/`tsx` child process to exercise the MCP transport, so the suite
# is i/o-bound and serializes inside a single JVM — running it in its own
# CI job lets the faster `checks` job report status promptly even when
# this one is still working through its subprocess fan-out.
checks-scripting-subprocess:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'
check-latest: true
- name: Setup Gradle
# Dependency + build cache reuse across runs (seeded on main pushes,
# restored read-only on PRs).
uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6.3.0
with:
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
- name: Setup Bun
# The subprocess tests `bun install` and then spawn `bun`/`tsx` for each
# MCP server fixture. The other Android jobs already set this up; the
# checks job didn't need it before, but this isolated suite does.
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
- name: Run scripting-subprocess tests
run: ./gradlew :trailblaze-scripting-subprocess:check
# PR-time web showcase validation shares the Linux uber JAR built above.
# The standalone Wikipedia workflow stays push-only so `main` still produces
# the docs gallery artifact that GitHub Pages publishes.
wikipedia-trails:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 60
needs: build-uber-jar
env:
OPENAI_API_KEY: no-key-set
# Record each session's screen so the report plays the recording (off by default).
TRAILBLAZE_CAPTURE_VIDEO: "true"
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: zulu
java-version: 17
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
- name: Cache Playwright driver
# The uber JAR ships without Playwright's ~200 MB driver-bundle; the CLI
# downloads it from Maven Central at first use and caches it under
# ~/.cache/trailblaze/playwright-driver. Restore it across runs so the
# trail isn't exposed to that download (a stalled Maven Central
# connection here has burned a full 10-minute no-progress timeout).
# The main-seeded entry comes from wikipedia-trails.yml, since caches
# created inside a PR are only visible to that PR.
uses: actions/cache@v4
with:
path: ~/.cache/trailblaze/playwright-driver
key: playwright-driver-${{ runner.os }}-${{ hashFiles('gradle/libs.versions.toml') }}
- name: Download prebuilt uber JAR
uses: actions/download-artifact@v4
with:
name: trailblaze-uber-jar
path: trailblaze-uber-jar/
- name: Install trailblaze from prebuilt artifact
env:
TRAILBLAZE_ARTIFACT_DIR: ${{ github.workspace }}/trailblaze-uber-jar
run: ./scripts/install-trailblaze-from-artifact.sh
- name: Install Playwright system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
ffmpeg \
libasound2t64 \
libatk-bridge2.0-0 \
libatk1.0-0 \
libcups2 \
libdrm2 \
libgbm1 \
libgtk-3-0 \
libnss3 \
libxcomposite1 \
libxdamage1 \
libxfixes3 \
libxkbcommon0 \
libxrandr2
- name: Install ffmpeg
# Session video encodes through it; see the script for why it is a pinned build.
run: ./.github/install-ffmpeg.sh
- name: Create and run Wikipedia trail
id: run-trails
continue-on-error: true
run: ./.github/pr_run_wikipedia_trails.sh
- name: Generate Trailblaze report
if: always()
continue-on-error: true
run: ./.github/pr_generate_trailblaze_report.sh
- name: Generate docs report-gallery assets
if: always()
continue-on-error: true
run: ./.github/pr_generate_report_assets.sh
- name: Create artifacts
if: always()
continue-on-error: true
run: ./.github/pr_create_artifacts.sh
- name: Upload artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: trailblaze-artifacts-wikipedia
path: |
trailblaze-logs.zip
trailblaze_report.html
- name: Upload docs report-gallery assets
if: always()
uses: actions/upload-artifact@v4
with:
name: docs-report-wikipedia
path: report-assets/
if-no-files-found: warn
- name: Fail if trails failed
if: steps.run-trails.outcome == 'failure'
run: |
echo "Wikipedia trails failed - failing the workflow"
exit 1
# PR-time iOS showcase validation shares the same uber JAR built above.
# The standalone iOS workflow stays push-only so `main` still produces the
# docs gallery artifact that GitHub Pages publishes.
#
# Runs on macos-26 (Xcode 26 / iOS 26 simulators, iPhone 17 Pro) to match the
# showcase recording in docs/showcase-trails.yml — the scripted Contacts tools
# drive the iOS 26 Contacts UI. Kept in sync with .github/workflows/ios-contacts-trails.yml.
ios-contacts-trails:
if: github.event_name == 'pull_request'
runs-on: macos-26
timeout-minutes: 60
needs: build-uber-jar
env:
OPENAI_API_KEY: no-key-set
# Record each session's screen so the report plays the recording (off by default).
TRAILBLAZE_CAPTURE_VIDEO: "true"
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: zulu
java-version: 17
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
- name: Download prebuilt uber JAR
uses: actions/download-artifact@v4
with:
name: trailblaze-uber-jar
path: trailblaze-uber-jar/
- name: Install trailblaze from prebuilt artifact
env:
TRAILBLAZE_ARTIFACT_DIR: ${{ github.workspace }}/trailblaze-uber-jar
run: ./scripts/install-trailblaze-from-artifact.sh
- name: Boot iOS Simulator
run: |
echo "Available iPhone simulators:"
xcrun simctl list devices available | grep "iPhone"
# Prefer iPhone 17 Pro (iOS 26 runtime on macos-26 — the device the
# showcase recording was captured on); fall back to the first iPhone.
SIMULATOR_UDID=$(
xcrun simctl list devices available |
grep "iPhone 17 Pro " | grep -v "Max\|Plus" |
head -1 |
grep -oE "[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12}"
)
if [ -z "$SIMULATOR_UDID" ]; then
echo "iPhone 17 Pro not found, falling back to first available iPhone..."
SIMULATOR_UDID=$(
xcrun simctl list devices available |
grep "iPhone" |
head -1 |
grep -oE "[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12}"
)
fi
if [ -z "$SIMULATOR_UDID" ]; then
echo "ERROR: No iPhone simulator found"
exit 1
fi
echo "Booting simulator UDID: $SIMULATOR_UDID"
xcrun simctl boot "$SIMULATOR_UDID"
xcrun simctl bootstatus "$SIMULATOR_UDID" -b
echo "SIMULATOR_UDID=$SIMULATOR_UDID" >> "$GITHUB_ENV"
echo "Simulator booted: $SIMULATOR_UDID"
- name: Install ffmpeg (session video + animated-timeline WebP)
continue-on-error: true
run: brew install ffmpeg
- name: Run iOS Contacts trail
id: run-trails
continue-on-error: true
run: ./.github/pr_run_ios_contacts_trails.sh
- name: Generate Trailblaze report
if: always()
continue-on-error: true
run: ./.github/pr_generate_trailblaze_report.sh
- name: Generate docs report-gallery assets
if: always()
continue-on-error: true
run: ./.github/pr_generate_report_assets.sh
- name: Create artifacts
if: always()
continue-on-error: true
run: ./.github/pr_create_artifacts.sh
- name: Upload artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: trailblaze-artifacts-ios-contacts
path: |
trailblaze-logs.zip
trailblaze_report.html
- name: Upload docs report-gallery assets
if: always()
uses: actions/upload-artifact@v4
with:
name: docs-report-ios-contacts
path: report-assets/
if-no-files-found: warn
- name: Fail if trails failed
if: steps.run-trails.outcome == 'failure'
run: |
echo "iOS Contacts trails failed - failing the workflow"
exit 1
# Drives the trail through `connectedDebugAndroidTest` — the test logic runs on the
# emulator inside the JUnit instrumentation process and talks to the headless desktop
# server on the default HTTPS port (TrailblazeDevicePort.TRAILBLAZE_DEFAULT_HTTPS_PORT) for agent orchestration.
android-tests-on-device:
runs-on: ubuntu-latest
timeout-minutes: 60
env:
# These CI checks replay recorded trails, so LLM inference is never invoked.
# A non-empty sentinel value is required to satisfy the provider/client wiring
# (e.g., `examples/build.gradle.kts` forwards this to `trailblaze.llm.auth.token.openai`
# and the on-device client map is built from whichever tokens are present).
OPENAI_API_KEY: no-key-set
steps:
- name: Enable KVM group perms
if: runner.os == 'Linux'
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
ls /dev/kvm
- name: Keep the daemon's ports out of the ephemeral range
# 52525/52526 fall inside Linux's ephemeral range (32768-60999), and the emulator and its
# helpers bind random ports from it. One landing on 52525 first makes the daemon exit with
# "Address already in use". Reserving them keeps the kernel from handing them out.
if: runner.os == 'Linux'
run: sudo sysctl -w net.ipv4.ip_local_reserved_ports=52525-52526
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: zulu
java-version: 17
- name: Setup Gradle
# Dependency + build cache reuse across runs (seeded on main pushes,
# restored read-only on PRs). This job runs Gradle twice — the
# instrumentation build below and the WASM-enabled report fallback in
# pr_generate_trailblaze_report.sh — both benefit.
uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6.3.0
with:
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
- name: Create and start emulator and run tests (Linux)
if: runner.os == 'Linux'
uses: reactivecircus/android-emulator-runner@b530d96654c385303d652368551fb075bc2f0b6b
id: run-tests-linux
continue-on-error: true
with:
api-level: 34
arch: x86_64
disable-animations: true
disk-size: 6000M
heap-size: 600M
profile: Nexus 6
script: ./.github/pr_run_android_tests_on_device.sh
- name: Verify logs were pulled
if: always()
run: ./.github/pr_verify_logs_were_pulled.sh
- name: Generate Trailblaze report
if: always()
continue-on-error: true
run: ./.github/pr_generate_trailblaze_report.sh
- name: Create artifacts
if: always()
continue-on-error: true
run: ./.github/pr_create_artifacts.sh
- name: Upload artifacts
if: always() # Ensures this runs even if the previous step failed
uses: actions/upload-artifact@v4
with:
name: trailblaze-artifacts-on-device
path: |
trailblaze-logs.zip
trailblaze_report.html
logcat.log
- name: Fail if tests failed
if: steps.run-tests-linux.outcome == 'failure'
run: |
echo "Tests failed - failing the workflow"
exit 1
# Drives the trail from the host via the Trailblaze CLI (`trailblaze trail …`).
# Agent loop runs in-process on the host; tools dispatch over RPC to the bundled
# on-device APK that the CLI auto-installs over ADB.
android-tests-host-rpc:
runs-on: ubuntu-latest
timeout-minutes: 60
needs: build-uber-jar
env:
# Recordings-only — LLM is never invoked. See android-tests-on-device above.
OPENAI_API_KEY: no-key-set
# Record each session's screen so the report plays the recording (off by default).
TRAILBLAZE_CAPTURE_VIDEO: "true"
steps:
- name: Enable KVM group perms
if: runner.os == 'Linux'
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
ls /dev/kvm
- name: Keep the daemon's ports out of the ephemeral range
# 52525/52526 fall inside Linux's ephemeral range (32768-60999), and the emulator and its
# helpers bind random ports from it. One landing on 52525 first makes the daemon exit with
# "Address already in use". Reserving them keeps the kernel from handing them out.
if: runner.os == 'Linux'
run: sudo sysctl -w net.ipv4.ip_local_reserved_ports=52525-52526
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: zulu
java-version: 17
- name: Setup Android SDK
uses: android-actions/setup-android@9fc6c4e9069bf8d3d10b2204b1fb8f6ef7065407
with:
# Drop the action's default `tools` package. Google removed the obsolete SDK Tools
# package from the repository, so `sdkmanager tools` fails outright on runner images
# that no longer ship it preinstalled. `platform-tools` is what the build needs.
packages: platform-tools
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
- name: Download prebuilt uber JAR
uses: actions/download-artifact@v4
with:
name: trailblaze-uber-jar
path: trailblaze-uber-jar/
- name: Install trailblaze from prebuilt artifact
env:
TRAILBLAZE_ARTIFACT_DIR: ${{ github.workspace }}/trailblaze-uber-jar
run: ./scripts/install-trailblaze-from-artifact.sh
- name: Install ffmpeg
# Session video encodes through it; see the script for why it is a pinned build.
run: ./.github/install-ffmpeg.sh
- name: Create and start emulator and run tests (Linux)
if: runner.os == 'Linux'
uses: reactivecircus/android-emulator-runner@b530d96654c385303d652368551fb075bc2f0b6b
id: run-tests-linux
continue-on-error: true
with:
api-level: 34
arch: x86_64
disable-animations: true
disk-size: 6000M
heap-size: 600M
profile: Nexus 6
script: ./.github/pr_run_android_tests_host_rpc.sh
- name: Verify logs were pulled
if: always()
run: ./.github/pr_verify_logs_were_pulled.sh
- name: Generate Trailblaze report
if: always()
continue-on-error: true
run: ./.github/pr_generate_trailblaze_report.sh
- name: Create artifacts
if: always()
continue-on-error: true
run: ./.github/pr_create_artifacts.sh
- name: Upload artifacts
if: always() # Ensures this runs even if the previous step failed
uses: actions/upload-artifact@v4
with:
name: trailblaze-artifacts-host-rpc
path: |
trailblaze-logs.zip
trailblaze_report.html
logcat.log
- name: Fail if tests failed
if: steps.run-tests-linux.outcome == 'failure'
run: |
echo "Tests failed - failing the workflow"
exit 1
# Drives a first-class TrailblazeTool over the daemon's `POST /mcp` endpoint —
# the surface an external MCP client (Claude Code, Codex, Goose) uses. This is
# the only job that reaches `TrailblazeMcpBridgeImpl.executeToolViaRpc` with
# the interface's `blocking = false` default: android-tests-on-device is pure
# instrumentation, and android-tests-host-rpc goes through DesktopYamlRunner.
# Asserts an on-device failure surfaces as `isError` and a success returns the
# tool's own output rather than an outcome-free placeholder.
android-tests-mcp-dispatch:
runs-on: ubuntu-latest
timeout-minutes: 60
needs: build-uber-jar
env:
# Tools are dispatched by name — the inner agent (and therefore the LLM) is
# never invoked. See android-tests-on-device above.
OPENAI_API_KEY: no-key-set
# Record each session's screen so the report plays the recording (off by default).
TRAILBLAZE_CAPTURE_VIDEO: "true"
steps:
- name: Enable KVM group perms
if: runner.os == 'Linux'
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
ls /dev/kvm
- name: Keep the daemon's ports out of the ephemeral range
# 52525/52526 fall inside Linux's ephemeral range (32768-60999), and the emulator and its
# helpers bind random ports from it. One landing on 52525 first makes the daemon exit with
# "Address already in use". Reserving them keeps the kernel from handing them out.
if: runner.os == 'Linux'
run: sudo sysctl -w net.ipv4.ip_local_reserved_ports=52525-52526
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: zulu
java-version: 17
- name: Setup Android SDK
uses: android-actions/setup-android@9fc6c4e9069bf8d3d10b2204b1fb8f6ef7065407
with:
# Drop the action's default `tools` package. Google removed the obsolete SDK Tools
# package from the repository, so `sdkmanager tools` fails outright on runner images
# that no longer ship it preinstalled. `platform-tools` is what the build needs.
packages: platform-tools
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
- name: Download prebuilt uber JAR
uses: actions/download-artifact@v4
with:
name: trailblaze-uber-jar
path: trailblaze-uber-jar/
- name: Install trailblaze from prebuilt artifact
env:
TRAILBLAZE_ARTIFACT_DIR: ${{ github.workspace }}/trailblaze-uber-jar
run: ./scripts/install-trailblaze-from-artifact.sh
- name: Install ffmpeg
# Session video encodes through it; see the script for why it is a pinned build.
run: ./.github/install-ffmpeg.sh
- name: Create and start emulator and run MCP dispatch check (Linux)
if: runner.os == 'Linux'
uses: reactivecircus/android-emulator-runner@b530d96654c385303d652368551fb075bc2f0b6b
id: run-tests-linux
continue-on-error: true
with:
api-level: 34
arch: x86_64
disable-animations: true
disk-size: 6000M
heap-size: 600M
profile: Nexus 6
script: ./.github/pr_run_android_mcp_dispatch.sh
- name: Create artifacts
if: always()
continue-on-error: true
run: ./.github/pr_create_artifacts.sh
- name: Upload artifacts
if: always() # Ensures this runs even if the previous step failed
uses: actions/upload-artifact@v4
with:
name: trailblaze-artifacts-mcp-dispatch
path: |
trailblaze-logs.zip
logcat.log
mcp-dispatch/
- name: Fail if the MCP dispatch check failed
if: steps.run-tests-linux.outcome == 'failure'
run: |
echo "MCP dispatch check failed - failing the workflow"
exit 1