-
Notifications
You must be signed in to change notification settings - Fork 0
491 lines (447 loc) · 21.2 KB
/
Copy pathci.yml
File metadata and controls
491 lines (447 loc) · 21.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
# 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"
# BUILD_SHARED_LIBS=OFF + static-linking the MinGW runtime: without
# this, mc3togltf.exe links against Manifold/tinyxml2 as DLLs
# (they inherit Manifold's own BUILD_SHARED_LIBS=ON default) AND
# the MinGW toolchain's own runtime (libgcc_s_seh-1.dll/
# libwinpthread-1.dll/libstdc++-6.dll) -- none of which the
# "Publish qualified Windows CLI artifacts" step below stages
# alongside the .exe, so the *published* artifact fails to start
# at all with STATUS_DLL_NOT_FOUND outside this build tree.
# Confirmed via a real downloaded artifact + MinGW/Wine repro
# (2026-07-27, SYS-W11-06 verification): fully static removes
# every DLL dependency and produces byte-identical MC3->MCB/GLB
# output to the dynamic build.
cmake -S $component -B $buildDir -G Ninja `
-DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON `
-DBUILD_SHARED_LIBS=OFF `
-DCMAKE_EXE_LINKER_FLAGS="-static -static-libgcc -static-libstdc++"
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. No runtime DLLs to stage
# (fixed 2026-07-27, SYS-W11-06 verification): the configure step above
# now links everything -- Manifold, tinyxml2, and the MinGW runtime
# itself -- statically, so these two .exe files have zero third-party
# DLL dependencies 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.
# Bumped 2026-07-27 (SYS-W8-08): the previous pin (d0c21ee6) turned
# out to not even be an ancestor of CNA's current develop branch
# (its history was rewritten after that commit was recorded here),
# and predates CNA's Task 1079 ("wire ShaderEffect into
# GraphicsDevice's 3D draw path", commit b08c7aa8) adding
# ShaderEffect::setWorldProperty/setViewProperty/
# setProjectionProperty/SetTexture -- methods
# src/MeshCraft/Renderer/SceneRenderer.cpp already calls. This
# revision is CNA's own current develop tip, confirmed building
# and passing the full non-render MeshCraft suite locally
# (176/180, the 4 failures being the already-known unrelated
# Blender/numpy gap) together with mesh-craft's current source.
ref: ac3aaaeb2a5ba27dbd9e22e782c7041e6e40947c
# 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:
# Corrected 2026-07-27: this job used clang/clang++ since its very
# first commit, contradicting this file's own SYS-W11-09 writeup in
# plan.md ("the new sanitizer job [uses gcc/g++] too, matching" the
# plain `editor` job below) -- that claim described intent that was
# never actually applied here. GCC's ASan+UBSan support is equally
# complete; switching removes the untested risk of hitting the
# documented Clang/CNA::Internal::JsonValue incompatibility, and keeps
# this job on the same toolchain as the plain `editor` job for a
# sanitizer finding that can't be blamed on a compiler difference.
CC: gcc-14
CXX: g++-14
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
# See the "editor" job's own "Checkout CNA" step comment: bumped
# 2026-07-27 (SYS-W8-08) to CNA's current develop tip, since the
# old pin predated the ShaderEffect API mesh-craft's source uses.
ref: ac3aaaeb2a5ba27dbd9e22e782c7041e6e40947c
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 \
g++-14 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$"