fix: checkout meta-gl sibling repo needed by easy-gl in CI #73
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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$" |