Repository navigation
Port: stop blending from motion sets whose memory was released #205
Workflow file for this run
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
| name: PC builds | |
| on: | |
| push: | |
| branches: [master] | |
| pull_request: | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| build: | |
| name: Build and test | |
| runs-on: ubuntu-26.04 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| submodules: true | |
| fetch-depth: 0 | |
| - name: Select the PAL_TIMING baseline | |
| env: | |
| PR_BASE: ${{ github.event.pull_request.base.sha }} | |
| BEFORE: ${{ github.event.before }} | |
| EVENT: ${{ github.event_name }} | |
| DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} | |
| run: | | |
| base="$PR_BASE" | |
| if [ "$EVENT" = push ] && [ -n "$BEFORE" ] && ! [[ "$BEFORE" =~ ^0+$ ]]; then | |
| base="$BEFORE" | |
| elif [ "$EVENT" != pull_request ]; then | |
| [ -n "$DEFAULT_BRANCH" ] || { echo "No default branch for the PAL_TIMING baseline" >&2; exit 1; } | |
| git fetch --no-tags origin "refs/heads/$DEFAULT_BRANCH" || { echo "Cannot fetch the default branch for the PAL_TIMING baseline" >&2; exit 1; } | |
| base=$(git merge-base HEAD FETCH_HEAD) || { echo "No merge-base with the default branch for the PAL_TIMING baseline" >&2; exit 1; } | |
| fi | |
| git cat-file -e "$base^{commit}" || { echo "Missing PAL_TIMING baseline: $base" >&2; exit 1; } | |
| echo "CT_PAL_TIMING_BASE=$base" >> "$GITHUB_ENV" | |
| # FFmpeg uses Kazarov's pinned build configuration; cxxbridge-cmd is a prebuilt release asset. | |
| - name: Install the toolchain and libraries | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y build-essential clang-22 lld-22 llvm-22 libclang1-22 python3-clang-22 cmake ninja-build glslang-tools \ | |
| mesa-vulkan-drivers vulkan-validationlayers libsdl3-dev libvulkan-dev libgtest-dev nlohmann-json3-dev | |
| # clang++, ld.lld and llvm-readobj under their plain names. | |
| echo "/usr/lib/llvm-22/bin" >> "$GITHUB_PATH" | |
| rustup toolchain install 1.99.0 --profile minimal | |
| rustup default 1.99.0 | |
| tools/ci/prebuilt-deps.sh linux-x64 | |
| # Lavapipe renders on the CPU, so the unit tests' per-case limit is widened from its 5 second default. | |
| # CT_SYMBOLS=split also writes darkchronicle.debug with objcopy, which the symboliser check reads. | |
| # Debug keeps the Vulkan validation layer and assertions on; the Flatpak is the shipped, Release Linux build. | |
| - name: Configure | |
| run: cmake --preset linux-x64 -DCT_TEST_TIMEOUT=60 -DCT_PAL_TIMING_BASE="$CT_PAL_TIMING_BASE" -DCT_SYMBOLS=split | |
| - name: Build | |
| run: cmake --build --preset linux-x64 | |
| # Truncations.Check and Records.Check exit 77 (SKIPPED) without the clang bindings, and a skip passes CI silently. | |
| - name: Check that the pointer checks can run | |
| run: python3 -c "import clang.cindex" | |
| - name: Test | |
| run: ctest --test-dir port/build/pc --output-on-failure -j4 | |
| - name: Test Rust data publisher | |
| run: cargo test --locked --manifest-path tools/kazarov/Cargo.toml | |
| # docs/SYMBOLS.md: the report symboliser, end to end against a small clang-built probe. | |
| - name: Test the crash report symboliser | |
| run: python3 -m unittest discover -s tools/crash -p "test_*.py" -v | |
| # A raw frame at main resolves to main.cpp through the build id'd binary's split debug file. | |
| - name: Check the build id and the split symbols | |
| run: | | |
| llvm-readelf --notes port/build/pc/darkchronicle | grep -q 'Build ID' | |
| llvm-readelf --sections port/build/pc/darkchronicle | grep -q '.gnu_debuglink' | |
| offset=$(llvm-nm port/build/pc/darkchronicle | awk '$3 == "main" { print $1 }') | |
| printf '#0 darkchronicle+0x%s\n' "$offset" > report.txt | |
| python3 tools/crash/symbolize.py report.txt --binary port/build/pc/darkchronicle.debug | tee symbolized.txt | |
| grep -q 'main.cpp:' symbolized.txt | |
| # The VU1 programs are native: their packed CPU halves live only in the test oracles. | |
| - name: Check that no PS2 packing or VU1 layout helper is in the runtime | |
| run: python3 scripts/port/native_gate.py --binary port/build/pc/darkchronicle | |
| # A non-PIE link places the game below 4 GiB, where a pointer truncated to 32 bits still works and hides the bug. | |
| - name: Check that darkchronicle is position-independent | |
| run: | | |
| llvm-readobj --file-headers port/build/pc/darkchronicle | grep -q 'Type: SharedObject' | |
| macos: | |
| name: Build and test (macOS arm64) | |
| runs-on: macos-26 | |
| env: | |
| HOMEBREW_NO_AUTO_UPDATE: 1 | |
| HOMEBREW_NO_INSTALL_CLEANUP: 1 | |
| # These 14 rendering tests read back black frames or wrong pixels only on the hosted runner's virtual | |
| # GPU (Apple Paravirtual device under MoltenVK). The same test binary passes all 14 on Apple Silicon | |
| # hardware (M3, macOS 27.0.1, MoltenVK 1.4.2), and Linux CI gates them on lavapipe. They are reported | |
| # here without failing the job; remove this once the runner's GPU renders them correctly. | |
| MACOS_GPU_REPORT_ONLY: >- | |
| ^(MgDrawPrimRender\.LinearAtlasCellsKeepTopOutlinesWithoutSamplingTheNextCell|MgShadow\.OverlappingCastersShadeTheirUnionNotTheirSum|MgVisual\.DrawManagerPathMatchesDirect|MgVisual\.DirectMaterialUsesItsOwnTextureWrap|MgVisual\.QueuedMaterialRetainsItsOwnTextureWrap|MglibAspect\.MenuFormsHideParkedStatsWithoutClippingEnteringPanel|MglibPresent\.BackBufferCapturePreservesWidePixelsAndHoldsUntilRecaptured|MglibSeam\.ReusedTextureKeyDoesNotSampleRetiredRenderTarget|MenuIconGpu\.ItemDrawSamplesSelectedAtlasCellsInCanonicalAndDisplayFrames|MenuIconGpu\.EffectUsesSelectedBakedRgbaAtlasAndRestoresNormally|MgTextureGpu\.HighResolutionKeepsLogicalCpuStrideAndSpriteBounds|GfxGpuMeshDc2\.RefSphere|GfxGpuMeshDc2\.Prog0CullModeFollowsFlagAndMirror|GfxGpuDisplayList\.PresentationCompositeDoesNotWriteTransparentDepth)$ | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| submodules: true | |
| - name: Install the toolchain and libraries | |
| run: | | |
| brew install llvm lld cmake ninja python glslang sdl3 vulkan-headers vulkan-loader vulkan-tools molten-vk \ | |
| googletest nlohmann-json | |
| rustup toolchain install 1.99.0 --profile minimal --component clippy,rustfmt | |
| rustup default 1.99.0 | |
| tools/ci/prebuilt-deps.sh macos-arm64 | |
| # SDL loads the Vulkan loader by name, and dyld does not search Homebrew's prefix. | |
| echo "SDL_VULKAN_LIBRARY=$(brew --prefix vulkan-loader)/lib/libvulkan.1.dylib" >> "$GITHUB_ENV" | |
| echo "VK_DRIVER_FILES=$(brew --prefix)/etc/vulkan/icd.d/MoltenVK_icd.json" >> "$GITHUB_ENV" | |
| - name: Describe the Vulkan driver | |
| run: | | |
| mkdir -p artifacts | |
| vulkaninfo --summary > artifacts/vulkaninfo.txt 2>&1 || true | |
| cat artifacts/vulkaninfo.txt | |
| # CT_SYMBOLS=split runs dsymutil after the link, for the symbol artifact. | |
| - name: Configure | |
| run: cmake --preset macos-arm64-release -DCT_TEST_TIMEOUT=60 -DCT_SYMBOLS=split | |
| - name: Build | |
| run: cmake --build --preset macos-arm64-release | |
| - name: Test | |
| run: ctest --preset macos-arm64-release -E "$MACOS_GPU_REPORT_ONLY" | |
| - name: Test cases the hosted runner's virtual GPU renders wrongly (report only) | |
| continue-on-error: true | |
| run: ctest --preset macos-arm64-release -R "$MACOS_GPU_REPORT_ONLY" | |
| - name: Test Rust data publisher | |
| run: cargo test --locked --manifest-path tools/kazarov/Cargo.toml | |
| - name: Package the macOS build | |
| run: tar -czf artifacts/chronicletwo-macos-arm64.tar.gz -C port/build/macos-arm64-release darkchronicle scripts Luau-LICENSE.txt -C assets data.zip | |
| - name: Upload the macOS build | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: chronicletwo-macos-arm64 | |
| path: artifacts/chronicletwo-macos-arm64.tar.gz | |
| if-no-files-found: error | |
| # Without Homebrew's llvm on PATH the symboliser falls back to atos, against the dSYM. | |
| - name: Check the dSYM resolves a frame | |
| run: | | |
| address=$(nm port/build/macos-arm64-release/darkchronicle | awk '$3 == "_main" { print $1 }') | |
| printf '#0 darkchronicle+0x%x\n' $((0x$address - 0x100000000)) > report.txt | |
| python3 tools/crash/symbolize.py report.txt --binary port/build/macos-arm64-release/darkchronicle.dSYM | tee symbolized.txt | |
| grep -q 'main.cpp:' symbolized.txt | |
| # docs/SYMBOLS.md: tools/crash/symbolize.py resolves a report from this build with the dSYM. | |
| - name: Package the macOS symbols | |
| run: tar -czf artifacts/chronicletwo-macos-arm64-symbols.tar.gz -C port/build/macos-arm64-release darkchronicle darkchronicle.dSYM | |
| - name: Upload the macOS symbols | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: chronicletwo-macos-arm64-symbols-${{ github.sha }} | |
| path: artifacts/chronicletwo-macos-arm64-symbols.tar.gz | |
| if-no-files-found: error | |
| - name: Upload the Vulkan description | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: macos | |
| path: artifacts/vulkaninfo.txt | |
| if-no-files-found: warn | |
| windows: | |
| name: Build and test (Windows x64) | |
| runs-on: windows-2025 | |
| defaults: | |
| run: | |
| shell: pwsh | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| submodules: true | |
| # Runtime DLLs, including the Vulkan loader, are acquired and bundled by default. | |
| - name: Install the toolchain and libraries | |
| run: | | |
| ./tools/windows/acquire.ps1 -Root $env:RUNNER_TEMP | |
| - name: Configure | |
| run: | | |
| ./tools/windows/configure.ps1 -Root $env:RUNNER_TEMP -BuildDirectory $env:GITHUB_WORKSPACE/port/build/windows-x64-release-tests -Tests -BuildType Release -TestTimeout 60 | |
| - name: Build | |
| run: | | |
| ./tools/windows/build.ps1 -Root $env:RUNNER_TEMP -BuildDirectory $env:GITHUB_WORKSPACE/port/build/windows-x64-release-tests -Tests | |
| if ($LASTEXITCODE) { exit $LASTEXITCODE } | |
| # The runner has no Vulkan device, so cases labelled gpu are excluded. | |
| - name: Test | |
| run: ctest --test-dir port/build/windows-x64-release-tests --output-on-failure -j4 -LE gpu | |
| - name: Test Rust data publisher | |
| run: | | |
| $env:CARGO_HOME = "$env:RUNNER_TEMP/deps/rust/cargo-home" | |
| $rust = "$env:RUNNER_TEMP/deps/rust/1.99.0-gnullvm/bin" | |
| $llvm = "$env:RUNNER_TEMP/deps/llvm/llvm-mingw-20260922-ucrt-x86_64/bin" | |
| $env:PATH = "$rust;$llvm;$env:PATH" | |
| & "$rust/cargo.exe" test --locked --manifest-path tools/kazarov/Cargo.toml | |
| if ($LASTEXITCODE) { exit $LASTEXITCODE } | |
| - name: Package the Windows build | |
| run: | | |
| ./tools/windows/package.ps1 -BuildDirectory port/build/windows-x64-release-tests -Destination chronicletwo-windows-x64.zip | |
| - name: Upload the Windows build | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: chronicletwo-windows-x64 | |
| path: chronicletwo-windows-x64.zip | |
| if-no-files-found: error | |
| - name: Check the executable resolves a frame | |
| run: | | |
| $llvm = "$env:RUNNER_TEMP/deps/llvm/llvm-mingw-20260922-ucrt-x86_64/bin" | |
| $exe = 'port/build/windows-x64-release-tests/darkchronicle.exe' | |
| $address = (& "$llvm/llvm-nm.exe" $exe | Where-Object { $_ -match ' T wmain$' }).Split(' ')[0] | |
| '#0 darkchronicle.exe+0x{0:x}' -f ([Convert]::ToUInt64($address, 16) - 0x140000000) | Set-Content report.txt | |
| python tools/crash/symbolize.py report.txt --binary $exe --llvm-symbolizer "$llvm/llvm-symbolizer.exe" | Tee-Object symbolized.txt | |
| if (!(Select-String -Quiet -Path symbolized.txt -Pattern 'main.cpp:')) { exit 1 } | |
| # docs/SYMBOLS.md: the executables (their DWARF), any PDBs and their build ids, for tools/crash/symbolize.py. | |
| - name: Package the Windows symbols | |
| run: | | |
| ./tools/windows/package-symbols.ps1 -Root $env:RUNNER_TEMP -BuildDirectory port/build/windows-x64-release-tests -Destination chronicletwo-windows-x64-symbols.zip | |
| - name: Upload the Windows symbols | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: chronicletwo-windows-x64-symbols-${{ github.sha }} | |
| path: chronicletwo-windows-x64-symbols.zip | |
| if-no-files-found: error | |
| # docs/FLATPAK.md: the Linux build packaged in Flathub's freedesktop 26.08 image. The manifest uses the | |
| # commit under test as a git source, and the smoke run checks that the packaged binary reaches its data check. | |
| flatpak: | |
| name: Build the Flatpak (Linux x86_64) | |
| runs-on: ubuntu-26.04 | |
| container: | |
| image: ghcr.io/flathub-infra/flatpak-github-actions:freedesktop-26.08 | |
| options: --privileged | |
| env: | |
| MANIFEST: port/flatpak/ci.yml | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| submodules: true | |
| - name: Check that the vendored crates match Kazarov's Cargo.lock | |
| run: | | |
| # The workspace belongs to another user in the container, which git refuses until it is marked safe. | |
| git config --global --add safe.directory "$GITHUB_WORKSPACE" | |
| python3 port/flatpak/cargo_sources.py | |
| git diff --exit-code port/flatpak/cargo-sources.json | |
| - name: Point the manifest at this commit | |
| run: | | |
| awk -v commit="$GITHUB_SHA" ' | |
| /# chronicletwo-source:/ { | |
| print " - type: git" | |
| print " path: ../.." | |
| print " commit: " commit | |
| skip = 1 | |
| next | |
| } | |
| /# chronicletwo-source-end/ { skip = 0 } | |
| !skip { print } | |
| ' port/flatpak/org.themoonpeople.ChronicleTwo.yml > "$MANIFEST" | |
| sed -n '/name: chronicletwo$/,$p' "$MANIFEST" | head -80 | |
| - uses: flatpak/flatpak-github-actions/flatpak-builder@v6 | |
| with: | |
| manifest-path: ${{ env.MANIFEST }} | |
| bundle: chronicletwo.flatpak | |
| artifact-name: chronicletwo-x86_64.flatpak | |
| cache-key: flatpak-builder-${{ hashFiles('port/flatpak/org.themoonpeople.ChronicleTwo.yml', 'port/flatpak/cargo-sources.json') }} | |
| - name: Start darkchronicle without data | |
| run: | | |
| set +e | |
| flatpak build --env=XDG_DATA_HOME=/tmp/xdg flatpak_app darkchronicle --headless --frames 1 > run.txt 2>&1 | |
| status=$? | |
| cat run.txt | |
| echo "darkchronicle exited $status" | |
| [ "$status" -eq 3 ] && grep -q 'No current Dark Chronicle data at /tmp/xdg/chronicletwo/data' run.txt | |
| # The packaged darkchronicle keeps its line tables (the manifest sets no-debuginfo), so it is its own | |
| # symbol file for tools/crash/symbolize.py. | |
| - name: Upload the Flatpak symbols | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: chronicletwo-flatpak-x86_64-symbols-${{ github.sha }} | |
| path: flatpak_app/files/bin/darkchronicle | |
| if-no-files-found: error |