Ironic Backport Agent
by jadhaj
README.md
# Ironic Backport Agent (MCP Version)
AI-assisted automation for backporting upstream Ironic changes across OpenShift release branches.
**Works with Claude Code** - No separate API keys needed!
## Project Goal
Automate the repetitive backport workflow for OpenShift BareMetal/Ironic releases using Claude AI for intelligent decision-making. Runs as an MCP server that integrates seamlessly with Claude Code.
**JIRA Epic**: [METAL-1814](https://redhat.atlassian.net/browse/METAL-1814)
**Research Spike**: [METAL-1817](https://redhat.atlassian.net/browse/METAL-1817)
## How It Works
Instead of using CLI commands, you **talk to Claude naturally**:
```
You: "Backport PR #370 to release-4.20"
Claude: [analyzes PR] "I found 3 commits. Based on the changes,
only commit 42ac11d31 should be backported. Proceed?"
You: "Yes"
Claude: [executes backport, creates PR] "✅ Done! PR #456 created"
```
## Features
### 🤖 AI-Powered (via Claude Code)
- Analyzes PRs to recommend which commits to backport
- Determines which release branches need the fix
- Suggests merge conflict resolutions
- Generates PR titles and descriptions following OpenShift conventions
- Adapts to errors and retries intelligently
### ⚙️ Automated Operations
- Git cherry-pick with conflict detection
- Branch management and analysis
- GitHub PR creation with proper formatting
- Dependency file updates (requirements.cachito, main-package-list.ocp)
### 💬 Natural Conversation
- No commands to memorize - just describe what you want
- Context-aware - Claude remembers the conversation
- Human oversight - You approve critical steps naturally
- Audit trail built into Claude conversation history
## Quick Start
### 1. Install
```bash
cd /Users/jhajyahy/ironic-backport-agent
./install.sh
```
### 2. Configure
```bash
# Only need GitHub token - no Claude API key!
export GITHUB_TOKEN="ghp_xxxxxxxxxxxx"
```
Get token from: https://github.com/settings/tokens (scopes: `repo` + `workflow`)
### 3. Set Up MCP
Add to `~/.claude/config.json`:
```json
{
"mcpServers": {
"ironic-backport": {
"command": "python",
"args": ["/Users/jhajyahy/ironic-backport-agent/src/backport_agent/mcp_server.py"],
"env": {"GITHUB_TOKEN": "${GITHUB_TOKEN}"}
}
}
}
```
### 4. Restart Claude Code
The backport tools will now be available in your Claude Code session!
**📖 See [SETUP-MCP.md](SETUP-MCP.md) for detailed setup guide.**
### Config File
Create `config.yaml`:
```yaml
github:
base_org: openshift
repos:
- openstack-ironic
- ironic-image
- ironic-python-agent-image
claude:
model: claude-sonnet-4-5
max_tokens: 4096
release_branches:
- release-4.17
- release-4.18
- release-4.19
- release-4.20
- release-4.21
- release-4.22
workflow:
auto_approve: false
conflict_strategy: ai_suggest
```
## Usage Examples
### Simple Backport
```
You: "Backport PR #370 from openstack-ironic to release-4.20"
Claude: "I found PR #370 with 3 commits. Analyzing..."
[uses analyze_pr tool]
"Based on the changes:
- 42ac11d31: Update heartbeat ✓ BACKPORT
- abc123de4: Update dev deps ✗ SKIP
- def456g78: Fix pep8 ✗ SKIP
Proceed with backporting commit 42ac11d31?"
You: "Yes"
Claude: [creates branch, cherry-picks, creates PR]
"✅ PR created: https://github.com/.../pull/456"
```
### Check Branch Coverage
```
You: "Does release-4.20 already have commit 42ac11d31?"
Claude: [uses analyze_branch_coverage tool]
"No, it's not in release-4.20.
Present in: release-4.21, release-4.22
Would you like to backport it?"
```
### Batch Backport
```
You: "Backport PR #370 to all active releases"
Claude: "Analyzing which branches need this fix..."
[checks each branch]
"Results:
- release-4.18: Needs it ✓
- release-4.19: Needs it ✓
- release-4.20: Needs it ✓
- release-4.21: Already has it ✗
- release-4.22: Already has it ✗
Create 3 backport PRs?"
You: "Yes"
Claude: [creates PRs for 4.18, 4.19, 4.20]
"✅ All done!
- 4.18: PR #457
- 4.19: PR #458
- 4.20: PR #459"
```
### Conflict Handling
```
You: "Backport commit 42ac11d31 to release-4.20"
Claude: [attempts cherry-pick]
"⚠️ Conflict in ironic/conductor/manager.py
Analyzing..."
[reads conflict content]
"The conflict is in import order. Suggested resolution:
- Use THEIR version for update_heartbeat function
- Keep OURS version for imports
Apply this?"
You: "Yes"
Claude: [resolves conflict, completes cherry-pick]
"✅ Resolved and cherry-picked!"
```
## Architecture
See [ARCHITECTURE.md](ARCHITECTURE.md) for detailed design documentation.
## Development
### Run Tests
```bash
pytest tests/ -v --cov=backport_agent
```
### Code Quality
```bash
# Format
black src/
# Lint
ruff check src/
# Type check
mypy src/
```
## METAL-1817 Research Findings
This prototype addresses all research questions from the spike:
### ✅ Branch Analysis
- Implemented via `git branch --contains` and AI-assisted applicability detection
- See: `src/backport_agent/git_ops.py:analyze_branch_coverage()`
### ✅ Cherry-Pick Automation
- Conflict detection with AI-suggested resolutions
- See: `src/backport_agent/git_ops.py:cherry_pick_with_ai()`
### ✅ GitHub Integration
- PAT scope requirements documented above
- PR creation via PyGithub with proper title format
- See: `src/backport_agent/github_client.py`
### ✅ Dependency File Updates
- AI determines which file to update (requirements.cachito vs main-package-list.ocp)
- Automated hash updates
- See: `src/backport_agent/dependency_updater.py`
### ✅ GitLab Integration
- Python-gitlab for ospinfo repos
- See: `src/backport_agent/gitlab_client.py`
## Roadmap
- [x] METAL-1817: Git/GitHub/GitLab integration research
- [ ] METAL-1820: Phase 1 prototype (Scenario A)
- [ ] METAL-1821: JIRA API integration
- [ ] METAL-1819: CI monitoring
- [ ] METAL-1822: Brew/Koji support (Scenario B)
- [ ] METAL-1823: Optimized semi-autonomous mode
- [ ] METAL-1824: Production deployment
## Contributing
This is a team effort! See the [Slack channel](https://redhat.enterprise.slack.com/archives/C0B32MK7S1J) for coordination.
## License
Internal Red Hat tooling - not for public distribution.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues