perf: add wgpu timestamp phase queries #1357
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: CI | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - 'release-please--**' | |
| pull_request: | |
| branches: [ main ] | |
| merge_group: | |
| types: [checks_requested] | |
| permissions: | |
| contents: read | |
| actions: read | |
| pull-requests: read | |
| concurrency: | |
| group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| # sdl2-sys bundled build ships an older SDL2 CMakeLists.txt that uses | |
| # cmake_minimum_required(VERSION 3.1.3). Newer CMake versions (4.0+) | |
| # removed compatibility with policies < 3.5; this env var restores it. | |
| CMAKE_POLICY_VERSION_MINIMUM: "3.5" | |
| jobs: | |
| # Fast sanity checks to fail quickly before heavy matrix jobs | |
| preflight: | |
| name: Preflight (Ubuntu Stable) | |
| runs-on: ubuntu-latest | |
| env: | |
| RUSTC_WRAPPER: sccache | |
| SCCACHE_GHA_ENABLED: "true" | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: rustfmt, clippy | |
| - name: Set up sccache | |
| uses: mozilla-actions/sccache-action@v0.0.10 | |
| - name: Restore Rust cache | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxxf86vm-dev libasound2-dev libudev-dev | |
| - name: Set up Python (for codegen) | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.11' | |
| - name: Validate architecture docs | |
| run: python3 scripts/generate-architecture-docs.py --check | |
| - name: Validate AGENTS.md constraints | |
| run: bash scripts/check-agents-md.sh | |
| - name: Run SDK codegen (generates .g.rs files needed by workspace) | |
| run: | | |
| python codegen/validate_coverage.py | |
| python codegen/gen_csharp.py | |
| python codegen/gen_python.py | |
| python codegen/gen_ts_node.py | |
| python codegen/gen_ts_web.py | |
| python codegen/gen_kotlin.py | |
| - name: Upload shared codegen artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: codegen-generated | |
| path: | | |
| sdks/csharp/generated/ | |
| sdks/python/goudengine/generated/ | |
| sdks/python/goudengine/__init__.py | |
| sdks/typescript/src/generated/ | |
| sdks/typescript/native/src/*.g.rs | |
| sdks/typescript/native/src/lib.rs | |
| if-no-files-found: error | |
| retention-days: 1 | |
| - name: Quick Rust check | |
| run: cargo check --workspace --all-targets | |
| - name: Check formatting | |
| run: | | |
| cargo fmt -p goud-engine-core -- --check | |
| # Format generated napi-rs files (gitignored, no --check needed) | |
| cargo fmt -p goud-engine-node | |
| - name: Run clippy | |
| run: cargo clippy --all-targets --all-features -- -D warnings | |
| # Rust checks and tests | |
| rust-check: | |
| name: Rust ${{ matrix.rust }} on ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| needs: [preflight] | |
| env: | |
| RUSTC_WRAPPER: sccache | |
| SCCACHE_GHA_ENABLED: ${{ (github.event_name != 'pull_request' || (matrix.os == 'ubuntu-latest' && matrix.rust == 'stable' && matrix.lane == 'full')) && 'true' || 'false' }} | |
| strategy: | |
| fail-fast: ${{ github.event_name == 'pull_request' }} | |
| matrix: | |
| include: ${{ fromJSON(github.event_name == 'pull_request' && '[{"os":"ubuntu-latest","rust":"stable","lane":"full","run_windows_native_clippy":false},{"os":"ubuntu-latest","rust":"nightly","lane":"smoke","run_windows_native_clippy":false},{"os":"macos-latest","rust":"stable","lane":"smoke","run_windows_native_clippy":false},{"os":"windows-latest","rust":"stable","lane":"clippy-only","run_windows_native_clippy":true}]' || '[{"os":"ubuntu-latest","rust":"stable","lane":"full","run_windows_native_clippy":false},{"os":"macos-latest","rust":"stable","lane":"full","run_windows_native_clippy":false},{"os":"windows-latest","rust":"stable","lane":"full","run_windows_native_clippy":true},{"os":"ubuntu-latest","rust":"nightly","lane":"smoke","run_windows_native_clippy":false},{"os":"macos-latest","rust":"nightly","lane":"smoke","run_windows_native_clippy":false}]') }} | |
| steps: | |
| - name: Free disk space (Ubuntu) | |
| if: matrix.os == 'ubuntu-latest' && matrix.lane == 'full' | |
| run: | | |
| sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL | |
| sudo docker image prune --all --force || true | |
| df -h / | |
| - uses: actions/checkout@v7 | |
| - name: Download shared codegen artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: codegen-generated | |
| path: sdks | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: ${{ matrix.rust }} | |
| components: clippy | |
| - name: Set up sccache | |
| uses: mozilla-actions/sccache-action@v0.0.10 | |
| - name: Restore Rust cache | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Install system dependencies (Ubuntu) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxxf86vm-dev libasound2-dev libudev-dev libxkbcommon-x11-dev | |
| - name: Run clippy (Windows stable) | |
| if: matrix.run_windows_native_clippy | |
| run: cargo clippy --all-targets --features native -- -D warnings | |
| shell: bash | |
| - name: Nightly check/build smoke | |
| if: matrix.rust == 'nightly' | |
| run: | | |
| cargo check --workspace --all-targets --all-features | |
| cargo build --workspace --all-targets --all-features | |
| - name: Stable smoke checks | |
| if: matrix.rust == 'stable' && matrix.lane == 'smoke' | |
| run: | | |
| cargo check --workspace --all-targets --all-features | |
| cargo test --lib sdk -- --nocapture | |
| cargo test --test ffi_safety -- --nocapture | |
| - name: Stable full suite (non-doc tests) | |
| if: matrix.rust == 'stable' && matrix.lane == 'full' | |
| run: cargo test --workspace --lib --bins --tests -- --nocapture | |
| - name: Headless profile tests | |
| if: matrix.rust == 'stable' && matrix.lane == 'full' && matrix.os == 'ubuntu-latest' | |
| run: cargo test --features headless --lib -- null --nocapture | |
| - name: Documentation tests (once per lane) | |
| if: matrix.rust == 'stable' && matrix.lane == 'full' && matrix.os == 'ubuntu-latest' | |
| run: cargo test --workspace --doc -- --nocapture | |
| # Only run on stable for coverage | |
| - name: Install cargo-tarpaulin | |
| if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && github.event_name == 'merge_group' | |
| uses: taiki-e/install-action@cargo-tarpaulin | |
| - name: Generate coverage | |
| if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && github.event_name == 'merge_group' | |
| run: | | |
| cargo tarpaulin \ | |
| --out xml html \ | |
| --output-dir coverage-report \ | |
| --all-features \ | |
| -p goud-engine-core \ | |
| --timeout 300 \ | |
| --branch \ | |
| --exclude-files "*/build.rs" \ | |
| --exclude-files "*/tests/*" \ | |
| --exclude-files "*/examples/*" \ | |
| --exclude-files "*/ffi/**" \ | |
| --exclude-files "*/sdk.rs" | |
| - name: Check branch coverage threshold (70%) | |
| if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && github.event_name == 'merge_group' && always() | |
| run: | | |
| if [ ! -f coverage-report/cobertura.xml ]; then | |
| echo "WARNING: Coverage report not found, skipping branch check" | |
| exit 0 | |
| fi | |
| BRANCH_RATE=$(python3 -c " | |
| import xml.etree.ElementTree as ET | |
| tree = ET.parse('coverage-report/cobertura.xml') | |
| rate = tree.getroot().attrib.get('branch-rate') | |
| if rate is None: | |
| print('SKIP') | |
| else: | |
| print(f'{float(rate) * 100:.2f}') | |
| ") | |
| if [ "$BRANCH_RATE" = "SKIP" ]; then | |
| echo "WARNING: branch-rate attribute not found in cobertura.xml" | |
| exit 0 | |
| fi | |
| echo "Branch coverage: ${BRANCH_RATE}%" | |
| if python3 -c "exit(0 if float('${BRANCH_RATE}') >= 70.0 else 1)"; then | |
| echo "PASS: Branch coverage meets 70% threshold" | |
| else | |
| echo "WARNING: Branch coverage ${BRANCH_RATE}% is below 70% target (informational)" | |
| fi | |
| - name: Upload coverage report | |
| if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && github.event_name == 'merge_group' && always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-report | |
| path: coverage-report/ | |
| retention-days: 1 | |
| - name: Upload coverage to Codecov | |
| if: matrix.rust == 'stable' && matrix.os == 'ubuntu-latest' && github.event_name == 'merge_group' | |
| uses: codecov/codecov-action@v7 | |
| with: | |
| file: ./coverage-report/cobertura.xml | |
| flags: rust | |
| name: rust-coverage | |
| fail_ci_if_error: false | |
| # Cargo deny check (license/security) | |
| cargo-deny: | |
| name: Cargo Deny Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: EmbarkStudios/cargo-deny-action@v2 | |
| with: | |
| log-level: warn | |
| command: check | |
| arguments: --all-features | |
| # Codegen drift detection — ensures generated SDK code is up to date | |
| codegen-drift-check: | |
| name: Codegen Drift Check | |
| runs-on: ubuntu-latest | |
| needs: [preflight] | |
| env: | |
| RUSTC_WRAPPER: sccache | |
| SCCACHE_GHA_ENABLED: ${{ github.event_name != 'pull_request' && 'true' || 'false' }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Set up sccache | |
| uses: mozilla-actions/sccache-action@v0.0.10 | |
| - name: Restore Rust cache | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxxf86vm-dev libasound2-dev libudev-dev | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.11' | |
| - name: Build (generates ffi_manifest.json) | |
| run: cargo build | |
| - name: Run full codegen pipeline | |
| run: ./codegen.sh | |
| - name: Validate codegen | |
| run: | | |
| python codegen/validate.py | |
| python codegen/validate_coverage.py | |
| - name: Lint layer dependencies | |
| run: cargo run -p lint-layers | |
| - name: Check for codegen drift | |
| run: bash scripts/check-generated-artifacts.sh | |
| - name: Verify SDK READMEs are up to date | |
| run: python3 codegen/gen_sdk_readmes.py --check | |
| # Build native release libraries once per OS and share across SDK jobs | |
| native-release: | |
| name: Native Release Artifact on ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| needs: [preflight] | |
| env: | |
| RUSTC_WRAPPER: sccache | |
| SCCACHE_GHA_ENABLED: ${{ github.event_name != 'pull_request' && 'true' || 'false' }} | |
| strategy: | |
| fail-fast: ${{ github.event_name == 'pull_request' }} | |
| matrix: | |
| os: ${{ fromJSON(github.event_name == 'pull_request' && '["ubuntu-latest","macos-latest"]' || '["ubuntu-latest","macos-latest","windows-latest"]') }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Set up sccache | |
| uses: mozilla-actions/sccache-action@v0.0.10 | |
| - name: Restore Rust cache | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Download shared codegen artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: codegen-generated | |
| path: sdks | |
| - name: Install system dependencies (Ubuntu) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxxf86vm-dev libasound2-dev libudev-dev libxkbcommon-x11-dev | |
| - name: Build native library | |
| run: cargo build --release | |
| - name: Stage native release artifact | |
| run: | | |
| mkdir -p native-release | |
| if [[ "$RUNNER_OS" == "Linux" ]]; then | |
| cp target/release/libgoud_engine.so native-release/ | |
| elif [[ "$RUNNER_OS" == "macOS" ]]; then | |
| cp target/release/libgoud_engine.dylib native-release/ | |
| else | |
| cp target/release/goud_engine.dll native-release/ | |
| fi | |
| shell: bash | |
| - name: Upload native release artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: native-release-${{ matrix.os }} | |
| path: native-release/ | |
| if-no-files-found: error | |
| retention-days: 1 | |
| # Python SDK checks and tests | |
| python-sdk-check: | |
| name: Python SDK on ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| needs: [preflight, native-release] | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest] | |
| python-version: ['3.10', '3.11', '3.12'] | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Download shared codegen artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: codegen-generated | |
| path: sdks | |
| - name: Install system dependencies (Ubuntu) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxxf86vm-dev libasound2-dev libudev-dev libxkbcommon-x11-dev | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Install Python coverage tooling | |
| if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11' | |
| run: python -m pip install coverage | |
| - name: Download native release artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: native-release-${{ matrix.os }} | |
| path: native-release | |
| - name: Set up library path (Ubuntu) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: echo "LD_LIBRARY_PATH=${{ github.workspace }}/native-release:$LD_LIBRARY_PATH" >> $GITHUB_ENV | |
| - name: Set up library path (macOS) | |
| if: matrix.os == 'macos-latest' | |
| run: echo "DYLD_LIBRARY_PATH=${{ github.workspace }}/native-release:$DYLD_LIBRARY_PATH" >> $GITHUB_ENV | |
| - name: Run Python SDK tests | |
| env: | |
| PYTHONPATH: ${{ github.workspace }}/sdks/python | |
| GOUD_ENGINE_LIB: ${{ github.workspace }}/native-release | |
| run: | | |
| python --version | |
| python sdks/python/test_bindings.py | |
| python sdks/python/test_network_loopback.py | |
| - name: Test Python demo imports | |
| env: | |
| PYTHONPATH: ${{ github.workspace }}/sdks/python | |
| GOUD_ENGINE_LIB: ${{ github.workspace }}/native-release | |
| run: | | |
| cd examples/python | |
| python << 'EOF' | |
| import sys | |
| sys.path.insert(0, '../../sdks/python') | |
| from goudengine import ( | |
| GoudGame, Entity, Transform2D, Sprite, Vec2, Color | |
| ) | |
| print('Python SDK imports successful') | |
| # Basic component tests | |
| t = Transform2D.from_position(100, 200) | |
| print(f'Transform2D: {t}') | |
| s = Sprite(texture_handle=42) | |
| print(f'Sprite: {s}') | |
| print('All Python SDK basic tests passed!') | |
| EOF | |
| - name: Generate Python coverage report | |
| if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11' | |
| env: | |
| PYTHONPATH: ${{ github.workspace }}/sdks/python | |
| GOUD_ENGINE_LIB: ${{ github.workspace }}/native-release | |
| run: | | |
| python -m coverage erase | |
| python -m coverage run --source=sdks/python/goudengine sdks/python/test_bindings.py | |
| python -m coverage run --append --source=sdks/python/goudengine sdks/python/test_network_loopback.py | |
| python -m coverage report --fail-under=80 | |
| python -m coverage xml -o sdks/python/coverage.xml | |
| - name: Upload Python coverage results | |
| if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: python-coverage | |
| path: sdks/python/coverage.xml | |
| if-no-files-found: error | |
| retention-days: 3 | |
| # .NET SDK checks and tests | |
| dotnet-check: | |
| name: .NET SDK on ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| needs: [preflight, native-release] | |
| strategy: | |
| fail-fast: ${{ github.event_name == 'pull_request' }} | |
| matrix: | |
| os: ${{ fromJSON(github.event_name == 'pull_request' && '["ubuntu-latest","macos-latest"]' || '["ubuntu-latest","macos-latest","windows-latest"]') }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Download shared codegen artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: codegen-generated | |
| path: sdks | |
| - name: Install system dependencies (Ubuntu) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxxf86vm-dev libasound2-dev libudev-dev | |
| - name: Download native release artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: native-release-${{ matrix.os }} | |
| path: native-release | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: '8.0.x' | |
| - name: Set up library path (Ubuntu) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: echo "LD_LIBRARY_PATH=${{ github.workspace }}/native-release:$LD_LIBRARY_PATH" >> $GITHUB_ENV | |
| - name: Set up library path (macOS) | |
| if: matrix.os == 'macos-latest' | |
| run: echo "DYLD_LIBRARY_PATH=${{ github.workspace }}/native-release:$DYLD_LIBRARY_PATH" >> $GITHUB_ENV | |
| - name: Cache NuGet packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.nuget/packages | |
| key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }} | |
| restore-keys: | | |
| ${{ runner.os }}-nuget- | |
| - name: Restore dependencies | |
| working-directory: sdks/csharp | |
| run: dotnet restore ../csharp.tests/GoudEngine.Tests.csproj | |
| - name: Build | |
| working-directory: sdks/csharp | |
| run: dotnet build ../csharp.tests/GoudEngine.Tests.csproj --no-restore --configuration Release | |
| - name: Copy native library to test directory (Ubuntu) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: cp native-release/libgoud_engine.so sdks/csharp.tests/bin/Release/net8.0/ | |
| - name: Copy native library to test directory (macOS) | |
| if: matrix.os == 'macos-latest' | |
| run: cp native-release/libgoud_engine.dylib sdks/csharp.tests/bin/Release/net8.0/ | |
| - name: Copy native library to test directory (Windows) | |
| if: matrix.os == 'windows-latest' | |
| run: copy native-release\goud_engine.dll sdks\csharp.tests\bin\Release\net8.0\libgoud_engine.dll | |
| - name: Test | |
| working-directory: sdks/csharp | |
| run: dotnet test ../csharp.tests/GoudEngine.Tests.csproj --no-build --configuration Release --verbosity normal --logger "trx;LogFileName=test-results.trx" /p:CollectCoverage=true /p:CoverletOutput=../csharp.tests/TestResults/${{ matrix.os }}/coverage/ /p:CoverletOutputFormat=cobertura | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: dotnet-test-results-${{ matrix.os }} | |
| path: '**/test-results.trx' | |
| retention-days: 3 | |
| - name: Upload C# coverage results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: dotnet-coverage-${{ matrix.os }} | |
| path: 'sdks/csharp.tests/TestResults/${{ matrix.os }}/coverage/coverage.cobertura.xml' | |
| retention-days: 3 | |
| - name: Upload C# coverage to Codecov | |
| if: matrix.os == 'ubuntu-latest' | |
| uses: codecov/codecov-action@v7 | |
| with: | |
| file: sdks/csharp.tests/TestResults/${{ matrix.os }}/coverage/coverage.cobertura.xml | |
| flags: dotnet | |
| name: dotnet-coverage | |
| fail_ci_if_error: false | |
| # Build check to ensure everything compiles together | |
| integration-build: | |
| name: Integration Build Check | |
| runs-on: ${{ matrix.os }} | |
| # Intentionally parallelized for faster feedback; ci-success still gates SDK jobs. | |
| needs: [preflight] | |
| env: | |
| RUSTC_WRAPPER: sccache | |
| SCCACHE_GHA_ENABLED: ${{ github.event_name != 'pull_request' && 'true' || 'false' }} | |
| strategy: | |
| fail-fast: ${{ github.event_name == 'pull_request' }} | |
| matrix: | |
| os: [ubuntu-latest, macos-latest] | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Download shared codegen artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: codegen-generated | |
| path: sdks | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Set up sccache | |
| uses: mozilla-actions/sccache-action@v0.0.10 | |
| - name: Restore Rust cache | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: '8.0.x' | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.11' | |
| - name: Install system dependencies (Ubuntu) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxxf86vm-dev libasound2-dev libudev-dev | |
| - name: Run full build script | |
| run: | | |
| chmod +x build.sh | |
| ./build.sh --local | |
| - name: Verify build artifacts | |
| run: | | |
| # Check Rust library exists | |
| if [[ "$RUNNER_OS" == "macOS" ]]; then | |
| if [[ "$RUNNER_ARCH" == "ARM64" ]]; then | |
| test -f sdks/csharp/runtimes/osx-arm64/native/libgoud_engine.dylib | |
| else | |
| test -f sdks/csharp/runtimes/osx-x64/native/libgoud_engine.dylib | |
| fi | |
| elif [[ "$RUNNER_OS" == "Linux" ]]; then | |
| test -f sdks/csharp/runtimes/linux-x64/native/libgoud_engine.so | |
| fi | |
| # Check .NET package exists | |
| test -f sdks/nuget_package_output/GoudEngine.*.nupkg | |
| - name: Verify Python SDK can import | |
| env: | |
| PYTHONPATH: ${{ github.workspace }}/sdks/python | |
| LD_LIBRARY_PATH: ${{ github.workspace }}/target/debug:${{ env.LD_LIBRARY_PATH }} | |
| DYLD_LIBRARY_PATH: ${{ github.workspace }}/target/debug:${{ env.DYLD_LIBRARY_PATH }} | |
| run: | | |
| python -c "from goudengine import GoudGame, Entity, Transform2D, Sprite; print('Python SDK integration check passed')" | |
| # TypeScript SDK — native addon build + tests | |
| typescript-sdk-native: | |
| name: TS SDK Native on ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| needs: [preflight] | |
| env: | |
| RUSTC_WRAPPER: sccache | |
| SCCACHE_GHA_ENABLED: ${{ (github.event_name != 'pull_request' || matrix.os == 'ubuntu-latest') && 'true' || 'false' }} | |
| strategy: | |
| fail-fast: ${{ github.event_name == 'pull_request' }} | |
| matrix: | |
| os: ${{ fromJSON(github.event_name == 'pull_request' && '["ubuntu-latest","macos-latest"]' || '["ubuntu-latest","macos-latest","windows-latest"]') }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Download shared codegen artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: codegen-generated | |
| path: sdks | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Set up sccache | |
| uses: mozilla-actions/sccache-action@v0.0.10 | |
| - name: Restore Rust cache | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| cache-dependency-path: sdks/typescript/package-lock.json | |
| - name: Install system dependencies (Ubuntu) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxxf86vm-dev libasound2-dev libudev-dev libxkbcommon-x11-dev | |
| - name: Install npm dependencies | |
| working-directory: sdks/typescript | |
| run: npm ci | |
| - name: Install Playwright Chromium | |
| working-directory: sdks/typescript | |
| run: npx playwright install --with-deps chromium | |
| - name: Create native typing shim (PR macOS smoke lane) | |
| if: github.event_name == 'pull_request' && matrix.os != 'ubuntu-latest' | |
| working-directory: sdks/typescript | |
| run: | | |
| cat > index.d.ts <<'EOF' | |
| export type GameConfig = { | |
| width?: number; | |
| height?: number; | |
| title?: string; | |
| }; | |
| export class GoudGame { | |
| constructor(config?: GameConfig); | |
| [key: string]: any; | |
| } | |
| export class GoudContext { | |
| constructor(); | |
| [key: string]: any; | |
| } | |
| export class Entity { | |
| [key: string]: any; | |
| } | |
| export class UiManager { | |
| constructor(); | |
| [key: string]: any; | |
| } | |
| EOF | |
| - name: Build native addon | |
| if: github.event_name != 'pull_request' || matrix.os == 'ubuntu-latest' | |
| working-directory: sdks/typescript | |
| run: npm run build:native | |
| - name: Build TypeScript (Node) | |
| working-directory: sdks/typescript | |
| run: npm run build:ts | |
| - name: Type-check TypeScript examples | |
| run: | | |
| cd examples/typescript/flappy_bird && npm install && npx tsc --noEmit | |
| - name: Run smoke tests (Ubuntu with virtual display) | |
| if: matrix.os == 'ubuntu-latest' | |
| working-directory: sdks/typescript | |
| run: xvfb-run npm run test:native | |
| - name: Generate TypeScript coverage report | |
| if: matrix.os == 'ubuntu-latest' | |
| working-directory: sdks/typescript | |
| run: xvfb-run npm run coverage:native | |
| - name: Run smoke tests (macOS/Windows — skip GLFW window tests in headless CI) | |
| if: matrix.os != 'ubuntu-latest' | |
| working-directory: sdks/typescript | |
| run: | | |
| echo "Smoke tests require a display (GLFW window). Build verified above." | |
| echo "Full smoke tests run on ubuntu-latest with xvfb." | |
| - name: Upload TypeScript coverage results | |
| if: matrix.os == 'ubuntu-latest' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ts-coverage | |
| path: sdks/typescript/coverage/native/cobertura-coverage.xml | |
| if-no-files-found: error | |
| retention-days: 3 | |
| - name: Upload native addon | |
| if: github.event_name != 'pull_request' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ts-native-${{ matrix.os }} | |
| path: sdks/typescript/*.node | |
| retention-days: 1 | |
| # TypeScript SDK — wasm build (Ubuntu only, one platform sufficient) | |
| typescript-sdk-wasm: | |
| name: TS SDK Wasm Build | |
| if: github.event_name == 'pull_request' || github.event_name == 'merge_group' | |
| runs-on: ubuntu-latest | |
| needs: [preflight] | |
| env: | |
| RUSTC_WRAPPER: sccache | |
| SCCACHE_GHA_ENABLED: ${{ github.event_name != 'pull_request' && 'true' || 'false' }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Download shared codegen artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: codegen-generated | |
| path: sdks | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: wasm32-unknown-unknown | |
| - name: Set up sccache | |
| uses: mozilla-actions/sccache-action@v0.0.10 | |
| - name: Restore Rust cache | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| cache-dependency-path: sdks/typescript/package-lock.json | |
| - name: Install pinned wasm-pack | |
| env: | |
| WASM_PACK_VERSION: "0.13.1" | |
| run: | | |
| curl -sSfL "https://github.com/rustwasm/wasm-pack/releases/download/v${WASM_PACK_VERSION}/wasm-pack-v${WASM_PACK_VERSION}-x86_64-unknown-linux-musl.tar.gz" -o /tmp/wasm-pack.tar.gz | |
| tar -xzf /tmp/wasm-pack.tar.gz -C /tmp | |
| sudo install /tmp/wasm-pack-v${WASM_PACK_VERSION}-x86_64-unknown-linux-musl/wasm-pack /usr/local/bin/wasm-pack | |
| wasm-pack --version | |
| - name: Install npm dependencies | |
| working-directory: sdks/typescript | |
| run: npm ci | |
| - name: Install Playwright Chromium | |
| working-directory: sdks/typescript | |
| run: npx playwright install --with-deps chromium | |
| - name: Build wasm module | |
| working-directory: sdks/typescript | |
| # wasm-pack already runs wasm-opt for this bundle; a second manual pass | |
| # broke Chromium's externref table initialization in the runtime smoke. | |
| run: npm run build:wasm | |
| - name: Build web TypeScript | |
| working-directory: sdks/typescript | |
| run: npm run build:ts:web | |
| - name: Type-check web sources | |
| working-directory: sdks/typescript | |
| run: npx tsc -p tsconfig.web.json --noEmit | |
| - name: Generate TypeScript web coverage report | |
| working-directory: sdks/typescript | |
| run: npm run coverage:web-runtime | |
| - name: Verify wasm output structure | |
| working-directory: sdks/typescript | |
| run: | | |
| echo "=== Wasm output ===" | |
| ls -la wasm/ | |
| echo "=== Web dist output ===" | |
| find dist/web/ -name "*.js" | head -20 || echo "No JS files in dist/web/" | |
| test -f wasm/goud_engine_bg.wasm | |
| test -f wasm/goud_engine.js | |
| - name: Upload TypeScript web coverage results | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ts-web-coverage | |
| path: sdks/typescript/coverage/web/cobertura-coverage.xml | |
| if-no-files-found: error | |
| retention-days: 3 | |
| - name: Upload wasm artifacts | |
| if: github.event_name != 'pull_request' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ts-wasm | |
| path: | | |
| sdks/typescript/wasm/*.wasm | |
| sdks/typescript/wasm/*.js | |
| sdks/typescript/wasm/*.d.ts | |
| retention-days: 1 | |
| # C++ SDK tests (non-GL only, headless CI safe) | |
| # Windows C++ CI is excluded: MSVC support is scaffolded in FindGoudEngine.cmake | |
| # but not yet validated in CI. Add windows-latest when a Windows native-release | |
| # artifact is reliably available on PRs. | |
| cpp-tests: | |
| name: C++ SDK Tests on ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| needs: [preflight, native-release] | |
| strategy: | |
| fail-fast: ${{ github.event_name == 'pull_request' }} | |
| matrix: | |
| os: [ubuntu-latest, macos-latest] | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Download native release artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: native-release-${{ matrix.os }} | |
| path: native-release | |
| - name: Stage native library | |
| run: | | |
| mkdir -p target/release target/release/deps | |
| cp native-release/* target/release/ | |
| cp native-release/* target/release/deps/ | |
| shell: bash | |
| - name: Install system dependencies (Ubuntu) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y cmake | |
| - name: Configure C++ tests | |
| run: | | |
| cmake -B sdks/cpp/build \ | |
| -DGOUD_BUILD_TESTS=ON \ | |
| -DCMAKE_BUILD_TYPE=Release \ | |
| sdks/cpp | |
| - name: Build C++ tests | |
| run: cmake --build sdks/cpp/build --config Release | |
| - name: Run non-GL C++ tests | |
| run: sdks/cpp/build/tests/goud_cpp_tests "~[gl_required]" | |
| # Kotlin SDK tests | |
| kotlin-sdk-test: | |
| name: Kotlin SDK Test | |
| runs-on: ubuntu-latest | |
| needs: [preflight] | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.11' | |
| - name: Set up JDK 17 | |
| uses: actions/setup-java@v5 | |
| with: | |
| distribution: temurin | |
| java-version: '17' | |
| - name: Generate Kotlin SDK | |
| run: python codegen/gen_kotlin.py | |
| - name: Run Kotlin SDK tests | |
| working-directory: sdks/kotlin | |
| run: ./gradlew test --no-daemon -x buildNative | |
| sandbox-parity: | |
| name: Sandbox Recovery Smoke | |
| runs-on: ubuntu-latest | |
| needs: [preflight] | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y xvfb libgl1-mesa-dev libglu1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxxf86vm-dev libasound2-dev libudev-dev libxkbcommon-x11-dev | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: wasm32-unknown-unknown | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: '8.0.x' | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.11' | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| cache-dependency-path: | | |
| sdks/typescript/package-lock.json | |
| examples/typescript/sandbox/package-lock.json | |
| - name: Install pinned wasm-pack | |
| env: | |
| WASM_PACK_VERSION: "0.13.1" | |
| run: | | |
| cargo install wasm-pack --version "${WASM_PACK_VERSION}" --locked | |
| wasm-pack --version | |
| - name: Run Rust Sandbox (default smoke) | |
| env: | |
| GOUD_SANDBOX_SMOKE_SECONDS: "1" | |
| run: xvfb-run -a cargo run -p sandbox | |
| - name: Build native Python library for sandbox smoke | |
| run: | | |
| cargo build -p goud-engine-core | |
| test -f target/debug/libgoud_engine.so | |
| - name: Run Python Sandbox (default smoke) | |
| env: | |
| GOUD_ENGINE_LIB: ${{ github.workspace }}/target/debug/libgoud_engine.so | |
| GOUD_SANDBOX_SMOKE_SECONDS: "1" | |
| PYTHONPATH: ${{ github.workspace }}/sdks/python | |
| run: xvfb-run -a python3 examples/python/sandbox.py | |
| - name: Run native peer smoke (Rust host + Python client) | |
| env: | |
| GOUD_SANDBOX_SMOKE_SECONDS: "6" | |
| run: bash scripts/sandbox-peer-smoke.sh | |
| - name: Run C# Sandbox (2D/3D/Hybrid smoke) | |
| env: | |
| GOUD_SANDBOX_SMOKE_SECONDS: "1" | |
| LD_LIBRARY_PATH: ${{ github.workspace }}/target/debug:${{ env.LD_LIBRARY_PATH }} | |
| run: | | |
| cd examples/csharp/sandbox | |
| dotnet build | |
| xvfb-run -a env DOTNET_ROLL_FORWARD=Major GOUD_SANDBOX_START_MODE=1 dotnet run --no-build | |
| xvfb-run -a env DOTNET_ROLL_FORWARD=Major GOUD_SANDBOX_START_MODE=2 dotnet run --no-build | |
| xvfb-run -a env DOTNET_ROLL_FORWARD=Major GOUD_SANDBOX_START_MODE=3 dotnet run --no-build | |
| - name: Run TypeScript Sandbox (desktop + web smoke) | |
| run: | | |
| cd examples/typescript/sandbox | |
| npm ci | |
| npx playwright install --with-deps chromium | |
| npm run build:web | |
| npm run desktop:check | |
| xvfb-run -a env GOUD_SANDBOX_SMOKE_SECONDS=1 npm run desktop | |
| npm run smoke:web | |
| node -e "import('./dist/sandbox.js').then(()=>console.log('sandbox dist import ok'))" | |
| # Go SDK tests (needs native library for CGO linking) | |
| go-sdk-check: | |
| name: Go SDK Tests | |
| runs-on: ubuntu-latest | |
| needs: [preflight, native-release] | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Set up Go | |
| uses: actions/setup-go@v6 | |
| with: | |
| go-version: '1.22' | |
| - name: Download native release artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: native-release-ubuntu-latest | |
| path: native-release | |
| - name: Stage native library | |
| run: | | |
| mkdir -p target/release | |
| cp native-release/* target/release/ | |
| - name: Build Go SDK (verify compilation) | |
| working-directory: sdks/go | |
| run: go build ./... | |
| - name: Vet Go SDK | |
| working-directory: sdks/go | |
| run: go vet ./... | |
| # Swift SDK tests (macOS only, pure-Swift value type tests) | |
| swift-sdk-check: | |
| name: Swift SDK Tests | |
| runs-on: macos-latest | |
| needs: [preflight, native-release] | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Download native release artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: native-release-macos-latest | |
| path: native-release | |
| - name: Stage native library | |
| run: | | |
| mkdir -p target/release | |
| cp native-release/* target/release/ | |
| - name: Run Swift tests | |
| working-directory: sdks/swift | |
| run: swift test | |
| continue-on-error: true | |
| ios-build-pipeline: | |
| name: iOS Build Pipeline | |
| runs-on: macos-latest | |
| if: github.event_name != 'pull_request' | |
| needs: [preflight] | |
| timeout-minutes: 35 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Restore Rust cache | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Build iOS static libraries | |
| run: ./platform/ios/build-ios.sh | |
| - name: Build iOS template for simulator | |
| run: | | |
| xcodebuild \ | |
| -project platform/ios/template/MobileTemplate.xcodeproj \ | |
| -scheme MobileTemplate \ | |
| -configuration Debug \ | |
| -sdk iphonesimulator \ | |
| -destination 'generic/platform=iOS Simulator' \ | |
| CODE_SIGNING_ALLOWED=NO \ | |
| build | |
| - name: Build iOS Flappy Bird example for simulator | |
| env: | |
| GOUD_ENGINE_IOS_LIB_DIR: ${{ github.workspace }}/platform/ios/build/simulator | |
| working-directory: examples/ios/flappy_bird | |
| run: | | |
| # Resolve SPM dependencies and build for iOS Simulator | |
| xcodebuild \ | |
| -scheme FlappyBird \ | |
| -configuration Debug \ | |
| -sdk iphonesimulator \ | |
| -destination 'generic/platform=iOS Simulator' \ | |
| -derivedDataPath .build/derivedData \ | |
| CODE_SIGNING_ALLOWED=NO \ | |
| build 2>&1 || { | |
| echo "xcodebuild failed, trying swift build as fallback..." | |
| swift build \ | |
| --sdk "$(xcrun --sdk iphonesimulator --show-sdk-path)" \ | |
| --triple arm64-apple-ios-simulator \ | |
| -Xlinker -L"${GOUD_ENGINE_IOS_LIB_DIR}" | |
| } | |
| - name: Shutdown iOS Simulator | |
| if: always() | |
| run: xcrun simctl shutdown booted || true | |
| android-build-pipeline: | |
| name: Android Build Pipeline | |
| runs-on: ubuntu-latest | |
| if: github.event_name != 'pull_request' | |
| needs: [preflight] | |
| timeout-minutes: 25 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Restore Rust cache | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Set up JDK 17 | |
| uses: actions/setup-java@v5 | |
| with: | |
| distribution: temurin | |
| java-version: '17' | |
| - name: Set up Android SDK | |
| uses: android-actions/setup-android@v4 | |
| - name: Install Android build tooling | |
| run: sdkmanager "platforms;android-34" "build-tools;34.0.0" "ndk;27.2.12479018" | |
| - name: Build Android shared libraries | |
| env: | |
| ANDROID_NDK_HOME: ${{ env.ANDROID_SDK_ROOT }}/ndk/27.2.12479018 | |
| ANDROID_NDK_ROOT: ${{ env.ANDROID_SDK_ROOT }}/ndk/27.2.12479018 | |
| run: ./platform/android/build-android.sh | |
| - name: Build Android template | |
| working-directory: platform/android/template | |
| run: ./gradlew assembleDebug --no-daemon | |
| - name: Copy native libraries to Flappy Bird example | |
| run: | | |
| mkdir -p examples/android/flappy_bird/app/src/main/jniLibs | |
| cp -r platform/android/template/app/src/main/jniLibs/* \ | |
| examples/android/flappy_bird/app/src/main/jniLibs/ | |
| - name: Build Android Flappy Bird example | |
| working-directory: examples/android/flappy_bird | |
| env: | |
| GOUD_REPO_ROOT: ${{ github.workspace }} | |
| run: ./gradlew assembleDebug --no-daemon | |
| - name: Enable KVM group permissions | |
| 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 | |
| - name: Smoke test on Android emulator | |
| uses: reactivecircus/android-emulator-runner@v2 | |
| with: | |
| api-level: 30 | |
| arch: x86_64 | |
| force-avd-creation: false | |
| emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio | |
| disable-animations: true | |
| script: | | |
| adb install examples/android/flappy_bird/app/build/outputs/apk/debug/app-debug.apk | |
| adb shell am start -n com.goudengine.flappybird/.MainActivity | |
| sleep 5 | |
| adb exec-out screencap -p > android-smoke-test.png | |
| # Verify the app was installed and launched (may crash due to no GPU in CI) | |
| adb shell pm list packages | grep -q "com.goudengine.flappybird" | |
| - name: Upload Android smoke test screenshot | |
| if: failure() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: android-smoke-screenshot | |
| path: android-smoke-test.png | |
| retention-days: 1 | |
| # C SDK tests (CMake-based, needs native library) | |
| c-sdk-check: | |
| name: C SDK Tests on ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| needs: [preflight, native-release] | |
| strategy: | |
| fail-fast: ${{ github.event_name == 'pull_request' }} | |
| matrix: | |
| os: [ubuntu-latest, macos-latest] | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Download native release artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: native-release-${{ matrix.os }} | |
| path: native-release | |
| - name: Stage native library | |
| run: | | |
| mkdir -p target/release | |
| cp native-release/* target/release/ | |
| shell: bash | |
| - name: Stage generated C header | |
| run: | | |
| cp codegen/generated/goud_engine.h sdks/c/include/goud_engine.h | |
| shell: bash | |
| - name: Install system dependencies (Ubuntu) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y cmake | |
| - name: Configure C tests | |
| run: cmake -B sdks/c/tests/build -S sdks/c/tests -DCMAKE_BUILD_TYPE=Release | |
| - name: Build C tests | |
| run: cmake --build sdks/c/tests/build --config Release | |
| - name: Run C tests | |
| run: ctest --test-dir sdks/c/tests/build --output-on-failure | |
| continue-on-error: true | |
| # Lua SDK tests (pure-Lua constant validation, no native library needed) | |
| lua-sdk-check: | |
| name: Lua SDK Tests | |
| runs-on: ubuntu-latest | |
| needs: [preflight] | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install Lua | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y lua5.4 | |
| - name: Run Lua tests | |
| working-directory: sdks/lua/luarocks | |
| run: lua5.4 test_constants.lua | |
| clean-room-regeneration: | |
| name: Clean Room Regeneration | |
| runs-on: ubuntu-latest | |
| if: github.event_name != 'pull_request' | |
| needs: [preflight] | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libgl1-mesa-dev libglu1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxxf86vm-dev libasound2-dev libudev-dev | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.11' | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: '8.0.x' | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| cache-dependency-path: | | |
| sdks/typescript/package-lock.json | |
| - name: Install mdBook | |
| run: | | |
| mkdir -p "$HOME/.cargo/bin" | |
| tag=$(curl -sI https://github.com/rust-lang/mdBook/releases/latest | grep -i '^location:' | sed 's|.*/tag/||;s/\r//') | |
| curl -sSL "https://github.com/rust-lang/mdBook/releases/download/${tag}/mdbook-${tag}-x86_64-unknown-linux-gnu.tar.gz" \ | |
| | tar -xz -C "$HOME/.cargo/bin" | |
| echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" | |
| - name: Install pdoc | |
| run: pip install pdoc | |
| - name: Install DocFX | |
| run: | | |
| dotnet tool install -g docfx | |
| echo "$HOME/.dotnet/tools" >> "$GITHUB_PATH" | |
| - name: Verify clean-room regeneration | |
| run: bash scripts/clean-room-regenerate.sh --docs | |
| # Final status check | |
| ci-success: | |
| name: CI Success | |
| if: always() | |
| needs: [preflight, rust-check, cargo-deny, codegen-drift-check, native-release, dotnet-check, python-sdk-check, integration-build, typescript-sdk-native, typescript-sdk-wasm, cpp-tests, kotlin-sdk-test, go-sdk-check, swift-sdk-check, ios-build-pipeline, android-build-pipeline, c-sdk-check, lua-sdk-check, sandbox-parity, clean-room-regeneration] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check all jobs | |
| run: | | |
| check_job() { | |
| local name="$1" | |
| local result="$2" | |
| local allow_skipped="$3" | |
| if [[ "$result" == "success" ]]; then | |
| echo "$name: success" | |
| return 0 | |
| fi | |
| if [[ "$allow_skipped" == "true" && ( "$result" == "skipped" || "$result" == "cancelled" ) ]]; then | |
| echo "$name: $result (allowed)" | |
| return 0 | |
| fi | |
| echo "$name: unexpected result '$result'" | |
| return 1 | |
| } | |
| EVENT="${{ github.event_name }}" | |
| ALLOW_FASTLANE_SKIPPED="false" | |
| ALLOW_RUST_SKIPPED="false" | |
| ALLOW_PUSH_SKIPPED="false" | |
| ALLOW_HEAVY_SKIPPED="false" | |
| if [[ "$EVENT" == "pull_request" ]]; then | |
| ALLOW_FASTLANE_SKIPPED="true" | |
| ALLOW_RUST_SKIPPED="true" | |
| ALLOW_HEAVY_SKIPPED="true" | |
| fi | |
| if [[ "$EVENT" == "push" ]]; then | |
| ALLOW_RUST_SKIPPED="true" | |
| ALLOW_PUSH_SKIPPED="true" | |
| fi | |
| FAIL=0 | |
| check_job "preflight" "${{ needs.preflight.result }}" "false" || FAIL=1 | |
| check_job "rust-check" "${{ needs.rust-check.result }}" "$ALLOW_RUST_SKIPPED" || FAIL=1 | |
| check_job "cargo-deny" "${{ needs.cargo-deny.result }}" "false" || FAIL=1 | |
| check_job "codegen-drift-check" "${{ needs.codegen-drift-check.result }}" "false" || FAIL=1 | |
| check_job "native-release" "${{ needs.native-release.result }}" "$ALLOW_FASTLANE_SKIPPED" || FAIL=1 | |
| check_job "dotnet-check" "${{ needs.dotnet-check.result }}" "$ALLOW_FASTLANE_SKIPPED" || FAIL=1 | |
| check_job "python-sdk-check" "${{ needs.python-sdk-check.result }}" "$ALLOW_FASTLANE_SKIPPED" || FAIL=1 | |
| check_job "integration-build" "${{ needs.integration-build.result }}" "$ALLOW_FASTLANE_SKIPPED" || FAIL=1 | |
| check_job "typescript-sdk-native" "${{ needs.typescript-sdk-native.result }}" "$ALLOW_FASTLANE_SKIPPED" || FAIL=1 | |
| check_job "typescript-sdk-wasm" "${{ needs.typescript-sdk-wasm.result }}" "$ALLOW_PUSH_SKIPPED" || FAIL=1 | |
| check_job "cpp-tests" "${{ needs.cpp-tests.result }}" "$ALLOW_FASTLANE_SKIPPED" || FAIL=1 | |
| check_job "kotlin-sdk-test" "${{ needs.kotlin-sdk-test.result }}" "false" || FAIL=1 | |
| check_job "go-sdk-check" "${{ needs.go-sdk-check.result }}" "$ALLOW_FASTLANE_SKIPPED" || FAIL=1 | |
| check_job "swift-sdk-check" "${{ needs.swift-sdk-check.result }}" "$ALLOW_FASTLANE_SKIPPED" || FAIL=1 | |
| check_job "ios-build-pipeline" "${{ needs.ios-build-pipeline.result }}" "$ALLOW_HEAVY_SKIPPED" || FAIL=1 | |
| check_job "android-build-pipeline" "${{ needs.android-build-pipeline.result }}" "$ALLOW_HEAVY_SKIPPED" || FAIL=1 | |
| check_job "c-sdk-check" "${{ needs.c-sdk-check.result }}" "$ALLOW_FASTLANE_SKIPPED" || FAIL=1 | |
| check_job "lua-sdk-check" "${{ needs.lua-sdk-check.result }}" "false" || FAIL=1 | |
| check_job "sandbox-parity" "${{ needs.sandbox-parity.result }}" "false" || FAIL=1 | |
| check_job "clean-room-regeneration" "${{ needs.clean-room-regeneration.result }}" "$ALLOW_HEAVY_SKIPPED" || FAIL=1 | |
| if [[ "$FAIL" -ne 0 ]]; then | |
| echo "One or more jobs failed" | |
| exit 1 | |
| fi | |
| echo "All checks passed!" |