Loading skill
Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use when you need to monitor pull requests through CI/CD pipeline and handle failures automatically. Monitors PR status, retries flaky CI, resolves merge conflicts, enables auto-merge when criteria are met, and provides comprehensive PR management for development workflows.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 147% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 165% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 184% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 164% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 247% | 0% |
Automated pull request monitoring and management system that handles CI/CD pipeline failures, retry logic, conflict resolution, and merge automation to streamline development workflows.
pythonclass PRMonitor: def __init__(self, github_client, ci_client): self.github = github_client self.ci = ci_client self.active_prs = {} def monitor_pr(self, pr_number): """Monitor a specific PR through the pipeline""" pr = self.github.get_pull_request(pr_number) # Check CI status ci_status = self.ci.get_build_status(pr.head.sha) # Check required reviews reviews = self.github.get_reviews(pr_number) required_reviews = self._check_review_requirements(reviews) # Check merge conflicts conflicts = self.github.check_merge_conflicts(pr_number) return { 'pr_number': pr_number, 'status': pr.state, 'ci_status': ci_status, 'reviews': required_reviews, 'conflicts': conflicts, 'mergeable': pr.mergeable }
pythonclass CIRetryHandler: def __init__(self, max_retries=3, retry_delay=300): self.max_retries = max_retries self.retry_delay = retry_delay self.retry_history = {} def should_retry(self, pr_number, build_result): """Determine if a build should be retried""" if build_result.status == 'success': return False retry_count = self.retry_history.get(pr_number, 0) if retry_count >= self.max_retries: return False # Check if failure is retryable return self._is_retryable_failure(build_result) def _is_retryable_failure(self, build_result): """Check if failure type is suitable for retry""" retryable_patterns = [ 'timeout', 'network error', 'infrastructure failure', 'flaky test', 'resource constraint' ] failure_message = build_result.message.lower() return any(pattern in failure_message for pattern in retryable_patterns) def retry_build(self, pr_number): """Retry a failed build""" retry_count = self.retry_history.get(pr_number, 0) + 1 self.retry_history[pr_number] = retry_count # Trigger new build build_id = self.ci.trigger_build(pr_number) # Schedule monitoring self._schedule_build_monitoring(pr_number, build_id) return { 'retry_count': retry_count, 'build_id': build_id, 'max_retries': self.max_retries }
pythonclass ConflictResolver: def __init__(self, github_client): self.github = github_client def resolve_conflicts(self, pr_number): """Attempt to resolve merge conflicts""" pr = self.github.get_pull_request(pr_number) if not pr.mergeable: conflicts = self._detect_conflicts(pr) resolution_attempts = [] for conflict in conflicts: resolution = self._attempt_resolution(conflict) if resolution.success: resolution_attempts.append(resolution) if resolution_attempts: # Create commit with resolutions commit_sha = self._commit_resolutions(pr_number, resolution_attempts) return { 'resolved': True, 'commit_sha': commit_sha, 'resolutions': resolution_attempts } return {'resolved': False, 'reason': 'No conflicts or unresolvable'} def _detect_conflicts(self, pr): """Detect specific conflict types""" # Implementation for detecting common conflict patterns return [] def _attempt_resolution(self, conflict): """Attempt to resolve a specific conflict""" # Implementation for conflict resolution logic return ConflictResolution(success=False)
yaml# pr-babysitter-config.yaml repository: "company/product" protected_branches: - main - production - staging auto_merge_rules: require_tests_pass: true require_code_review: true require_approval_count: 2 max_age_hours: 72 exclude_labels: ["wip", "do-not-merge"] retry_configuration: max_retries: 3 retry_delay_seconds: 300 flaky_test_patterns: - "integration_test_*" - "e2e_test_*" - "performance_test_*" notification_settings: slack: webhook_url: "${SLACK_WEBHOOK_URL}" channel: "#pr-updates" notify_on_failure: true notify_on_merge: true github: comment_on_retry: true comment_on_conflict_resolution: true comment_on_auto_merge: true
pythonclass QualityGates: def __init__(self, config): self.config = config def check_merge_eligibility(self, pr): """Check if PR is eligible for auto-merge""" checks = { 'ci_status': self._check_ci_status(pr), 'code_review': self._check_code_review(pr), 'age_check': self._check_pr_age(pr), 'label_check': self._check_labels(pr), 'conflict_check': self._check_conflicts(pr) } return all(checks.values()), checks def _check_ci_status(self, pr): """Check if all CI checks are passing""" required_checks = self.config.get('required_ci_checks', []) for check in required_checks: status = self.github.get_commit_status(pr.head.sha, check) if status.state != 'success': return False return True def _check_code_review(self, pr): """Check code review requirements""" required_approvals = self.config.get('required_approvals', 1) approvals = [r for r in pr.reviews if r.state == 'APPROVED'] return len(approvals) >= required_approvals def _check_pr_age(self, pr): """Check PR age requirements""" max_age_hours = self.config.get('max_age_hours', 72) age_hours = (datetime.now() - pr.created_at).total_seconds() / 3600 return age_hours <= max_age_hours def _check_labels(self, pr): """Check for blocking labels""" blocking_labels = self.config.get('blocking_labels', []) pr_labels = [label.name for label in pr.labels] return not any(label in pr_labels for label in blocking_labels)
yaml# .github/workflows/pr-babysitter.yml name: PR Babysitter on: pull_request: types: [opened, synchronize, reopened] jobs: babysit-pr: runs-on: ubuntu-latest steps: - name: Checkout PR uses: actions/checkout@v3 with: token: ${{ secrets.BABYSITTER_TOKEN }} - name: Run PR Babysitter run: | python -m pr_babysitter monitor \ --pr-number ${{ github.event.number }} \ --repo ${{ github.repository }} \ --token ${{ secrets.BABYSITTER_TOKEN }}
pythonclass SlackNotifier: def __init__(self, webhook_url): self.webhook_url = webhook_url def notify_pr_update(self, pr, event_type, details): """Send PR update notification to Slack""" message = { "text": f"PR #{pr.number}: {event_type}", "attachments": [{ "color": self._get_color_for_event(event_type), "fields": [ {"title": "Title", "value": pr.title, "short": True}, {"title": "Author", "value": pr.user.login, "short": True}, {"title": "Details", "value": details, "short": False} ], "actions": [ { "type": "button", "text": "View PR", "url": pr.html_url } ] }] } requests.post(self.webhook_url, json=message) def _get_color_for_event(self, event_type): colors = { 'retry_triggered': 'warning', 'conflict_resolved': 'good', 'auto_merged': 'good', 'merge_failed': 'danger' } return colors.get(event_type, 'gray')
pythonclass PRMetrics: def __init__(self, analytics_db): self.db = analytics_db def get_pr_statistics(self, time_period_days=30): """Get PR statistics for dashboard""" query = """ SELECT COUNT(*) as total_prs, COUNT(CASE WHEN auto_merged = true THEN 1 END) as auto_merged_prs, COUNT(CASE WHEN retries_attempted > 0 THEN 1 END) as retried_prs, COUNT(CASE WHEN conflicts_resolved > 0 THEN 1 END) as conflict_resolved_prs, AVG(time_to_merge_hours) as avg_time_to_merge, AVG(ci_execution_time_minutes) as avg_ci_time FROM pr_metrics WHERE created_at >= NOW() - INTERVAL '%s days' """ % time_period_days return self.db.execute(query).fetchone() def get_failure_patterns(self): """Analyze common failure patterns""" query = """ SELECT failure_type, COUNT(*) as occurrences, AVG(retry_success_rate) as avg_retry_success FROM ci_failures WHERE timestamp >= NOW() - INTERVAL '30 days' GROUP BY failure_type ORDER BY occurrences DESC """ return self.db.execute(query).fetchall()
Load these files when needed:
scripts/pr-monitor.py - Core PR monitoring and status trackingscripts/conflict-resolver.py - Merge conflict detection and resolutionscripts/quality-gates.py - Quality gate validation and enforcementreferences/github-api-patterns.md - GitHub API integration patternsexamples/notification-templates/ - Slack and email notification templatesOther measured skills in the registry, with their headline benchmark lift.