chore: add breaking change detector #5
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: Breaking Change Detector | |
| on: | |
| pull_request: | |
| branches: | |
| - main | |
| paths: | |
| - 'src/**' | |
| jobs: | |
| check-api: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.10' | |
| - name: Install dependencies | |
| uses: astral-sh/setup-uv@v5 | |
| with: | |
| version: "latest" | |
| - name: Install project | |
| run: | | |
| uv sync --extra test | |
| uv pip install griffe | |
| - name: Run Breaking Change Detection | |
| run: | | |
| uv run python - <<EOF | |
| import sys | |
| import griffe | |
| from griffe import find_breaking_changes, load, load_git | |
| def print_debug_info(api_obj, label): | |
| try: | |
| # Navigate to Runner.run to check what Griffe sees | |
| runner = api_obj.members["Runner"] | |
| run_method = runner.members["run"] | |
| print(f"DEBUG [{label}]: Runner.run return annotation: '{run_method.returns}'") | |
| except KeyError as e: | |
| print(f"DEBUG [{label}]: Could not find 'Runner.run' member. Missing: {e}") | |
| print(f"DEBUG [{label}]: Available members: {list(api_obj.members.keys())}") | |
| try: | |
| # 1. Load NEW API (Force static analysis) | |
| print("Loading new API from src/...") | |
| new_api = load("google.adk", search_paths=["src"], allow_inspection=False) | |
| print(f"DEBUG: New API filepath: {new_api.filepath}") | |
| print_debug_info(new_api, "NEW") | |
| # 2. Load OLD API (Force static analysis from git) | |
| print("Loading old API from main branch...") | |
| old_api = load_git("google.adk", ref="main", search_paths=["src"], allow_inspection=False) | |
| print(f"DEBUG: Old API filepath: {old_api.filepath}") | |
| print_debug_info(old_api, "OLD") | |
| # 3. Compare | |
| print("Comparing...") | |
| breakages = list(find_breaking_changes(old_api, new_api)) | |
| if breakages: | |
| print(f"::error::Found {len(breakages)} breaking changes!") | |
| for breakage in breakages: | |
| print(breakage.explain()) | |
| sys.exit(1) | |
| # If we see different return types in DEBUG logs but 0 breakages here, | |
| # it means Griffe considers them compatible. | |
| print("Success: No breaking changes detected.") | |
| except Exception as e: | |
| print(f"::error::Breaking change detection failed: {e}") | |
| sys.exit(1) | |
| EOF |