Skip to content

Comments

ci: make optional C++ components non-fatal#75

Open
heidi-dang wants to merge 3 commits intomainfrom
ci/cross-platform-gating-16828375979512091972
Open

ci: make optional C++ components non-fatal#75
heidi-dang wants to merge 3 commits intomainfrom
ci/cross-platform-gating-16828375979512091972

Conversation

@heidi-dang
Copy link
Owner

This PR addresses cross-platform CI breakages where macOS and Windows runners fail during test collection because they try to import or build optional C++ components (heidi_cpp, heidid) that are only supported/present on Linux.

Key changes:

  1. Test Gating: Updated all tests that depend on heidi_cpp to use pytest.importorskip("heidi_cpp"). This ensures that if the extension is not built, the tests are skipped instead of causing a collection error.
  2. Daemon Tests: Added a check for the heidid binary in tests/test_daemon.py.
  3. CI Orchestration:
    • Added a preflight job to .github/workflows/ci.yml to detect if setup_cpp.py exists.
    • Gated C++ build and test steps with if: runner.os == 'Linux'.
    • Added a ci-complete job to all workflows that always runs and aggregates status. This is critical for branch protection when some jobs are skipped.
  4. Test Fixes: Updated tests/test_jsonl_utils.py to provide valid telemetry data, satisfying the "Zero-Trust" validation in load_jsonl without changing the core engine logic. Refactored tests/test_loop_runner.py to safely handle the absence of heidi_cpp.

These changes ensure that CI remains green on all platforms while still running the full suite on Linux. No product behavior was changed.


PR created automatically by Jules for task 16828375979512091972 started by @heidi-dang

- Use pytest.importorskip('heidi_cpp') in tests to avoid collection errors on macOS/Windows.
- Add a preflight CI job to detect C++ availability.
- Gate C++ build/test jobs behind runner OS and preflight output.
- Add an always-run 'ci-complete' job to every workflow for reliable branch protection status.
- Ensure integration tests check for heidid binary existence before running.
- Fix tests/test_jsonl_utils.py and tests/test_loop_runner.py to work with current engine logic while safely skipping C++ components.
@google-labs-jules
Copy link
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@gemini-code-assist
Copy link

Summary of Changes

Hello @heidi-dang, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the cross-platform compatibility and stability of the CI pipeline by making optional C++ components non-fatal on platforms where they are not supported or built. The changes primarily involve modifying test files to conditionally skip tests that rely on these components, rather than failing due to missing imports or binaries. This ensures that CI runs smoothly across different operating systems while maintaining full test coverage on Linux.

Highlights

  • Conditional C++ Extension Imports: Tests that depend on the heidi_cpp C++ extension now use pytest.importorskip to gracefully skip if the extension is not built or available, preventing import errors on unsupported platforms.
  • Daemon Binary Availability Check: A check was added in tests/test_daemon.py to skip daemon integration tests if the heidid binary is not found, ensuring these tests do not fail on platforms where the daemon is not expected to be present.
  • JSONL Utility Test Data Validation: The tests/test_jsonl_utils.py file was updated to use a new get_valid_sample helper function, ensuring that test data conforms to the 'Zero-Trust' validation requirements of load_jsonl.
  • Loop Runner C++ Dependency Handling: The tests/test_loop_runner.py was refactored to safely handle the absence of heidi_cpp by conditionally skipping CppLoopRunner tests if the extension is not found, improving test stability.
