Skip to content

fix: checkout meta-gl sibling repo needed by easy-gl in CI #73

fix: checkout meta-gl sibling repo needed by easy-gl in CI

fix: checkout meta-gl sibling repo needed by easy-gl in CI #73

Workflow file for this run

# MeshCraft CI.
#
# Scope: Linux and Windows jobs build and test the CNA-independent libraries
# (mc3, mcb, mc3togltf, mc3tomcb) as standalone CMake projects. These have no
# CNA / SDL3 / OpenGL / ImGui dependency, so they cover format/export tests but
# NOT editor (render/smoke/registry/ai/commands) tests. The Windows job also
# publishes only CLI binaries that passed the deterministic cross-platform
# fixture. For exact live counts run `ctest -N`; they are deliberately not
# hard-coded here.
#
# The editor job below checks out the three required sibling repositories
# beside this checkout, exactly matching the root CMake project layout
# (`../cna`, `../sharp-runtime`, `../easy-gl` -- the last one only because
# CNA's own CNA_BACKEND_EASY_GL option, which every matrix entry enables,
# requires it as a sibling checkout). EASYGL runs the complete root CTest
# suite, while the Vulkan matrix entry always configures and builds the real
# editor.
# Vulkan is enabled for the explicit manual SYS-W8-05 qualification run;
# WebGPU remains gated pending its own pixel-qualified runner.
name: CI
on:
push:
branches: [ master, develop ]
pull_request:
branches: [ master, develop ]
# Cancel superseded runs for the same ref.
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
standalone:
name: ${{ matrix.component }} (standalone)
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
component: [ mc3, mcb, mc3togltf, mc3tomcb ]
env:
CC: gcc-14
CXX: g++-14
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 ninja-build g++-14 python3
# AUDIT-0051: cache CMake FetchContent downloads (tinyxml2/manifold/
# tinygltf/etc., fetched per-component into build/_deps). Keyed on BOTH the
# component's own CMakeLists.txt AND mc3/CMakeLists.txt: mcb/mc3togltf/
# mc3tomcb pull in mc3, which pins several of their real dependencies, so a
# dependency version bump in either file must invalidate the cache instead
# of silently reusing a stale fetch.
- name: Cache CMake FetchContent downloads
uses: actions/cache@v4
with:
path: build/_deps
key: ${{ runner.os }}-fetchcontent-${{ matrix.component }}-${{ hashFiles(format('{0}/CMakeLists.txt', matrix.component), 'mc3/CMakeLists.txt') }}
restore-keys: |
${{ runner.os }}-fetchcontent-${{ matrix.component }}-
- name: Configure (${{ matrix.component }})
run: >
cmake -S ${{ matrix.component }} -B build -G Ninja
-DCMAKE_BUILD_TYPE=Release
-DBUILD_TESTING=ON
- name: Build
run: cmake --build build -j2
- name: Test
run: ctest --test-dir build --output-on-failure -j2
standalone-windows:
name: Standalone Windows qualification
runs-on: windows-2022
steps:
- name: Checkout
uses: actions/checkout@v4
# Each standalone component owns a FetchContent tree. Cache all four
# without checking out CNA or sharp-runtime: this qualification must
# remain independent of the editor backend blockers.
- name: Cache CMake FetchContent downloads
uses: actions/cache@v4
with:
path: build/*/_deps
key: ${{ runner.os }}-standalone-fetchcontent-${{ hashFiles('mc3/CMakeLists.txt', 'mcb/CMakeLists.txt', 'mc3togltf/CMakeLists.txt', 'mc3tomcb/CMakeLists.txt') }}
restore-keys: |
${{ runner.os }}-standalone-fetchcontent-
- name: Configure, build, and test every standalone component
shell: pwsh
run: |
$components = @('mc3', 'mcb', 'mc3togltf', 'mc3tomcb')
foreach ($component in $components) {
$buildDir = "build/$component"
cmake -S $component -B $buildDir -G Ninja `
-DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON
cmake --build $buildDir --parallel 2
ctest --test-dir $buildDir --output-on-failure --parallel 2
}
- name: Verify deterministic CLI fixture before publishing
shell: pwsh
run: >
python test/cross_platform_cli_fixture_test.py
build/mc3tomcb/mc3tomcb.exe
build/mc3togltf/mc3togltf.exe
test/house.mc3.xml
build/cli-cross-platform-fixture
# SYS-W11-08: bundle the same notices/SHA-256 manifest the Linux
# meshcraft_cli_release archive gets, so the Windows artifact isn't a
# bare, unverifiable pair of executables. Does not attempt to stage
# Manifold/tinyobjloader runtime DLLs here -- that is a separate,
# already-tracked gap (the in-tree ctest run above can currently fail
# with STATUS_DLL_NOT_FOUND for the same underlying reason), and adding
# a manifest for an incomplete artifact is still strictly better than
# no manifest at all.
- name: Stage release manifest and notices
shell: pwsh
run: |
Copy-Item LICENSE build/
Copy-Item THIRD_PARTY.md build/
$files = @('build/mc3tomcb/mc3tomcb.exe', 'build/mc3togltf/mc3togltf.exe',
'build/LICENSE', 'build/THIRD_PARTY.md')
$lines = foreach ($f in $files) {
$hash = (Get-FileHash -Algorithm SHA256 $f).Hash.ToLower()
"$hash $(Split-Path -Leaf $f)"
}
Set-Content -Path build/SHA256SUMS.txt -Value $lines
- name: Publish qualified Windows CLI artifacts
uses: actions/upload-artifact@v4
with:
name: meshcraft-cli-windows
if-no-files-found: error
path: |
build/mc3tomcb/mc3tomcb.exe
build/mc3togltf/mc3togltf.exe
build/LICENSE
build/THIRD_PARTY.md
build/SHA256SUMS.txt
sanitizers-and-fuzz:
name: Clang ASan+UBSan and bounded fuzz
runs-on: ubuntu-24.04
env:
CC: clang
CXX: clang++
ASAN_OPTIONS: detect_leaks=1:halt_on_error=1
UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
clang cmake ninja-build ccache python3 zlib1g-dev
# The sanitizer and fuzz configurations reuse their component-local
# FetchContent trees. The key covers every standalone component because
# mc3 is a transitive dependency of three of them.
- name: Cache CMake FetchContent downloads
uses: actions/cache@v4
with:
path: |
build-sanitize/mc3/_deps
build-sanitize/mcb/_deps
build-sanitize/mc3togltf/_deps
build-sanitize/mc3tomcb/_deps
key: ${{ runner.os }}-clang-sanitize-fetchcontent-${{ hashFiles('mc3/CMakeLists.txt', 'mcb/CMakeLists.txt', 'mc3togltf/CMakeLists.txt', 'mc3tomcb/CMakeLists.txt') }}
restore-keys: |
${{ runner.os }}-clang-sanitize-fetchcontent-
- name: Configure, build, and test all standalone components under ASan+UBSan
run: |
sanitize_flags='-fsanitize=address,undefined -fno-omit-frame-pointer -g'
for component in mc3 mcb mc3togltf mc3tomcb; do
build_dir="build-sanitize/$component"
cmake -S "$component" -B "$build_dir" -G Ninja \
-DCMAKE_BUILD_TYPE=Debug \
-DBUILD_TESTING=ON \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_FLAGS="$sanitize_flags" \
-DCMAKE_EXE_LINKER_FLAGS="$sanitize_flags"
cmake --build "$build_dir" -j2
ctest --test-dir "$build_dir" --output-on-failure -j2
done
- name: Build bounded libFuzzer targets
run: |
for component in mc3 mcb mc3togltf; do
cmake -S "$component" -B "build-sanitize/$component" \
-DMESHCRAFT_FUZZ=ON
done
cmake --build build-sanitize/mc3 --target mc3_xml_libfuzzer mc3_json_libfuzzer -j2
cmake --build build-sanitize/mcb --target mcb_libfuzzer -j2
cmake --build build-sanitize/mc3togltf --target mc3togltf_glb_libfuzzer -j2
- name: Run corpus-seeded fuzz smoke tests
run: |
mkdir -p build-sanitize/fuzz-corpus/mcb build-sanitize/fuzz-corpus/glb
build-sanitize/mc3tomcb/mc3tomcb \
mc3/test/fuzz/corpus/xml/basic_scene.mc3.xml \
build-sanitize/fuzz-corpus/mcb/basic_scene.mcb
build-sanitize/mc3togltf/mc3togltf \
mc3togltf/test/golden/basic_scene.mc3.xml \
build-sanitize/fuzz-corpus/glb/basic_scene.glb
python3 test/run_fuzz_smoke.py --seconds 20 --rss-mib 2048 \
--work-dir build-sanitize/fuzz-work \
--target build-sanitize/mc3/mc3_xml_libfuzzer mc3/test/fuzz/corpus/xml \
--target build-sanitize/mc3/mc3_json_libfuzzer mc3/test/fuzz/corpus/json \
--target build-sanitize/mcb/mcb_libfuzzer build-sanitize/fuzz-corpus/mcb \
--target build-sanitize/mc3togltf/mc3togltf_glb_libfuzzer build-sanitize/fuzz-corpus/glb
editor:
name: Editor (${{ matrix.backend }})
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
backend: [ EASYGL, VULKAN ]
env:
CC: gcc-14
CXX: g++-14
steps:
# Keep the three repositories as siblings: root CMake deliberately uses
# add_subdirectory(../cna) and CNA uses ../sharp-runtime.
- name: Checkout MeshCraft
uses: actions/checkout@v4
with:
path: mesh-craft
- name: Checkout CNA
uses: actions/checkout@v4
with:
repository: openeggbert/cna
path: cna
# Keep the editor job on the sibling revision recorded and tested
# by this repository (AUD-057), rather than an arbitrary branch tip.
ref: d0c21ee613ebd8f8b0055f7868103dd5c5c30fc7
# cna/cmake/ThirdPartySDL.cmake vendors SDL/SDL_image/SDL_mixer as
# submodules and fails configure without them. Non-recursive: those
# submodules' own nested submodules are optional codec dependencies
# this project's CMAKE_ARGS disable, so recursing into them would
# only add a slower, unused fetch.
submodules: true
- name: Checkout sharp-runtime
uses: actions/checkout@v4
with:
repository: openeggbert/sharp-runtime
path: sharp-runtime
ref: 5cdaafb2bace46dce5393da21dad9ff9f8ad3c58
# CNA's CNA_BACKEND_EASY_GL option (which the EASYGL backend this job
# matrix builds turns on) requires a sibling 'easy-gl' checkout --
# CNA's own CMakeLists.txt hard-fails configure without it
# ("Missing sibling repository 'easy-gl'"). Every matrix entry needs
# it, not just EASYGL: the single "Configure editor" step below always
# configures both backends (it's followed by both an EASYGL-only build
# step and an unconditioned "Build Vulkan editor" step).
- name: Checkout easy-gl
uses: actions/checkout@v4
with:
repository: openeggbert/easy-gl
path: easy-gl
ref: 62c0a248a6c4144abaf92c0530cc2a2395e5fd37
# easy-gl's own CMakeLists.txt in turn add_subdirectory(../meta-gl)s --
# a second, one-deeper sibling requirement discovered the same way as
# easy-gl itself above.
- name: Checkout meta-gl
uses: actions/checkout@v4
with:
repository: openeggbert/meta-gl
path: meta-gl
ref: d51fcd7f455de8e3df3549edbed84f2b5527f18a
- name: Install editor build dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
cmake ninja-build g++-14 python3 pkg-config \
libgl1-mesa-dev libegl1-mesa-dev libglvnd-dev \
libvulkan-dev \
libx11-dev libxext-dev libxrandr-dev libxcursor-dev \
libxi-dev libxfixes-dev libxss-dev libxtst-dev \
libavcodec-dev libavformat-dev libavutil-dev libswresample-dev \
libsqlite3-dev libssl-dev libxml2-dev xvfb x11-utils
- name: Cache root CMake FetchContent downloads
uses: actions/cache@v4
with:
path: mesh-craft/build-${{ matrix.backend }}/_deps
key: ${{ runner.os }}-editor-${{ matrix.backend }}-fetchcontent-${{ hashFiles('mesh-craft/CMakeLists.txt', 'mesh-craft/mc3/CMakeLists.txt', 'cna/CMakeLists.txt', 'sharp-runtime/CMakeLists.txt') }}
restore-keys: |
${{ runner.os }}-editor-${{ matrix.backend }}-fetchcontent-
- name: Configure editor
working-directory: mesh-craft
run: >
cmake -S . -B build-${{ matrix.backend }} -G Ninja
-DCMAKE_BUILD_TYPE=Release
-DBUILD_TESTING=ON
-DMESH_CRAFT_GRAPHICS_BACKEND=${{ matrix.backend }}
-DFETCHCONTENT_UPDATES_DISCONNECTED=ON
- name: Build EASYGL editor and tests
if: matrix.backend == 'EASYGL'
working-directory: mesh-craft
run: cmake --build build-EASYGL -j2
- name: Test root project
if: matrix.backend == 'EASYGL'
working-directory: mesh-craft
run: ctest --test-dir build-EASYGL --output-on-failure -j2
- name: Build Vulkan editor
if: matrix.backend == 'VULKAN'
working-directory: mesh-craft
run: cmake --build build-VULKAN --target MeshCraft -j2
- name: Assert Vulkan runtime gate is enabled
if: matrix.backend == 'VULKAN'
working-directory: mesh-craft
run: |
./build-VULKAN/MeshCraft --version
# SYS-W11-09: SYS-W11-04's sanitizer/fuzz job only covers the CNA-free
# standalone components (mc3/mcb/mc3togltf/mc3tomcb); the editor's own
# ~35,700 lines of src/+include/ had no sanitizer coverage at all until
# this job. Uses the same MESHCRAFT_SANITIZE=ON root CMake support the
# standalone job already exercises, now also applied to every first-party
# editor test executable (not just the main MeshCraft binary), with the
# SAME pinned CNA/sharp-runtime revisions as the plain `editor` job above
# so a sanitizer finding can't be blamed on an unrelated sibling-repo
# version drift. Starts with the CNA-free and non-render editor tests
# (the vast majority), then adds the smallest reliable EASYGL render
# smoke test under Xvfb -- not the full render suite, which needs a much
# larger, separately-justified time/memory budget.
editor-sanitizer:
name: Editor (EASYGL) ASan+UBSan
runs-on: ubuntu-24.04
env:
CC: clang
CXX: clang++
ASAN_OPTIONS: detect_leaks=1:halt_on_error=1
UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1
steps:
- name: Checkout MeshCraft
uses: actions/checkout@v4
with:
path: mesh-craft
- name: Checkout CNA
uses: actions/checkout@v4
with:
repository: openeggbert/cna
path: cna
ref: d0c21ee613ebd8f8b0055f7868103dd5c5c30fc7
submodules: true
- name: Checkout sharp-runtime
uses: actions/checkout@v4
with:
repository: openeggbert/sharp-runtime
path: sharp-runtime
ref: 5cdaafb2bace46dce5393da21dad9ff9f8ad3c58
# See the "editor" job's own "Checkout easy-gl"/"Checkout meta-gl" step
# comments: CNA's CNA_BACKEND_EASY_GL option (which this EASYGL-
# specific job enables) requires a sibling 'easy-gl' checkout, which in
# turn requires a sibling 'meta-gl' checkout, or configure hard-fails.
- name: Checkout easy-gl
uses: actions/checkout@v4
with:
repository: openeggbert/easy-gl
path: easy-gl
ref: 62c0a248a6c4144abaf92c0530cc2a2395e5fd37
- name: Checkout meta-gl
uses: actions/checkout@v4
with:
repository: openeggbert/meta-gl
path: meta-gl
ref: d51fcd7f455de8e3df3549edbed84f2b5527f18a
- name: Install editor build dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
clang cmake ninja-build python3 pkg-config \
libgl1-mesa-dev libegl1-mesa-dev libglvnd-dev \
libx11-dev libxext-dev libxrandr-dev libxcursor-dev \
libxi-dev libxfixes-dev libxss-dev libxtst-dev \
libavcodec-dev libavformat-dev libavutil-dev libswresample-dev \
libsqlite3-dev libssl-dev libxml2-dev xvfb x11-utils
- name: Cache root CMake FetchContent downloads
uses: actions/cache@v4
with:
path: mesh-craft/build-sanitize/_deps
key: ${{ runner.os }}-editor-sanitize-fetchcontent-${{ hashFiles('mesh-craft/CMakeLists.txt', 'mesh-craft/mc3/CMakeLists.txt', 'cna/CMakeLists.txt', 'sharp-runtime/CMakeLists.txt') }}
restore-keys: |
${{ runner.os }}-editor-sanitize-fetchcontent-
- name: Configure editor with MESHCRAFT_SANITIZE
working-directory: mesh-craft
run: >
cmake -S . -B build-sanitize -G Ninja
-DCMAKE_BUILD_TYPE=Debug
-DBUILD_TESTING=ON
-DMESH_CRAFT_GRAPHICS_BACKEND=EASYGL
-DMESHCRAFT_SANITIZE=ON
-DFETCHCONTENT_UPDATES_DISCONNECTED=ON
- name: Build editor and tests under ASan+UBSan
working-directory: mesh-craft
run: cmake --build build-sanitize -j2
- name: Test non-render, CNA-free-and-editor targets
working-directory: mesh-craft
run: ctest --test-dir build-sanitize --output-on-failure -j2 -LE render
- name: Test one EASYGL render smoke case
working-directory: mesh-craft
# smoke_test.sh wraps itself in xvfb-run when available (same
# convention the plain `editor` job's ctest invocation above relies
# on), so no outer xvfb-run wrapper is needed here either.
#
# detect_leaks=0 ONLY for this one render test: confirmed locally
# that every leak this specific test reports traces into libasan.so
# itself or an unknown (stripped) system module -- Mesa/llvmpipe's
# software-rasterizer driver stack under Xvfb, not any first-party,
# CNA, or sharp-runtime symbol anywhere in the stack. A narrow,
# documented exclusion for a known third-party/system noise source,
# not a blanket leak-detection disable -- every other sanitizer
# target in this job (and ASan's own crash/corruption detection
# here) keeps full leak detection.
run: >
ASAN_OPTIONS=detect_leaks=0
ctest --test-dir build-sanitize --output-on-failure -R "^smoke_test$"