Skip to content

Nightly

Nightly #11

Workflow file for this run

name: Nightly
# The exit criteria, run by a machine.
#
# releaseGate.mjs holds 31 automated criteria and nothing ever ran them: the only
# runner was a release captain typing 27 commands, so a criterion could be red for
# weeks with every push green. hot-update-lands-or-rolls-back was, and the pixel
# gates at the `nightly` tier — declared, named, and invoked by nothing at all.
#
# The list is NOT repeated here. Each job calls run-release-gate.mjs for the host
# it is standing on, because a workflow that named the commands itself would be
# the second list gates.mjs exists to prevent. `host` lives on the criterion.
#
# A release tag runs the same thing: an exit criterion is what a RELEASE has to
# be able to say, so the list is answered again against the commit being shipped
# rather than trusted from whatever the cron last saw.
permissions:
contents: read
on:
schedule:
# 04:00 UTC, after the day's pushes have settled.
- cron: '0 4 * * *'
push:
tags:
- 'v*'
workflow_dispatch:
jobs:
# The criteria read a real engine, and the render host takes the artifact from
# THIS run — so the nightly builds its own rather than reaching for a push's.
build-emscripten:
name: Web (Emscripten)
runs-on: ubuntu-latest
timeout-minutes: 40
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/engine-submodules
- uses: ./.github/actions/setup
- name: Setup Emscripten
uses: mymindstorm/setup-emsdk@v16
with:
version: 5.0.0
- name: Setup ccache
uses: hendrikmuhs/ccache-action@v1.2.23
with:
key: ${{ runner.os }}-emscripten
max-size: 500M
- name: Build every target
run: node build-tools/cli.js build -t all --no-sync
- name: Upload web wasm artifact
uses: actions/upload-artifact@v7
with:
name: wasm-web
path: build/wasm/web/
retention-days: 3
# `-t all` builds this and nothing carried it, so every wechat package after
# it said "wechat engine runtime not found" — a whole platform's packaging
# answered by an artifact that was built and dropped.
- name: Upload wechat wasm artifact
uses: actions/upload-artifact@v7
with:
name: wasm-wechat
path: build/wasm/wechat/
retention-days: 3
# The three criteria that ask what a COMPILED system does on a host with no JIT
# can only be answered against a template — and against THIS branch's, not a
# release's: the host is half of what they measure, so answering with a
# published binary would be answering about an engine this commit is not.
# Its own job, because a cold Dawn is tens of minutes and the criteria list
# should not be waiting behind it inside one timeout.
linux-template:
name: Linux runtime template (HEAD)
runs-on: ubuntu-latest
timeout-minutes: 120
env:
CC: clang
CXX: clang++
ESTELLA_NATIVE_TEMPLATES: ${{ github.workspace }}/.native-templates
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/engine-submodules
- uses: ./.github/actions/setup
# The SDK bundle is compiled into the host binary.
- name: Build SDK
run: pnpm --filter ./sdk build
- name: Read the native dependency pins
id: pins
run: node build-tools/cli.js native --deps-cache-key linux >> "$GITHUB_OUTPUT"
# The same key build.yml's desktop job writes, so whichever ran last warms
# the other and a nightly rarely pays for Dawn.
- name: Cache the pinned checkouts + Dawn build
uses: actions/cache@v4
with:
path: build/native-deps
key: ${{ steps.pins.outputs.key }}
- name: Set up the Linux desktop dependencies
run: |
sudo apt-get update
sudo apt-get install -y ninja-build libvulkan-dev mesa-vulkan-drivers \
libx11-dev libx11-xcb-dev libxcb1-dev libxext-dev libxfixes-dev libxrandr-dev \
libxi-dev libxcursor-dev libxinerama-dev libxss-dev libxtst-dev \
libxkbcommon-dev libwayland-dev wayland-protocols libdecor-0-dev \
libdbus-1-dev libibus-1.0-dev libudev-dev libdrm-dev libgbm-dev \
libgl1-mesa-dev libegl1-mesa-dev libgles2-mesa-dev \
libasound2-dev libpulse-dev libfontconfig1-dev libcurl4-openssl-dev
- name: Fetch Dawn + QuickJS + SDL at their pinned commits
run: node build-tools/cli.js native --fetch-deps
- name: Build the Linux host and its runtime template
run: node build-tools/cli.js native --target linux
# Through tar, because an artifact is a zip and a zip does not carry the
# executable bit — and what this ships is a host binary.
- name: Upload the template
run: tar -czf native-template-linux.tgz -C .native-templates .
- uses: actions/upload-artifact@v7
with:
name: native-template-linux
path: native-template-linux.tgz
retention-days: 3
# 26 of the 33. The runner names the ones it cannot answer from here and the
# four nobody can automate, so a green job is never read as a green release.
#
# One job per SHARD of the list, not one job for the list: run in a row the
# 26 took 94 minutes, and 73 of those were two criteria. A shard is whole by
# command (naming golden-packages takes the verify-golden run and every
# criterion it answers), and `--except` takes what the named shards did not,
# so a criterion added tomorrow runs in `rest` rather than nowhere.
linux:
name: Exit criteria (linux, ${{ matrix.shard }})
runs-on: ubuntu-latest
needs: [build-emscripten, linux-template]
# A template that failed to build costs three criteria, not twenty-six: they
# report a machine that cannot answer, and the rest of the list still does.
if: always() && needs.build-emscripten.result == 'success'
strategy:
fail-fast: false
matrix:
include:
- shard: flagship
criteria: --only flagship-plays-through
- shard: golden
criteria: --only golden-packages
- shard: perf
criteria: --only performance-ceilings
- shard: static
criteria: --only static-gates
- shard: rest
criteria: --except flagship-plays-through,golden-packages,performance-ceilings,static-gates
env:
ESTELLA_NATIVE_TEMPLATES: ${{ github.workspace }}/.native-templates
# The longest shard is golden at about a quarter of an hour.
timeout-minutes: 60
steps:
# verify-legacy reads examples out of RELEASE TAGS (git archive v0.20.0 …),
# which a shallow checkout has none of: old-projects-open failed on all five
# with "an unknown tag" every night it ran.
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: ./.github/actions/engine-submodules
# play-stop-conserves, scene-churn-flat and the scale budgets measure the
# EDITOR, and golden compares a package against the editor's own frame. All
# four reported a missing checkout as a verdict.
- uses: ./.github/actions/editor-checkout
with:
ssh-key: ${{ secrets.EDITOR_SSH_KEY }}
- uses: ./.github/actions/setup
- uses: ./.github/actions/render-host
- uses: ./.github/actions/editor-host
# A golden project marks a system @compiled, and packaging one runs the AOT
# step rather than falling back — so the three AOT criteria said "there is no
# emcc" on a runner that had never been given one.
- name: Setup Emscripten
uses: mymindstorm/setup-emsdk@v16
with:
version: 5.0.0
# electron-preconditions: job-wide. play-stop-conserves and scene-churn-flat
# run the EDITOR's own check scripts, which live in the private submodule and
# cannot import electronRun — so both aborted in the SUID sandbox helper and
# reported "timeout initialize" about the editor. One display for every step,
# rather than a prefix on a command that lives in releaseGate.mjs.
- name: A display for the whole job
run: |
Xvfb :99 -screen 0 1920x1080x24 &
for _ in $(seq 1 30); do [ -e /tmp/.X11-unix/X99 ] && break; sleep 1; done
test -e /tmp/.X11-unix/X99
echo "DISPLAY=:99" >> "$GITHUB_ENV"
echo "ELECTRON_DISABLE_SANDBOX=1" >> "$GITHUB_ENV"
# What the AOT criteria package into, built by this run from this commit.
- name: Take this run's linux template
continue-on-error: true
uses: actions/download-artifact@v8
with:
name: native-template-linux
- name: Unpack the template
continue-on-error: true
run: |
mkdir -p .native-templates
tar -xzf native-template-linux.tgz -C .native-templates
ls -R .native-templates | head -20
# A packaged desktop game is SDL + Dawn: the four AOT criteria launch one,
# so the runner needs what it links against and a software Vulkan to draw on.
- name: Set up what a packaged desktop game runs on
run: |
sudo apt-get update
sudo apt-get install -y ninja-build libvulkan-dev mesa-vulkan-drivers \
libx11-dev libx11-xcb-dev libxcb1-dev libxext-dev libxfixes-dev libxrandr-dev \
libxi-dev libxcursor-dev libxinerama-dev libxss-dev libxtst-dev \
libxkbcommon-dev libwayland-dev wayland-protocols libdecor-0-dev \
libdbus-1-dev libibus-1.0-dev libudev-dev libdrm-dev libgbm-dev \
libgl1-mesa-dev libegl1-mesa-dev libgles2-mesa-dev \
libasound2-dev libpulse-dev libfontconfig1-dev libcurl4-openssl-dev
- name: Run the exit criteria
run: node tools/run-release-gate.mjs --host linux ${{ matrix.criteria }}
# every-pixel-gate-runs, whose second half needs a GPU: a Linux runner ships no
# graphics driver and every webgpu run there died in requestDevice. The
# criterion says so itself, in its `why`.
macos:
name: Exit criteria (macos)
runs-on: macos-latest
needs: build-emscripten
timeout-minutes: 90
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/engine-submodules
# Half the nightly scenes name the editor host, and without it verify-render
# got as far as "Command \"vite\" not found" — one second, and read as a
# verdict on 141 scenes.
- uses: ./.github/actions/editor-checkout
with:
ssh-key: ${{ secrets.EDITOR_SSH_KEY }}
- uses: ./.github/actions/setup
- uses: ./.github/actions/render-host
- uses: ./.github/actions/editor-host
- name: Run the exit criteria
run: node tools/run-release-gate.mjs --host macos
# The two criteria that package for Android and boot what they packaged. An
# emulator answers both: verify-native-boot installs on a simulator by design,
# and what it asks — did the boot record reach `ready in`, is the frame more
# than one flat colour — is not a question about a driver. Ubuntu minutes, so
# this rides the cron with the rest.
android:
name: Exit criteria (android)
runs-on: ubuntu-latest
needs: build-emscripten
timeout-minutes: 90
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/engine-submodules
- uses: ./.github/actions/setup
- uses: ./.github/actions/render-host
# The corpus it boots includes projects with @compiled systems, which package
# through the AOT step.
- name: Setup Emscripten
uses: mymindstorm/setup-emsdk@v16
with:
version: 5.0.0
# A game is packaged INTO a template, and this job never had one: the default
# path is a directory a checkout does not carry, so all 47 exports failed at
# once. The action's own comment says why this takes the released one.
- uses: ./.github/actions/native-template
with:
platform: android
token: ${{ secrets.GITHUB_TOKEN }}
# Nested virtualisation for the emulator, as the compat matrix does.
- name: Enable KVM
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
# The runner IS the emulator: the criteria's own commands run inside it, so
# the list stays in releaseGate.mjs and this file names none of them.
- name: Run the exit criteria
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 34
arch: x86_64
disable-animations: true
script: node tools/run-release-gate.mjs --host android