Changelog
  • tests/test_budget_guardrails.py
    • Updated the import of heidi_cpp to use pytest.importorskip.
  • tests/test_core_integration.py
    • Updated the import of heidi_cpp to use pytest.importorskip.
  • tests/test_cpp_ext.py
    • Replaced a custom try-except block for heidi_cpp import with pytest.importorskip.
  • tests/test_daemon.py
    • Added a conditional check to skip daemon integration tests if the heidid binary is not found.
  • tests/test_doctor.py
    • Updated the import of heidi_cpp to use pytest.importorskip.
  • tests/test_jsonl_utils.py
    • Added a get_valid_sample helper function to generate valid telemetry data for tests.
    • Updated existing tests (test_save_and_load_roundtrip, test_save_creates_directories, test_load_skips_blank_lines, test_save_current_directory) to utilize the get_valid_sample function.
    • Modified test_load_handles_invalid_json to assert SystemExit when invalid JSON is encountered, aligning with the strict behavior of load_jsonl.
  • tests/test_loop_runner.py
    • Removed a duplicate monkeypatch.setenv call for RUN_ID.
    • Refactored get_runner_classes to import CppLoopRunner as CppLR and always include it in test parameters.
    • Modified the runner_class fixture to conditionally skip CppLoopRunner tests if heidi_cpp cannot be imported.
    • Updated conditional checks from runner_class == PythonLoopRunner to `
  • tests/test_perf_baseline.py
    • Updated the import of heidi_cpp to use pytest.importorskip.
  • tests/test_sec_redteam.py
    • Added import pytest.
    • Updated the import of heidi_cpp to use pytest.importorskip.
Ignored Files
  • Ignored by pattern: .github/workflows/** (4)
    • .github/workflows/ci-autotrain.yml
    • .github/workflows/ci-ml.yml
    • .github/workflows/ci.yml
    • .github/workflows/repo-hygiene.yml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively addresses CI breakages on non-Linux platforms by making optional C++ components non-fatal. The use of pytest.importorskip and existence checks for binaries are appropriate solutions. The test data in test_jsonl_utils.py has been updated to align with stricter validation, which is a great improvement. I've identified a critical issue in tests/test_doctor.py where a missing import will cause tests to fail. Additionally, I've suggested a couple of improvements in tests/test_loop_runner.py to make the type checks more robust and less reliant on string comparisons. Overall, the changes are solid and move in the right direction for cross-platform compatibility.


def test_real_mode_blocked_in_core_integration():
import heidi_cpp
heidi_cpp = pytest.importorskip("heidi_cpp")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The pytest module is used here but it does not appear to be imported in this file. This will cause a NameError when the test runs. Please add import pytest at the top of the file to resolve this.

@pytest.fixture(params=get_runner_classes())
def runner_class(request, monkeypatch):
if CppLoopRunner and request.param == CppLoopRunner:
if "CppLoopRunner" in str(request.param):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using str() for type checking is brittle and can lead to bugs if class names change or if another class name contains this substring. It's better to check the class name directly using __name__ for robustness.

Suggested change
if "CppLoopRunner" in str(request.param):
if request.param.__name__ == "CppLoopRunner":


# Check that scripts were "called" if using Python
if runner_class == PythonLoopRunner:
if "PythonLoopRunner" in str(runner_class):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using str() for type checking is brittle. Since PythonLoopRunner is imported in this module, you can use a direct identity check with is. This is more robust and Pythonic. This feedback applies to similar checks on lines 94, 108, and 136 in this file.

Suggested change
if "PythonLoopRunner" in str(runner_class):
if runner_class is PythonLoopRunner:

- Re-implemented pytest gating using standard importorskip and subclass checks.
- Added os.X_OK check for heidid binary in integration tests.
- Hardened CI preflight job to check for both build scripts and source files.
- Ensured all tests skip gracefully on non-Linux platforms without collection errors.
- Verified ci-complete aggregator logic across all workflows.
- Use pytest.importorskip('heidi_cpp') in all relevant tests.
- Gate C++ builds in CI using a robust preflight check and runner.os filter.
- Add always-run ci-complete aggregator jobs to all workflows.
- Fix load_jsonl to support optional telemetry validation (defaulting to True).
- Update scripts/02_validate_clean.py and scripts/03_unit_test_gate.py to correctly opt-out of telemetry validation.
- Restore validate_schema in scripts/02_validate_clean.py to fix NameError.
- Add os.X_OK check for heidid binary in integration tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant