-
-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Add github-repo-maintainer agent for autonomous PR/issue management #114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Add github-repo-maintainer agent for autonomous PR/issue management #114
Conversation
…ment Adds a new Claude agent with 6 documented skills: 1. Issue Triage - Categorize and label incoming issues 2. Pull Request Review - Automated code review checks 3. Merge Conflict Resolution - Detect and help resolve conflicts 4. Release Management - Automate changelog and version tagging 5. Stale Issue Management - Clean up inactive issues/PRs 6. Dependency Security Monitoring - Track and respond to vulnerabilities Each skill includes workflow documentation, PHP code examples using the github-client package, and CLI commands using the gh CLI. Closes #113 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughA new comprehensive documentation file introducing a GitHub Repository Maintainer Agent blueprint with six core skills: Issue Triage, Pull Request Review, Merge Conflict Resolution, Release Management, Stale Issue Management, and Dependency Security Monitoring. Includes workflow descriptions, PHP code examples, CLI commands, error handling patterns, and CI/CD integration guidance. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~28 minutes Poem
Pre-merge checks✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
.claude/agents/github-repo-maintainer.md (2)
43-58: Issue Triage categorization logic may misclassify ambiguous issues.The keyword-matching approach uses exclusive if/elseif branches, so issues containing both "bug" and "feature" keywords will only receive the first matching category. Consider whether ambiguous issues should receive multiple labels or explicit handling.
🔎 Optional refinement for multi-category detection
$labels = []; if (str_contains($title, 'bug') || str_contains($body, 'error') || str_contains($body, 'crash')) { $labels[] = 'bug'; } if (str_contains($title, 'feature') || str_contains($body, 'would be nice')) { $labels[] = 'enhancement'; } if (str_contains($title, '?') || str_contains($body, 'how do i')) { $labels[] = 'question'; } $priority = match(true) { in_array('bug', $labels) => 'high', in_array('enhancement', $labels) => 'medium', in_array('question', $labels) => 'low', default => 'low' };
641-661: CI/CD workflow structure is sound.The GitHub Actions setup correctly triggers on schedule/dispatch, configures PHP environment, and runs the maintenance commands. The workflow provides a practical foundation for autonomous maintenance execution.
Consider adding explicit error handling (e.g.,
continue-on-error: falsefor critical steps, notifications on failure) for production deployments to ensure visibility into maintenance task failures.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.claude/agents/github-repo-maintainer.md
🔇 Additional comments (6)
.claude/agents/github-repo-maintainer.md (6)
180-221: Merge Conflict Resolution approach is sound.The detection logic using
mergeableproperty and helpful git commands are well-implemented. The use ofcreateComment()on issues for PR comments is correct since PRs inherit from issues in the GitHub API.
373-416: Stale Issue Management implementation is well-structured.The two-phase approach (close if past grace period, then mark as stale) with label skipping for pinned/help-wanted issues is a sound pattern. Date calculations and state transitions are correct.
602-624: Error handling patterns are comprehensive.The exception handling covers the main failure modes (rate limiting, authentication, API errors) with appropriate logging and recovery hints (getResetTime for rate limits). This provides a solid foundation for production use.
1-20: Comprehensive agent documentation with all required skills.The documentation successfully covers all six skills (Issue Triage, PR Review, Merge Conflicts, Release Management, Stale Issues, Dependency Security) with clear workflows, PHP examples using the github-client package, and CLI command alternatives. The documentation structure is professional and well-organized.
However, several code examples depend on accurate github-client package API signatures. Please verify:
- The commit object structure returned from
Github::commits()->all()(line 278 accessing->message)- The exact JSON structure of
composer audit --format=jsonoutput (line 496 referencingreportedAt)These verification steps will ensure examples work correctly when implemented.
98-143: Update method calls to usepullRequests()and fixcreateReview()signature.The code uses non-existent method
Github::pulls()which should beGithub::pullRequests(). Additionally,createReview()accepts separate parameters, not an array. The correct approach:use JordanPartridge\GithubClient\Facades\Github; $pulls = Github::pullRequests()->all('owner', 'repo', ['state' => 'open']); foreach ($pulls as $pr) { $files = Github::pullRequests()->files('owner', 'repo', $pr->number); $issues = []; foreach ($files as $file) { if (str_ends_with($file->filename, '.php')) { if (str_contains($file->patch ?? '', 'dd(') || str_contains($file->patch ?? '', 'dump(')) { $issues[] = "Found debugging statement in `{$file->filename}`"; } if (str_contains($file->patch ?? '', 'var_dump')) { $issues[] = "Found `var_dump` in `{$file->filename}` - use proper logging instead"; } } if ($file->changes > 500) { $issues[] = "Large change ({$file->changes} lines) in `{$file->filename}` - consider splitting"; } } if (empty($issues)) { Github::pullRequests()->createReview('owner', 'repo', $pr->number, 'Automated checks passed. LGTM!', 'APPROVE'); } else { Github::pullRequests()->createReview('owner', 'repo', $pr->number, "Found issues:\n- " . implode("\n- ", $issues), 'REQUEST_CHANGES'); } }The facade provides
pullRequests()notpulls(). ThecreateReview()method signature iscreateReview(string $owner, string $repo, int $number, string $body, string $event = 'COMMENT', array $comments = []).Likely an incorrect or invalid review comment.
481-504: Use correct field for fixed version in composer audit advisory.Line 496 uses
{$advisory['reportedAt']}, but composer audit JSON output does not include a 'reportedAt' field as a version number. UsefixedInorfirst_patched_version['name'](depending on the advisory source) instead. The current code will produce a malformed message with a missing version number.
| // Get commits since last release | ||
| $commits = Github::commits()->all('owner/repo', since: $latestRelease?->created_at); | ||
|
|
||
| // Categorize commits by conventional commit prefixes | ||
| $features = []; | ||
| $fixes = []; | ||
| $breaking = []; | ||
| $other = []; | ||
|
|
||
| foreach ($commits as $commit) { | ||
| $message = $commit->message; | ||
|
|
||
| if (str_starts_with($message, 'feat:') || str_starts_with($message, 'feat(')) { | ||
| $features[] = $message; | ||
| } elseif (str_starts_with($message, 'fix:') || str_starts_with($message, 'fix(')) { | ||
| $fixes[] = $message; | ||
| } elseif (str_contains($message, 'BREAKING CHANGE')) { | ||
| $breaking[] = $message; | ||
| } else { | ||
| $other[] = $message; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, let's locate and read the file in question
find . -name "github-repo-maintainer.md" -type fRepository: jordanpartridge/github-client
Length of output: 115
🏁 Script executed:
# Search for github-client package or related commit handling code
fd -type f \( -name "*.php" -o -name "*.md" \) | xargs grep -l "github-client\|Github::" 2>/dev/null | head -10Repository: jordanpartridge/github-client
Length of output: 243
🏁 Script executed:
# Look for how commits are accessed in the codebase
rg -B3 -A3 "commit.*message\|->message" --type php | head -30Repository: jordanpartridge/github-client
Length of output: 55
🏁 Script executed:
# Read the file to see the actual code and context
cat -n ./.claude/agents/github-repo-maintainer.md | sed -n '260,295p'Repository: jordanpartridge/github-client
Length of output: 1382
🏁 Script executed:
# Search for the github-client package or related code in the repository
find . -name "*.php" | head -20Repository: jordanpartridge/github-client
Length of output: 763
🏁 Script executed:
# Look for commit handling or Github class definitions
rg "class.*Commit\|function.*commit\|->commit\|->message" --type-listRepository: jordanpartridge/github-client
Length of output: 462
🏁 Script executed:
# Try a simpler search for commit-related code
rg "commit" --max-count=20Repository: jordanpartridge/github-client
Length of output: 17478
🏁 Script executed:
# Read the CommitData class to understand the structure
cat -n ./src/Data/Commits/CommitData.phpRepository: jordanpartridge/github-client
Length of output: 2572
🏁 Script executed:
# Also check CommitDetailsData which likely contains the message
cat -n ./src/Data/Commits/CommitDetailsData.phpRepository: jordanpartridge/github-client
Length of output: 2210
🏁 Script executed:
# Look at the actual command usage to see how commits are accessed
cat -n ./src/Commands/GithubClientCommand.php | sed -n '80,100p'Repository: jordanpartridge/github-client
Length of output: 715
🏁 Script executed:
# Continue reading the showCommits method to see actual usage
cat -n ./src/Commands/GithubClientCommand.php | sed -n '100,130p'Repository: jordanpartridge/github-client
Length of output: 1311
🏁 Script executed:
# Check if CommitData has any magic methods like __get or __call
rg -A20 "class CommitData" ./src/Data/Commits/CommitData.php | grep -E "__get|__call|__isset"Repository: jordanpartridge/github-client
Length of output: 55
🏁 Script executed:
# Also verify by looking at test files to see how commits are actually used
cat -n ./tests/CommitResourceTest.phpRepository: jordanpartridge/github-client
Length of output: 4628
Fix commit message access to use nested property.
Line 278 should access the message through the nested commit property: $commit->commit->message instead of $commit->message. The CommitData object contains a commit property (type CommitDetailsData) which holds the message field.
Corrected code snippet
foreach ($commits as $commit) {
$message = $commit->commit->message;
if (str_starts_with($message, 'feat:') || str_starts_with($message, 'feat(')) {
$features[] = $message;
} elseif (str_starts_with($message, 'fix:') || str_starts_with($message, 'fix(')) {
$fixes[] = $message;
} elseif (str_contains($message, 'BREAKING CHANGE')) {
$breaking[] = $message;
} else {
$other[] = $message;
}
}🤖 Prompt for AI Agents
.claude/agents/github-repo-maintainer.md around lines 268 to 289: the loop reads
commit message from $commit->message but the GitHub CommitData nests the text
under $commit->commit->message; update the code to read $message =
$commit->commit->message (and optionally guard with null checks if
$commit->commit or ->message may be missing) so categorization uses the actual
commit message.
Summary
.claude/agents/github-repo-maintainer.mdwith 6 documented skills for autonomous repository maintenanceSkills Included:
Test plan
.claude/agents/github-repo-maintainer.mdexists and is properly formattedCloses #113
🤖 Generated with Claude Code
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.