diff --git a/.agents.yaml b/.agents.yaml index 33de2f2..9633db1 100644 --- a/.agents.yaml +++ b/.agents.yaml @@ -85,9 +85,9 @@ model_overrides: # Using explicit model specification with API key authentication # Model names verified from gemini-config.json gemini: - pro_model: gemini-3-pro-preview # Latest preview model (NOT 3.0!) + pro_model: gemini-3.1-pro-preview # Latest preview model (NOT 3.0!) flash_model: gemini-3-flash-preview # Fast fallback model (Gemini 3 Flash) - default_model: gemini-3-flash-preview # Primary model for PR reviews (faster, lower rate limits) + default_model: gemini-3.1-pro-preview # Primary model for PR reviews # OpenRouter agents configuration opencode: diff --git a/.env.example b/.env.example index a5a35d1..64b5cc3 100644 --- a/.env.example +++ b/.env.example @@ -38,8 +38,8 @@ GOOGLE_API_KEY=your_api_key_here GEMINI_API_KEY=your_api_key_here # Gemini Model Configuration (optional - defaults configured in .agents.yaml) -# Available models: gemini-3-pro-preview, gemini-3-flash-preview -GEMINI_PRIMARY_MODEL=gemini-3-pro-preview +# Available models: gemini-3.1-pro-preview, gemini-3-flash-preview +GEMINI_PRIMARY_MODEL=gemini-3.1-pro-preview GEMINI_FALLBACK_MODEL=gemini-3-flash-preview # ============================================================================= diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 88544b5..a64ba16 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,6 +41,9 @@ jobs: echo "USER_ID=$(id -u)" >> $GITHUB_ENV echo "GROUP_ID=$(id -g)" >> $GITHUB_ENV + - name: Build CI Docker image + run: docker compose --profile ci build rust-ci + # -- Formatting ------------------------------------------------------- - name: Format check run: docker compose --profile ci run --rm rust-ci cargo fmt --all -- --check @@ -51,7 +54,10 @@ jobs: # -- Tests ------------------------------------------------------------- - name: Test - run: docker compose --profile ci run --rm rust-ci cargo test --workspace + run: | + set -o pipefail + docker compose --profile ci run --rm rust-ci \ + cargo test --workspace 2>&1 | tee test_output.txt # -- Build ------------------------------------------------------------- - name: Build (release) @@ -59,9 +65,11 @@ jobs: # -- Screenshot Regression Tests ---------------------------------------- - name: Screenshot tests (generate) + timeout-minutes: 5 run: | - docker compose --profile ci run --rm rust-ci \ - bash -c 'xvfb-run -a cargo run -p oasis-app --bin screenshot-tests --release' + docker compose --profile ci run --rm \ + -e SDL_VIDEODRIVER=dummy -e SDL_RENDER_DRIVER=software \ + rust-ci cargo run -p oasis-app --bin screenshot-tests --release - name: Upload screenshot report if: always() @@ -78,6 +86,7 @@ jobs: # -- Benchmarks -------------------------------------------------------- - name: Benchmarks run: | + set -o pipefail docker compose --profile ci run --rm rust-ci \ cargo bench --workspace 2>&1 | tee bench_results.txt echo "::group::Benchmark Results" @@ -96,9 +105,12 @@ jobs: - name: Test metrics summary if: always() run: | - # Re-run tests capturing output for summary (quick -- already compiled). - docker compose --profile ci run --rm rust-ci \ - cargo test --workspace 2>&1 | tee test_output.txt || true + if [ ! -f test_output.txt ]; then + echo "No test output captured (test step may have been skipped)." + echo "### Test Summary" >> $GITHUB_STEP_SUMMARY + echo "No test output available." >> $GITHUB_STEP_SUMMARY + exit 0 + fi PASS=$(grep -c '\.\.\. *ok$' test_output.txt 2>/dev/null) || PASS=0 FAIL=$(grep -c 'FAILED$' test_output.txt 2>/dev/null) || FAIL=0 TOTAL=$((PASS + FAIL)) diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index 77e9c16..b811a00 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -61,6 +61,9 @@ jobs: echo "USER_ID=$(id -u)" >> $GITHUB_ENV echo "GROUP_ID=$(id -g)" >> $GITHUB_ENV + - name: Build CI Docker image + run: docker compose --profile ci build rust-ci + # -- Formatting ------------------------------------------------------- - name: Format check run: docker compose --profile ci run --rm rust-ci cargo fmt --all -- --check @@ -71,16 +74,73 @@ jobs: # -- Tests ------------------------------------------------------------- - name: Test - run: docker compose --profile ci run --rm rust-ci cargo test --workspace + run: | + set -o pipefail + docker compose --profile ci run --rm rust-ci \ + cargo test --workspace 2>&1 | tee test_output.txt # -- Build ------------------------------------------------------------- - name: Build (release) run: docker compose --profile ci run --rm rust-ci cargo build --workspace --release + # -- Screenshot Regression Tests ---------------------------------------- + - name: Screenshot tests (generate) + timeout-minutes: 5 + run: | + docker compose --profile ci run --rm \ + -e SDL_VIDEODRIVER=dummy -e SDL_RENDER_DRIVER=software \ + rust-ci cargo run -p oasis-app --bin screenshot-tests --release + + - name: Upload screenshot report + if: always() + uses: actions/upload-artifact@v4 + with: + name: screenshot-report + path: screenshots/tests/ + retention-days: 14 + # -- License / Advisory ------------------------------------------------ - name: cargo-deny run: docker compose --profile ci run --rm rust-ci cargo deny check + # -- Benchmarks -------------------------------------------------------- + - name: Benchmarks + run: | + set -o pipefail + docker compose --profile ci run --rm rust-ci \ + cargo bench --workspace 2>&1 | tee bench_results.txt + echo "::group::Benchmark Results" + grep -E '(time:|bench)' bench_results.txt || true + echo "::endgroup::" + + - name: Upload benchmark results + if: always() + uses: actions/upload-artifact@v4 + with: + name: benchmark-results + path: bench_results.txt + retention-days: 30 + + # -- Test Metrics ------------------------------------------------------- + - name: Test metrics summary + if: always() + run: | + if [ ! -f test_output.txt ]; then + echo "No test output captured (test step may have been skipped)." + echo "### Test Summary" >> $GITHUB_STEP_SUMMARY + echo "No test output available." >> $GITHUB_STEP_SUMMARY + exit 0 + fi + PASS=$(grep -c '\.\.\. *ok$' test_output.txt 2>/dev/null) || PASS=0 + FAIL=$(grep -c 'FAILED$' test_output.txt 2>/dev/null) || FAIL=0 + TOTAL=$((PASS + FAIL)) + echo "### Test Summary" >> $GITHUB_STEP_SUMMARY + echo "| Metric | Count |" >> $GITHUB_STEP_SUMMARY + echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY + echo "| Passed | $PASS |" >> $GITHUB_STEP_SUMMARY + echo "| Failed | $FAIL |" >> $GITHUB_STEP_SUMMARY + echo "| Total | $TOTAL |" >> $GITHUB_STEP_SUMMARY + # -- PSP Backend Build ------------------------------------------------- - name: Setup PSP SDK run: | diff --git a/crates/oasis-backend-sdl/src/lib.rs b/crates/oasis-backend-sdl/src/lib.rs index 9947cd3..d390b2d 100644 --- a/crates/oasis-backend-sdl/src/lib.rs +++ b/crates/oasis-backend-sdl/src/lib.rs @@ -70,10 +70,13 @@ impl SdlBackend { .position_centered() .build() .map_err(|e| OasisError::Backend(e.to_string()))?; - let canvas = window - .into_canvas() - .accelerated() - .present_vsync() + let headless = + std::env::var("SDL_RENDER_DRIVER").is_ok_and(|v| v.eq_ignore_ascii_case("software")); + let mut builder = window.into_canvas(); + if !headless { + builder = builder.accelerated().present_vsync(); + } + let canvas = builder .build() .map_err(|e| OasisError::Backend(e.to_string()))?; let texture_creator = canvas.texture_creator(); diff --git a/docker/rust-ci.Dockerfile b/docker/rust-ci.Dockerfile index bd8d3af..00ac6fb 100644 --- a/docker/rust-ci.Dockerfile +++ b/docker/rust-ci.Dockerfile @@ -13,6 +13,8 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ libsdl2-dev \ libsdl2-mixer-dev \ xvfb \ + xauth \ + libgl1-mesa-dri \ && rm -rf /var/lib/apt/lists/* # Install nightly toolchain (for format checking with edition 2024)