Update breaking-change-detector.yml

This commit is contained in:
sasha-gitg
2026-01-12 17:19:10 -05:00
committed by GitHub
parent 97542097c9
commit b0610cac8e
+48 -27
View File
@@ -14,65 +14,86 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-depth: 0 # Required for accessing the main branch history
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Install dependencies
- name: Install the latest version of uv
uses: astral-sh/setup-uv@v5
with:
version: "latest"
- name: Install project
- name: Install dependencies
# Syncing installs the package and its dependencies (populating google.* namespace)
# Installing 'griffe' ensures the tool is available in the environment
run: |
uv sync --extra test
uv pip install griffe
- name: Run Breaking Change Detection
# Uses 'uv run python' to execute in the environment with all dependencies installed
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):
def check_return_types(old_obj, new_obj):
"""Custom check to strictly compare return type annotations."""
errors = []
# Check Runner.run specifically, or extend to check all methods
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())}")
old_run = old_obj.members["Runner"].members["run"]
new_run = new_obj.members["Runner"].members["run"]
# Convert to string and strip to compare the annotation text
old_ret = str(old_run.returns).strip()
new_ret = str(new_run.returns).strip()
if old_ret != new_ret:
errors.append(
f"Breaking Change in {new_run.path}: Return type changed from '{old_ret}' to '{new_ret}'"
)
except KeyError:
pass # Member missing (will be caught by standard checks)
except AttributeError:
pass # Member might not be a function
return errors
try:
# 1. Load NEW API (Force static analysis)
print("Loading new API from src/...")
print("Loading new API (from local source)...")
# allow_inspection=False forces static analysis, preventing sys.modules caching issues
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...")
print("Loading baseline 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...")
print("Running detection...")
# 1. Standard Griffe Checks (Removals, Parameter changes)
breakages = list(find_breaking_changes(old_api, new_api))
# 2. Custom Return Type Checks (Workaround for Griffe limitation)
custom_errors = check_return_types(old_api, new_api)
found_issues = False
if breakages:
print(f"::error::Found {len(breakages)} breaking changes!")
found_issues = True
print(f"::error::Found {len(breakages)} standard breaking changes!")
for breakage in breakages:
print(breakage.explain())
if custom_errors:
found_issues = True
print(f"::error::Found {len(custom_errors)} return type mismatches!")
for error in custom_errors:
print(f"- {error}")
if found_issues:
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: