Skip to content

Update submodules: htmlayout, bronze, brosurface (sync to standalone … #213

Update submodules: htmlayout, bronze, brosurface (sync to standalone …

Update submodules: htmlayout, bronze, brosurface (sync to standalone … #213

Workflow file for this run

name: CI
# Build check for the default (app) profile on every push/PR: the full renderer
# + net/video/steam, no AI tower/CUDA so it stays fast. This is the signal
# behind the "CI" badge. The heavier full+CUDA build runs in nightly.yml.
#
# The `minimal` job below covers the other end: the profile BUILDING.md hands
# to someone who has just cloned and has no vcpkg. See its own comment.
#
# The bronze host layer (src/bronze_host, 17K lines) is built on all three
# platforms — it is off by default in a local configure, so without this it
# would compile nowhere until someone noticed. Only Linux also builds the
# bronze COMPILER (BRONZE_WITH_LLVM=ON, against the prebuilt LLVM hosted on the
# bronze repo): Linux is the job that runs the test suite, and the twenty-two
# tests/bronze_host checks need a compiler to produce their subject — without
# one they report SKIP forever, which is the failure mode this exists to avoid.
# The other two get the host layer compiled and linked, which is what breaks
# there. Nightly builds the compiler everywhere, because it ships it.
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
env:
# Must match vcpkg.json's builtin-baseline — the manifest pins port versions,
# this pins the vcpkg tool + scripts to the same commit (the runner's
# preinstalled vcpkg drifts with every image update).
VCPKG_COMMIT: 0b88aacde46a853151730fbe7d0b7ee45f4b6864
# Persist the sccache object cache in the GitHub Actions cache across runs.
# Without this sccache silently falls back to per-runner LOCAL DISK, which is
# wiped between runs — 0% hits, every object recompiled (measured 0/1220).
SCCACHE_GHA_ENABLED: "true"
# Which llvm-prebuilt-<ver> release from the bronze repo to build the bronze
# compiler against. Keep in step with LLVM_VERSION in bronze's own ci.yml:
# the tarball is what that repo publishes and tests itself against, and a
# version it has retired is a version nothing guarantees still builds.
# vcpkg would build LLVM from source instead — hours, versus about a minute.
LLVM_VERSION: "22.1.8"
jobs:
build:
name: ${{ matrix.name }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
# bronze_llvm: build the bronze compiler here, not only the host
# layer. llvm: which prebuilt tarball that needs (unused when off).
- { name: linux, os: ubuntu-24.04, triplet: x64-linux, test: true, bronze_llvm: true, llvm: linux-x64 }
- { name: windows, os: windows-2022, triplet: x64-windows, test: false, bronze_llvm: false, llvm: windows-x64 }
- { name: macos, os: macos-14, triplet: arm64-osx, test: false, bronze_llvm: false, llvm: macos-arm64 }
steps:
- name: Rewrite SSH submodule URLs to HTTPS
run: git config --global url."https://github.com/".insteadOf "git@github.com:"
# submodules: recursive brings third_party/bronze along with the rest, at
# the commit this bro records — so the bronze built here is a pinned one
# that moves when someone bumps the pointer, never whatever bronze main
# happens to be this morning.
- uses: actions/checkout@v7
with:
submodules: recursive
# The bronze_host checks compile fixtures that import three.js and pixi.js
# OUT OF the bronze tree, by sibling-relative path
# (`../../../../bronze/tests/oracle/threejs/three.module.js`, and
# node_modules shims whose "main" points the same way) — the layout every
# developer has, with bronze checked out beside bro. A runner has the same
# tree at third_party/bronze and no sibling, so give it the sibling name.
# A symlink, not a copy: one pinned tree under both names, which also
# means the configure resolves it as the standalone checkout and the
# checks run in exactly the layout they were written for. (Windows and
# macOS get no link and so exercise the submodule branch of that
# resolution instead.)
- name: Link the bronze submodule as the sibling checkout
if: matrix.test
run: ln -s "$PWD/third_party/bronze" "$PWD/../bronze"
# SDL3 builds from third_party/SDL. Linux also gets xvfb + mesa so the
# headless test suite can run its GPU (GL) path against llvmpipe software
# rendering — the same code that ships, not the --no-gpu raster fallback.
- name: Linux build dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
ninja-build nasm xvfb libgl1-mesa-dri \
libgl1-mesa-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev \
libxi-dev libxfixes-dev libxss-dev libxtst-dev libwayland-dev libxkbcommon-dev \
libegl1-mesa-dev libasound2-dev libpulse-dev libudev-dev \
libfreetype-dev libfontconfig1-dev libpng-dev libjpeg-dev libwebp-dev
- name: Ninja (macOS)
if: runner.os == 'macOS'
run: brew install ninja
# The LLVM the bronze codegen backend links against, cached extracted; on
# a miss it downloads from the bronze repo's llvm-prebuilt-<ver> release.
# Keyed by version alone — a release's assets are immutable.
- name: LLVM prebuilt cache
if: matrix.bronze_llvm
id: llvm-cache
uses: actions/cache@v6
with:
path: ${{ runner.temp }}/llvm-prebuilt
key: llvm-${{ env.LLVM_VERSION }}-${{ matrix.llvm }}
# curl, not `gh release download`: this asset lives in a DIFFERENT repo
# (wlejon/bronze), and GITHUB_TOKEN is scoped to this one. bronze is
# public, so its release assets need no credential at all.
- name: Fetch LLVM prebuilt
if: matrix.bronze_llvm && steps.llvm-cache.outputs.cache-hit != 'true'
shell: bash
run: |
mkdir -p "$RUNNER_TEMP/llvm-prebuilt"
TARBALL="bronze-llvm-${LLVM_VERSION}-${{ matrix.llvm }}.tar.gz"
# cd first: $RUNNER_TEMP is a D:\... path on Windows, and GNU tar reads
# the colon in an -f argument as a remote-host separator.
cd "$RUNNER_TEMP"
curl -fsSL -o "$TARBALL" \
"https://github.com/wlejon/bronze/releases/download/llvm-prebuilt-${LLVM_VERSION}/$TARBALL"
tar -xzf "$TARBALL" -C llvm-prebuilt
# bronze's configure takes LLVM_DIR from the environment when it is set
# and only autodetects otherwise, and find_package(LLVM CONFIG) reads the
# same name — so this one variable is the whole handoff.
- name: Point LLVM_DIR at the prebuilt
if: matrix.bronze_llvm
shell: bash
run: echo "LLVM_DIR=$RUNNER_TEMP/llvm-prebuilt/llvm/lib/cmake/llvm" >> "$GITHUB_ENV"
- name: sccache
uses: mozilla-actions/sccache-action@v0.0.11
# Persist vcpkg's built-package archives across runs. The pinned manifest
# keeps package ABIs stable, so after one warm run the configure-time dep
# install restores zips in seconds instead of building protobuf/openssl/
# GNS from source (15-30 min). The key is unique per run and restore-keys
# pick the newest prior cache: this way a run that had to rebuild
# anything (e.g. a runner-image compiler bump changed ABIs) saves the new
# archives instead of hitting the "exact key exists, skip save" trap.
- name: vcpkg binary cache
uses: actions/cache@v6
with:
path: ${{ runner.temp }}/vcpkg-bincache
key: vcpkg-bin-${{ matrix.triplet }}-${{ hashFiles('vcpkg.json') }}-${{ github.run_id }}
restore-keys: |
vcpkg-bin-${{ matrix.triplet }}-${{ hashFiles('vcpkg.json') }}-
vcpkg-bin-${{ matrix.triplet }}-
# Dependencies (gamenetworkingsockets, libvpx, libwebm, opus,
# recastnavigation + transitives) come from vcpkg.json, pinned by its
# builtin-baseline; the vcpkg toolchain installs them during CMake
# configure. Clone vcpkg at that same commit so tool + ports + scripts
# are all pinned together.
- name: vcpkg (pinned)
shell: bash
run: |
git clone https://github.com/microsoft/vcpkg "$RUNNER_TEMP/vcpkg"
git -C "$RUNNER_TEMP/vcpkg" checkout "$VCPKG_COMMIT"
if [ "$RUNNER_OS" = "Windows" ]; then
"$RUNNER_TEMP/vcpkg/bootstrap-vcpkg.bat" -disableMetrics
else
"$RUNNER_TEMP/vcpkg/bootstrap-vcpkg.sh" -disableMetrics
fi
mkdir -p "$RUNNER_TEMP/vcpkg-bincache"
echo "VCPKG_ROOT=$RUNNER_TEMP/vcpkg" >> "$GITHUB_ENV"
echo "VCPKG_DEFAULT_BINARY_CACHE=$RUNNER_TEMP/vcpkg-bincache" >> "$GITHUB_ENV"
# Put cl.exe on PATH so Windows can use the Ninja generator below — the
# default Visual Studio generator ignores CMAKE_*_COMPILER_LAUNCHER, so
# sccache would see zero compiles (same setup as nightly.yml).
- name: MSVC dev environment (Windows)
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64
- name: Configure
shell: bash
run: |
GEN_ARGS=""
if [ "$RUNNER_OS" = "Windows" ]; then
# Ninja (with the MSVC env set above) so the sccache compiler
# launcher is actually honored. Embedded debug info (/Z7) instead
# of a separate PDB (/Zi) is what lets sccache cache MSVC objects.
GEN_ARGS="-G Ninja -DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT=Embedded"
fi
cmake -B build \
-DBRO_PROFILE=app \
-DBROGAMEAGENT_WITH_NAVMESH=ON \
-DBRO_WITH_BRONZE=ON \
-DBRONZE_WITH_LLVM=${{ matrix.bronze_llvm && 'ON' || 'OFF' }} \
-DVCPKG_TARGET_TRIPLET=${{ matrix.triplet }} \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_COMPILER_LAUNCHER=sccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache \
$GEN_ARGS
- name: Build
# Bounded jobs: a bare --parallel passes unlimited -j to make and OOM-kills
# the runner (exit 143). app profile has no AI tower, so 4 is safe on 16 GB.
run: cmake --build build --config Release --parallel 4
# bronze is added EXCLUDE_FROM_ALL (src/bronze_host/CMakeLists.txt), so
# the default target does not build its CLI — bro links the runtime, not
# the compiler. Name it, or the bronze_host checks find no compiler and
# skip. bronze-cli rather than bronze: same binary, one name that every
# generator can reach (see the target's comment).
- name: Build the bronze compiler
if: matrix.bronze_llvm
run: cmake --build build --config Release --parallel 4 --target bronze-cli
# run_tests.sh enumerates the bronze_host checks alongside the JS tests
# (tests/bronze_host/run_checks.sh --list) and compiles each check's app
# module with the compiler built above. They are the only coverage that
# layer has, so they run here in full rather than being deferred.
- name: Test (headless, GPU path under Xvfb)
if: matrix.test
shell: bash
env:
# pixi.js v8 is the slowest module in the tree to compile — on a
# runner it does not finish inside the 900 s per-check timeout, so
# the check can only ever report TIMEOUT here. Left out of CI; run
# it locally with tests/bronze_host/run_checks.sh pixi.
BRO_TEST_BRONZE_SKIP: pixi
run: xvfb-run -a ./tests/run_tests.sh
# The onramp. `cmake -B build -DBRO_PROFILE=minimal` is what BUILDING.md tells
# someone to run when they have just cloned and do not have vcpkg, so it is the
# first thing a newcomer's machine actually does -- and until this job existed,
# nothing checked it. Three separate things were broken in it at once:
#
# * bro.media's compiled-out stub sat outside its own #include block, so the
# TU did not compile with BRO_WITH_VIDEO off at all;
# * curl linked a zstd it found on PATH next to the one basisu bundles, so
# every executable failed at link -- on machines with vcpkg installed, and
# only those, which is the worst way for a build to break;
# * bro.gizmo and bro.impostor were guarded at their call sites rather than
# stubbed, so they vanished instead of reporting themselves unavailable.
#
# None of it was visible from the app profile, where every one of those flags
# is on and the #else branches are never even parsed. Hence a job whose whole
# job is to have the flags off.
#
# Deliberately bare: no vcpkg, no LLVM, no bronze, nothing in the configure
# line that BUILDING.md does not print. If this job needs a flag added to keep
# working, that flag belongs in the docs first.
minimal:
name: minimal (${{ matrix.name }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
# Linux also runs the built binary: a build that links but cannot open
# a document is not what "it just works" means.
- { name: linux, os: ubuntu-24.04, smoke: true }
- { name: windows, os: windows-2022, smoke: false }
- { name: macos, os: macos-14, smoke: false }
steps:
- name: Rewrite SSH submodule URLs to HTTPS
run: git config --global url."https://github.com/".insteadOf "git@github.com:"
- uses: actions/checkout@v7
with:
submodules: recursive
# The same list the app job installs, minus nothing: minimal still wants a
# window, fonts and audio. Xvfb + mesa so the smoke run below exercises the
# GL path that ships rather than a raster fallback.
- name: Linux build dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends ninja-build nasm xvfb libgl1-mesa-dri libgl1-mesa-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxi-dev libxfixes-dev libxss-dev libxtst-dev libwayland-dev libxkbcommon-dev libegl1-mesa-dev libasound2-dev libpulse-dev libudev-dev libfreetype-dev libfontconfig1-dev libpng-dev libjpeg-dev libwebp-dev
- name: Ninja (macOS)
if: runner.os == 'macOS'
run: brew install ninja
- name: MSVC dev environment (Windows)
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64
- name: sccache
uses: mozilla-actions/sccache-action@v0.0.11
- name: Configure
shell: bash
run: |
GEN_ARGS=""
if [ "$RUNNER_OS" = "Windows" ]; then
GEN_ARGS="-G Ninja -DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT=Embedded"
fi
cmake -B build -DBRO_PROFILE=minimal -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache $GEN_ARGS
- name: Build
run: cmake --build build --config Release --parallel 4
# Not the full suite -- most of tests/ needs features this profile does not
# have. This asserts the floor minimal promises (HTML parses, layout
# measures, Canvas2D draws) and then that every gated `bro.*` namespace is
# still present and says why it is unavailable.
- name: Smoke (headless, GPU path under Xvfb)
if: matrix.smoke
shell: bash
run: xvfb-run -a ./build/bro-headless tests/_smoke_app tests/_smoke_app/minimal_smoke.js