Skip to content

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) | [![age](https://developer.mend.io/api/mc/badges/age/npm/react/18.3.1?slim=true)](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 PRs
  • patch/minor/major: Based on semantic version changes
  • security: Auto-detected for security-related packages
  • bulk-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:

  1. Title Similarity: Detects similar PR titles
  2. Branch Pattern: Recognizes buddy-bot/* branches
  3. Content Analysis: Compares package lists in PR bodies
  4. 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

  1. Checkbox Detection: Scans PR body for checked rebase box
  2. Content Analysis: Extracts current package updates
  3. Fresh Scan: Gets latest available versions
  4. In-Place Update: Updates existing PR (preserves PR number)
  5. 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

  1. Creation: New branch from base branch (main/develop)
  2. Commits: Package.json updates with descriptive messages
  3. PR Creation: Automated PR creation with full metadata
  4. Updates: In-place updates preserve branch and PR number
  5. 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

  1. Group Related Updates: Keep ecosystem packages together
  2. Separate Major Updates: Create individual PRs for breaking changes
  3. Batch Patch Updates: Combine small patch updates
  4. Label Strategically: Use labels for workflow automation

Review Process

  1. Automated Checks: Let CI validate updates first
  2. Review Major Updates: Always review breaking changes manually
  3. Test Thoroughly: Run full test suites on update branches
  4. 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:

  1. GitHub CLI (Primary): More reliable for permissions
  2. 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)
}

Released under the MIT License.