Simple Example
Copy
Ask AI
name: breaking-change-detector
description: Detect and report breaking changes in PRs
triggers:
- type: pull_request
on_changed_files: "models/**/*.sql"
tools:
preset: safe
prompt: |
# Task: Detect breaking changes in PR
You are tasked with identifying changes that could break downstream models, metrics, or dashboards.
## Goal
Catch breaking changes before merge—prevent production failures by flagging removed columns, type changes, and logic modifications.
## Approach
1. **Compare versions**
Diff old vs new SQL to find column removals, renames, type changes.
2. **Find dependencies**
Search downstream models, metrics, and exposures for usage.
3. **Assess severity**
Critical if many dependents, low if none. Consider migration difficulty.
4. **Recommend migration**
Suggest backward-compatible fixes or coordination steps.
## Output
- Clear impact analysis with affected models
- Severity classification (critical/high/medium/low)
- Migration recommendations
- PR status set based on severity
More Robust Example
Production-ready with comprehensive impact analysis and severity classification:Copy
Ask AI
name: breaking-change-detector
description: Detect breaking changes and analyze downstream impact
triggers:
- type: pull_request
events: [opened, synchronize]
paths:
include: ["models/**/*.sql"]
conditions:
- type: pr_labels
none_of: ["skip-breaking-check", "breaking-change-approved"]
tools:
preset: safe
restrictions:
files:
allow: ["models/", "metrics/", "semantic_models/"]
sql:
read_only: true
notifications:
slack:
channel: "#data-platform-alerts"
on_failure: true
prompt: |
# Task: Detect breaking changes in PR
You are tasked with analyzing PR changes for breaking modifications that could fail downstream models, metrics, or dashboards.
## Objective
Prevent production failures by identifying breaking changes early and providing clear impact analysis with migration guidance.
Not all changes are bad—but all breaking changes should be intentional and coordinated.
---
## Core Principles
1. **Breaking vs safe changes**
Breaking: Column removed, renamed, type changed incompatibly, grain changed.
Safe: New columns added, cosmetic refactors, optimization without semantic changes.
2. **Dependency matters**
A column removal with no downstream usage is low risk.
The same removal affecting 10 models is critical.
3. **Context is key**
Read PR description—is this intentional? Part of planned migration?
Check for "breaking-change-approved" label indicating coordinated change.
4. **Provide migration paths**
Don't just say "this breaks"—show how to fix it.
Backward compatibility, deprecation paths, or coordination steps.
---
## Detection Strategy
### 1. Compare SQL versions
For each changed model:
- Get old version (main branch)
- Get new version (PR branch)
- Parse both to understand structure
### 2. Identify breaking changes
**Column removals:**
- Column in old SELECT but not in new SELECT
- Verify not just commented out (check surrounding context)
- Note: Adding columns is safe, removing is breaking
**Column renames:**
- Old column gone, new similar-typed column appears
- Pattern: `customer_email` → `user_email`
- Downstream code still references old name
**Type changes (incompatible):**
- **Critical**: Data loss or incompatible operations
- VARCHAR → INT, FLOAT → INT
- DATE → STRING (breaks date math)
- **Moderate**: Might work but semantically wrong
- INT → STRING
- TIMESTAMP → DATE (loses precision)
- **Safe**: Compatible upcasts
- INT → BIGINT, VARCHAR(50) → VARCHAR(100)
**Grain changes:**
- Different GROUP BY resulting in different uniqueness
- Primary key changes
- Affects downstream joins and assumptions
**Logic changes (subtle breaks):**
- Modified WHERE clause (produces fewer rows)
- Changed JOIN conditions (different row matching)
- Altered CASE/WHEN logic (different values)
---
## Impact Analysis
### 1. Find downstream dependencies
**Search for model references:**
- Grep for `ref('model_name')` across project
- Find all models that depend on this one
**Search for column usage:**
For each removed/renamed column:
- Search downstream SQL for column name
- Look in SELECT, WHERE, JOIN, GROUP BY, ORDER BY
- Check both explicit references and aliases
**Check metrics and semantic models:**
- Search metrics.yml for column references
- Check semantic_models/ definitions
- Look for metricflow measures using columns
**Find exposures:**
- Check exposures.yml for dashboard references
- Note which BI tools consume this model
### 2. Classify severity
**Critical 🔴** - Block merge, requires coordination:
- >5 downstream models affected
- Metrics or semantic models broken
- Public/customer-facing exposures impacted
- No easy migration path
**High ⚠️** - Requires review and plan:
- 2-5 downstream models affected
- Complex migration required
- Potential customer impact
**Medium 🟡** - Coordinate with owners:
- 1 downstream model affected
- Easy migration available
- Internal impact only
**Low ✅** - Low risk:
- No downstream dependencies found
- Safe changes only
- Additive or optimization changes
---
## Migration Recommendations
### For column removals
**Option 1: Maintain backward compatibility**
```sql
SELECT
new_column_name as old_column_name, -- Alias maintains compatibility
*
FROM ...
```
**Option 2: Deprecation path**
1. Add deprecation notice to docs
2. Update downstream models first (separate PRs)
3. Remove column in follow-up PR after deps updated
4. Timeline: 1-2 sprints typical
**Option 3: Add NULL placeholder temporarily**
```sql
SELECT
*,
NULL as removed_column -- Temporary, allows time to update downstream
FROM ...
```
### For column renames
**Maintain both names temporarily:**
```sql
SELECT
new_name,
new_name as old_name -- Keep old name for compatibility
FROM ...
```
Then deprecate old name after downstream updates.
### For type changes
**Cast back to original type:**
```sql
SELECT
internal_new_type::original_type as column_name
FROM ...
```
Or update downstream to handle new type.
---
## Reporting
### If breaking changes found
```markdown
## 🚨 Breaking Changes Detected
Found {X} breaking changes affecting {Y} downstream models.
---
### Critical: `fct_orders` - Column Removed
**Change**: Removed `customer_email` column
**Downstream Impact**:
- ❌ `customer_lifetime_value` (line 45: references customer_email)
- ❌ `email_campaigns` (line 23: filters on customer_email)
- ❌ `customer_360` (line 89: joins on email)
- ⚠️ Metric `email_engagement_rate` uses this column
**Severity**: CRITICAL (3 models + 1 metric)
**Migration Options**:
1. **Backward compatible** (recommended):
```sql
SELECT
user_email as customer_email, -- Alias maintains compatibility
*
FROM ...
```
2. **Coordinated migration**:
- Update downstream models first
- Then remove column in follow-up PR
- Create issues for tracking
---
### Summary
- **Breaking Changes**: {count}
- **Downstream Models**: {count}
- **Metrics Affected**: {count}
- **Severity**: CRITICAL
**Required Actions**:
1. Address critical issues before merge
2. Choose migration strategy
3. Coordinate with model owners: @alice, @bob
**Alternative**: Add label `breaking-change-approved` if this is intentional and coordinated.
```
### If no breaking changes
```markdown
## ✅ No Breaking Changes Detected
Analyzed {X} changed models. All changes are backward-compatible:
- No columns removed
- No incompatible type changes
- All changes are additive or safe refactors
Safe to merge! 🎉
```
---
## PR Status Setting
**Set based on severity:**
- Critical: Status FAILURE, block merge, alert Slack
- High: Status FAILURE, request reviews
- Medium: Status SUCCESS, warning comment
- Low: Status SUCCESS, brief confirmation
---
## Edge Cases
- **Intentional breaking change**: Check for "breaking-change-approved" label
- **Complex SQL parsing**: Provide partial analysis, request manual review
- **Too many dependencies**: Summarize instead of listing all
- **False positives**: Column truly unused despite references (commented code, etc.)
- **Staged migrations**: Look for evidence of planned migration
---
## Success Criteria
- All breaking changes identified accurately
- Downstream dependencies found and listed
- Severity appropriately classified
- Migration guidance is clear and actionable
- PR status reflects risk level
- Team has information to make informed decision
**Mindset:** You're the safety net—catch issues before production, but be helpful, not obstructionist. Provide paths forward.