feat: finalize cli plugin integration #12
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: Engine Smoke Tests | ||
| on: | ||
| push: | ||
| branches: [main, 'release/**', 'feat/**'] | ||
| pull_request: | ||
| branches: [main, 'release/**'] | ||
| workflow_dispatch: | ||
| inputs: | ||
| godot-version: | ||
| description: 'Godot CI image tag' | ||
| required: false | ||
| default: '4.3' | ||
| unreal-image: | ||
| description: 'Custom Unreal Engine Docker image (optional, leave empty to skip UE test)' | ||
| required: false | ||
| default: '' | ||
| permissions: | ||
| contents: read | ||
| jobs: | ||
| # ─── Godot — detect + build using third-party image ──────────── | ||
| godot-build: | ||
| name: Godot build | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Set up Bun | ||
| uses: oven-sh/setup-bun@v2 | ||
| with: | ||
| bun-version: latest | ||
| - name: Install dependencies | ||
| run: bun install --frozen-lockfile | ||
| - name: Test Godot engine detection | ||
| run: | | ||
| bun -e " | ||
| import { GodotVersionDetector } from './src/middleware/engine-detection/godot-version-detector.ts'; | ||
| const v = GodotVersionDetector.getGodotVersion('test-projects/godot-minimal'); | ||
| console.log('Detected Godot version:', v); | ||
| if (v !== '4.3') throw new Error('Expected 4.3, got ' + v); | ||
| " | ||
| - name: Export Godot project in container | ||
| run: | | ||
| GODOT_VERSION="${{ github.event.inputs.godot-version || '4.3' }}" | ||
| mkdir -p test-projects/godot-minimal/build | ||
| docker run --rm \ | ||
| -v "${{ github.workspace }}/test-projects/godot-minimal:/project" \ | ||
| -w /project \ | ||
| "barichello/godot-ci:${GODOT_VERSION}" \ | ||
| bash -c ' | ||
| set -euo pipefail | ||
| echo "Godot $(godot --headless --version)" | ||
| mkdir -p build | ||
| if [ -f export_presets.cfg ]; then | ||
| godot --headless --verbose --export-release "Linux/X11" build/game.x86_64 2>&1 || \ | ||
| godot --headless --verbose --export-release "Linux" build/game.x86_64 2>&1 | ||
| else | ||
| echo "No export presets found, running import validation instead" | ||
| godot --headless --import 2>&1 | ||
| fi | ||
| ls -la build/ | ||
| ' | ||
| - name: Verify output | ||
| run: | | ||
| if [ -f test-projects/godot-minimal/build/game.x86_64 ]; then | ||
| echo "Godot binary exported successfully" | ||
| else | ||
| echo "Godot project validated (import-only for minimal project)" | ||
| fi | ||
| # ─── UE — detect + stub build ───────────────────────────────── | ||
| unreal-build: | ||
| name: UE stub build | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Set up Bun | ||
| uses: oven-sh/setup-bun@v2 | ||
| with: | ||
| bun-version: latest | ||
| - name: Install dependencies | ||
| run: bun install --frozen-lockfile | ||
| - name: Test Unreal engine detection | ||
| run: | | ||
| bun -e " | ||
| import { UnrealProjectDetector } from './src/middleware/engine-detection/unreal-project-detector.ts'; | ||
| const v = UnrealProjectDetector.getUnrealVersion('test-projects/unreal-minimal'); | ||
| console.log('Detected UE version:', v); | ||
| if (v !== '5.4') throw new Error('Expected 5.4, got ' + v); | ||
| " | ||
| - name: Build UE CI stub | ||
| run: | | ||
| mkdir -p /tmp/ue-stub-ctx | ||
| cat > /tmp/ue-stub-ctx/RunUAT.sh <<'SCRIPT' | ||
| #!/bin/bash | ||
| echo "=== RunUAT.sh (CI Stub) ===" | ||
| PROJECT="" | ||
| ARCHIVE_DIR="" | ||
| for arg in "$@"; do | ||
| case "$arg" in | ||
| -project=*) PROJECT="${arg#-project=}" ;; | ||
| -archivedirectory=*) ARCHIVE_DIR="${arg#-archivedirectory=}" ;; | ||
| esac | ||
| done | ||
| if [ -n "$PROJECT" ] && [ -f "$PROJECT" ]; then | ||
| echo "Project: $PROJECT" | ||
| cat "$PROJECT" | ||
| fi | ||
| if [ -n "$ARCHIVE_DIR" ]; then | ||
| mkdir -p "$ARCHIVE_DIR" | ||
| echo "{\"engine\":\"unreal\",\"stub\":true}" > "$ARCHIVE_DIR/build-manifest.json" | ||
| fi | ||
| echo "=== Build OK ===" | ||
| SCRIPT | ||
| chmod +x /tmp/ue-stub-ctx/RunUAT.sh | ||
| cat > /tmp/ue-stub-ctx/Dockerfile <<'DOCKERFILE' | ||
| FROM alpine:3.19 | ||
| RUN apk add --no-cache bash | ||
| RUN mkdir -p /home/ue4/UnrealEngine/Engine/Build/BatchFiles | ||
| COPY RunUAT.sh /home/ue4/UnrealEngine/Engine/Build/BatchFiles/RunUAT.sh | ||
| RUN chmod +x /home/ue4/UnrealEngine/Engine/Build/BatchFiles/RunUAT.sh | ||
| WORKDIR /build | ||
| DOCKERFILE | ||
| docker build -t game-ci/ue-stub:latest -f /tmp/ue-stub-ctx/Dockerfile /tmp/ue-stub-ctx | ||
| - name: Run UE stub build | ||
| run: | | ||
| docker run --rm \ | ||
| -v "${{ github.workspace }}/test-projects/unreal-minimal:/build" \ | ||
| -w /build \ | ||
| game-ci/ue-stub:latest \ | ||
| /home/ue4/UnrealEngine/Engine/Build/BatchFiles/RunUAT.sh \ | ||
| BuildCookRun \ | ||
| -project=/build/MinimalTest.uproject \ | ||
| -targetplatform=Linux \ | ||
| -clientconfig=Shipping \ | ||
| -build -cook -stage -pak -archive \ | ||
| -archivedirectory=/build/output | ||
| - name: Verify build artifacts | ||
| run: | | ||
| cat test-projects/unreal-minimal/output/build-manifest.json | ||
| bun -e " | ||
| const m = JSON.parse(require('fs').readFileSync('test-projects/unreal-minimal/output/build-manifest.json', 'utf-8')); | ||
| if (m.engine !== 'unreal') throw new Error('wrong engine'); | ||
| console.log('UE stub build verified:', JSON.stringify(m)); | ||
| " | ||
| # ─── Unreal Engine real image (manual only) ───────────────────── | ||
| unreal-smoke-test: | ||
| name: Unreal Engine smoke test | ||
| runs-on: ubuntu-latest | ||
| if: github.event.inputs.unreal-image != '' | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Set up Bun | ||
| uses: oven-sh/setup-bun@v2 | ||
| with: | ||
| bun-version: latest | ||
| - name: Install dependencies | ||
| run: bun install --frozen-lockfile | ||
| - name: Pull and verify Unreal Engine container | ||
| run: | | ||
| UE_IMAGE="${{ github.event.inputs.unreal-image }}" | ||
| echo "Pulling: ${UE_IMAGE}" | ||
| docker pull "${UE_IMAGE}" | ||
| docker run --rm "${UE_IMAGE}" \ | ||
| bash -c "echo 'UE container OK'" | ||
| # ─── Executable CLI Plugin Tests ──────────────────────────────── | ||
| protocol-tests: | ||
| name: Executable CLI plugin tests | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Set up Bun | ||
| uses: oven-sh/setup-bun@v2 | ||
| with: | ||
| bun-version: latest | ||
| - name: Install dependencies | ||
| run: bun install --frozen-lockfile | ||
| - name: Test CLI plugin system can load executable plugin | ||
| run: | | ||
| bun -e " | ||
| import { CliProtocolPlugin } from './src/plugin/cli-protocol-plugin.ts'; | ||
| // Verify construction with executable path | ||
| const plugin = new CliProtocolPlugin({ providerExecutable: '/usr/bin/echo' }); | ||
| console.log('CliProtocolPlugin constructed OK'); | ||
| // Verify all execution methods required by the CLI exist | ||
| const methods = ['setupWorkflow', 'cleanupWorkflow', 'runTaskInWorkflow', | ||
| 'garbageCollect', 'listResources', 'listWorkflow', 'watchWorkflow']; | ||
| for (const m of methods) { | ||
| if (typeof plugin[m] !== 'function') { | ||
| throw new Error('Missing method: ' + m); | ||
| } | ||
| } | ||
| console.log('All required CLI execution methods present'); | ||
| " | ||
| - name: Test PluginLoader handles executable: prefix | ||
| run: | | ||
| bun -e " | ||
| import { PluginLoader } from './src/plugin/plugin-loader.ts'; | ||
| import { PluginRegistry } from './src/plugin/plugin-registry.ts'; | ||
| PluginRegistry.reset(); | ||
| // Verify executable: prefix with a real binary on the system | ||
| try { | ||
| const plugin = await PluginLoader.load('executable:/usr/bin/echo'); | ||
| console.log('Loaded executable plugin:', plugin.name); | ||
| console.log('Providers:', Object.keys(plugin.providers || {})); | ||
| const providers = PluginRegistry.getAvailableProviders(); | ||
| console.log('Registered providers:', providers); | ||
| if (!providers.includes('cli-protocol')) { | ||
| throw new Error('cli-protocol provider not registered'); | ||
| } | ||
| console.log('Executable plugin integration test PASSED'); | ||
| } catch (e) { | ||
| console.error('Test failed:', e.message); | ||
| process.exit(1); | ||
| } | ||
| " | ||
| - name: Run CLI plugin tests | ||
| run: bun test src/plugin/cli-protocol-plugin.test.ts | ||
| - name: Run plugin loader tests | ||
| run: bun test src/plugin/plugin-loader.test.ts | ||