Pull Request Generation
Buddy automatically creates professional, well-formatted pull requests that match industry standards set by tools like Renovate. Each PR includes detailed information, release notes, and interactive features.
PR Format & Structure
Professional Layout
Buddy generates PRs with a standardized format:
markdown
# chore(deps): update dependency react to v18.3.1
This PR contains the following updates:
| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [react](https://react.dev) ([source](https://github.com/facebook/react)) | [`^18.2.0` -> `^18.3.1`](https://renovatebot.com/diffs/npm/react/18.2.0/18.3.1) | [](https://docs.renovatebot.com/merge-confidence/) | ... |
---
### Release Notes
<details>
<summary>facebook/react (react)</summary>
**18.2.0 -> 18.3.1**
Bug fixes and performance improvements...
</details>
---
### 📊 Package Statistics
- **react**: 20,102,656 weekly downloads
---
This PR was generated by [Buddy](https://github.com/stacksjs/buddy-bot) 🤖
Key Features
- 📊 Confidence Metrics: Age, adoption, and compatibility scores
- 🔗 Source Links: Direct links to repositories and changelogs
- 📈 Download Stats: Weekly download numbers for popularity context
- 📝 Release Notes: Automatically fetched from GitHub releases
- ♻️ Rebase Support: Interactive checkbox for PR updates
Dynamic Labeling
Buddy automatically applies contextual labels based on update content:
Core Labels
dependencies
: Applied to all dependency update PRspatch
/minor
/major
: Based on semantic version changessecurity
: Auto-detected for security-related packagesbulk-update
: For PRs with 5+ package updates
Configuration
typescript
// buddy-bot.config.ts
export default {
pullRequest: {
labels: [
'dependencies', // Always included
'automated', // Custom label
'needs-review', // Custom workflow label
]
}
}
Smart Label Detection
typescript
// Automatically detected labels
const securityPackages = [
'helmet',
'express-rate-limit',
'cors',
'bcrypt',
'jsonwebtoken'
]
// Applied when detected in updates
if (hasSecurityPackage) {
labels.add('security')
}
Assignees & Reviewers
Configuration
typescript
export default {
pullRequest: {
reviewers: ['team-lead', 'senior-dev'],
assignees: ['project-maintainer'],
labels: ['dependencies', 'auto-merge-candidate']
}
}
Automatic Assignment
- Reviewers: Automatically requested for PR review
- Assignees: Assigned ownership of the PR
- Teams: Support for GitHub team assignments
Duplicate Detection & Updates
Smart PR Management
Buddy prevents duplicate PRs by:
- Title Similarity: Detects similar PR titles
- Branch Pattern: Recognizes
buddy-bot/*
branches - Content Analysis: Compares package lists in PR bodies
- Author Filtering: Only checks PRs from automation
Update Behavior
typescript
const existingPR = existingPRs.find(pr =>
(pr.title === prTitle
|| pr.head.startsWith(branchPattern)
|| this.isSimilarPRTitle(pr.title, prTitle))
&& (pr.author === 'github-actions[bot]'
|| pr.author.includes('buddy')
|| pr.head.startsWith('buddy-bot/')),
)
if (existingPR) {
// Update existing PR instead of creating new one
await gitProvider.updatePullRequest(existingPR.number, {
title: prTitle,
body: prBody,
labels: dynamicLabels,
assignees: this.config.pullRequest?.assignees,
})
}
Rebase Functionality
Interactive Rebase
PRs include a rebase checkbox for manual triggers:
markdown
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
CLI Commands
bash
# Manually rebase a specific PR
buddy-bot rebase 17
# Auto-detect and rebase checked PRs
buddy-bot check-rebase
# Force rebase even if up-to-date
buddy-bot rebase 17 --force
Rebase Process
- Checkbox Detection: Scans PR body for checked rebase box
- Content Analysis: Extracts current package updates
- Fresh Scan: Gets latest available versions
- In-Place Update: Updates existing PR (preserves PR number)
- Notification: Unchecks box and notifies completion
Package.json Formatting
Preserves Original Format
Buddy maintains your exact JSON formatting:
javascript
// Before (your format)
const beforeFormat = {
files: ['README.md', 'bin', 'dist'],
dependencies: {
cac: '6.7.13'
}
}
// After (format preserved)
const afterFormat = {
files: ['README.md', 'bin', 'dist'],
dependencies: {
cac: '6.7.14'
}
}
Version Prefix Preservation
- Without caret:
"react": "18.2.0"
→"react": "18.3.1"
- With caret:
"react": "^18.2.0"
→"react": "^18.3.1"
- With tilde:
"react": "~18.2.0"
→"react": "~18.3.1"
Release Notes Integration
Automatic Fetching
Buddy automatically fetches release notes from:
- GitHub Releases: Official release notes from repositories
- Changelog Files: CHANGELOG.md, HISTORY.md, etc.
- Package Registry: npm registry metadata
- Repository Links: Direct links to compare views
Content Processing
typescript
interface ReleaseNotesOptions {
packageName: string
fromVersion: string
toVersion: string
}
interface ReleaseNotesResult {
content: string
source: string
}
async function fetchReleaseNotes(
options: ReleaseNotesOptions
): Promise<ReleaseNotesResult> {
// 1. Try GitHub releases API
const releases = await github.repos.listReleases()
// 2. Fallback to changelog files
const changelog = await fetchChangelog(repoUrl)
// 3. Extract relevant sections
return extractVersionNotes(changelog, options.fromVersion, options.toVersion)
}
Branch Management
Naming Convention
typescript
const branchName = `buddy-bot/update-${group.name.toLowerCase().replace(/\s+/g, '-')}-${timestamp}`
// Examples:
// buddy-bot/update-non-major-dependencies-1704123456789
// buddy-bot/update-react-ecosystem-1704123456789
// buddy-bot/update-security-patches-1704123456789
Branch Lifecycle
- Creation: New branch from base branch (main/develop)
- Commits: Package.json updates with descriptive messages
- PR Creation: Automated PR creation with full metadata
- Updates: In-place updates preserve branch and PR number
- Cleanup: Automatic cleanup after merge/close
Customization Options
PR Title Format
typescript
export default {
pullRequest: {
titleFormat: 'chore(deps): {updateType} {packages}',
// Results in: "chore(deps): update dependencies react, typescript"
}
}
Body Template
typescript
export default {
pullRequest: {
bodyTemplate: `
# 🤖 Automated Dependency Update
{updateTable}
## 📋 Changes
{releaseNotes}
## 🔧 Configuration
This update was generated with strategy: {strategy}
`
}
}
Commit Message Format
typescript
export default {
pullRequest: {
commitMessageFormat: 'chore(deps): update {packages}',
// Results in: "chore(deps): update react to v18.3.1"
}
}
Best Practices
PR Organization
- Group Related Updates: Keep ecosystem packages together
- Separate Major Updates: Create individual PRs for breaking changes
- Batch Patch Updates: Combine small patch updates
- Label Strategically: Use labels for workflow automation
Review Process
- Automated Checks: Let CI validate updates first
- Review Major Updates: Always review breaking changes manually
- Test Thoroughly: Run full test suites on update branches
- Monitor Performance: Watch for performance regressions
Merge Strategy
typescript
export default {
pullRequest: {
autoMerge: {
enabled: true,
strategy: 'squash',
conditions: ['patch-only', 'ci-passing']
}
}
}
GitHub Integration
Required Permissions
yaml
permissions:
contents: write # Create branches and commits
pull-requests: write # Create and update PRs
issues: write # Assign users and add labels
actions: read # Read workflow status
API vs CLI
Buddy uses a dual approach:
- GitHub CLI (Primary): More reliable for permissions
- GitHub API (Fallback): Direct API calls when CLI fails
typescript
try {
return await this.createPullRequestWithCLI(options)
}
catch (error) {
console.warn('GitHub CLI failed, trying API...', error)
return await this.createPullRequestWithAPI(options)
}