also looking at this
docs: replace the claims the source does not support
#1400
32 files
+1660
-1772
Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.
| @@ -955,17 +955,17 @@ Choose from several carefully crafted presets with smart recommendations: | ||
| 955 | 955 | |
| 956 | 956 | #### 📝 Step 7: Enhanced Configuration Generation |
| 957 | 957 | |
| 958 | - Creates `buddy.config.json` with repository-specific settings | |
| 958 | - Creates `buddy.config.ts` with repository-specific settings | |
| 959 | 959 | - **Project-aware defaults** - Configuration optimized for detected project type |
| 960 | 960 | - **Ecosystem integration** - Includes detected package managers and dependency files |
| 961 | 961 | - Includes sensible defaults and customization options |
| 962 | 962 | |
| 963 | 963 | **�� Step 8: Workflow Generation & Validation** |
| 964 | 964 | |
| 965 | - Generates three core GitHub Actions workflows: | |
| 966 | - `buddy-dashboard.yml` - Dependency Dashboard Management | |
| 967 | - `buddy-check.yml` - Auto-rebase PR checker | |
| 968 | - `buddy-update.yml` - Scheduled dependency updates | |
| 965 | - Generates two GitHub Actions workflows: | |
| 966 | - `buddy.yml` - Unified workflow: rebase checks, scheduled updates and the dashboard | |
| 967 | - `buddy-security.yml` - Security audit, kept separate so it triggers on its own path filters | |
| 968 | - Removes the stale `buddy-check.yml`, `buddy-update.yml`, `buddy-dashboard.yml` and `gh-audit.yml` if an earlier version left them behind | |
| 969 | 969 | - **YAML validation** - Ensures generated workflows are syntactically correct |
| 970 | 970 | - **Security best practices** - Validates token usage and permissions |
| 971 | 971 | - **Workflow testing** - Verifies generated workflows meet requirements |
| @@ -1018,7 +1018,7 @@ buddy update-check --dry-run | ||
| 1018 | 1018 | buddy update-check --verbose |
| 1019 | 1019 | |
| 1020 | 1020 | # Get help |
| 1021 | buddy help | |
| 1021 | buddy --help | |
| 1022 | 1022 | ``` |
| 1023 | 1023 | |
| 1024 | 1024 | ### Configuration |
| @@ -1281,7 +1281,7 @@ All Buddy pull requests include a rebase checkbox at the bottom: | ||
| 1281 | 1281 | ### Using the Rebase Feature |
| 1282 | 1282 | |
| 1283 | 1283 | 1. **Check the box**: In any Buddy PR, check the rebase checkbox |
| 1284 | 2. **Automatic detection**: The rebase workflow runs every minute to detect checked boxes | |
| 1284 | 2. **Automatic detection**: Editing the PR body fires the workflow, which detects the checked box | |
| 1285 | 1285 | 3. **Updates applied**: The PR is automatically updated with the latest dependency versions |
| 1286 | 1286 | 4. **Checkbox unchecked**: After successful rebase, the checkbox is automatically unchecked |
| 1287 | 1287 | |
| @@ -1302,9 +1302,9 @@ buddy update-check --verbose | ||
| 1302 | 1302 | |
| 1303 | 1303 | ### Automated Rebase Workflow |
| 1304 | 1304 | |
| 1305 | Buddy includes a pre-built GitHub Actions workflow (`.github/workflows/buddy-check.yml`) that: | |
| 1305 | Buddy includes a pre-built GitHub Actions workflow (`.github/workflows/buddy.yml`) that: | |
| 1306 | 1306 | |
| 1307 | - **�� Runs every minute**: Automatically checks for rebase requests | |
| 1307 | - **�� Event-driven**: Triggers on `pull_request: [edited]` and `issues: [edited]`, so ticking a checkbox runs it immediately — no polling | |
| 1308 | 1308 | - **�� Scans all PRs**: Finds Buddy PRs with checked rebase boxes |
| 1309 | 1309 | - **�� Updates dependencies**: Re-scans for latest versions and updates files |
| 1310 | 1310 | - **�� Updates PR content**: Refreshes PR title, body, and file changes |
| @@ -1346,9 +1346,9 @@ buddy dashboard --title "My Dependencies" | ||
| 1346 | 1346 | |
| 1347 | 1347 | ### Automated Dashboard Updates |
| 1348 | 1348 | |
| 1349 | Buddy includes a pre-built GitHub workflow (`.github/workflows/buddy-dashboard.yml`) that automatically updates your dependency dashboard: | |
| 1349 | Buddy includes a pre-built GitHub workflow (`.github/workflows/buddy.yml`) that automatically updates your dependency dashboard: | |
| 1350 | 1350 | |
| 1351 | - **�� Scheduled**: Runs Monday, Wednesday, Friday at 9 AM UTC | |
| 1351 | - **�� Scheduled**: Every 2 hours, 15 minutes after the dependency update run (cron `15 */2 * * *`) | |
| 1352 | 1352 | - **��️ Manual**: Trigger from Actions tab with custom options |
| 1353 | 1353 | - **�� Auto-Pin**: Keeps dashboard pinned by default |
| 1354 | 1354 | - **�� Dry-Run**: Preview mode available |
| @@ -1423,7 +1423,7 @@ Buddy automatically detects and updates the following dependency file formats: | ||
| 1423 | 1423 | - **.github/workflows/*.yml** - GitHub Actions workflow files |
| 1424 | 1424 | - **.github/workflows/*.yaml** - Alternative YAML extension |
| 1425 | 1425 | |
| 1426 | All dependency files are parsed using the `ts-pkgx` library to ensure compatibility with the pkgx registry ecosystem while maintaining support for tools like Launchpad that reuse the same registry format. GitHub Actions are detected by parsing `uses:` statements in workflow files and checking for updates via the GitHub releases API. | |
| 1426 | All dependency files are parsed using the `ts-pantry` library to ensure compatibility with the pkgx registry ecosystem while maintaining support for tools like Launchpad that reuse the same registry format. GitHub Actions are detected by parsing `uses:` statements in workflow files and checking for updates via the GitHub releases API. | |
| 1427 | 1427 | |
| 1428 | 1428 | ### Pull Request Format |
| 1429 | 1429 | |
| @@ -26,7 +26,7 @@ Neither half requires the other. Run the reviewer with no dependency workflows, | ||
| 26 | 26 | |
| 27 | 27 | - **Inline Findings**: _Anchored to changed lines, describing the failure rather than a style preference_ |
| 28 | 28 | - **Incremental by Default**: _A second push gets new findings, not the ones you already read_ |
| 29 | - **Conversational**: _`@buddy review`, `full-review`, `summary`, `resolve`, `pause`, `resume`, `plan`, `remember` — or just ask a question_ | |
| 29 | - **Conversational**: _`@buddy review`, `full-review`, `summary`, `pause`, `resume`, `rebase`, `remember` — or just ask a question_ | |
| 30 | 30 | - **Local Review**: _`buddy review` reads your working tree, so problems are found before the PR exists_ |
| 31 | 31 | - **Works Without a Key**: _`--light` runs secret scanning, actionlint, shellcheck, hadolint, markdownlint and syntax checks with no model and no network_ |
| 32 | 32 | - **Merge Gates**: _Title format, description quality, linked issue and dependency policy published as a check run_ |
| @@ -206,17 +206,17 @@ Choose from several carefully crafted presets with smart recommendations: | ||
| 206 | 206 | |
| 207 | 207 | #### 📝 Step 7: Enhanced Configuration Generation |
| 208 | 208 | |
| 209 | - Creates `buddy.config.json` with repository-specific settings | |
| 209 | - Creates `buddy.config.ts` with repository-specific settings | |
| 210 | 210 | - **Project-aware defaults** - Configuration optimized for detected project type |
| 211 | 211 | - **Ecosystem integration** - Includes detected package managers and dependency files |
| 212 | 212 | - Includes sensible defaults and customization options |
| 213 | 213 | |
| 214 | 214 | **�� Step 8: Workflow Generation & Validation** |
| 215 | 215 | |
| 216 | - Generates three core GitHub Actions workflows: | |
| 217 | - `buddy-dashboard.yml` - Dependency Dashboard Management | |
| 218 | - `buddy-check.yml` - Auto-rebase PR checker | |
| 219 | - `buddy-update.yml` - Scheduled dependency updates | |
| 216 | - Generates two GitHub Actions workflows: | |
| 217 | - `buddy.yml` - Unified workflow (rebase checks, dependency updates, dashboard management) | |
| 218 | - `buddy-security.yml` - Security audit, kept separate so it can trigger on its own path filters | |
| 219 | - Removes stale `buddy-check.yml`, `buddy-update.yml` and `buddy-dashboard.yml` files from earlier versions | |
| 220 | 220 | - **YAML validation** - Ensures generated workflows are syntactically correct |
| 221 | 221 | - **Security best practices** - Validates token usage and permissions |
| 222 | 222 | - **Workflow testing** - Verifies generated workflows meet requirements |
| @@ -269,7 +269,7 @@ buddy update-check --dry-run | ||
| 269 | 269 | buddy update-check --verbose |
| 270 | 270 | |
| 271 | 271 | # Get help |
| 272 | buddy help | |
| 272 | buddy --help | |
| 273 | 273 | ``` |
| 274 | 274 | |
| 275 | 275 | ### Configuration |
| @@ -532,7 +532,7 @@ All Buddy pull requests include a rebase checkbox at the bottom: | ||
| 532 | 532 | ### Using the Rebase Feature |
| 533 | 533 | |
| 534 | 534 | 1. **Check the box**: In any Buddy PR, check the rebase checkbox |
| 535 | 2. **Automatic detection**: The rebase workflow runs every minute to detect checked boxes | |
| 535 | 2. **Automatic detection**: Editing the PR body fires the workflow, which detects the checked box | |
| 536 | 536 | 3. **Updates applied**: The PR is automatically updated with the latest dependency versions |
| 537 | 537 | 4. **Checkbox unchecked**: After successful rebase, the checkbox is automatically unchecked |
| 538 | 538 | |
| @@ -553,9 +553,9 @@ buddy update-check --verbose | ||
| 553 | 553 | |
| 554 | 554 | ### Automated Rebase Workflow |
| 555 | 555 | |
| 556 | Buddy includes a pre-built GitHub Actions workflow (`.github/workflows/buddy-check.yml`) that: | |
| 556 | Buddy includes a pre-built GitHub Actions workflow (`.github/workflows/buddy.yml`) that: | |
| 557 | 557 | |
| 558 | - **�� Runs every minute**: Automatically checks for rebase requests | |
| 558 | - **�� Event-driven**: Triggers on `pull_request: [edited]` and `issues: [edited]`, so ticking a checkbox runs it immediately — no polling | |
| 559 | 559 | - **�� Scans all PRs**: Finds Buddy PRs with checked rebase boxes |
| 560 | 560 | - **�� Updates dependencies**: Re-scans for latest versions and updates files |
| 561 | 561 | - **�� Updates PR content**: Refreshes PR title, body, and file changes |
| @@ -598,9 +598,9 @@ buddy dashboard --title "My Dependencies" | ||
| 598 | 598 | |
| 599 | 599 | ### Automated Dashboard Updates |
| 600 | 600 | |
| 601 | Buddy includes a pre-built GitHub workflow (`.github/workflows/buddy-dashboard.yml`) that automatically updates your dependency dashboard: | |
| 601 | The unified workflow (`.github/workflows/buddy.yml`) automatically updates your dependency dashboard: | |
| 602 | 602 | |
| 603 | - **�� Scheduled**: Runs Monday, Wednesday, Friday at 9 AM UTC | |
| 603 | - **�� Scheduled**: Runs every 2 hours, 15 minutes after the dependency update run | |
| 604 | 604 | - **��️ Manual**: Trigger from Actions tab with custom options |
| 605 | 605 | - **�� Auto-Pin**: Keeps dashboard pinned by default |
| 606 | 606 | - **�� Dry-Run**: Preview mode available |
| @@ -684,7 +684,7 @@ Detected anywhere in the tree, in all three naming conventions: | ||
| 684 | 684 | - `<prefix>.dockerfile` - e.g. `docker/api.dockerfile`, common in monorepos |
| 685 | 685 | - `Containerfile`, `<prefix>.containerfile` - the OCI/Podman spelling |
| 686 | 686 | |
| 687 | All dependency files are parsed using the `ts-pkgx` library to ensure compatibility with the pkgx registry ecosystem while maintaining support for tools like Launchpad that reuse the same registry format. GitHub Actions are detected by parsing `uses:` statements in workflow files and checking for updates via the GitHub releases API. | |
| 687 | All dependency files are parsed using the `ts-pantry` library to ensure compatibility with the pkgx registry ecosystem while maintaining support for tools like Launchpad that reuse the same registry format. GitHub Actions are detected by parsing `uses:` statements in workflow files and checking for updates via the GitHub releases API. | |
| 688 | 688 | |
| 689 | 689 | ### Pull Request Format |
| 690 | 690 | |
| @@ -748,8 +748,8 @@ Each table is followed by detailed release notes, changelogs, and package statis | ||
| 748 | 748 | |
| 749 | 749 | - **`all`**: Update all dependencies regardless of semver impact |
| 750 | 750 | - **`major`**: Only major version updates |
| 751 | - **`minor`**: Major and minor updates (no patch-only) | |
| 752 | - **`patch`**: All updates (major, minor, and patch) | |
| 751 | - **`minor`**: Minor and patch updates (no majors) | |
| 752 | - **`patch`**: Only patch updates | |
| 753 | 753 | |
| 754 | 754 | ## Auto-Merge Configuration |
| 755 | 755 | |
| @@ -1033,7 +1033,7 @@ bun run build | ||
| 1033 | 1033 | |
| 1034 | 1034 | ## Changelog |
| 1035 | 1035 | |
| 1036 | Please see our [releases](https://github.com/stacksjs/stacks/releases) page for more information on what has changed recently. | |
| 1036 | Please see our [releases](https://github.com/stacksjs/buddy/releases) page for more information on what has changed recently. | |
| 1037 | 1037 | |
| 1038 | 1038 | ## Contributing |
| 1039 | 1039 | |
| @@ -1043,7 +1043,7 @@ Please see the [Contributing Guide](https://github.com/stacksjs/contributing) fo | ||
| 1043 | 1043 | |
| 1044 | 1044 | For help, discussion about best practices, or any other conversation that would benefit from being searchable: |
| 1045 | 1045 | |
| 1046 | [Discussions on GitHub](https://github.com/stacksjs/stacks/discussions) | |
| 1046 | [Discussions on GitHub](https://github.com/stacksjs/buddy/discussions) | |
| 1047 | 1047 | |
| 1048 | 1048 | For casual chit-chat with others using this package: |
| 1049 | 1049 | |
| @@ -1078,8 +1078,8 @@ The MIT License (MIT). Please see [LICENSE](LICENSE.md) for more information. | ||
| 1078 | 1078 | Made with �� |
| 1079 | 1079 | |
| 1080 | 1080 | <!-- Badges --> |
| 1081 | [npm-version-src]: https://img.shields.io/npm/v/buddy?style=flat-square | |
| 1082 | [npm-version-href]: https://npmjs.com/package/buddy | |
| 1081 | [npm-version-src]: https://img.shields.io/npm/v/%40buddysh%2Fbuddy?style=flat-square | |
| 1082 | [npm-version-href]: https://npmjs.com/package/%40buddysh%2Fbuddy | |
| 1083 | 1083 | [github-actions-src]: https://img.shields.io/github/actions/workflow/status/stacksjs/buddy/ci.yml?style=flat-square&branch=main |
| 1084 | 1084 | [github-actions-href]: https://github.com/stacksjs/buddy/actions?query=workflow%3Aci |
| 1085 | 1085 | |
| @@ -191,9 +191,8 @@ Buddy automatically generates optimized GitHub Actions workflows: | ||
| 191 | 191 | buddy setup |
| 192 | 192 | |
| 193 | 193 | # Generated files |
| 194 | # .github/workflows/buddy-dashboard.yml | |
| 195 | # .github/workflows/buddy-check.yml | |
| 196 | # .github/workflows/buddy-update.yml | |
| 194 | # .github/workflows/buddy.yml — checks, updates and the dashboard | |
| 195 | # .github/workflows/buddy-security.yml — the security audit | |
| 197 | 196 | ``` |
| 198 | 197 | |
| 199 | 198 | ### Removing Old Configurations |
| @@ -376,9 +376,8 @@ buddy dashboard | ||
| 376 | 376 | |
| 377 | 377 | Check generated GitHub Actions: |
| 378 | 378 | |
| 379 | - `.github/workflows/buddy-dashboard.yml` | |
| 380 | - `.github/workflows/buddy-check.yml` | |
| 381 | - `.github/workflows/buddy-update.yml` | |
| 379 | - `.github/workflows/buddy.yml` — the unified workflow: rebase checks, dependency updates and the dashboard | |
| 380 | - `.github/workflows/buddy-security.yml` — the security audit, kept separate so it triggers on its own path filters | |
| 382 | 381 | |
| 383 | 382 | ### 6. Monitor and Adjust |
| 384 | 383 | |
| @@ -360,9 +360,8 @@ buddy update --dry-run | ||
| 360 | 360 | |
| 361 | 361 | Check the generated GitHub Actions workflows: |
| 362 | 362 | |
| 363 | - `.github/workflows/buddy-dashboard.yml` | |
| 364 | - `.github/workflows/buddy-check.yml` | |
| 365 | - `.github/workflows/buddy-update.yml` | |
| 363 | - `.github/workflows/buddy.yml` — the unified workflow: rebase checks, dependency updates and the dashboard | |
| 364 | - `.github/workflows/buddy-security.yml` — the security audit, kept separate so it triggers on its own path filters | |
| 366 | 365 | |
| 367 | 366 | ### 5. Gradual Transition |
| 368 | 367 | |
| @@ -52,13 +52,11 @@ interface BuddyMethods { | ||
| 52 | 52 | |
| 53 | 53 | ```typescript |
| 54 | 54 | interface UpdateScanResult { |
| 55 | totalPackages: number | |
| 55 | 56 | updates: PackageUpdate[] |
| 56 | 57 | groups: UpdateGroup[] |
| 57 | metadata: { | |
| 58 | scanTime: Date | |
| 59 | strategy: string | |
| 60 | packageCount: number | |
| 61 | } | |
| 58 | scannedAt: Date | |
| 59 | duration: number | |
| 62 | 60 | } |
| 63 | 61 | ``` |
| 64 | 62 | |
| @@ -101,7 +99,8 @@ if (scanResult.updates.length > 0) { | ||
| 101 | 99 | |
| 102 | 100 | ### run() |
| 103 | 101 | |
| 104 | Runs the complete update process (scan + create PRs). | |
| 102 | Runs the complete update process: scans, then creates pull requests when | |
| 103 | `pullRequest` is configured. | |
| 105 | 104 | |
| 106 | 105 | ```typescript |
| 107 | 106 | interface BuddyRunMethod { |
| @@ -224,6 +223,7 @@ Main configuration interface: | ||
| 224 | 223 | interface BuddyConfig { |
| 225 | 224 | verbose?: boolean |
| 226 | 225 | repository?: { |
| 226 | /** Only 'github' is implemented; the others are rejected at validation */ | |
| 227 | 227 | provider: 'github' | 'gitlab' | 'bitbucket' |
| 228 | 228 | owner: string |
| 229 | 229 | name: string |
| @@ -231,7 +231,9 @@ interface BuddyConfig { | ||
| 231 | 231 | token?: string |
| 232 | 232 | } |
| 233 | 233 | packages?: { |
| 234 | /** 'all': every update · 'major': majors only · 'minor': minors and patches · 'patch': patches only */ | |
| 234 | 235 | strategy: 'major' | 'minor' | 'patch' | 'all' |
| 236 | /** Package names, matched exactly */ | |
| 235 | 237 | ignore?: string[] |
| 236 | 238 | pin?: Record<string, string> |
| 237 | 239 | groups?: PackageGroup[] |
| @@ -266,11 +268,15 @@ interface PackageUpdate { | ||
| 266 | 268 | currentVersion: string |
| 267 | 269 | newVersion: string |
| 268 | 270 | updateType: 'major' | 'minor' | 'patch' |
| 269 | dependencyType: 'dependencies' | 'devDependencies' | 'peerDependencies' | 'optionalDependencies' | |
| 270 | repository?: string | |
| 271 | /** 'dependencies' | 'devDependencies' | 'github-actions' | 'docker-image' | … */ | |
| 272 | dependencyType: Dependency['type'] | |
| 273 | /** Manifest the dependency was found in */ | |
| 274 | file: string | |
| 275 | metadata?: PackageMetadata | |
| 276 | releaseNotesUrl?: string | |
| 277 | changelogUrl?: string | |
| 271 | 278 | homepage?: string |
| 272 | description?: string | |
| 273 | changelog?: string | |
| 279 | securityAdvisories?: SecurityAdvisory[] | |
| 274 | 280 | } |
| 275 | 281 | ``` |
| 276 | 282 | |
| @@ -281,9 +287,10 @@ Groups related package updates: | ||
| 281 | 287 | ```typescript |
| 282 | 288 | interface UpdateGroup { |
| 283 | 289 | name: string |
| 284 | title: string | |
| 285 | 290 | updates: PackageUpdate[] |
| 286 | strategy: string | |
| 291 | updateType: 'major' | 'minor' | 'patch' | |
| 292 | title: string | |
| 293 | body: string | |
| 287 | 294 | } |
| 288 | 295 | ``` |
| 289 | 296 | |
| @@ -293,42 +300,48 @@ Result of scanning for updates: | ||
| 293 | 300 | |
| 294 | 301 | ```typescript |
| 295 | 302 | interface UpdateScanResult { |
| 303 | totalPackages: number | |
| 296 | 304 | updates: PackageUpdate[] |
| 297 | 305 | groups: UpdateGroup[] |
| 298 | metadata: { | |
| 299 | scanTime: Date | |
| 300 | strategy: string | |
| 301 | packageCount: number | |
| 302 | ignoredCount: number | |
| 303 | } | |
| 306 | scannedAt: Date | |
| 307 | duration: number | |
| 304 | 308 | } |
| 305 | 309 | ``` |
| 306 | 310 | |
| 307 | 311 | ## Error Handling |
| 308 | 312 | |
| 309 | The Buddy class throws errors for various failure scenarios: | |
| 310 | ||
| 311 | 313 | ### Configuration Errors |
| 312 | 314 | |
| 315 | The constructor does not validate. A missing `repository` is reported when it | |
| 316 | is needed — `createPullRequests()` logs `Repository configuration required for | |
| 317 | PR creation` and returns without opening anything — so check the configuration | |
| 318 | before you rely on it: | |
| 319 | ||
| 313 | 320 | ```typescript |
| 314 | try { | |
| 315 | const buddy = new Buddy(invalidConfig) | |
| 316 | } | |
| 317 | catch (error) { | |
| 318 | if (error.message.includes('Repository configuration required')) { | |
| 319 | // Handle missing repository config | |
| 320 | } | |
| 321 | } | |
| 321 | import { Buddy, formatConfigIssues, validateConfig } from '@buddysh/buddy' | |
| 322 | ||
| 323 | const issues = validateConfig(config) | |
| 324 | if (issues.length > 0) | |
| 325 | throw new Error(formatConfigIssues(issues)) | |
| 326 | ||
| 327 | if (!config.repository?.owner || !config.repository?.name) | |
| 328 | throw new Error('repository.owner and repository.name are required to open pull requests') | |
| 329 | ||
| 330 | const buddy = new Buddy(config) | |
| 322 | 331 | ``` |
| 323 | 332 | |
| 324 | 333 | ### GitHub Token Errors |
| 325 | 334 | |
| 335 | When no token can be resolved — neither `repository.token`, nor `GITHUB_TOKEN`, | |
| 336 | nor `BUDDY_TOKEN` — creating the provider throws `No token for github. Set one | |
| 337 | of: GITHUB_TOKEN, BUDDY_TOKEN.` | |
| 338 | ||
| 326 | 339 | ```typescript |
| 327 | 340 | try { |
| 328 | 341 | await buddy.createPullRequests(scanResult) |
| 329 | 342 | } |
| 330 | 343 | catch (error) { |
| 331 | if (error.message.includes('GITHUB_TOKEN')) { | |
| 344 | if (error.message.includes('No token for')) { | |
| 332 | 345 | // Handle missing or invalid GitHub token |
| 333 | 346 | } |
| 334 | 347 | } |
| @@ -407,6 +420,10 @@ async function updateDependencies() { | ||
| 407 | 420 | }, |
| 408 | 421 | packages: { |
| 409 | 422 | strategy: process.env.UPDATE_STRATEGY as any || 'patch' |
| 423 | }, | |
| 424 | // `run()` only opens pull requests when `pullRequest` is configured | |
| 425 | pullRequest: { | |
| 426 | labels: ['dependencies'] | |
| 410 | 427 | } |
| 411 | 428 | }) |
| 412 | 429 | |
| @@ -2,772 +2,745 @@ | ||
| 2 | 2 | |
| 3 | 3 | TypeScript interfaces and types for buddy configuration. |
| 4 | 4 | |
| 5 | Everything on this page comes from `BuddyConfig` in `src/types.ts` and | |
| 6 | `PackageRule` in `src/rules/engine.ts`. A config file — `buddy.config.ts`, | |
| 7 | `buddy.config.js` or `buddy.config.json` — is merged over the packaged | |
| 8 | defaults and validated before any network or git work happens. | |
| 9 | ||
| 5 | 10 | ## Core Configuration |
| 6 | 11 | |
| 7 | 12 | ### `BuddyConfig` |
| 8 | 13 | |
| 9 | Main configuration interface for buddy. | |
| 14 | Every key is optional, and every section is inert until you set it. | |
| 10 | 15 | |
| 11 | 16 | ```typescript |
| 12 | 17 | interface BuddyConfig { |
| 13 | /** Repository configuration */ | |
| 14 | repository?: RepositoryConfig | |
| 15 | ||
| 16 | /** Package management settings */ | |
| 17 | packages?: PackageConfig | |
| 18 | ||
| 19 | /** Pull request configuration */ | |
| 20 | pullRequest?: PullRequestConfig | |
| 21 | ||
| 22 | /** Scheduling configuration */ | |
| 23 | schedule?: ScheduleConfig | |
| 18 | verbose?: boolean | |
| 19 | logLevel?: LogLevel | |
| 20 | repository?: RepositorySettings | |
| 21 | registries?: RegistrySettings | |
| 22 | security?: SecuritySettings | |
| 23 | schedule?: ScheduleSettings | |
| 24 | packages?: PackageSettings | |
| 25 | gates?: GateSettings | |
| 26 | issues?: IssueSettings | |
| 27 | reports?: ReportSettings | |
| 28 | analysis?: AnalysisSettings | |
| 29 | ai?: AiSettings | |
| 30 | notifications?: NotificationSettings | |
| 31 | maxPRsPerRun?: number | |
| 32 | pullRequest?: PullRequestSettings | |
| 33 | releaseNotes?: ReleaseNotesSettings | |
| 34 | workflows?: WorkflowSettings | |
| 35 | dashboard?: DashboardSettings | |
| 36 | } | |
| 37 | ||
| 38 | type BuddyOptions = Partial<BuddyConfig> | |
| 39 | ``` | |
| 24 | 40 | |
| 25 | /** Release notes configuration */ | |
| 26 | releaseNotes?: ReleaseNotesConfig | |
| 41 | The nested type names above are for reading convenience; in source they are | |
| 42 | inline object types on `BuddyConfig`. Each is described below, in declaration | |
| 43 | order. | |
| 27 | 44 | |
| 28 | /** Git provider settings */ | |
| 29 | git?: GitProviderConfig | |
| 45 | ## Logging | |
| 30 | 46 | |
| 31 | /** Registry configuration */ | |
| 32 | registries?: RegistryConfig[] | |
| 47 | ```typescript | |
| 48 | interface BuddyConfig { | |
| 49 | /** Enable verbose logging. Equivalent to `logLevel: 'debug'`. */ | |
| 50 | verbose?: boolean | |
| 33 | 51 | |
| 34 | /** Global settings */ | |
| 35 | global?: GlobalConfig | |
| 52 | /** How much output to emit. Overrides `verbose` when both are set. */ | |
| 53 | logLevel?: LogLevel | |
| 36 | 54 | } |
| 37 | ``` | |
| 38 | 55 | |
| 39 | ## Repository Configuration | |
| 56 | type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug' | |
| 57 | ``` | |
| 40 | 58 | |
| 41 | ### `RepositoryConfig` | |
| 59 | Use `'silent'` when embedding buddy in another tool that owns its own output. | |
| 60 | `logLevel` can also be set with the `BUDDY_LOG_LEVEL` environment variable. | |
| 61 | The packaged defaults set `verbose: true`. | |
| 42 | 62 | |
| 43 | Repository-specific settings. | |
| 63 | ## Repository | |
| 44 | 64 | |
| 45 | 65 | ```typescript |
| 46 | interface RepositoryConfig { | |
| 66 | interface RepositorySettings { | |
| 67 | /** Git provider */ | |
| 68 | provider: GitProviderName | |
| 69 | ||
| 47 | 70 | /** Repository owner/organization */ |
| 48 | 71 | owner: string |
| 49 | 72 | |
| 50 | 73 | /** Repository name */ |
| 51 | 74 | name: string |
| 52 | 75 | |
| 53 | /** Default branch */ | |
| 54 | defaultBranch?: string | |
| 55 | ||
| 56 | /** Repository URL */ | |
| 57 | url?: string | |
| 58 | ||
| 59 | /** Clone configuration */ | |
| 60 | clone?: { | |
| 61 | depth?: number | |
| 62 | sparse?: boolean | |
| 63 | submodules?: boolean | |
| 64 | } | |
| 65 | } | |
| 66 | ``` | |
| 67 | ||
| 68 | ## Package Configuration | |
| 69 | ||
| 70 | ### `PackageConfig` | |
| 71 | ||
| 72 | Package management and update configuration. | |
| 73 | ||
| 74 | ```typescript | |
| 75 | interface PackageConfig { | |
| 76 | /** Update strategy */ | |
| 77 | strategy?: UpdateStrategy | |
| 78 | ||
| 79 | /** Package manager to use */ | |
| 80 | manager?: PackageManager | |
| 81 | ||
| 82 | /** Packages to ignore */ | |
| 83 | ignore?: string[] | |
| 84 | ||
| 85 | /** Package groups */ | |
| 86 | groups?: PackageGroup[] | |
| 76 | /** Base branch for PRs */ | |
| 77 | baseBranch?: string | |
| 87 | 78 | |
| 88 | /** Workspace configuration */ | |
| 89 | workspaces?: WorkspaceConfig | |
| 79 | /** Access token for API operations */ | |
| 80 | token?: string | |
| 90 | 81 | |
| 91 | /** Version constraints */ | |
| 92 | constraints?: Record<string, string> | |
| 82 | /** REST API base URL */ | |
| 83 | apiUrl?: string | |
| 93 | 84 | |
| 94 | /** Include/exclude patterns */ | |
| 95 | include?: string[] | |
| 96 | exclude?: string[] | |
| 85 | /** Web base URL used for links in PR bodies and the dashboard */ | |
| 86 | serverUrl?: string | |
| 97 | 87 | } |
| 98 | 88 | ``` |
| 99 | 89 | |
| 100 | ### `UpdateStrategy` | |
| 90 | Only `github` is implemented. `gitlab` and `bitbucket` type-check but are | |
| 91 | rejected at validation with a link to the issue tracking them, so a config | |
| 92 | typo cannot reach a workflow run. | |
| 101 | 93 | |
| 102 | Available update strategies. | |
| 94 | `apiUrl` defaults to `GITHUB_API_URL` when set — GitHub Actions exports it on | |
| 95 | both github.com and Enterprise Server runners — otherwise | |
| 96 | `https://api.github.com`. Set it explicitly for GitHub Enterprise Server, for | |
| 97 | example `https://github.acme.com/api/v3`. `serverUrl` defaults to | |
| 98 | `GITHUB_SERVER_URL`, otherwise `https://github.com`. | |
| 103 | 99 | |
| 104 | ```typescript | |
| 105 | type UpdateStrategy = 'patch' | 'minor' | 'major' | 'all' | |
| 106 | ``` | |
| 100 | ## Registries | |
| 107 | 101 | |
| 108 | ### `PackageManager` | |
| 109 | ||
| 110 | Supported package managers. | |
| 102 | Package registry endpoints, for private or self-hosted mirrors. | |
| 111 | 103 | |
| 112 | 104 | ```typescript |
| 113 | type PackageManager = 'bun' | 'npm' | 'yarn' | 'pnpm' | 'auto' | |
| 114 | ``` | |
| 105 | interface RegistrySettings { | |
| 106 | /** npm registry base URL (default: `.npmrc` `registry=`, else registry.npmjs.org) */ | |
| 107 | npm?: string | |
| 115 | 108 | |
| 116 | ### `PackageGroup` | |
| 109 | /** Per-scope npm registry overrides, keyed by scope including the `@` */ | |
| 110 | npmScopes?: Record<string, string> | |
| 117 | 111 | |
| 118 | Package grouping configuration. | |
| 112 | /** Composer/Packagist base URL (default: packagist.org) */ | |
| 113 | composer?: string | |
| 119 | 114 | |
| 120 | ```typescript | |
| 121 | interface PackageGroup { | |
| 122 | /** Group name */ | |
| 123 | name: string | |
| 124 | ||
| 125 | /** Packages in group */ | |
| 126 | packages: string[] | |
| 127 | ||
| 128 | /** Group-specific strategy */ | |
| 129 | strategy?: UpdateStrategy | |
| 130 | ||
| 131 | /** Group labels */ | |
| 132 | labels?: string[] | |
| 133 | ||
| 134 | /** Group reviewers */ | |
| 135 | reviewers?: string[] | |
| 136 | ||
| 137 | /** Auto-merge for group */ | |
| 138 | autoMerge?: boolean | |
| 139 | ||
| 140 | /** Group description */ | |
| 141 | description?: string | |
| 115 | /** Per-host container registry credentials, keyed by host */ | |
| 116 | docker?: Record<string, { | |
| 117 | username?: string | |
| 118 | /** Environment variable holding the password */ | |
| 119 | passwordEnv?: string | |
| 120 | /** Environment variable holding a pre-issued bearer token */ | |
| 121 | tokenEnv?: string | |
| 122 | }> | |
| 142 | 123 | } |
| 143 | 124 | ``` |
| 144 | 125 | |
| 145 | ### `WorkspaceConfig` | |
| 126 | Docker secrets are referenced by environment variable name, never inlined, so | |
| 127 | a registry can be committed to the repository without committing the | |
| 128 | credential that reaches it. `ghcr.io` falls back to `GITHUB_TOKEN` | |
| 129 | automatically, so private GHCR images work in Actions with no config. | |
| 146 | 130 | |
| 147 | Monorepo workspace configuration. | |
| 131 | ## Security | |
| 148 | 132 | |
| 149 | 133 | ```typescript |
| 150 | interface WorkspaceConfig { | |
| 151 | /** Auto-detect workspaces */ | |
| 152 | autoDetect?: boolean | |
| 153 | ||
| 154 | /** Workspace patterns */ | |
| 155 | patterns?: string[] | |
| 156 | ||
| 157 | /** Workspace-specific configs */ | |
| 158 | configs?: Record<string, WorkspacePackageConfig> | |
| 159 | ||
| 160 | /** Coordination settings */ | |
| 161 | coordination?: WorkspaceCoordination | |
| 162 | } | |
| 134 | interface SecuritySettings { | |
| 135 | /** Query the OSV.dev advisory database (default: true) */ | |
| 136 | enabled?: boolean | |
| 163 | 137 | |
| 164 | interface WorkspacePackageConfig extends PackageConfig { | |
| 165 | /** Workspace path */ | |
| 166 | path?: string | |
| 138 | /** Move advisory-resolving updates to the front of the queue (default: true) */ | |
| 139 | prioritize?: boolean | |
| 167 | 140 | |
| 168 | /** Downstream workspaces */ | |
| 169 | downstream?: string[] | |
| 141 | /** Label name associated with advisory-resolving PRs (default: `security`) */ | |
| 142 | label?: string | |
| 170 | 143 | |
| 171 | /** Requires testing */ | |
| 172 | requiresTesting?: boolean | |
| 144 | /** Minimum severity to act on (default: `low`, i.e. everything) */ | |
| 145 | minimumSeverity?: VulnerabilitySeverity | |
| 173 | 146 | } |
| 174 | 147 | |
| 175 | interface WorkspaceCoordination { | |
| 176 | /** Align shared dependencies */ | |
| 177 | alignSharedDeps?: boolean | |
| 178 | ||
| 179 | /** Shared dependency groups */ | |
| 180 | sharedGroups?: Record<string, SharedGroupConfig> | |
| 181 | ||
| 182 | /** Update ordering */ | |
| 183 | updateOrder?: string[] | |
| 184 | } | |
| 148 | type VulnerabilitySeverity = 'low' | 'moderate' | 'high' | 'critical' | |
| 185 | 149 | ``` |
| 186 | 150 | |
| 187 | ## Pull Request Configuration | |
| 188 | ||
| 189 | ### `PullRequestConfig` | |
| 151 | Disable `enabled` for fully offline runs. `prioritize` is what lets a security | |
| 152 | update survive the `maxPRsPerRun` cap. `label` is the label name that | |
| 153 | auto-merge's `security-only` condition looks for on a pull request. | |
| 190 | 154 | |
| 191 | Pull request generation settings. | |
| 155 | ## Schedule | |
| 192 | 156 | |
| 193 | 157 | ```typescript |
| 194 | interface PullRequestConfig { | |
| 195 | /** PR title template */ | |
| 196 | title?: string | |
| 197 | ||
| 198 | /** PR body template */ | |
| 199 | body?: string | |
| 200 | ||
| 201 | /** PR labels */ | |
| 202 | labels?: LabelConfig | |
| 203 | ||
| 204 | /** Assignees */ | |
| 205 | assignees?: AssigneeConfig | |
| 206 | ||
| 207 | /** Reviewers */ | |
| 208 | reviewers?: ReviewerConfig | |
| 209 | ||
| 210 | /** Auto-merge settings */ | |
| 211 | autoMerge?: AutoMergeConfig | |
| 212 | ||
| 213 | /** Draft PR settings */ | |
| 214 | draft?: boolean | |
| 158 | interface ScheduleSettings { | |
| 159 | /** Cron expression for scheduled runs */ | |
| 160 | cron?: string | |
| 215 | 161 | |
| 216 | /** Branch naming */ | |
| 217 | branchNaming?: BranchNamingConfig | |
| 162 | /** Time zone for scheduling */ | |
| 163 | timezone?: string | |
| 218 | 164 | } |
| 219 | 165 | ``` |
| 220 | 166 | |
| 221 | ### `LabelConfig` | |
| 167 | Per-update scheduling windows live on `packages.rules[].schedule`, not here. | |
| 222 | 168 | |
| 223 | Label configuration for pull requests. | |
| 169 | ## Packages | |
| 224 | 170 | |
| 225 | 171 | ```typescript |
| 226 | interface LabelConfig { | |
| 227 | /** Static labels (always applied) */ | |
| 228 | static?: string[] | |
| 172 | interface PackageSettings { | |
| 173 | /** Update strategy for dependencies */ | |
| 174 | strategy: 'major' | 'minor' | 'patch' | 'all' | |
| 229 | 175 | |
| 230 | /** Dynamic labeling rules */ | |
| 231 | dynamic?: DynamicLabelConfig | |
| 176 | /** Packages to ignore */ | |
| 177 | ignore?: string[] | |
| 232 | 178 | |
| 233 | /** Pattern-based labels */ | |
| 234 | patterns?: Record<string, string[]> | |
| 179 | /** File/directory paths to ignore using glob patterns */ | |
| 180 | ignorePaths?: string[] | |
| 235 | 181 | |
| 236 | /** Conditional labels */ | |
| 237 | conditions?: LabelCondition[] | |
| 238 | } | |
| 182 | /** Packages to pin to specific versions */ | |
| 183 | pin?: Record<string, string> | |
| 239 | 184 | |
| 240 | interface DynamicLabelConfig { | |
| 241 | /** Enable dynamic labeling */ | |
| 242 | enabled?: boolean | |
| 185 | /** Group related packages together */ | |
| 186 | groups?: PackageGroup[] | |
| 243 | 187 | |
| 244 | /** Update type labels */ | |
| 245 | updateType?: Record<UpdateStrategy, string> | |
| 188 | /** Include prerelease versions (alpha, beta, rc, etc.) */ | |
| 189 | includePrerelease?: boolean | |
| 246 | 190 | |
| 247 | /** Ecosystem detection */ | |
| 248 | ecosystems?: Record<string, string[]> | |
| 191 | /** Exclude major version updates (even if strategy allows them) */ | |
| 192 | excludeMajor?: boolean | |
| 249 | 193 | |
| 250 | /** Custom rules */ | |
| 251 | rules?: LabelRule[] | |
| 252 | } | |
| 194 | /** Respect "latest" and "*" version indicators (default: true) */ | |
| 195 | respectLatest?: boolean | |
| 253 | 196 | |
| 254 | interface LabelCondition { | |
| 255 | /** Condition function */ | |
| 256 | when: (pr: PullRequestContext) => boolean | |
| 197 | /** Minimum age in minutes a version must have before installation (default: 0) */ | |
| 198 | minimumReleaseAge?: number | |
| 257 | 199 | |
| 258 | /** Labels to apply */ | |
| 259 | apply: string[] | |
| 260 | } | |
| 200 | /** Package names exempt from the minimum release age */ | |
| 201 | minimumReleaseAgeExclude?: string[] | |
| 261 | 202 | |
| 262 | interface LabelRule { | |
| 263 | /** Rule condition */ | |
| 264 | condition: string | |
| 203 | /** Conditional rules applied to matching updates */ | |
| 204 | rules?: PackageRule[] | |
| 265 | 205 | |
| 266 | /** Label to apply */ | |
| 267 | label: string | |
| 206 | /** Report updates held back by a range declared elsewhere (default: true) */ | |
| 207 | detectResolutionDrift?: boolean | |
| 268 | 208 | } |
| 269 | 209 | ``` |
| 270 | 210 | |
| 271 | ### `AssigneeConfig` | |
| 211 | A strategy names the greatest semver impact a run may propose, and admits | |
| 212 | everything gentler beneath it: | |
| 272 | 213 | |
| 273 | Assignee configuration. | |
| 214 | | `strategy` | Admits | | |
| 215 | |---|---| | |
| 216 | | `all` | major, minor and patch | | |
| 217 | | `major` | major only | | |
| 218 | | `minor` | minor and patch | | |
| 219 | | `patch` | patch only | | |
| 274 | 220 | |
| 275 | ```typescript | |
| 276 | interface AssigneeConfig { | |
| 277 | /** Static assignees */ | |
| 278 | static?: string[] | |
| 221 | `rules` are evaluated in order and later matches override earlier ones per | |
| 222 | field, so a broad rule can set a default and a narrow one refine it. | |
| 279 | 223 | |
| 280 | /** Dynamic assignment rules */ | |
| 281 | rules?: AssigneeRule[] | |
| 224 | `detectResolutionDrift` surfaces packages held below their latest version by a | |
| 225 | range declared elsewhere in the dependency tree. These cannot be fixed by | |
| 226 | updating this repository — somebody has to widen a range in the dependant — so | |
| 227 | they are reported on the dashboard rather than turned into pull requests. | |
| 282 | 228 | |
| 283 | /** Maximum assignees */ | |
| 284 | maxAssignees?: number | |
| 229 | ### `PackageGroup` | |
| 285 | 230 | |
| 286 | /** Require assignee */ | |
| 287 | requiresAssignee?: boolean | |
| 288 | } | |
| 231 | ```typescript | |
| 232 | interface PackageGroup { | |
| 233 | /** Group name */ | |
| 234 | name: string | |
| 289 | 235 | |
| 290 | interface AssigneeRule { | |
| 291 | /** Rule condition */ | |
| 292 | condition: string | |
| 236 | /** Package patterns to include */ | |
| 237 | patterns: string[] | |
| 293 | 238 | |
| 294 | /** Assignees to assign */ | |
| 295 | assignees: string[] | |
| 239 | /** Update strategy for this group */ | |
| 240 | strategy?: 'major' | 'minor' | 'patch' | 'all' | |
| 296 | 241 | } |
| 297 | 242 | ``` |
| 298 | 243 | |
| 299 | ### `ReviewerConfig` | |
| 300 | ||
| 301 | Reviewer configuration. | |
| 244 | A group has exactly these three fields, and only decides batching — which | |
| 245 | packages share a pull request. Anything conditional belongs in | |
| 246 | `packages.rules`. | |
| 302 | 247 | |
| 303 | ```typescript | |
| 304 | interface ReviewerConfig { | |
| 305 | /** Default reviewers */ | |
| 306 | default?: string[] | |
| 248 | ## Gates | |
| 307 | 249 | |
| 308 | /** Package-based reviewers */ | |
| 309 | packageOwners?: Record<string, string[]> | |
| 250 | Pre-merge gates and post-merge actions. | |
| 310 | 251 | |
| 311 | /** Team configuration */ | |
| 312 | teams?: Record<string, TeamConfig> | |
| 252 | ```typescript | |
| 253 | interface GateSettings { | |
| 254 | /** Require a conventional-commit pull request title */ | |
| 255 | titleFormat?: 'off' | 'warning' | 'error' | |
| 256 | ||
| 257 | /** Require a description, optionally with named sections */ | |
| 258 | description?: { | |
| 259 | mode: 'off' | 'warning' | 'error' | |
| 260 | requireSections?: string[] | |
| 261 | } | |
| 313 | 262 | |
| 314 | /** Review requirements */ | |
| 315 | requirements?: ReviewRequirements | |
| 263 | /** Block dependencies by licence, advisory or deprecation */ | |
| 264 | dependencyGate?: { | |
| 265 | mode: 'off' | 'warning' | 'error' | |
| 266 | licenseAllowlist?: string[] | |
| 267 | blockVulnerable?: boolean | |
| 268 | blockDeprecated?: boolean | |
| 269 | /** Block base images whose release cycle no longer gets security fixes */ | |
| 270 | blockEol?: boolean | |
| 271 | } | |
| 316 | 272 | |
| 317 | /** Fallback reviewers */ | |
| 318 | fallback?: string[] | |
| 273 | /** Check that a change addresses the issue it says it closes */ | |
| 274 | linkedIssue?: 'off' | 'warning' | 'error' | |
| 275 | ||
| 276 | /** Repository-specific natural-language assertions */ | |
| 277 | custom?: Array<{ | |
| 278 | name: string | |
| 279 | assertion: string | |
| 280 | mode?: 'off' | 'warning' | 'error' | |
| 281 | }> | |
| 282 | ||
| 283 | /** What to do once a pull request merges */ | |
| 284 | postMerge?: { | |
| 285 | changelog?: { enabled?: boolean, path?: string } | |
| 286 | commentOnIssues?: boolean | |
| 287 | refreshDashboard?: boolean | |
| 288 | } | |
| 319 | 289 | } |
| 290 | ``` | |
| 320 | 291 | |
| 321 | interface TeamConfig { | |
| 322 | /** Team members */ | |
| 323 | members: string[] | |
| 324 | ||
| 325 | /** Packages owned by team */ | |
| 326 | packages: string[] | |
| 327 | ||
| 328 | /** Required reviews from team */ | |
| 329 | requiredReviews?: number | |
| 330 | ||
| 331 | /** Auto-assign to team */ | |
| 332 | autoAssign?: boolean | |
| 333 | } | |
| 292 | The deterministic gates need no AI. The assertion gates — `linkedIssue` and | |
| 293 | `custom` — degrade to a neutral result rather than a pass when no provider is | |
| 294 | configured, so a check that could not run never reads as one that succeeded. | |
| 334 | 295 | |
| 335 | interface ReviewRequirements { | |
| 336 | /** Minimum required reviews */ | |
| 337 | required?: number | |
| 296 | ## Issues | |
| 338 | 297 | |
| 339 | /** Count team reviews */ | |
| 340 | teamReviews?: boolean | |
| 298 | ```typescript | |
| 299 | interface IssueSettings { | |
| 300 | /** Post the quick-links comment on new issues (default: false) */ | |
| 301 | quickLinks?: boolean | |
| 341 | 302 | |
| 342 | /** Dismiss stale reviews */ | |
| 343 | dismissStale?: boolean | |
| 303 | /** Include dependency context when the issue names a known package */ | |
| 304 | dependencyContext?: boolean | |
| 344 | 305 | } |
| 345 | 306 | ``` |
| 346 | 307 | |
| 347 | ### `AutoMergeConfig` | |
| 308 | Both actions are opt-in checkboxes on the posted comment: an issue is a | |
| 309 | request for a conversation as often as for code, and a bot that opens a pull | |
| 310 | request against every new issue is one a maintainer turns off in a week. | |
| 311 | ||
| 312 | ## Reports | |
| 348 | 313 | |
| 349 | Auto-merge configuration. | |
| 314 | Scheduled dependency-health and activity reports. | |
| 350 | 315 | |
| 351 | 316 | ```typescript |
| 352 | interface AutoMergeConfig { | |
| 353 | /** Enable auto-merge */ | |
| 317 | interface ReportSettings { | |
| 318 | /** Generate reports (default: false) */ | |
| 354 | 319 | enabled?: boolean |
| 355 | 320 | |
| 356 | /** Required status checks */ | |
| 357 | requiredChecks?: string[] | |
| 358 | ||
| 359 | /** Merge method */ | |
| 360 | method?: MergeMethod | |
| 361 | ||
| 362 | /** Conditions for auto-merge */ | |
| 363 | conditions?: AutoMergeCondition[] | |
| 364 | ||
| 365 | /** Delay before merge */ | |
| 366 | delay?: number | |
| 367 | } | |
| 321 | /** Cron expression for the scheduled run */ | |
| 322 | schedule?: string | |
| 368 | 323 | |
| 369 | type MergeMethod = 'merge' | 'squash' | 'rebase' | |
| 324 | /** Reporting window (default: `30d`) */ | |
| 325 | period?: '7d' | '30d' | '90d' | |
| 370 | 326 | |
| 371 | interface AutoMergeCondition { | |
| 372 | /** Update type */ | |
| 373 | updateType?: UpdateStrategy | |
| 327 | /** What the AI narrative should emphasise */ | |
| 328 | prompt?: string | |
| 374 | 329 | |
| 375 | /** Package patterns */ | |
| 376 | packages?: string[] | |
| 330 | /** Title of the report issue (default: `Dependency Report`) */ | |
| 331 | title?: string | |
| 377 | 332 | |
| 378 | /** Labels required */ | |
| 333 | /** Labels applied to the report issue */ | |
| 379 | 334 | labels?: string[] |
| 380 | ||
| 381 | /** Reviews required */ | |
| 382 | reviews?: number | |
| 383 | 335 | } |
| 384 | 336 | ``` |
| 385 | 337 | |
| 386 | ### `BranchNamingConfig` | |
| 338 | The report is computed from scan results and pull request history, so it works | |
| 339 | with no AI provider. A configured provider adds a narrative around the | |
| 340 | numbers; it never produces them. | |
| 387 | 341 | |
| 388 | Branch naming configuration. | |
| 342 | ## Analysis | |
| 389 | 343 | |
| 390 | 344 | ```typescript |
| 391 | interface BranchNamingConfig { | |
| 392 | /** Branch prefix */ | |
| 393 | prefix?: string | |
| 394 | ||
| 395 | /** Include update type */ | |
| 396 | includeUpdateType?: boolean | |
| 397 | ||
| 398 | /** Include package count */ | |
| 399 | includePackageCount?: boolean | |
| 400 | ||
| 401 | /** Custom template */ | |
| 402 | template?: string | |
| 345 | interface AnalysisSettings { | |
| 346 | /** Turn all analyzers off (default: true, they are cheap and local) */ | |
| 347 | enabled?: boolean | |
| 403 | 348 | |
| 404 | /** Separator character */ | |
| 405 | separator?: string | |
| 349 | /** Per-analyzer switches, keyed by name. Absent means enabled. */ | |
| 350 | tools?: Record<string, boolean> | |
| 406 | 351 | } |
| 407 | 352 | ``` |
| 408 | 353 | |
| 409 | ## Schedule Configuration | |
| 354 | Recognised tool names are `secrets`, `github-actions`, `syntax`, `linter`, | |
| 355 | `actionlint`, `shellcheck`, `hadolint` and `markdownlint`. Analyzers run | |
| 356 | whether or not an AI provider is configured, so a repository with no key still | |
| 357 | gets secret scanning, workflow auditing and whatever external linters the | |
| 358 | runner has installed. | |
| 410 | 359 | |
| 411 | ### `ScheduleConfig` | |
| 412 | ||
| 413 | Scheduling and automation settings. | |
| 360 | ## AI | |
| 414 | 361 | |
| 415 | 362 | ```typescript |
| 416 | interface ScheduleConfig { | |
| 417 | /** Cron expression */ | |
| 418 | cron?: string | |
| 419 | ||
| 420 | /** Timezone */ | |
| 421 | timezone?: string | |
| 422 | ||
| 423 | /** Enable scheduling */ | |
| 363 | interface AiSettings { | |
| 364 | /** Turn all AI features off even when a key is present */ | |
| 424 | 365 | enabled?: boolean |
| 425 | 366 | |
| 426 | /** Multiple schedules */ | |
| 427 | schedules?: NamedSchedule[] | |
| 367 | /** Which provider to use */ | |
| 368 | provider?: 'anthropic' | 'openai' | 'google' | 'openrouter' | 'openai-compatible' | |
| 428 | 369 | |
| 429 | /** Environment-based scheduling */ | |
| 430 | environments?: Record<string, EnvironmentSchedule> | |
| 370 | /** Model alias or concrete ID */ | |
| 371 | model?: string | |
| 431 | 372 | |
| 432 | /** Trigger-based updates */ | |
| 433 | triggers?: TriggerConfig | |
| 434 | } | |
| 373 | /** Reasoning depth to request (default: provider default) */ | |
| 374 | effort?: 'low' | 'medium' | 'high' | |
| 435 | 375 | |
| 436 | interface NamedSchedule { | |
| 437 | /** Schedule name */ | |
| 438 | name: string | |
| 376 | /** Environment variable holding the API key, when not the provider default */ | |
| 377 | apiKeyEnv?: string | |
| 439 | 378 | |
| 440 | /** Cron expression */ | |
| 441 | cron: string | |
| 379 | /** Base URL override, for gateways and OpenAI-compatible endpoints */ | |
| 380 | baseUrl?: string | |
| 442 | 381 | |
| 443 | /** Schedule-specific strategy */ | |
| 444 | strategy?: UpdateStrategy | |
| 382 | /** Hard ceiling on output tokens generated per run */ | |
| 383 | maxTokensPerRun?: number | |
| 445 | 384 | |
| 446 | /** Schedule labels */ | |
| 447 | labels?: string[] | |
| 385 | majorUpgrades?: MajorUpgradeSettings | |
| 386 | review?: ReviewSettings | |
| 387 | } | |
| 388 | ``` | |
| 448 | 389 | |
| 449 | /** Schedule reviewers */ | |
| 450 | reviewers?: string[] | |
| 390 | Every AI-powered feature is off unless a provider key is available, and | |
| 391 | degrades to a no-op rather than failing the run — the dependency bot works | |
| 392 | exactly as before with no AI configured. | |
| 451 | 393 | |
| 452 | /** Auto-merge for schedule */ | |
| 453 | autoMerge?: boolean | |
| 454 | } | |
| 394 | With `provider` omitted, the first provider with an available API key is | |
| 395 | chosen, in the order anthropic, openai, google, openrouter. Model aliases | |
| 396 | (`opus`, `sonnet`, `haiku`) resolve to current Anthropic models; every other | |
| 397 | provider needs a concrete ID. `BUDDY_MODEL` overrides `model` per run. Once | |
| 398 | `maxTokensPerRun` is reached, further requests fail rather than spending more. | |
| 455 | 399 | |
| 456 | interface EnvironmentSchedule extends NamedSchedule { | |
| 457 | /** Environment name */ | |
| 458 | environment?: string | |
| 400 | ### `ai.majorUpgrades` | |
| 459 | 401 | |
| 460 | /** Require approval */ | |
| 461 | requireApproval?: boolean | |
| 462 | } | |
| 402 | ```typescript | |
| 403 | interface MajorUpgradeSettings { | |
| 404 | /** Analyse major updates (default: false — opt in, it costs tokens) */ | |
| 405 | enabled?: boolean | |
| 406 | ||
| 407 | /** Attempt the migration rather than only analysing it (default: false) */ | |
| 408 | autoMigrate?: boolean | |
| 463 | 409 | |
| 464 | interface TriggerConfig { | |
| 465 | /** Security triggers */ | |
| 466 | security?: SecurityTrigger | |
| 410 | /** Open as a draft below this confidence (default: `high`) */ | |
| 411 | draftBelowConfidence?: 'high' | 'medium' | |
| 467 | 412 | |
| 468 | /** Major release triggers */ | |
| 469 | majorRelease?: MajorReleaseTrigger | |
| 413 | /** Maximum agent attempts per upgrade */ | |
| 414 | maxAttempts?: number | |
| 470 | 415 | |
| 471 | /** Batch threshold triggers */ | |
| 472 | batchThreshold?: BatchThresholdTrigger | |
| 416 | /** Globs limiting which packages are analysed; empty means all majors */ | |
| 417 | packages?: string[] | |
| 473 | 418 | } |
| 474 | 419 | ``` |
| 475 | 420 | |
| 476 | ## Release Notes Configuration | |
| 477 | ||
| 478 | ### `ReleaseNotesConfig` | |
| 421 | `autoMigrate` defaults off because a wrong migration is far more expensive | |
| 422 | than a missing one. | |
| 479 | 423 | |
| 480 | Release notes extraction and formatting. | |
| 424 | ### `ai.review` | |
| 481 | 425 | |
| 482 | 426 | ```typescript |
| 483 | interface ReleaseNotesConfig { | |
| 484 | /** Data sources */ | |
| 485 | sources?: ReleaseNotesSource | |
| 427 | interface ReviewSettings { | |
| 428 | /** Enable AI review (default: false until you opt in) */ | |
| 429 | enabled?: boolean | |
| 486 | 430 | |
| 487 | /** Content formatting */ | |
| 488 | formatting?: ReleaseNotesFormatting | |
| 431 | /** How thorough to be */ | |
| 432 | profile?: 'chill' | 'assertive' | |
| 489 | 433 | |
| 490 | /** Template configuration */ | |
| 491 | template?: ReleaseNotesTemplate | |
| 434 | /** Review draft pull requests too (default: false) */ | |
| 435 | drafts?: boolean | |
| 492 | 436 | |
| 493 | /** Aggregation settings */ | |
| 494 | aggregation?: ReleaseNotesAggregation | |
| 437 | /** Review automatically on open and push (default: true when enabled) */ | |
| 438 | autoReview?: boolean | |
| 495 | 439 | |
| 496 | /** Caching configuration */ | |
| 497 | caching?: CacheConfig | |
| 498 | } | |
| 440 | /** Skip pull requests whose title contains any of these, e.g. `wip` */ | |
| 441 | ignoreTitleKeywords?: string[] | |
| 499 | 442 | |
| 500 | interface ReleaseNotesSource { | |
| 501 | /** GitHub releases */ | |
| 502 | githubReleases?: GitHubReleasesConfig | |
| 443 | /** Skip pull requests opened by these users */ | |
| 444 | ignoreUsernames?: string[] | |
| 503 | 445 | |
| 504 | /** Changelog files */ | |
| 505 | changelog?: ChangelogConfig | |
| 446 | /** Request changes at this severity, or never (default: never) */ | |
| 447 | requestChangesOn?: 'never' | 'critical' | |
| 506 | 448 | |
| 507 | /** NPM registry */ | |
| 508 | npmRegistry?: NpmRegistryConfig | |
| 449 | /** Post only the summary and walkthrough, no inline findings */ | |
| 450 | summaryOnly?: boolean | |
| 509 | 451 | |
| 510 | /** Git commits */ | |
| 511 | gitCommits?: GitCommitsConfig | |
| 512 | } | |
| 452 | /** Gitignore-style path filters; `!` excludes */ | |
| 453 | pathFilters?: string[] | |
| 513 | 454 | |
| 514 | interface ReleaseNotesFormatting { | |
| 515 | /** Markdown processing */ | |
| 516 | markdown?: MarkdownConfig | |
| 455 | /** Guidance applied when reviewing files matching a glob */ | |
| 456 | pathInstructions?: Array<{ path: string, instructions: string }> | |
| 517 | 457 | |
| 518 | /** Content filters */ | |
| 519 | filters?: ContentFilters | |
| 458 | /** Convention files read from the base branch, or `false` to disable */ | |
| 459 | guidelineFiles?: string[] | false | |
| 520 | 460 | |
| 521 | /** Content enhancement */ | |
| 522 | enhance?: ContentEnhancement | |
| 461 | /** Global guidance prepended to every review */ | |
| 462 | instructions?: string | |
| 523 | 463 | } |
| 464 | ``` | |
| 524 | 465 | |
| 525 | interface ReleaseNotesTemplate { | |
| 526 | /** Header template */ | |
| 527 | header?: string | |
| 528 | ||
| 529 | /** Package section template */ | |
| 530 | packageSection?: string | |
| 466 | `chill` reports only confident defects; `assertive` also reports | |
| 467 | lower-confidence findings, marked so they can be filtered downstream. | |
| 468 | `pathFilters` apply on top of the built-in exclusions for lock files and build | |
| 469 | output. `guidelineFiles` defaults to the usual convention files — CLAUDE.md, | |
| 470 | AGENTS.md, .cursorrules and similar — and a list overrides those defaults. | |
| 531 | 471 | |
| 532 | /** Footer template */ | |
| 533 | footer?: string | |
| 472 | ## Notifications | |
| 534 | 473 | |
| 535 | /** Empty state message */ | |
| 536 | empty?: string | |
| 474 | ```typescript | |
| 475 | interface NotificationSettings { | |
| 476 | slack?: { webhookEnv?: string, events?: string[] } | |
| 477 | discord?: { webhookEnv?: string, events?: string[] } | |
| 537 | 478 | |
| 538 | /** Error message */ | |
| 539 | error?: string | |
| 479 | /** Signed JSON POSTs to your own endpoints */ | |
| 480 | webhooks?: Array<{ url: string, secretEnv?: string, events?: string[] }> | |
| 540 | 481 | } |
| 541 | 482 | ``` |
| 542 | 483 | |
| 543 | ## Git Provider Configuration | |
| 544 | ||
| 545 | ### `GitProviderConfig` | |
| 484 | Credentials are referenced by environment variable name, never inlined, so a | |
| 485 | destination can be committed without committing its credential. | |
| 546 | 486 | |
| 547 | Git provider settings. | |
| 487 | ## Pull Requests | |
| 548 | 488 | |
| 549 | 489 | ```typescript |
| 550 | interface GitProviderConfig { | |
| 551 | /** Provider type */ | |
| 552 | provider: GitProvider | |
| 553 | ||
| 554 | /** Provider-specific settings */ | |
| 555 | github?: GitHubConfig | |
| 556 | gitlab?: GitLabConfig | |
| 557 | ||
| 558 | /** Authentication */ | |
| 559 | auth?: AuthConfig | |
| 490 | interface BuddyConfig { | |
| 491 | /** Maximum number of PRs to create per workflow run (default: 10) */ | |
| 492 | maxPRsPerRun?: number | |
| 560 | 493 | |
| 561 | /** API configuration */ | |
| 562 | api?: ApiConfig | |
| 494 | pullRequest?: PullRequestSettings | |
| 563 | 495 | } |
| 564 | 496 | |
| 565 | type GitProvider = 'github' | 'gitlab' | |
| 497 | interface PullRequestSettings { | |
| 498 | /** Commit message format */ | |
| 499 | commitMessageFormat?: string | |
| 566 | 500 | |
| 567 | interface GitHubConfig { | |
| 568 | /** GitHub API URL */ | |
| 569 | apiUrl?: string | |
| 501 | /** PR title format */ | |
| 502 | titleFormat?: string | |
| 570 | 503 | |
| 571 | /** GitHub Enterprise URL */ | |
| 572 | baseUrl?: string | |
| 573 | ||
| 574 | /** App ID for GitHub App */ | |
| 575 | appId?: string | |
| 504 | /** PR body template */ | |
| 505 | bodyTemplate?: string | |
| 576 | 506 | |
| 577 | /** Installation ID */ | |
| 578 | installationId?: string | |
| 507 | /** Auto-merge settings */ | |
| 508 | autoMerge?: { | |
| 509 | enabled: boolean | |
| 510 | strategy: 'merge' | 'squash' | 'rebase' | |
| 511 | conditions?: string[] | |
| 512 | requireGreenCI?: boolean | |
| 513 | optOutLabel?: string | |
| 514 | } | |
| 579 | 515 | |
| 580 | /** Private key path */ | |
| 581 | privateKeyPath?: string | |
| 582 | } | |
| 516 | /** Reviewers to assign */ | |
| 517 | reviewers?: string[] | |
| 583 | 518 | |
| 584 | interface GitLabConfig { | |
| 585 | /** GitLab instance URL */ | |
| 586 | url?: string | |
| 519 | /** GitHub teams to request review from, by team slug */ | |
| 520 | teamReviewers?: string[] | |
| 587 | 521 | |
| 588 | /** Project ID */ | |
| 589 | projectId?: number | |
| 522 | /** Assignees to assign */ | |
| 523 | assignees?: string[] | |
| 590 | 524 | |
| 591 | /** Group ID */ | |
| 592 | groupId?: number | |
| 525 | /** Labels to add */ | |
| 526 | labels?: string[] | |
| 593 | 527 | } |
| 528 | ``` | |
| 594 | 529 | |
| 595 | interface AuthConfig { | |
| 596 | /** Personal access token */ | |
| 597 | token?: string | |
| 530 | `reviewers`, `assignees` and `labels` are plain string arrays. `teamReviewers` | |
| 531 | takes team slugs without the organisation prefix. Reviewers and assignees | |
| 532 | configured here are unioned with whatever the matching `packages.rules` | |
| 533 | contributed for the updates in the pull request. | |
| 598 | 534 | |
| 599 | /** Token environment variable */ | |
| 600 | tokenEnv?: string | |
| 535 | The labels a generated pull request carries are derived from its update types | |
| 536 | and the ecosystems it touches — `dependencies`, `major`/`minor`/`patch`, | |
| 537 | `npm`, `composer`, `zig`, `system`, `github-actions`, plus the package name | |
| 538 | itself on a single-package PR — unioned with the `labels` effect of any | |
| 539 | matching `packages.rules`. Per-update labelling therefore belongs in | |
| 540 | `packages.rules[].labels`. | |
| 601 | 541 | |
| 602 | /** OAuth configuration */ | |
| 603 | oauth?: OAuthConfig | |
| 604 | } | |
| 542 | ### `pullRequest.autoMerge` | |
| 605 | 543 | |
| 606 | interface ApiConfig { | |
| 607 | /** Request timeout */ | |
| 608 | timeout?: number | |
| 544 | `conditions` accepts `patch-only`, `minor-only`, `security-only` and `all`. A | |
| 545 | pull request qualifies when any listed condition accepts it. An empty or | |
| 546 | missing list means nothing auto-merges — the safe reading of a half-written | |
| 547 | config. Update types are read from the metadata manifest embedded in the PR | |
| 548 | body, not from its title, and a PR whose manifest is missing or truncated is | |
| 549 | never eligible. | |
| 609 | 550 | |
| 610 | /** Retry attempts */ | |
| 611 | retries?: number | |
| 551 | `requireGreenCI` defaults to `true` and is only meaningful on repositories | |
| 552 | without branch protection, where buddy merges directly instead of handing the | |
| 553 | pull request to GitHub's own auto-merge queue. `optOutLabel` defaults to | |
| 554 | `no-auto-merge`; a pull request carrying it never merges unattended. | |
| 612 | 555 | |
| 613 | /** Rate limiting */ | |
| 614 | rateLimit?: RateLimitConfig | |
| 615 | } | |
| 616 | ``` | |
| 556 | ## Release Notes | |
| 617 | 557 | |
| 618 | ## Registry Configuration | |
| 558 | ```typescript | |
| 559 | interface ReleaseNotesSettings { | |
| 560 | /** Enable release notes in PRs (default: true) */ | |
| 561 | enabled?: boolean | |
| 619 | 562 | |
| 620 | ### `RegistryConfig` | |
| 563 | /** Sanitize GitHub references (#123, issue/PR URLs) to prevent spam notifications (default: true) */ | |
| 564 | sanitizeReferences?: boolean | |
| 621 | 565 | |
| 622 | Package registry settings. | |
| 566 | /** Maximum number of releases to show per package (default: 3) */ | |
| 567 | maxReleases?: number | |
| 623 | 568 | |
| 624 | ```typescript | |
| 625 | interface RegistryConfig { | |
| 626 | /** Registry name */ | |
| 627 | name: string | |
| 569 | /** Maximum character length per release body (default: 1000) */ | |
| 570 | maxBodyLength?: number | |
| 628 | 571 | |
| 629 | /** Registry URL */ | |
| 630 | url: string | |
| 572 | /** Include compare links between versions (default: true) */ | |
| 573 | includeCompareLinks?: boolean | |
| 574 | } | |
| 575 | ``` | |
| 631 | 576 | |
| 632 | /** Authentication token */ | |
| 633 | token?: string | |
| 577 | ## Workflows | |
| 634 | 578 | |
| 635 | /** Scope for scoped registries */ | |
| 636 | scope?: string | |
| 579 | ```typescript | |
| 580 | interface WorkflowSettings { | |
| 581 | /** Enable workflow generation */ | |
| 582 | enabled?: boolean | |
| 637 | 583 | |
| 638 | /** Registry type */ | |
| 639 | type?: RegistryType | |
| 584 | /** Output directory for workflows (default: `.github/workflows`) */ | |
| 585 | outputDir?: string | |
| 586 | ||
| 587 | /** Workflow templates to generate */ | |
| 588 | templates?: { | |
| 589 | comprehensive?: boolean | |
| 590 | daily?: boolean | |
| 591 | weekly?: boolean | |
| 592 | monthly?: boolean | |
| 593 | docker?: boolean | |
| 594 | monorepo?: boolean | |
| 595 | } | |
| 640 | 596 | |
| 641 | /** Cache configuration */ | |
| 642 | cache?: CacheConfig | |
| 597 | /** Custom workflow configurations */ | |
| 598 | custom?: Array<{ | |
| 599 | name: string | |
| 600 | schedule: string | |
| 601 | strategy?: 'major' | 'minor' | 'patch' | 'all' | |
| 602 | autoMerge?: boolean | |
| 603 | reviewers?: string[] | |
| 604 | assignees?: string[] | |
| 605 | labels?: string[] | |
| 606 | }> | |
| 643 | 607 | } |
| 644 | ||
| 645 | type RegistryType = 'npm' | 'github' | 'private' | |
| 646 | 608 | ``` |
| 647 | 609 | |
| 648 | ## Global Configuration | |
| 649 | ||
| 650 | ### `GlobalConfig` | |
| 651 | ||
| 652 | Global settings and defaults. | |
| 610 | ## Dashboard | |
| 653 | 611 | |
| 654 | 612 | ```typescript |
| 655 | interface GlobalConfig { | |
| 656 | /** Verbose logging */ | |
| 657 | verbose?: boolean | |
| 613 | interface DashboardSettings { | |
| 614 | /** Enable dependency dashboard */ | |
| 615 | enabled?: boolean | |
| 616 | ||
| 617 | /** Dashboard title (default: `Dependency Dashboard`) */ | |
| 618 | title?: string | |
| 658 | 619 | |
| 659 | /** Dry run mode */ | |
| 660 | dryRun?: boolean | |
| 620 | /** Dashboard body template */ | |
| 621 | bodyTemplate?: string | |
| 661 | 622 | |
| 662 | /** Concurrency limit */ | |
| 663 | concurrency?: number | |
| 623 | /** Labels to add to dashboard issue */ | |
| 624 | labels?: string[] | |
| 664 | 625 | |
| 665 | /** Timeout settings */ | |
| 666 | timeout?: number | |
| 626 | /** Assignees to assign to dashboard issue */ | |
| 627 | assignees?: string[] | |
| 667 | 628 | |
| 668 | /** Error handling */ | |
| 669 | errorHandling?: ErrorHandlingConfig | |
| 629 | /** Include package.json dependencies */ | |
| 630 | includePackageJson?: boolean | |
| 670 | 631 | |
| 671 | /** Performance settings */ | |
| 672 | performance?: PerformanceConfig | |
| 673 | } | |
| 632 | /** Include dependency files (deps.yaml, etc.) */ | |
| 633 | includeDependencyFiles?: boolean | |
| 674 | 634 | |
| 675 | interface ErrorHandlingConfig { | |
| 676 | /** Retry configuration */ | |
| 677 | retry?: RetryConfig | |
| 635 | /** Include GitHub Actions */ | |
| 636 | includeGitHubActions?: boolean | |
| 678 | 637 | |
| 679 | /** Fallback strategies */ | |
| 680 | fallback?: FallbackConfig | |
| 638 | /** Show open PRs section */ | |
| 639 | showOpenPRs?: boolean | |
| 681 | 640 | |
| 682 | /** Error reporting */ | |
| 683 | reporting?: ErrorReportingConfig | |
| 684 | } | |
| 641 | /** Show detected dependencies section */ | |
| 642 | showDetectedDependencies?: boolean | |
| 685 | 643 | |
| 686 | interface PerformanceConfig { | |
| 687 | /** Caching strategy */ | |
| 688 | cache?: CacheStrategy | |
| 644 | /** Show deprecated dependencies section */ | |
| 645 | showDeprecatedDependencies?: boolean | |
| 689 | 646 | |
| 690 | /** Parallel processing */ | |
| 691 | parallel?: ParallelConfig | |
| 647 | /** Issue number to update (if it exists) */ | |
| 648 | issueNumber?: number | |
| 692 | 649 | |
| 693 | /** Memory management */ | |
| 694 | memory?: MemoryConfig | |
| 650 | /** Pin the dashboard issue to the top of the issue list (default: false) */ | |
| 651 | pin?: boolean | |
| 695 | 652 | } |
| 696 | 653 | ``` |
| 697 | 654 | |
| 698 | ## Utility Types | |
| 655 | GitHub allows at most three pinned issues per repository; when that limit is | |
| 656 | already reached the dashboard is still created, just unpinned. | |
| 699 | 657 | |
| 700 | ### `PullRequestContext` | |
| 701 | ||
| 702 | Context object passed to conditional functions. | |
| 703 | ||
| 704 | ```typescript | |
| 705 | interface PullRequestContext { | |
| 706 | /** Packages being updated */ | |
| 707 | packages: PackageUpdate[] | |
| 658 | ## Package Rules | |
| 708 | 659 | |
| 709 | /** Update type */ | |
| 710 | updateType: UpdateStrategy | |
| 660 | ### `PackageRule` | |
| 711 | 661 | |
| 712 | /** Total package count */ | |
| 713 | packageCount: number | |
| 662 | The main extension point. Rules live on `packages.rules` and are the place for | |
| 663 | everything that varies per update. | |
| 714 | 664 | |
| 715 | /** Has breaking changes */ | |
| 716 | hasBreakingChanges: boolean | |
| 717 | ||
| 718 | /** Is security update */ | |
| 719 | isSecurityUpdate: boolean | |
| 720 | ||
| 721 | /** Repository information */ | |
| 722 | repository: RepositoryContext | |
| 665 | ```typescript | |
| 666 | interface PackageRule { | |
| 667 | // Matchers — all present matchers must match (AND within a rule) | |
| 668 | /** Package names or globs */ | |
| 669 | matchPackages?: string[] | |
| 670 | matchEcosystems?: RuleEcosystem[] | |
| 671 | matchDepTypes?: string[] | |
| 672 | matchUpdateTypes?: Array<'major' | 'minor' | 'patch'> | |
| 673 | /** Globs on the manifest path, for monorepo directories */ | |
| 674 | matchFiles?: string[] | |
| 675 | /** Semver range the currently installed version must satisfy */ | |
| 676 | matchCurrentVersion?: string | |
| 677 | /** Cron expression describing when these updates may be proposed */ | |
| 678 | schedule?: string | |
| 679 | /** IANA time zone `schedule` is written in (default: the runner's) */ | |
| 680 | scheduleTimezone?: string | |
| 681 | ||
| 682 | // Effects | |
| 683 | /** `false` drops matching updates entirely */ | |
| 684 | enabled?: boolean | |
| 685 | strategy?: 'major' | 'minor' | 'patch' | 'all' | |
| 686 | groupName?: string | |
| 687 | labels?: string[] | |
| 688 | reviewers?: string[] | |
| 689 | assignees?: string[] | |
| 690 | autoMerge?: boolean | |
| 691 | /** Minutes a version must have been published, overriding the global */ | |
| 692 | minimumReleaseAge?: number | |
| 693 | /** Ordering within the per-run PR cap; higher goes first */ | |
| 694 | prPriority?: number | |
| 695 | /** Attempt the migration for matching majors, overriding the global */ | |
| 696 | autoMigrate?: boolean | |
| 723 | 697 | } |
| 724 | 698 | |
| 725 | interface PackageUpdate { | |
| 726 | /** Package name */ | |
| 727 | name: string | |
| 728 | ||
| 729 | /** Current version */ | |
| 730 | currentVersion: string | |
| 731 | ||
| 732 | /** Target version */ | |
| 733 | targetVersion: string | |
| 699 | type RuleEcosystem = | |
| 700 | | 'npm' | 'composer' | 'github-actions' | 'docker' | 'pkgx' | |
| 701 | | 'zig' | 'python' | 'rust' | 'go' | 'ruby' | |
| 702 | ``` | |
| 734 | 703 | |
| 735 | /** Update type */ | |
| 736 | updateType: UpdateStrategy | |
| 704 | Matchers combine with AND, so a rule with several matchers is a conjunction. A | |
| 705 | rule with no matchers at all matches everything, which is why validation rejects | |
| 706 | it and asks for an explicit matcher rather than accepting silence. Write the | |
| 707 | deliberate catch-all as `matchPackages: ['**']`: a glob `*` stops at `/`, so it | |
| 708 | matches `react` but not `@types/node`. | |
| 737 | 709 | |
| 738 | /** Has breaking changes */ | |
| 739 | hasBreakingChanges: boolean | |
| 710 | `matchCurrentVersion` lets a rule target a version series rather than a | |
| 711 | package — holding back everything still on `<2.0.0` while letting the rest | |
| 712 | through. Declared versions are stripped to their concrete floor first, so | |
| 713 | `^1.2.3` is tested as `1.2.3`. | |
| 740 | 714 | |
| 741 | /** Is dev dependency */ | |
| 742 | isDevDependency: boolean | |
| 715 | `schedule` describes a window, not a firing minute: `0 0 * * 6,0` holds | |
| 716 | updates back on a weekday run and releases them on a weekend one. | |
| 743 | 717 | |
| 744 | /** Release notes */ | |
| 745 | releaseNotes?: string | |
| 746 | } | |
| 747 | ``` | |
| 718 | ### How effects combine | |
| 748 | 719 | |
| 749 | ### Helper Types | |
| 720 | `labels`, `reviewers` and `assignees` accumulate across every matching rule. | |
| 721 | A package matching both a "security" and a "frontend" rule carries both sets, | |
| 722 | rather than whichever rule happened to be last. | |
| 750 | 723 | |
| 751 | 724 | ```typescript |
| 752 | /** Deep partial type */ | |
| 753 | type DeepPartial<T> = { | |
| 754 | [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P] | |
| 755 | } | |
| 756 | ||
| 757 | /** Configuration with environment overrides */ | |
| 758 | type ConfigWithEnv<T> = T & { | |
| 759 | env?: Record<string, DeepPartial<T>> | |
| 760 | } | |
| 761 | ||
| 762 | /** Conditional configuration */ | |
| 763 | type ConditionalConfig<T> = T | ((context: any) => T) | |
| 725 | rules: [ | |
| 726 | { matchUpdateTypes: ['patch'], labels: ['patch-update'] }, | |
| 727 | { matchPackages: ['react*'], labels: ['frontend'], reviewers: ['ui-team'] }, | |
| 728 | ] | |
| 729 | // A patch update to react-dom carries both labels and the ui-team reviewer. | |
| 764 | 730 | ``` |
| 765 | 731 | |
| 766 | ## Configuration Validation | |
| 732 | Every other effect — `enabled`, `strategy`, `groupName`, `autoMerge`, | |
| 733 | `minimumReleaseAge`, `prPriority`, `autoMigrate` — is a per-field override, | |
| 734 | and the last matching rule wins. | |
| 767 | 735 | |
| 768 | ### `validateConfig` | |
| 736 | When several updates share one pull request, their resolved effects are merged | |
| 737 | for the group: labels, reviewers and assignees union; `prPriority` takes the | |
| 738 | maximum; `autoMerge` requires every update to have opted in, because one | |
| 739 | package that must not merge unattended has to hold back the whole PR; | |
| 740 | `autoMigrate` needs only one, because migrating what can be migrated leaves | |
| 741 | the rest unchanged. | |
| 769 | 742 | |
| 770 | Validate configuration object. | |
| 743 | ## Configuration Validation | |
| 771 | 744 | |
| 772 | 745 | ```typescript |
| 773 | 746 | import { assertValidConfig, formatConfigIssues, validateConfig } from '@buddysh/buddy' |
| @@ -796,6 +769,10 @@ if (issues.length > 0) | ||
| 796 | 769 | console.error(formatConfigIssues(issues)) |
| 797 | 770 | ``` |
| 798 | 771 | |
| 772 | `getConfig()` calls `assertValidConfig` for you, before any network or git | |
| 773 | work happens. A malformed strategy or a group with no patterns otherwise | |
| 774 | produces a run that silently does the wrong thing and reports success. | |
| 775 | ||
| 799 | 776 | ## Example Configurations |
| 800 | 777 | |
| 801 | 778 | ### Basic Configuration |
| @@ -805,21 +782,18 @@ import type { BuddyConfig } from '@buddysh/buddy' | ||
| 805 | 782 | |
| 806 | 783 | const config: BuddyConfig = { |
| 807 | 784 | repository: { |
| 785 | provider: 'github', | |
| 808 | 786 | owner: 'myorg', |
| 809 | name: 'myproject' | |
| 787 | name: 'myproject', | |
| 788 | token: process.env.GITHUB_TOKEN, | |
| 810 | 789 | }, |
| 811 | 790 | packages: { |
| 812 | 791 | strategy: 'minor', |
| 813 | ignore: ['react'] | |
| 792 | ignore: ['react'], | |
| 814 | 793 | }, |
| 815 | 794 | pullRequest: { |
| 816 | labels: { | |
| 817 | static: ['dependencies'] | |
| 818 | }, | |
| 819 | reviewers: { | |
| 820 | default: ['team-lead'] | |
| 821 | } | |
| 822 | } | |
| 795 | reviewers: ['team-lead'], | |
| 796 | }, | |
| 823 | 797 | } |
| 824 | 798 | |
| 825 | 799 | export default config |
| @@ -869,7 +843,6 @@ const config: BuddyConfig = { | ||
| 869 | 843 | }, |
| 870 | 844 | |
| 871 | 845 | pullRequest: { |
| 872 | labels: ['dependencies'], | |
| 873 | 846 | reviewers: ['maintainer'], |
| 874 | 847 | autoMerge: { |
| 875 | 848 | enabled: true, |
| @@ -888,10 +861,6 @@ const config: BuddyConfig = { | ||
| 888 | 861 | export default config |
| 889 | 862 | ``` |
| 890 | 863 | |
| 891 | Note the split between `groups` and `rules`. A `PackageGroup` has exactly | |
| 892 | three fields — `name`, `patterns` and `strategy` — and only decides batching. | |
| 893 | Anything conditional (labels, reviewers, assignees, auto-merge, release age, | |
| 894 | priority, scheduling windows) belongs in `packages.rules`. See | |
| 895 | [scheduling](/advanced/scheduling) for the full matcher and effect tables. | |
| 896 | ||
| 897 | See [Configuration Guide](/config) for detailed configuration examples and best practices. | |
| 864 | See [Configuration Guide](/config) for detailed configuration examples and | |
| 865 | best practices, and [scheduling](/advanced/scheduling) for the full matcher | |
| 866 | and effect tables. | |
| @@ -59,6 +59,15 @@ buddy <command> [options] [arguments] | ||
| 59 | 59 | | [`compare`](/cli/package#compare) | Compare two versions of a package | |
| 60 | 60 | | [`search`](/cli/package#search) | Search for packages in the registry | |
| 61 | 61 | |
| 62 | ### 📊 Dashboard & Review | |
| 63 | ||
| 64 | | Command | Description | | |
| 65 | |---------|-------------| | |
| 66 | | [`dashboard`](/features/dependency-dashboard) | Create or update the dependency dashboard issue | | |
| 67 | | [`review`](/cli/review) | Review local changes, or a pull request | | |
| 68 | | [`security`](/features/workflow-security) | Static-analyse GitHub Actions workflows | | |
| 69 | | [`doctor`](/cli/review#diagnosing-setup) | Diagnose credentials, git state and analyzer tooling | | |
| 70 | ||
| 62 | 71 | ### ⏰ Automation & Scheduling |
| 63 | 72 | |
| 64 | 73 | | Command | Description | |
| @@ -67,14 +76,16 @@ buddy <command> [options] [arguments] | ||
| 67 | 76 | |
| 68 | 77 | ## Global Options |
| 69 | 78 | |
| 70 | All commands support these global options: | |
| 79 | Every command accepts these: | |
| 71 | 80 | |
| 72 | 81 | ```bash |
| 73 | --verbose, -v Enable verbose logging | |
| 82 | --config <path> Path to a buddy config file | |
| 74 | 83 | --help, -h Show help information |
| 75 | 84 | --version Show version information |
| 76 | 85 | ``` |
| 77 | 86 | |
| 87 | Almost every command also takes `--verbose, -v` for detailed logging. Options are matched strictly: a flag a command does not declare is an error, not something quietly ignored. | |
| 88 | ||
| 78 | 89 | ## Examples |
| 79 | 90 | |
| 80 | 91 | ### Quick Start |
| @@ -153,14 +164,14 @@ export default { | ||
| 153 | 164 | Buddy uses these environment variables: |
| 154 | 165 | |
| 155 | 166 | ```bash |
| 156 | # Required for GitHub operations | |
| 167 | # Required for GitHub operations. GH_TOKEN is accepted as an alias | |
| 157 | 168 | GITHUB_TOKEN=ghp_xxxxxxxxxxxx |
| 158 | 169 | |
| 159 | # Optional: Explicitly set GitHub token | |
| 160 | GH_TOKEN=ghp_xxxxxxxxxxxx | |
| 170 | # Optional: a PAT with 'repo' and 'workflow' scopes, used ahead of GITHUB_TOKEN | |
| 171 | BUDDY_TOKEN=ghp_xxxxxxxxxxxx | |
| 161 | 172 | |
| 162 | # Optional: Configure Bun | |
| 163 | BUN_CONFIG_DIR=/path/to/config | |
| 173 | # Optional: output level - silent, error, warn, info, debug | |
| 174 | BUDDY_LOG_LEVEL=debug | |
| 164 | 175 | ``` |
| 165 | 176 | |
| 166 | 177 | ## Exit Codes |
| @@ -168,8 +179,7 @@ BUN_CONFIG_DIR=/path/to/config | ||
| 168 | 179 | Buddy uses standard exit codes: |
| 169 | 180 | |
| 170 | 181 | - **0**: Success |
| 171 | - **1**: General error (configuration, network, etc.) | |
| 172 | - **2**: Command not found or invalid arguments | |
| 182 | - **1**: Any failure — configuration, network, an unknown command, or an option the command does not accept | |
| 173 | 183 | |
| 174 | 184 | ## Debugging |
| 175 | 185 | |
| @@ -252,8 +262,8 @@ done | ||
| 252 | 262 | ## Performance Tips |
| 253 | 263 | |
| 254 | 264 | 1. **Use specific strategies**: `--strategy patch` is faster than `all` |
| 255 | 2. **Filter packages**: Use `--packages` for targeted updates | |
| 256 | 3. **Enable caching**: Set `BUN_CONFIG_NO_CACHE=false` | |
| 265 | 2. **Filter packages**: Use `buddy scan --packages` to check a short list | |
| 266 | 3. **Skip the noise**: Leave `--verbose` off unless you are debugging | |
| 257 | 267 | 4. **Parallel execution**: Run multiple commands in parallel for monorepos |
| 258 | 268 | |
| 259 | 269 | ## Getting Help |
| @@ -271,7 +281,7 @@ buddy update --help | ||
| 271 | 281 | |
| 272 | 282 | ### Documentation |
| 273 | 283 | |
| 274 | - **Full Documentation**: [<https://buddy.sh/doc>s](https://buddy.sh/docs) | |
| 284 | - **Full Documentation**: [buddy.sh/docs](https://buddy.sh/docs) | |
| 275 | 285 | - **Configuration Guide**: [/config](/config) |
| 276 | 286 | - **GitHub Setup**: [/features/github-actions](/features/github-actions) |
| 277 | 287 | |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | # Package Commands |
| 2 | 2 | |
| 3 | CLI commands for package analysis, management, and information retrieval. | |
| 3 | CLI commands for package analysis and information retrieval. | |
| 4 | 4 | |
| 5 | 5 | ## Package Information |
| 6 | 6 | |
| @@ -12,467 +12,216 @@ Get comprehensive information about a package: | ||
| 12 | 12 | # Basic package info |
| 13 | 13 | buddy info react |
| 14 | 14 | |
| 15 | # Detailed information | |
| 16 | buddy info react --detailed | |
| 17 | ||
| 18 | # Include dependencies | |
| 19 | buddy info react --include-deps | |
| 20 | ||
| 21 | # Show version history | |
| 22 | buddy info react --versions --limit 10 | |
| 15 | # Info for a specific dist-tag | |
| 16 | buddy info typescript@latest | |
| 23 | 17 | |
| 24 | 18 | # Output as JSON |
| 25 | 19 | buddy info react --json |
| 20 | ||
| 21 | # Verbose output | |
| 22 | buddy info react --verbose | |
| 26 | 23 | ``` |
| 27 | 24 | |
| 25 | Without `--json`, the command prints the description, homepage, repository, | |
| 26 | license, author, keywords, dependency counts and the number of published | |
| 27 | versions. | |
| 28 | ||
| 28 | 29 | **Options:** |
| 29 | 30 | |
| 30 | - `--detailed` - Show extended package information | |
| 31 | - `--include-deps` - Include dependency tree | |
| 32 | - `--versions` - Show available versions | |
| 33 | - `--limit <number>` - Limit version results | |
| 34 | 31 | - `--json` - Output as JSON |
| 32 | - `--verbose, -v` - Enable verbose logging | |
| 35 | 33 | |
| 36 | 34 | ### `versions` - Available Versions |
| 37 | 35 | |
| 38 | List all available versions for a package: | |
| 36 | List available versions for a package: | |
| 39 | 37 | |
| 40 | 38 | ```bash |
| 41 | # All versions | |
| 39 | # Most recent versions (10 by default) | |
| 42 | 40 | buddy versions typescript |
| 43 | 41 | |
| 44 | # Latest 10 versions | |
| 45 | buddy versions typescript --limit 10 | |
| 42 | # Latest 5 versions | |
| 43 | buddy versions typescript --latest 5 | |
| 44 | ``` | |
| 46 | 45 | |
| 47 | # Include pre-releases | |
| 48 | buddy versions typescript --include-pre | |
| 46 | The output shows the total number of published versions, the latest version, and | |
| 47 | the most recent versions in descending order. | |
| 49 | 48 | |
| 50 | # Filter by tag | |
| 51 | buddy versions typescript --tag latest | |
| 49 | **Options:** | |
| 52 | 50 | |
| 53 | # Show release dates | |
| 54 | buddy versions typescript --with-dates | |
| 55 | ``` | |
| 51 | - `--latest <count>` - Show only the latest N versions (default: `10`) | |
| 52 | - `--verbose, -v` - Enable verbose logging | |
| 56 | 53 | |
| 57 | 54 | ### `latest` - Latest Version |
| 58 | 55 | |
| 59 | 56 | Get the latest version of a package: |
| 60 | 57 | |
| 61 | 58 | ```bash |
| 62 | # Latest stable version | |
| 59 | # Latest version | |
| 63 | 60 | buddy latest vue |
| 64 | 61 | |
| 65 | # Latest including pre-releases | |
| 66 | buddy latest vue --include-pre | |
| 67 | ||
| 68 | # Latest for specific tag | |
| 69 | buddy latest vue --tag next | |
| 62 | # Works with scoped packages | |
| 63 | buddy latest @types/node | |
| 70 | 64 | ``` |
| 71 | 65 | |
| 66 | **Options:** | |
| 67 | ||
| 68 | - `--verbose, -v` - Enable verbose logging | |
| 69 | ||
| 72 | 70 | ## Package Analysis |
| 73 | 71 | |
| 74 | 72 | ### `deps` - Dependency Analysis |
| 75 | 73 | |
| 76 | Analyze package dependencies: | |
| 74 | Show the dependencies a package declares: | |
| 77 | 75 | |
| 78 | 76 | ```bash |
| 79 | # Direct dependencies | |
| 77 | # Production dependencies | |
| 80 | 78 | buddy deps react |
| 81 | 79 | |
| 82 | # Full dependency tree | |
| 83 | buddy deps react --tree | |
| 84 | ||
| 85 | # Specific depth | |
| 86 | buddy deps react --depth 2 | |
| 80 | # Dev dependencies | |
| 81 | buddy deps react --dev | |
| 87 | 82 | |
| 88 | # Include dev dependencies | |
| 89 | buddy deps react --include-dev | |
| 83 | # Peer dependencies | |
| 84 | buddy deps react --peer | |
| 90 | 85 | |
| 91 | # Show outdated dependencies | |
| 92 | buddy deps react --outdated | |
| 93 | ||
| 94 | # Export dependency graph | |
| 95 | buddy deps react --graph --output deps.json | |
| 86 | # Every dependency type | |
| 87 | buddy deps react --all | |
| 96 | 88 | ``` |
| 97 | 89 | |
| 98 | 90 | **Options:** |
| 99 | 91 | |
| 100 | - `--tree` - Show full dependency tree | |
| 101 | - `--depth <number>` - Limit tree depth | |
| 102 | - `--include-dev` - Include devDependencies | |
| 103 | - `--outdated` - Show outdated dependencies | |
| 104 | - `--graph` - Generate dependency graph | |
| 105 | - `--output <file>` - Save output to file | |
| 92 | - `--dev` - Show devDependencies | |
| 93 | - `--peer` - Show peerDependencies | |
| 94 | - `--all` - Show all dependency types | |
| 95 | - `--verbose, -v` - Enable verbose logging | |
| 106 | 96 | |
| 107 | 97 | ### `check` - Package Updates |
| 108 | 98 | |
| 109 | Check for available updates: | |
| 99 | Check named packages for available updates. At least one package name is | |
| 100 | required: | |
| 110 | 101 | |
| 111 | 102 | ```bash |
| 112 | # Check all packages | |
| 113 | buddy check | |
| 114 | ||
| 115 | 103 | # Check specific packages |
| 116 | 104 | buddy check react vue typescript |
| 117 | 105 | |
| 118 | # Check with strategy | |
| 119 | buddy check --strategy minor | |
| 120 | ||
| 121 | # Check security updates only | |
| 122 | buddy check --security-only | |
| 123 | ||
| 124 | # Check by pattern | |
| 125 | buddy check --pattern "@types/*" | |
| 106 | # Check with a strategy | |
| 107 | buddy check react --strategy minor | |
| 126 | 108 | |
| 127 | # Show changelogs | |
| 128 | buddy check --with-changelog | |
| 129 | ||
| 130 | # Group by update type | |
| 131 | buddy check --group-by-type | |
| 109 | # Verbose output | |
| 110 | buddy check react typescript --verbose | |
| 132 | 111 | ``` |
| 133 | 112 | |
| 134 | **Options:** | |
| 135 | ||
| 136 | - `--strategy <type>` - Update strategy (patch|minor|major|all) | |
| 137 | - `--security-only` - Security updates only | |
| 138 | - `--pattern <pattern>` - Package name pattern | |
| 139 | - `--with-changelog` - Include changelog information | |
| 140 | - `--group-by-type` - Group results by update type | |
| 141 | ||
| 142 | ### `outdated` - Outdated Packages | |
| 143 | ||
| 144 | List packages that have updates available: | |
| 145 | ||
| 146 | ```bash | |
| 147 | # All outdated packages | |
| 148 | buddy outdated | |
| 149 | ||
| 150 | # Outdated with severity | |
| 151 | buddy outdated --severity | |
| 152 | ||
| 153 | # Outdated dev dependencies | |
| 154 | buddy outdated --dev-only | |
| 113 | Each update is reported as `name: current → new (type)`. | |
| 155 | 114 | |
| 156 | # Outdated production dependencies | |
| 157 | buddy outdated --prod-only | |
| 115 | **Options:** | |
| 158 | 116 | |
| 159 | # Table format | |
| 160 | buddy outdated --table | |
| 117 | - `--strategy <type>` - Update strategy: `major|minor|patch|all` (default: `all`) | |
| 118 | - `--verbose, -v` - Enable verbose logging | |
| 161 | 119 | |
| 162 | # JSON output | |
| 163 | buddy outdated --json | |
| 164 | ``` | |
| 120 | To check every dependency in the project rather than a fixed list, use | |
| 121 | [`buddy scan`](/cli/update), which also accepts `--pattern "@types/*"` for | |
| 122 | glob matching. | |
| 165 | 123 | |
| 166 | 124 | ## Package Search |
| 167 | 125 | |
| 168 | 126 | ### `search` - Package Search |
| 169 | 127 | |
| 170 | Search for packages in registries: | |
| 128 | Search for packages in the registry: | |
| 171 | 129 | |
| 172 | 130 | ```bash |
| 173 | 131 | # Basic search |
| 174 | 132 | buddy search "state management" |
| 175 | 133 | |
| 176 | 134 | # Limit results |
| 177 | buddy search "testing" --limit 20 | |
| 178 | ||
| 179 | # Search by keywords | |
| 180 | buddy search --keywords "typescript,testing" | |
| 181 | ||
| 182 | # Search by maintainer | |
| 183 | buddy search --maintainer "facebook" | |
| 184 | ||
| 185 | # Include deprecated packages | |
| 186 | buddy search "react" --include-deprecated | |
| 187 | ||
| 188 | # Sort by popularity | |
| 189 | buddy search "ui components" --sort popularity | |
| 135 | buddy search "test framework" --limit 5 | |
| 190 | 136 | ``` |
| 191 | 137 | |
| 192 | 138 | **Options:** |
| 193 | 139 | |
| 194 | - `--limit <number>` - Limit search results | |
| 195 | - `--keywords <keywords>` - Search by keywords (comma-separated) | |
| 196 | - `--maintainer <name>` - Filter by maintainer | |
| 197 | - `--include-deprecated` - Include deprecated packages | |
| 198 | - `--sort <field>` - Sort by field (popularity|quality|maintenance) | |
| 140 | - `--limit <count>` - Limit number of results (default: `10`) | |
| 141 | - `--verbose, -v` - Enable verbose logging | |
| 199 | 142 | |
| 200 | 143 | ### `exists` - Package Existence |
| 201 | 144 | |
| 202 | Check if a package exists: | |
| 145 | Check whether a package exists in the registry: | |
| 203 | 146 | |
| 204 | 147 | ```bash |
| 205 | # Check if package exists | |
| 206 | buddy exists @types/unknown-package | |
| 148 | # Check if a package exists | |
| 149 | buddy exists react | |
| 207 | 150 | |
| 208 | # Check multiple packages | |
| 209 | buddy exists react vue angular | |
| 210 | ||
| 211 | # Check with version | |
| 212 | buddy exists react@18.0.0 | |
| 213 | ||
| 214 | # Silent mode (exit code only) | |
| 215 | buddy exists react --silent | |
| 151 | # Check a name you expect to be free | |
| 152 | buddy exists nonexistent-package-xyz | |
| 216 | 153 | ``` |
| 217 | 154 | |
| 218 | ## Package Comparison | |
| 219 | ||
| 220 | ### `compare` - Version Comparison | |
| 221 | ||
| 222 | Compare package versions: | |
| 155 | The command exits `0` when the package exists and `1` when it does not, so it | |
| 156 | can be used directly in shell conditionals: | |
| 223 | 157 | |
| 224 | 158 | ```bash |
| 225 | # Compare two versions | |
| 226 | buddy compare react 17.0.0 18.0.0 | |
| 227 | ||
| 228 | # Compare with current | |
| 229 | buddy compare react --current 17.0.0 --target 18.0.0 | |
| 230 | ||
| 231 | # Show breaking changes | |
| 232 | buddy compare react 17.0.0 18.0.0 --breaking-changes | |
| 233 | ||
| 234 | # Include changelog | |
| 235 | buddy compare react 17.0.0 18.0.0 --changelog | |
| 236 | ||
| 237 | # Detailed comparison | |
| 238 | buddy compare react 17.0.0 18.0.0 --detailed | |
| 159 | if buddy exists my-new-package-name; then | |
| 160 | echo "name is taken" | |
| 161 | fi | |
| 239 | 162 | ``` |
| 240 | 163 | |
| 241 | ### `diff` - Package Differences | |
| 242 | ||
| 243 | Show differences between package versions: | |
| 244 | ||
| 245 | ```bash | |
| 246 | # Show package.json differences | |
| 247 | buddy diff react 17.0.0 18.0.0 | |
| 248 | ||
| 249 | # Show dependency differences | |
| 250 | buddy diff react 17.0.0 18.0.0 --deps | |
| 251 | ||
| 252 | # Show size differences | |
| 253 | buddy diff react 17.0.0 18.0.0 --size | |
| 254 | ||
| 255 | # Show vulnerability differences | |
| 256 | buddy diff react 17.0.0 18.0.0 --vulnerabilities | |
| 257 | ``` | |
| 258 | ||
| 259 | ## Registry Operations | |
| 260 | ||
| 261 | ### `registry` - Registry Management | |
| 262 | ||
| 263 | Manage package registries: | |
| 264 | ||
| 265 | ```bash | |
| 266 | # List configured registries | |
| 267 | buddy registry list | |
| 268 | ||
| 269 | # Add new registry | |
| 270 | buddy registry add --name company --url https://npm.company.com | |
| 271 | ||
| 272 | # Set default registry | |
| 273 | buddy registry default company | |
| 274 | ||
| 275 | # Test registry connection | |
| 276 | buddy registry test company | |
| 277 | ||
| 278 | # Remove registry | |
| 279 | buddy registry remove company | |
| 280 | ``` | |
| 281 | ||
| 282 | ### `whoami` - Registry Authentication | |
| 283 | ||
| 284 | Check registry authentication: | |
| 285 | ||
| 286 | ```bash | |
| 287 | # Check current user | |
| 288 | buddy whoami | |
| 289 | ||
| 290 | # Check for specific registry | |
| 291 | buddy whoami --registry npm | |
| 292 | ||
| 293 | # Check all registries | |
| 294 | buddy whoami --all | |
| 295 | ``` | |
| 296 | ||
| 297 | ## Package Validation | |
| 298 | ||
| 299 | ### `validate` - Package Validation | |
| 300 | ||
| 301 | Validate package configurations: | |
| 302 | ||
| 303 | ```bash | |
| 304 | # Validate package.json | |
| 305 | buddy validate | |
| 306 | ||
| 307 | # Validate dependencies | |
| 308 | buddy validate --deps | |
| 309 | ||
| 310 | # Check for security issues | |
| 311 | buddy validate --security | |
| 312 | ||
| 313 | # Check licenses | |
| 314 | buddy validate --licenses | |
| 315 | ||
| 316 | # Validate workspace packages | |
| 317 | buddy validate --workspaces | |
| 318 | ``` | |
| 319 | ||
| 320 | ### `audit` - Security Audit | |
| 321 | ||
| 322 | Perform security audit: | |
| 323 | ||
| 324 | ```bash | |
| 325 | # Basic audit | |
| 326 | buddy audit | |
| 327 | ||
| 328 | # Audit with fix suggestions | |
| 329 | buddy audit --fix | |
| 330 | ||
| 331 | # Audit specific severity | |
| 332 | buddy audit --severity high | |
| 333 | ||
| 334 | # Audit production only | |
| 335 | buddy audit --production | |
| 336 | ||
| 337 | # Generate audit report | |
| 338 | buddy audit --report --output audit-report.json | |
| 339 | ``` | |
| 340 | ||
| 341 | ## Package Management | |
| 342 | ||
| 343 | ### `install` - Install Packages | |
| 344 | ||
| 345 | Install or update packages: | |
| 346 | ||
| 347 | ```bash | |
| 348 | # Install package | |
| 349 | buddy install lodash | |
| 350 | ||
| 351 | # Install with version | |
| 352 | buddy install lodash@4.17.21 | |
| 353 | ||
| 354 | # Install as dev dependency | |
| 355 | buddy install --dev @types/lodash | |
| 356 | ||
| 357 | # Install globally | |
| 358 | buddy install --global typescript | |
| 359 | ||
| 360 | # Install from specific registry | |
| 361 | buddy install lodash --registry company | |
| 362 | ``` | |
| 363 | ||
| 364 | ### `uninstall` - Remove Packages | |
| 365 | ||
| 366 | Remove packages: | |
| 367 | ||
| 368 | ```bash | |
| 369 | # Remove package | |
| 370 | buddy uninstall lodash | |
| 371 | ||
| 372 | # Remove dev dependency | |
| 373 | buddy uninstall --dev @types/lodash | |
| 374 | ||
| 375 | # Remove global package | |
| 376 | buddy uninstall --global typescript | |
| 164 | **Options:** | |
| 377 | 165 | |
| 378 | # Remove and update dependencies | |
| 379 | buddy uninstall lodash --update-deps | |
| 380 | ``` | |
| 166 | - `--verbose, -v` - Enable verbose logging | |
| 381 | 167 | |
| 382 | ## Workspace Operations | |
| 168 | ## Package Comparison | |
| 383 | 169 | |
| 384 | ### `workspace` - Workspace Commands | |
| 170 | ### `compare` - Version Comparison | |
| 385 | 171 | |
| 386 | Manage monorepo workspaces: | |
| 172 | Compare two versions of a package: | |
| 387 | 173 | |
| 388 | 174 | ```bash |
| 389 | # List workspaces | |
| 390 | buddy workspace list | |
| 391 | ||
| 392 | # Show workspace info | |
| 393 | buddy workspace info packages/ui | |
| 394 | ||
| 395 | # Check workspace dependencies | |
| 396 | buddy workspace deps packages/ui | |
| 397 | ||
| 398 | # Update workspace | |
| 399 | buddy workspace update packages/ui | |
| 175 | # Compare two versions | |
| 176 | buddy compare react 17.0.0 18.0.0 | |
| 400 | 177 | |
| 401 | # Validate workspace | |
| 402 | buddy workspace validate packages/ui | |
| 178 | # Compare across a major boundary | |
| 179 | buddy compare typescript 4.9.0 5.0.0 | |
| 403 | 180 | ``` |
| 404 | 181 | |
| 405 | ## Output Formats | |
| 406 | ||
| 407 | All package commands support multiple output formats: | |
| 408 | ||
| 409 | ```bash | |
| 410 | # JSON output | |
| 411 | buddy info react --json | |
| 412 | ||
| 413 | # Table format | |
| 414 | buddy outdated --table | |
| 415 | ||
| 416 | # YAML output | |
| 417 | buddy check --yaml | |
| 182 | Both versions are positional and required. The output reports the update type | |
| 183 | (`major`, `minor` or `patch`), how many published versions sit between the two, | |
| 184 | and which of them is newer. | |
| 418 | 185 | |
| 419 | # CSV format | |
| 420 | buddy outdated --csv | |
| 186 | **Options:** | |
| 421 | 187 | |
| 422 | # Custom format | |
| 423 | buddy info react --format "{name}@{version}" | |
| 424 | ``` | |
| 188 | - `--verbose, -v` - Enable verbose logging | |
| 425 | 189 | |
| 426 | 190 | ## Configuration |
| 427 | 191 | |
| 428 | Package commands respect global configuration: | |
| 192 | `--config` is a global option, so it works on every command: | |
| 429 | 193 | |
| 430 | 194 | ```bash |
| 431 | # Use specific config file | |
| 432 | buddy check --config custom-config.ts | |
| 433 | ||
| 434 | # Override registry | |
| 435 | buddy info react --registry https://npm.company.com | |
| 436 | ||
| 437 | # Override strategy | |
| 438 | buddy check --strategy major | |
| 439 | ||
| 440 | # Debug mode | |
| 441 | buddy check --debug | |
| 442 | ||
| 443 | # Verbose output | |
| 444 | buddy check --verbose | |
| 195 | # Use a specific config file | |
| 196 | buddy check react --config custom-config.ts | |
| 445 | 197 | ``` |
| 446 | 198 | |
| 199 | `check` reads `packages.strategy` from the configuration file and `--strategy` | |
| 200 | overrides it for that run. The registry lookup commands (`info`, `versions`, | |
| 201 | `latest`, `deps`, `compare`, `search`, `exists`) query the registry directly and | |
| 202 | take no configuration beyond the flags listed above. | |
| 203 | ||
| 447 | 204 | ## Examples |
| 448 | 205 | |
| 449 | ### Daily Package Health Check | |
| 206 | ### Investigating a package before adding it | |
| 450 | 207 | |
| 451 | 208 | ```bash |
| 452 | # Comprehensive package health check | |
| 453 | buddy outdated --table && \ | |
| 454 | buddy audit --severity high && \ | |
| 455 | buddy validate --deps | |
| 209 | buddy exists fast-glob && \ | |
| 210 | buddy info fast-glob && \ | |
| 211 | buddy deps fast-glob --all | |
| 456 | 212 | ``` |
| 457 | 213 | |
| 458 | ### Security-Focused Analysis | |
| 214 | ### Planning an upgrade | |
| 459 | 215 | |
| 460 | 216 | ```bash |
| 461 | # Check for security updates | |
| 462 | buddy check --security-only --with-changelog | |
| 217 | # See what versions are available | |
| 218 | buddy versions typescript --latest 20 | |
| 463 | 219 | |
| 464 | # Audit for vulnerabilities | |
| 465 | buddy audit --production --report | |
| 466 | ``` | |
| 467 | ||
| 468 | ### Monorepo Package Management | |
| 469 | ||
| 470 | ```bash | |
| 471 | # Check all workspaces | |
| 472 | buddy workspace list | xargs -I {} buddy check --workspace {} | |
| 220 | # Understand the jump | |
| 221 | buddy compare typescript 5.8.2 5.9.0 | |
| 473 | 222 | |
| 474 | # Validate workspace dependencies | |
| 475 | buddy workspace validate --all | |
| 223 | # Check what Buddy would do with it | |
| 224 | buddy check typescript --strategy minor | |
| 476 | 225 | ``` |
| 477 | 226 | |
| 478 | 227 | See [Package Management](/features/package-management) for more details on package handling features. |
| @@ -115,11 +115,12 @@ Found 2 available integration(s): | ||
| 115 | 115 | ### Pre-flight Validation |
| 116 | 116 | |
| 117 | 117 | ``` |
| 118 | �� Pre-flight Validation | |
| 119 | ✅ Git repository detected | |
| 120 | ✅ Bun v1.2.19 detected | |
| 121 | ⚠️ Found 2 existing workflows. Some may conflict with Buddy workflows. | |
| 122 | �� GitHub CLI detected. This can help with authentication. | |
| 118 | �� Pre-flight Validation: | |
| 119 | ⚠️ Warnings: | |
| 120 | • Found 2 existing workflow(s). Some may conflict with Buddy workflows. | |
| 121 | �� Suggestions: | |
| 122 | • Using Bun v1.2.19 | |
| 123 | • GitHub CLI detected. This can help with authentication. | |
| 123 | 124 | ``` |
| 124 | 125 | |
| 125 | 126 | **Environment Checks:** |
| @@ -163,9 +164,9 @@ Found 2 available integration(s): | ||
| 163 | 164 | ### Interactive Progress Tracking |
| 164 | 165 | |
| 165 | 166 | ``` |
| 166 | �� Setup Progress: 75% [███████████████░░░░░] | |
| 167 | �� Current Step: Workflow Generation (6/8) | |
| 168 | ✅ Completed: Pre-flight checks, Project analysis, Repository Detection, GitHub Token Setup, Repository Settings | |
| 167 | �� Setup Progress: 80% [████████████████░░░░] | |
| 168 | �� Current Step: Workflow Configuration (8/10) | |
| 169 | ✅ Completed: Detecting existing configurations, Discovering integrations, Running pre-flight checks, Analyzing project, Repository Detection, GitHub Token Setup, Repository Settings | |
| 169 | 170 | ``` |
| 170 | 171 | |
| 171 | 172 | **Progress Features:** |
| @@ -176,10 +177,10 @@ Found 2 available integration(s): | ||
| 176 | 177 | - **Time tracking** - Monitors setup duration for performance insights |
| 177 | 178 | - **Recovery support** - Maintains progress state for resumption after interruptions |
| 178 | 179 | |
| 179 | ### Step 3: Repository Detection & Validation | |
| 180 | ### Step 5: Repository Detection & Validation | |
| 180 | 181 | |
| 181 | 182 | ``` |
| 182 | �� Step 1: Repository Detection | |
| 183 | �� Repository Detection | |
| 183 | 184 | ✅ Detected repository: your-org/your-repo |
| 184 | 185 | �� GitHub URL: https://github.com/your-org/your-repo |
| 185 | 186 | ``` |
| @@ -193,24 +194,24 @@ Automatically detects your GitHub repository from `git remote get-url origin` an | ||
| 193 | 194 | - **Private repository support** - Enhanced validation for private repositories with appropriate token scopes |
| 194 | 195 | - **Organization settings** - Checks for organization-level restrictions that might affect setup |
| 195 | 196 | |
| 196 | ### Step 4: GitHub Token Setup | |
| 197 | ### Step 6: GitHub Token Setup | |
| 197 | 198 | |
| 198 | 199 | ``` |
| 199 | �� Step 2: GitHub Token Setup | |
| 200 | For full functionality, Buddy needs a Personal Access Token (PAT). | |
| 200 | �� GitHub Token Setup | |
| 201 | For full functionality, Buddy needs appropriate GitHub permissions. | |
| 201 | 202 | This enables workflow file updates and advanced GitHub Actions features. |
| 202 | 203 | ``` |
| 203 | 204 | |
| 204 | 205 | Provides three options: |
| 205 | 206 | |
| 206 | - **Create new token** - Full guidance through PAT creation process | |
| 207 | - **Have existing token** - Setup for existing PAT | |
| 208 | - **Skip for now** - Use limited GITHUB_TOKEN permissions | |
| 207 | - **Use organization/repository secrets** - A PAT is already configured as an organization or repository secret | |
| 208 | - **Set up a new Personal Access Token** - Full guidance through PAT creation and secret configuration | |
| 209 | - **Use default GITHUB_TOKEN only** - Limited permissions; workflow file updates will not work | |
| 209 | 210 | |
| 210 | ### Step 5: Repository Settings | |
| 211 | ### Step 7: Repository Settings | |
| 211 | 212 | |
| 212 | 213 | ``` |
| 213 | �� Step 3: Repository Settings | |
| 214 | �� Repository Settings | |
| 214 | 215 | ``` |
| 215 | 216 | |
| 216 | 217 | Guides you through configuring GitHub Actions permissions: |
| @@ -219,32 +220,35 @@ Guides you through configuring GitHub Actions permissions: | ||
| 219 | 220 | 2. Select "Read and write permissions" |
| 220 | 221 | 3. Enable "Allow GitHub Actions to create and approve pull requests" |
| 221 | 222 | |
| 222 | ### Step 6: Workflow Configuration | |
| 223 | ### Step 8: Workflow Configuration | |
| 223 | 224 | |
| 224 | 225 | ``` |
| 225 | ⚙️ Step 4: Workflow Configuration | |
| 226 | What type of update schedule would you like? | |
| 226 | ⚙️ Workflow Configuration | |
| 227 | ? What type of update schedule would you like? | |
| 227 | 228 | ``` |
| 228 | 229 | |
| 229 | 230 | Choose from carefully crafted presets: |
| 230 | 231 | |
| 231 | 232 | #### Available Presets |
| 232 | 233 | |
| 233 | | Preset | Description | Dashboard | Updates | Auto-merge | | |
| 234 | |--------|-------------|-----------|---------|------------| | |
| 235 | | **Standard Setup** | Balanced approach for most projects | 3x/week | Mon/Wed/Fri | Patch only | | |
| 236 | | **High Frequency** | Multiple checks per day | Daily | Every 6 hours | Patch only | | |
| 237 | | **Security Focused** | Security-first approach | Daily | Every 4 hours | Security patches | | |
| 238 | | **Minimal Updates** | Low-frequency updates | Weekly | Monday only | Manual | | |
| 239 | | **Development/Testing** | Testing and debugging | Manual | Every 15 min | Disabled | | |
| 240 | | **Custom Configuration** | Build your own schedule | Custom | Custom | Custom | | |
| 234 | | Preset | Description | | |
| 235 | |--------|-------------| | |
| 236 | | **Standard Setup (Recommended)** | Dashboard updates 3x/week, dependency updates on schedule | | |
| 237 | | **High Frequency** | Check for updates multiple times per day | | |
| 238 | | **Security Focused** | Frequent patch updates with security-first approach | | |
| 239 | | **Minimal Updates** | Weekly checks, lower frequency | | |
| 240 | | **Development/Testing** | Manual triggers + frequent checks for testing | | |
| 241 | | **Custom Configuration** | Create your own schedule | | |
| 241 | 242 | |
| 242 | ### Step 7: Configuration File Generation | |
| 243 | The preset names the intent you picked; the workflow it writes is the same either way. See [Preset Details](#preset-details) for what that means once setup is done. | |
| 244 | ||
| 245 | ### Step 9: Configuration File Generation | |
| 243 | 246 | |
| 244 | 247 | ``` |
| 245 | �� Step 5: Configuration File | |
| 246 | ✅ Created buddy.config.json with your repository settings. | |
| 248 | �� Configuration File | |
| 249 | ✅ Created buddy.config.ts with your repository settings. | |
| 247 | 250 | �� You can edit this file to customize Buddy's behavior. |
| 251 | �� The TypeScript config provides better IntelliSense and type safety. | |
| 248 | 252 | ``` |
| 249 | 253 | |
| 250 | 254 | Creates a complete configuration file with: |
| @@ -255,46 +259,45 @@ Creates a complete configuration file with: | ||
| 255 | 259 | - Package strategies |
| 256 | 260 | - Default options |
| 257 | 261 | |
| 258 | ### Step 8: Workflow Generation | |
| 262 | ### Step 10: Workflow Generation | |
| 259 | 263 | |
| 260 | 264 | ``` |
| 261 | �� Step 6: Workflow Generation | |
| 262 | ✨ Setting up Standard Setup... | |
| 263 | �� Dashboard updates 3x/week, balanced dependency updates | |
| 265 | �� Workflow Generation | |
| 266 | ✨ Setting up Standard Project... | |
| 267 | �� Daily patch updates, weekly minor updates, monthly major updates | |
| 268 | Generated unified buddy workflow (combines check, update, and dashboard) | |
| 269 | Generated GitHub Actions security audit workflow (buddy-security.yml) | |
| 270 | ✓ Generated unified workflow in .github/workflows | |
| 264 | 271 | ``` |
| 265 | 272 | |
| 266 | Generates three core workflows: | |
| 267 | ||
| 268 | #### 1. Dashboard Workflow (`buddy-dashboard.yml`) | |
| 273 | Generates two workflows: | |
| 269 | 274 | |
| 270 | - **Schedule**: Monday, Wednesday, Friday at 9 AM UTC | |
| 271 | - **Purpose**: Manages dependency dashboard issue | |
| 272 | - **Features**: Manual triggers, dry-run mode, verbose logging | |
| 275 | #### 1. Unified Workflow (`buddy.yml`) | |
| 273 | 276 | |
| 274 | #### 2. Update Check Workflow (`buddy-check.yml`) | |
| 277 | - **Schedule**: dependency updates every 2 hours, dashboard 15 minutes later, cleanup daily at 4 AM UTC, health report Monday at 9 AM UTC | |
| 278 | - **Events**: `pull_request`, `issues`, `issue_comment`, `pull_request_review_comment` and `workflow_run`, so a ticked rebase box or an `@buddy` comment is acted on immediately rather than waited for | |
| 279 | - **Purpose**: One workflow covering checks, updates, the dashboard, reviews and comment commands | |
| 280 | - **Features**: `workflow_dispatch` with a `job` input to run a single job by hand | |
| 275 | 281 | |
| 276 | - **Schedule**: Every 15 minutes | |
| 277 | - **Purpose**: Auto-rebase PRs with checked rebase boxes | |
| 278 | - **Features**: Automatic PR updates, conflict resolution | |
| 282 | #### 2. Security Audit Workflow (`buddy-security.yml`) | |
| 279 | 283 | |
| 280 | #### 3. Update Workflow (`buddy-update.yml`) | |
| 284 | - **Schedule**: Monday at 6 AM UTC, plus every push and pull request touching `.github/workflows/**` | |
| 285 | - **Purpose**: Static-analyses your GitHub Actions workflows for supply-chain footguns | |
| 286 | - **Features**: Kept separate so its path filters fire independently of the dependency pipeline | |
| 281 | 287 | |
| 282 | - **Schedule**: Based on selected preset | |
| 283 | - **Purpose**: Scheduled dependency updates | |
| 284 | - **Features**: Manual triggers, strategy selection, package filtering | |
| 288 | If an earlier version of Buddy left `buddy-check.yml`, `buddy-update.yml`, `buddy-dashboard.yml` or `gh-audit.yml` behind, setup deletes them — their jobs now live in `buddy.yml` and `buddy-security.yml`. | |
| 285 | 289 | |
| 286 | 290 | ### Workflow Validation & Testing |
| 287 | 291 | |
| 288 | 292 | ``` |
| 289 | 293 | �� Validating Generated Workflows |
| 290 | ✅ buddy-dashboard.yml validated successfully | |
| 291 | ✅ buddy-check.yml validated successfully | |
| 292 | ✅ buddy-update.yml validated successfully | |
| 293 | 294 | ``` |
| 294 | 295 | |
| 296 | The checks live in `validateWorkflowGeneration`, exported from `@buddysh/buddy/setup`, so you can run them over a workflow of your own as well. | |
| 297 | ||
| 295 | 298 | **Validation Features:** |
| 296 | 299 | |
| 297 | - **YAML syntax validation** - Ensures all generated workflows are syntactically correct | |
| 300 | - **YAML syntax validation** - Ensures a workflow is syntactically correct | |
| 298 | 301 | - **Required field verification** - Validates presence of name, on, jobs, and other essential fields |
| 299 | 302 | - **Security best practices** - Checks token usage, permissions, and security configurations |
| 300 | 303 | - **Buddy integration** - Verifies workflows include proper buddy execution commands |
| @@ -307,17 +310,13 @@ Generates three core workflows: | ||
| 307 | 310 | - **Secret handling** - Validates secure handling of tokens and sensitive information |
| 308 | 311 | - **Workflow permissions** - Checks for explicit permission definitions and security boundaries |
| 309 | 312 | |
| 310 | ### Step 9: Final Instructions & Integration Notifications | |
| 313 | ### Final Instructions & Integration Notifications | |
| 311 | 314 | |
| 312 | 315 | ``` |
| 313 | 316 | �� Setup Complete! |
| 314 | ✅ Generated 3 core workflows in .github/workflows/: | |
| 315 | ||
| 316 | - buddy-dashboard.yml (Dependency Dashboard Management) | |
| 317 | - buddy-check.yml (Auto-rebase PR checker) | |
| 318 | - buddy-update.yml (Scheduled dependency updates) | |
| 319 | ||
| 320 | �� Configuration file: buddy.config.json | |
| 317 | ✅ Generated unified buddy workflow in .github/workflows/: | |
| 318 | - buddy.yml (Combined check, update, and dashboard management) | |
| 319 | �� Configuration file: buddy.config.ts | |
| 321 | 320 | ``` |
| 322 | 321 | |
| 323 | 322 | Provides clear next steps with: |
| @@ -425,16 +424,17 @@ buddy setup --non-interactive --token-setup new-pat | ||
| 425 | 424 | |
| 426 | 425 | ### Preset Options |
| 427 | 426 | |
| 427 | Every preset writes the same `buddy.yml`: dependency updates every 2 hours on the `patch` strategy, the dashboard 15 minutes behind them, and a manual trigger for running any single job. The preset records the cadence you intended — change the cadence itself in the workflow's `schedule:` block afterwards. | |
| 428 | ||
| 428 | 429 | #### Standard Preset |
| 429 | 430 | |
| 430 | 431 | ```bash |
| 431 | 432 | buddy setup --non-interactive --preset standard |
| 432 | 433 | ``` |
| 433 | 434 | |
| 434 | - Balanced approach for most projects | |
| 435 | - Every 2 hours schedule for testing | |
| 436 | - Dry-run enabled by default | |
| 437 | - Manual triggers available | |
| 435 | - Reported as **Standard Project** | |
| 436 | - Daily patch updates, weekly minor updates, monthly major updates | |
| 437 | - The default when `--preset` is omitted | |
| 438 | 438 | |
| 439 | 439 | #### Testing Preset |
| 440 | 440 | |
| @@ -442,10 +442,9 @@ buddy setup --non-interactive --preset standard | ||
| 442 | 442 | buddy setup --non-interactive --preset testing |
| 443 | 443 | ``` |
| 444 | 444 | |
| 445 | - Reported as **Development/Testing** | |
| 446 | - Manual trigger + every 20 minutes (for testing) | |
| 445 | 447 | - Optimized for development and testing |
| 446 | - Every 2 hours schedule with enhanced logging | |
| 447 | - Dry-run mode by default | |
| 448 | - Verbose output and detailed summaries | |
| 449 | 448 | |
| 450 | 449 | #### Security Preset |
| 451 | 450 | |
| @@ -453,10 +452,9 @@ buddy setup --non-interactive --preset testing | ||
| 453 | 452 | buddy setup --non-interactive --preset security |
| 454 | 453 | ``` |
| 455 | 454 | |
| 456 | - Security-focused configuration | |
| 457 | - Every 2 hours schedule for rapid security updates | |
| 458 | - Enhanced monitoring and reporting | |
| 459 | - Security-first update strategy | |
| 455 | - Reported as **Security Focused** | |
| 456 | - Frequent patch updates with security-first approach | |
| 457 | - Suitable for security-critical applications | |
| 460 | 458 | |
| 461 | 459 | #### High-Frequency Preset |
| 462 | 460 | |
| @@ -464,9 +462,8 @@ buddy setup --non-interactive --preset security | ||
| 464 | 462 | buddy setup --non-interactive --preset high-frequency |
| 465 | 463 | ``` |
| 466 | 464 | |
| 467 | - Multiple updates per day | |
| 468 | - Every 2 hours schedule | |
| 469 | - Aggressive update strategy | |
| 465 | - Reported as **High Frequency Updates** | |
| 466 | - Check for updates 4 times per day (6AM, 12PM, 6PM, 12AM) | |
| 470 | 467 | - Suitable for active development |
| 471 | 468 | |
| 472 | 469 | #### Minimal Preset |
| @@ -475,10 +472,9 @@ buddy setup --non-interactive --preset high-frequency | ||
| 475 | 472 | buddy setup --non-interactive --preset minimal |
| 476 | 473 | ``` |
| 477 | 474 | |
| 478 | - Low-frequency updates | |
| 479 | - Every 2 hours schedule (same as others) | |
| 480 | - Conservative approach | |
| 481 | - Minimal noise and disruption | |
| 475 | - Reported as **Minimal Updates** | |
| 476 | - Weekly patch updates, monthly minor/major updates | |
| 477 | - Conservative approach for stable projects | |
| 482 | 478 | |
| 483 | 479 | ### CI/CD Integration Examples |
| 484 | 480 | |
| @@ -576,76 +572,99 @@ echo "Buddy setup complete!" | ||
| 576 | 572 | |
| 577 | 573 | The setup process creates several files: |
| 578 | 574 | |
| 579 | ### Configuration File (`buddy.config.json`) | |
| 575 | ### Configuration File (`buddy.config.ts`) | |
| 580 | 576 | |
| 581 | ```json | |
| 582 | { | |
| 583 | "repository": { | |
| 584 | "owner": "your-org", | |
| 585 | "name": "your-repo", | |
| 586 | "provider": "github" | |
| 577 | ```typescript | |
| 578 | import type { BuddyConfig } from '@buddysh/buddy' | |
| 579 | ||
| 580 | const config: BuddyConfig = { | |
| 581 | repository: { | |
| 582 | owner: 'your-org', | |
| 583 | name: 'your-repo', | |
| 584 | provider: 'github', | |
| 585 | // Uses GITHUB_TOKEN by default | |
| 587 | 586 | }, |
| 588 | "dashboard": { | |
| 589 | "enabled": true, | |
| 590 | "pin": false, | |
| 591 | "title": "Dependency Dashboard" | |
| 587 | dashboard: { | |
| 588 | enabled: true, | |
| 589 | title: 'Dependency Dashboard', | |
| 590 | // issueNumber: undefined, // Auto-generated | |
| 592 | 591 | }, |
| 593 | "workflows": { | |
| 594 | "enabled": true, | |
| 595 | "outputDir": ".github/workflows", | |
| 596 | "templates": { | |
| 597 | "daily": true, | |
| 598 | "weekly": true, | |
| 599 | "monthly": true | |
| 600 | } | |
| 592 | workflows: { | |
| 593 | enabled: true, | |
| 594 | outputDir: '.github/workflows', | |
| 595 | templates: { | |
| 596 | daily: true, | |
| 597 | weekly: true, | |
| 598 | monthly: true, | |
| 599 | }, | |
| 600 | custom: [], | |
| 601 | 601 | }, |
| 602 | "packages": { | |
| 603 | "strategy": "all", | |
| 604 | "ignore": [] | |
| 602 | packages: { | |
| 603 | strategy: 'all', | |
| 604 | ignore: [], | |
| 605 | ignorePaths: [], | |
| 605 | 606 | }, |
| 606 | "verbose": false | |
| 607 | verbose: false, | |
| 607 | 608 | } |
| 609 | ||
| 610 | export default config | |
| 608 | 611 | ``` |
| 609 | 612 | |
| 610 | 613 | ### Workflow Files |
| 611 | 614 | |
| 612 | #### Dashboard Workflow | |
| 615 | #### Unified Workflow (`buddy.yml`) | |
| 613 | 616 | |
| 614 | 617 | ```yaml |
| 615 | name: Buddy Dashboard | |
| 618 | name: Buddy | |
| 616 | 619 | |
| 617 | 620 | on: |
| 618 | schedule: | |
| 621 | pull_request: | |
| 622 | types: [edited, opened, ready_for_review, synchronize, closed] | |
| 619 | 623 | |
| 620 | - cron: '0 9 _ _ 1,3,5' # Monday, Wednesday, Friday at 9 AM UTC | |
| 624 | issues: | |
| 625 | types: [edited, opened] | |
| 621 | 626 | |
| 622 | workflow_dispatch: # Manual triggering | |
| 623 | ``` | |
| 627 | issue_comment: | |
| 628 | types: [created] | |
| 624 | 629 | |
| 625 | #### Update Check Workflow | |
| 630 | pull_request_review_comment: | |
| 631 | types: [created] | |
| 626 | 632 | |
| 627 | ```yaml | |
| 628 | name: Buddy Check | |
| 633 | workflow_run: | |
| 634 | types: [completed] | |
| 629 | 635 | |
| 630 | on: | |
| 631 | 636 | schedule: |
| 632 | 637 | |
| 633 | - cron: '_/15 _ _ _ _' # Check every 15 minutes | |
| 638 | - cron: '0 */2 * * *' # Dependency updates | |
| 639 | - cron: '15 */2 * * *' # Dashboard, 15 minutes behind | |
| 640 | - cron: '0 4 * * *' # Branch cleanup | |
| 641 | - cron: '0 9 * * 1' # Weekly dependency-health report | |
| 634 | 642 | |
| 635 | workflow_dispatch: # Manual trigger | |
| 643 | workflow_dispatch: # Manual trigger, with job/strategy/dry_run inputs | |
| 636 | 644 | ``` |
| 637 | 645 | |
| 638 | #### Update Workflow | |
| 646 | #### Security Audit Workflow (`buddy-security.yml`) | |
| 639 | 647 | |
| 640 | 648 | ```yaml |
| 641 | name: Buddy Update | |
| 649 | name: GH Actions Security Audit | |
| 642 | 650 | |
| 643 | 651 | on: |
| 652 | push: | |
| 653 | branches: [main] | |
| 654 | paths: | |
| 655 | ||
| 656 | - '.github/workflows/**' | |
| 657 | ||
| 658 | pull_request: | |
| 659 | paths: | |
| 660 | ||
| 661 | - '.github/workflows/**' | |
| 662 | ||
| 644 | 663 | schedule: |
| 645 | 664 | |
| 646 | - cron: '0 9 _ * 1,3,5' # Mon, Wed, Fri | |
| 665 | - cron: '0 6 * * 1' # Monday 06:00 UTC — weekly drift check | |
| 647 | 666 | |
| 648 | workflow_dispatch: # Manual trigger with options | |
| 667 | workflow_dispatch: | |
| 649 | 668 | ``` |
| 650 | 669 | |
| 651 | 670 | ## Token Setup Guide |
| @@ -716,44 +735,36 @@ Configure GitHub Actions permissions: | ||
| 716 | 735 | |
| 717 | 736 | ## Preset Details |
| 718 | 737 | |
| 738 | A preset is a statement of intent. Setup prints the one you chose and then writes the same `buddy.yml` for every preset: dependency updates every 2 hours (`0 */2 * * *`) on the `patch` strategy, the dashboard 15 minutes later, branch cleanup daily at 4 AM UTC and a dependency-health report on Monday at 9 AM UTC. Edit that `schedule:` block to change the cadence. | |
| 739 | ||
| 719 | 740 | ### Standard Setup (Recommended) |
| 720 | 741 | |
| 721 | - **Dashboard**: Monday, Wednesday, Friday at 9 AM UTC | |
| 722 | - **Updates**: Monday, Wednesday, Friday at 9 AM UTC | |
| 723 | - **Strategy**: All updates (major, minor, patch) | |
| 724 | - **Auto-merge**: Disabled (manual review required) | |
| 742 | - **Reported as**: Standard Project | |
| 743 | - **Intent**: Daily patch updates, weekly minor updates, monthly major updates | |
| 725 | 744 | - **Best for**: Most projects wanting balanced automation |
| 726 | 745 | |
| 727 | 746 | ### High Frequency |
| 728 | 747 | |
| 729 | - **Dashboard**: Daily at 9 AM UTC | |
| 730 | - **Updates**: Every 6 hours | |
| 731 | - **Strategy**: All updates | |
| 732 | - **Auto-merge**: Disabled | |
| 748 | - **Reported as**: High Frequency Updates | |
| 749 | - **Intent**: Check for updates 4 times per day (6AM, 12PM, 6PM, 12AM) | |
| 733 | 750 | - **Best for**: Active projects needing quick updates |
| 734 | 751 | |
| 735 | 752 | ### Security Focused |
| 736 | 753 | |
| 737 | - **Dashboard**: Daily at 9 AM UTC | |
| 738 | - **Updates**: Every 4 hours | |
| 739 | - **Strategy**: All updates | |
| 740 | - **Auto-merge**: Disabled | |
| 754 | - **Reported as**: Security Focused | |
| 755 | - **Intent**: Frequent patch updates with security-first approach | |
| 741 | 756 | - **Best for**: Security-critical applications |
| 742 | 757 | |
| 743 | 758 | ### Minimal Updates |
| 744 | 759 | |
| 745 | - **Dashboard**: Weekly on Monday at 9 AM UTC | |
| 746 | - **Updates**: Monday only at 9 AM UTC | |
| 747 | - **Strategy**: All updates | |
| 748 | - **Auto-merge**: Disabled | |
| 760 | - **Reported as**: Minimal Updates | |
| 761 | - **Intent**: Weekly patch updates, monthly minor/major updates | |
| 749 | 762 | - **Best for**: Stable projects with low change frequency |
| 750 | 763 | |
| 751 | 764 | ### Development/Testing |
| 752 | 765 | |
| 753 | - **Dashboard**: Manual trigger only | |
| 754 | - **Updates**: Every 15 minutes | |
| 755 | - **Strategy**: Patch updates only | |
| 756 | - **Auto-merge**: Disabled | |
| 766 | - **Reported as**: Development/Testing | |
| 767 | - **Intent**: Manual trigger + every 20 minutes (for testing) | |
| 757 | 768 | - **Best for**: Testing Buddy functionality |
| 758 | 769 | |
| 759 | 770 | ## Post-Setup |
| @@ -764,7 +775,7 @@ After running setup, follow these steps: | ||
| 764 | 775 | |
| 765 | 776 | ```bash |
| 766 | 777 | # Check configuration |
| 767 | cat buddy.config.json | |
| 778 | cat buddy.config.ts | |
| 768 | 779 | |
| 769 | 780 | # Review workflows |
| 770 | 781 | ls -la .github/workflows/ |
| @@ -776,15 +787,18 @@ ls -la .github/workflows/ | ||
| 776 | 787 | # Test repository detection |
| 777 | 788 | buddy scan --verbose |
| 778 | 789 | |
| 779 | # Test dashboard creation | |
| 780 | buddy dashboard --dry-run | |
| 790 | # See what an update run would open, without opening it | |
| 791 | buddy update --dry-run | |
| 792 | ||
| 793 | # Create or refresh the dashboard issue | |
| 794 | buddy dashboard | |
| 781 | 795 | ``` |
| 782 | 796 | |
| 783 | 797 | ### 3. Commit Changes |
| 784 | 798 | |
| 785 | 799 | ```bash |
| 786 | 800 | # Add generated files |
| 787 | git add .github/workflows/ buddy.config.json | |
| 801 | git add .github/workflows/ buddy.config.ts | |
| 788 | 802 | |
| 789 | 803 | # Commit setup |
| 790 | 804 | git commit -m "Add Buddy dependency management workflows" |
| @@ -797,7 +811,7 @@ git push | ||
| 797 | 811 | |
| 798 | 812 | 1. Go to repository **Actions** tab |
| 799 | 813 | 2. Verify workflows appear in the list |
| 800 | 3. Test manual trigger on dashboard workflow | |
| 814 | 3. Test the manual trigger on the Buddy workflow, picking the `dashboard` job | |
| 801 | 815 | 4. Check workflow permissions if needed |
| 802 | 816 | |
| 803 | 817 | ## Troubleshooting |
| @@ -884,7 +898,7 @@ buddy setup --verbose | ||
| 884 | 898 | buddy setup --non-interactive --preset testing --verbose |
| 885 | 899 | |
| 886 | 900 | # If setup completes, test scanning |
| 887 | buddy scan --dry-run | |
| 901 | buddy scan --verbose | |
| 888 | 902 | ``` |
| 889 | 903 | |
| 890 | 904 | ## Technical Implementation |
| @@ -19,6 +19,8 @@ buddy scan [options] | ||
| 19 | 19 | - `--pattern <pattern>` - Glob pattern to match packages |
| 20 | 20 | - `--strategy <type>` - Update strategy: major|minor|patch|all (default: all) |
| 21 | 21 | - `--ignore <names>` - Comma-separated list of packages to ignore |
| 22 | - `--respect-latest` - Leave `latest`, `*` and other dynamic ranges alone (default) | |
| 23 | - `--no-respect-latest` - Propose updates for dynamic ranges too | |
| 22 | 24 | |
| 23 | 25 | ### Examples |
| 24 | 26 | |
| @@ -40,6 +42,9 @@ buddy scan --strategy minor | ||
| 40 | 42 | |
| 41 | 43 | # Ignore specific packages |
| 42 | 44 | buddy scan --ignore "eslint,prettier" |
| 45 | ||
| 46 | # Include packages pinned to "latest" or "*" | |
| 47 | buddy scan --no-respect-latest | |
| 43 | 48 | ``` |
| 44 | 49 | |
| 45 | 50 | ### Output |
| @@ -73,6 +78,8 @@ buddy update [options] | ||
| 73 | 78 | - `--strategy <type>` - Update strategy: major|minor|patch|all (default: all) |
| 74 | 79 | - `--ignore <names>` - Comma-separated list of packages to ignore |
| 75 | 80 | - `--dry-run` - Preview changes without making them |
| 81 | - `--respect-latest` - Leave `latest`, `*` and other dynamic ranges alone (default) | |
| 82 | - `--no-respect-latest` - Update dynamic ranges too | |
| 76 | 83 | |
| 77 | 84 | ### Examples |
| 78 | 85 | |
| @@ -91,6 +98,9 @@ buddy update --verbose | ||
| 91 | 98 | |
| 92 | 99 | # Ignore specific packages |
| 93 | 100 | buddy update --ignore "@types/node,eslint" |
| 101 | ||
| 102 | # Include packages pinned to "latest" or "*" | |
| 103 | buddy update --no-respect-latest | |
| 94 | 104 | ``` |
| 95 | 105 | |
| 96 | 106 | ### Dry Run Output |
| @@ -238,37 +248,57 @@ When checked (marked with `x`): | ||
| 238 | 248 | |
| 239 | 249 | All update commands respect configuration from `buddy.config.ts`: |
| 240 | 250 | |
| 241 | ### Strategy Override | |
| 251 | ### Strategy | |
| 252 | ||
| 253 | `scan` and `update` always send a strategy of their own — `all` unless `--strategy` says otherwise — so `packages.strategy` is what the programmatic API and your own tooling read, not what these two commands run with. On the command line, name the strategy you want: | |
| 254 | ||
| 255 | ```bash | |
| 256 | # Patch releases only, for this run | |
| 257 | buddy update --strategy patch | |
| 258 | ``` | |
| 259 | ||
| 260 | To hold a strategy for particular packages rather than the whole run, put it in a package rule. Rules run after the global strategy filter, so a rule narrows what those packages may propose whatever `--strategy` was passed: | |
| 242 | 261 | |
| 243 | 262 | ```typescript |
| 244 | // Config strategy can be overridden by CLI | |
| 245 | 263 | export default { |
| 246 | 264 | packages: { |
| 247 | strategy: 'patch' // Default strategy | |
| 265 | strategy: 'all', | |
| 266 | rules: [ | |
| 267 | { | |
| 268 | matchPackages: ['react', 'react-dom'], | |
| 269 | strategy: 'patch' // React moves at patch pace regardless | |
| 270 | } | |
| 271 | ] | |
| 248 | 272 | } |
| 249 | 273 | } |
| 250 | 274 | ``` |
| 251 | 275 | |
| 252 | ```bash | |
| 253 | # Override config strategy | |
| 254 | buddy update --strategy minor | |
| 276 | ### Ignore Lists | |
| 277 | ||
| 278 | ```typescript | |
| 279 | export default { | |
| 280 | packages: { | |
| 281 | ignore: ['@types/node'] // Ignored on every run | |
| 282 | } | |
| 283 | } | |
| 255 | 284 | ``` |
| 256 | 285 | |
| 257 | ### Ignore Lists | |
| 286 | Names in `ignore` are matched exactly — `@types/*` matches no package at all. Use a rule for patterns: | |
| 258 | 287 | |
| 259 | 288 | ```typescript |
| 260 | // Combine config and CLI ignore lists | |
| 261 | 289 | export default { |
| 262 | 290 | packages: { |
| 263 | ignore: ['@types/node'] // Always ignored | |
| 291 | rules: [ | |
| 292 | { matchPackages: ['@types/*'], enabled: false } | |
| 293 | ] | |
| 264 | 294 | } |
| 265 | 295 | } |
| 266 | 296 | ``` |
| 267 | 297 | |
| 268 | 298 | ```bash |
| 269 | # Additional ignores for this run | |
| 299 | # Ignore a different set for this run | |
| 270 | 300 | buddy update --ignore "eslint,prettier" |
| 271 | # Result: ignores @types/node, eslint, and prettier | |
| 301 | # Result: ignores eslint and prettier; the config list is not consulted | |
| 272 | 302 | ``` |
| 273 | 303 | |
| 274 | 304 | ## Error Handling |
| @@ -346,7 +376,7 @@ name: Dependency Updates | ||
| 346 | 376 | on: |
| 347 | 377 | schedule: |
| 348 | 378 | |
| 349 | - cron: '0 2 _ _ 1' # Weekly on Monday | |
| 379 | - cron: '0 2 * * 1' # Weekly on Monday | |
| 350 | 380 | |
| 351 | 381 | workflow_dispatch: |
| 352 | 382 | |
| @@ -12,62 +12,49 @@ buddy open-settings [options] | ||
| 12 | 12 | |
| 13 | 13 | ### Description |
| 14 | 14 | |
| 15 | Quickly open the GitHub settings pages needed to configure permissions for buddy. This includes repository settings, organization settings, and Actions configurations. | |
| 15 | Quickly open the GitHub settings pages needed to configure permissions for buddy. It opens the repository's Actions settings, follows with the organization's, and prints the exact options to change on each. | |
| 16 | 16 | |
| 17 | 17 | ### Options |
| 18 | 18 | |
| 19 | 19 | | Option | Description | Default | |
| 20 | 20 | |--------|-------------|---------| |
| 21 | | `--type <type>` | Settings type to open | `'repo'` | | |
| 22 | 21 | | `--verbose, -v` | Enable verbose logging | `false` | |
| 23 | 22 | |
| 24 | ### Settings Types | |
| 25 | ||
| 26 | - **`repo`** - Repository settings page | |
| 27 | - **`actions`** - Repository Actions settings | |
| 28 | - **`org`** - Organization settings | |
| 29 | - **`tokens`** - Personal access tokens page | |
| 30 | ||
| 31 | 23 | ### Examples |
| 32 | 24 | |
| 33 | 25 | ```bash |
| 34 | # Open repository settings | |
| 26 | # Open the Actions settings pages for this repository | |
| 35 | 27 | buddy open-settings |
| 36 | 28 | |
| 37 | # Open Actions settings | |
| 38 | buddy open-settings --type actions | |
| 39 | ||
| 40 | # Open organization settings | |
| 41 | buddy open-settings --type org | |
| 42 | ||
| 43 | # Open personal tokens page | |
| 44 | buddy open-settings --type tokens | |
| 29 | # Show how the repository was resolved | |
| 30 | buddy open-settings --verbose | |
| 45 | 31 | ``` |
| 46 | 32 | |
| 47 | 33 | ### What Opens |
| 48 | 34 | |
| 49 | #### Repository Settings (`--type repo`) | |
| 35 | The repository comes from `repository.owner` and `repository.name` in `buddy.config.ts`, falling back to `git remote get-url origin`. | |
| 36 | ||
| 37 | #### Repository Actions settings | |
| 50 | 38 | |
| 51 | - General repository settings | |
| 52 | - Collaborators and teams | |
| 53 | - Branches and protection rules | |
| 39 | `https://github.com/<owner>/<repo>/settings/actions` | |
| 54 | 40 | |
| 55 | #### Actions Settings (`--type actions`) | |
| 41 | - Workflow permissions — select "Read and write permissions" | |
| 42 | - "Allow GitHub Actions to create and approve pull requests" | |
| 56 | 43 | |
| 57 | - GitHub Actions permissions | |
| 58 | - Workflow permissions | |
| 59 | - Runner settings | |
| 44 | #### Organization Actions settings | |
| 60 | 45 | |
| 61 | #### Organization Settings (`--type org`) | |
| 46 | `https://github.com/organizations/<owner>/settings/actions` | |
| 62 | 47 | |
| 63 | - Member privileges | |
| 64 | - Third-party access | |
| 65 | - GitHub Apps | |
| 48 | - The same two settings one level up, which may override the repository's | |
| 66 | 49 | |
| 67 | #### Tokens (`--type tokens`) | |
| 50 | If neither the config nor the git remote identifies a repository, buddy prints both URLs with placeholders instead of opening anything. | |
| 68 | 51 | |
| 69 | - Personal access tokens management | |
| 70 | - Fine-grained tokens | |
| 52 | ### Related Pages | |
| 53 | ||
| 54 | buddy does not open these, but setup points you at them: | |
| 55 | ||
| 56 | - Personal access tokens — `https://github.com/settings/tokens` | |
| 57 | - Repository secrets — `https://github.com/<owner>/<repo>/settings/secrets/actions` | |
| 71 | 58 | |
| 72 | 59 | ## schedule |
| 73 | 60 | |
| @@ -79,53 +66,47 @@ buddy schedule [options] | ||
| 79 | 66 | |
| 80 | 67 | ### Description |
| 81 | 68 | |
| 82 | Execute buddy updates on a predefined schedule. This command is typically used in CI/CD environments or cron jobs for automated dependency management. | |
| 69 | Starts a scheduler in the foreground: it works out the next run from a cron expression, scans for updates when that time arrives, and opens pull requests for what it finds. The process stays alive until you stop it with Ctrl+C, so it belongs on a machine that stays up. On a CI runner, put the cadence in the workflow trigger and run `buddy update` instead, as the CI/CD Integration section below shows. | |
| 83 | 70 | |
| 84 | 71 | ### Options |
| 85 | 72 | |
| 86 | 73 | | Option | Description | Default | |
| 87 | 74 | |--------|-------------|---------| |
| 88 | | `--cron <expression>` | Cron expression for scheduling | From config | | |
| 89 | | `--timezone <tz>` | Timezone for scheduling | `'UTC'` | | |
| 90 | | `--dry-run` | Show what would be updated without making changes | `false` | | |
| 91 | | `--strategy <type>` | Update strategy override | From config | | |
| 75 | | `--strategy <type>` | Update strategy, and the cadence that goes with it | `all` | | |
| 92 | 76 | | `--verbose, -v` | Enable verbose logging | `false` | |
| 93 | 77 | |
| 94 | 78 | ### Examples |
| 95 | 79 | |
| 96 | 80 | ```bash |
| 97 | # Run scheduled updates (uses config) | |
| 81 | # Run scheduled updates | |
| 98 | 82 | buddy schedule |
| 99 | 83 | |
| 100 | # Override cron schedule | |
| 101 | buddy schedule --cron "0 2 * * 1" | |
| 102 | ||
| 103 | # Different timezone | |
| 104 | buddy schedule --timezone "America/New*York" | |
| 105 | ||
| 106 | # Dry run to preview changes | |
| 107 | buddy schedule --dry-run | |
| 108 | ||
| 109 | # Override update strategy | |
| 84 | # Daily patch updates | |
| 110 | 85 | buddy schedule --strategy patch |
| 86 | ||
| 87 | # Watch what the scheduler is doing | |
| 88 | buddy schedule --verbose | |
| 111 | 89 | ``` |
| 112 | 90 | |
| 113 | ### Cron Expressions | |
| 91 | ### Schedules | |
| 114 | 92 | |
| 115 | Common scheduling patterns: | |
| 93 | The strategy picks the cadence, so that larger updates arrive less often: | |
| 116 | 94 | |
| 117 | ```bash | |
| 118 | # Every day at 2 AM UTC | |
| 119 | buddy schedule --cron "0 2 * * *" | |
| 95 | | Strategy | Cron | | |
| 96 | |----------|------| | |
| 97 | | `patch` | `0 2 * * *` | | |
| 98 | | `minor` | `0 2 * * 1,4` | | |
| 99 | | `major` | `0 2 * * 1` | | |
| 100 | | `all` | `0 2 * * 1` | | |
| 120 | 101 | |
| 121 | # Weekly on Monday at 2 AM | |
| 122 | buddy schedule --cron "0 2 * * 1" | |
| 102 | The next run is derived from the hour and minute fields; the day-of-month and day-of-week fields are not evaluated, so all four of these fire at 2 AM every day. When the day has to matter, drive the cadence from a real cron daemon or a workflow `schedule:` trigger. | |
| 123 | 103 | |
| 124 | # Every 6 hours | |
| 125 | buddy schedule --cron "0 */6 * * *" | |
| 104 | On start the scheduler prints the expression it settled on and when it will next fire: | |
| 126 | 105 | |
| 127 | # Weekdays at 9 AM | |
| 128 | buddy schedule --cron "0 9 * * 1-5" | |
| 106 | ```bash | |
| 107 | ✅ Scheduler started with cron: 0 2 * * 1 | |
| 108 | �� Next run: 2026-09-01T02:00:00.000Z | |
| 109 | �� Press Ctrl+C to stop the scheduler | |
| 129 | 110 | ``` |
| 130 | 111 | |
| 131 | 112 | ### Configuration Integration |
| @@ -135,17 +116,25 @@ The schedule command uses settings from `buddy.config.ts`: | ||
| 135 | 116 | ```typescript |
| 136 | 117 | export default { |
| 137 | 118 | schedule: { |
| 138 | cron: '0 2 * * 1', // Weekly on Monday at 2 AM | |
| 139 | timezone: 'UTC', | |
| 119 | timezone: 'America/New_York', // Time zone the cron is read in | |
| 120 | }, | |
| 121 | repository: { | |
| 122 | provider: 'github', | |
| 123 | owner: 'your-org', | |
| 124 | name: 'your-repo', | |
| 140 | 125 | }, |
| 141 | packages: { | |
| 142 | strategy: 'patch', // Used by scheduler | |
| 126 | pullRequest: { | |
| 127 | labels: ['dependencies'], | |
| 143 | 128 | }, |
| 144 | 129 | } satisfies BuddyConfig |
| 145 | 130 | ``` |
| 146 | 131 | |
| 132 | Repository details are required: without `repository.provider`, `repository.owner` and `repository.name`, the command exits before the scheduler starts. Pull requests are only opened when `pullRequest` is configured as well — otherwise a run scans, reports what it found, and stops there. | |
| 133 | ||
| 147 | 134 | ### CI/CD Integration |
| 148 | 135 | |
| 136 | A runner exits when the job does, so there is nothing for a long-lived scheduler to wait for. Let the workflow trigger carry the schedule and run `buddy update`: | |
| 137 | ||
| 149 | 138 | **GitHub Actions** |
| 150 | 139 | ```yaml |
| 151 | 140 | name: Scheduled Dependencies |
| @@ -163,19 +152,23 @@ jobs: | ||
| 163 | 152 | steps: |
| 164 | 153 | |
| 165 | 154 | - uses: actions/checkout@v4 |
| 166 | - uses: oven-sh/setup-bun@v1 | |
| 167 | - run: bunx @buddysh/buddy schedule | |
| 155 | - uses: oven-sh/setup-bun@v2 | |
| 156 | - run: bunx @buddysh/buddy update --strategy patch --verbose | |
| 168 | 157 | |
| 169 | 158 | env: |
| 170 | 159 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 171 | 160 | ``` |
| 172 | 161 | |
| 162 | Same reasoning on a server you own — cron supplies the cadence, `update` does the work: | |
| 163 | ||
| 173 | 164 | **Cron Job** |
| 174 | 165 | ```bash |
| 175 | 166 | # Add to crontab |
| 176 | 0 2 * * 1 cd /path/to/project && bunx @buddysh/buddy schedule | |
| 167 | 0 2 * * 1 cd /path/to/project && bunx @buddysh/buddy update --strategy patch | |
| 177 | 168 | ``` |
| 178 | 169 | |
| 170 | Reach for `buddy schedule` when you want one resident process instead, supervised by systemd or a process manager. | |
| 171 | ||
| 179 | 172 | ### Output |
| 180 | 173 | |
| 181 | 174 | The schedule command provides detailed information about: |
| @@ -189,7 +182,7 @@ The schedule command provides detailed information about: | ||
| 189 | 182 | |
| 190 | 183 | **Schedule not running:** |
| 191 | 184 | |
| 192 | - Check cron expression syntax | |
| 185 | - Check the strategy you passed, and the cadence it maps to | |
| 193 | 186 | - Verify timezone settings |
| 194 | 187 | - Ensure GitHub token is valid |
| 195 | 188 | |
| @@ -49,7 +49,7 @@ const config: BuddyConfig = { | ||
| 49 | 49 | |
| 50 | 50 | // Scheduling configuration |
| 51 | 51 | schedule: { |
| 52 | cron: '0 2 _ _ 1', // Weekly on Monday at 2 AM | |
| 52 | cron: '0 2 * * 1', // Weekly on Monday at 2 AM | |
| 53 | 53 | timezone: 'UTC', |
| 54 | 54 | }, |
| 55 | 55 | } |
| @@ -78,7 +78,7 @@ const supportedFiles = [ | ||
| 78 | 78 | ] |
| 79 | 79 | ``` |
| 80 | 80 | |
| 81 | All dependency files are parsed using the `ts-pkgx` library and updates are applied while preserving formatting, comments, and version prefixes (`^`, `~`, `>=`, etc.). | |
| 81 | All dependency files are parsed using the `ts-pantry` library and updates are applied while preserving formatting, comments, and version prefixes (`^`, `~`, `>=`, etc.). | |
| 82 | 82 | |
| 83 | 83 | ### Package Groups |
| 84 | 84 | |
| @@ -128,8 +128,8 @@ All matchers present on a rule must match (AND within a rule). | ||
| 128 | 128 | |
| 129 | 129 | | Matcher | Matches on | |
| 130 | 130 | | --------------------- | ------------------------------------------------------- | |
| 131 | | `matchPackages` | Package names or globs (`@types/_`) | | |
| 132 | | `matchEcosystems` | `npm`, `composer`, `github-actions`, `docker`, `pkgx`, `zig` | | |
| 131 | | `matchPackages` | Package names or globs (`@types/*`) | | |
| 132 | | `matchEcosystems` | `npm`, `composer`, `github-actions`, `docker`, `pkgx`, `zig`, `python`, `rust`, `go`, `ruby` | | |
| 133 | 133 | | `matchDepTypes` | `dependencies`, `devDependencies`, `peerDependencies`, … | |
| 134 | 134 | | `matchUpdateTypes` | `major`, `minor`, `patch` | |
| 135 | 135 | | `matchFiles` | Globs on the manifest path, for monorepo directories | |
| @@ -137,9 +137,14 @@ All matchers present on a rule must match (AND within a rule). | ||
| 137 | 137 | | `schedule` | Cron window during which the rule applies | |
| 138 | 138 | |
| 139 | 139 | A rule with no matchers applies to every update. Configuration validation |
| 140 | rejects that unless you write `matchPackages: ['_']`, because a matcherless | |
| 141 | rule is almost always a typo'd matcher — and a typo does not disable a rule, it | |
| 142 | widens it. | |
| 140 | rejects that unless you write an explicit catch-all matcher, because a | |
| 141 | matcherless rule is almost always a typo'd matcher — and a typo does not | |
| 142 | disable a rule, it widens it. | |
| 143 | ||
| 144 | Write that catch-all as `matchPackages: ['**']`, not `['*']`. Package names are | |
| 145 | matched as paths, so a single `*` stops at the `/` in a scoped name: `['*']` | |
| 146 | matches `react` but not `@types/node`. Use `['**']` for every package, or | |
| 147 | `['@scope/*']` to target one scope. | |
| 143 | 148 | |
| 144 | 149 | #### Effects |
| 145 | 150 | |
| @@ -204,7 +209,7 @@ Tuesday run holds these back and a Saturday run lets them through: | ||
| 204 | 209 | rules: [ |
| 205 | 210 | { |
| 206 | 211 | matchUpdateTypes: ['major'], |
| 207 | schedule: '0 0-23 _ _ 6,0', | |
| 212 | schedule: '0 0-23 * * 6,0', | |
| 208 | 213 | scheduleTimezone: 'Europe/Berlin', |
| 209 | 214 | }, |
| 210 | 215 | ] |
| @@ -222,7 +227,7 @@ rules: [ | ||
| 222 | 227 | |
| 223 | 228 | ```typescript |
| 224 | 229 | rules: [ |
| 225 | { matchPackages: ['*'], prPriority: 0 }, | |
| 230 | { matchPackages: ['**'], prPriority: 0 }, | |
| 226 | 231 | { matchDepTypes: ['dependencies'], prPriority: 10, labels: ['runtime'] }, |
| 227 | 232 | ] |
| 228 | 233 | ``` |
| @@ -299,7 +304,7 @@ const config: BuddyConfig = { | ||
| 299 | 304 | custom: [ |
| 300 | 305 | { |
| 301 | 306 | name: 'Security Updates', |
| 302 | schedule: '0 _/6 _ _ _', // Every 6 hours | |
| 307 | schedule: '0 */6 * * *', // Every 6 hours | |
| 303 | 308 | strategy: 'patch', |
| 304 | 309 | autoMerge: true, |
| 305 | 310 | reviewers: ['security-team'], |
| @@ -329,10 +334,18 @@ const config: BuddyConfig = { | ||
| 329 | 334 | | Option | Type | Description | Default | |
| 330 | 335 | |--------|------|-------------|---------| |
| 331 | 336 | | `strategy` | `'major' \| 'minor' \| 'patch' \| 'all'` | Update strategy | `'all'` | |
| 332 | | `ignore` | `string[]` | Packages to ignore | `[]` | | |
| 337 | | `ignore` | `string[]` | Package names to ignore, matched exactly | `[]` | | |
| 333 | 338 | | `pin` | `Record<string, string>` | Pin packages to versions | `{}` | |
| 334 | 339 | | `groups` | `PackageGroup[]` | Package groupings | `undefined` | |
| 335 | 340 | |
| 341 | The strategy selects which semver impacts are proposed: `all` admits every | |
| 342 | update, `major` majors only, `minor` minors and patches, `patch` patches only. | |
| 343 | ||
| 344 | `ignore` is compared by exact package name — `@types/*` matches nothing and | |
| 345 | silently ignores nothing. Use a [package rule](#package-rules) with | |
| 346 | `matchPackages` when you want a pattern. (`ignorePaths`, which takes file | |
| 347 | paths, does use globs.) | |
| 348 | ||
| 336 | 349 | ### Logging |
| 337 | 350 | |
| 338 | 351 | | Option | Type | Description | Default | |
| @@ -392,7 +405,7 @@ Set `security.enabled: false` for fully offline runs. | ||
| 392 | 405 | |--------|------|-------------|---------| |
| 393 | 406 | | `reviewers` | `string[]` | GitHub usernames for review | `[]` | |
| 394 | 407 | | `assignees` | `string[]` | GitHub usernames to assign | `[]` | |
| 395 | | `labels` | `string[]` | Labels to apply | `['dependencies']` | | |
| 408 | | `labels` | `string[]` | Labels to add, on top of the automatic set | `[]` | | |
| 396 | 409 | | `autoMerge` | `AutoMergeConfig` | Auto-merge configuration, see [Auto-Merge](/features/auto-merge) | `undefined` | |
| 397 | 410 | |
| 398 | 411 | ### Pull Request Templates |
| @@ -449,12 +462,13 @@ Buddy uses these environment variables: | ||
| 449 | 462 | # Required for GitHub operations |
| 450 | 463 | GITHUB_TOKEN=ghp_xxxxxxxxxxxx |
| 451 | 464 | |
| 452 | # Optional: Alternative token name | |
| 453 | GH_TOKEN=ghp_xxxxxxxxxxxx | |
| 454 | ||
| 455 | # Optional: alternative token, preferred when set (needs `workflow` scope) | |
| 465 | # Optional: the workflow token, a PAT with `repo` and `workflow` scopes. Also the | |
| 466 | # last fallback for API operations, used only when GITHUB_TOKEN is unset | |
| 456 | 467 | BUDDY_TOKEN=ghp_xxxxxxxxxxxx |
| 457 | 468 | |
| 469 | # Optional: fallback for read-only calls (registry lookups, release notes) | |
| 470 | GH_TOKEN=ghp_xxxxxxxxxxxx | |
| 471 | ||
| 458 | 472 | # Optional: GitHub Enterprise Server. GitHub Actions sets both automatically |
| 459 | 473 | GITHUB_API_URL=https://github.acme.com/api/v3 |
| 460 | 474 | GITHUB_SERVER_URL=https://github.acme.com |
| @@ -478,6 +492,20 @@ BUDDY_HTTP_TIMEOUT_MS=30000 | ||
| 478 | 492 | BUN_CONFIG_NO_CACHE=false |
| 479 | 493 | ``` |
| 480 | 494 | |
| 495 | ### Token precedence | |
| 496 | ||
| 497 | For git and pull request operations the token is resolved in this order: | |
| 498 | `repository.token` from your config, then `GITHUB_TOKEN`, then `BUDDY_TOKEN`. | |
| 499 | The ambient CI token deliberately comes first: it attributes pull requests to | |
| 500 | the CI bot rather than to whoever's personal token happens to be in the | |
| 501 | environment. | |
| 502 | ||
| 503 | Because GitHub Actions always injects `GITHUB_TOKEN`, `BUDDY_TOKEN` never wins | |
| 504 | that lookup on a runner. It has a different job there — it is picked up | |
| 505 | separately as the _workflow_ token, which is what lets Buddy commit changes to | |
| 506 | files under `.github/workflows/`. Set both: `GITHUB_TOKEN` for the API and PR | |
| 507 | work, `BUDDY_TOKEN` for the elevated `workflow` scope. | |
| 508 | ||
| 481 | 509 | ## GitHub Enterprise Server |
| 482 | 510 | |
| 483 | 511 | Buddy runs unmodified against GitHub Enterprise Server. On a GHES runner, |
| @@ -647,7 +675,7 @@ Buddy provides comprehensive dependency management across four categories: | ||
| 647 | 675 | - **dependencies.yaml**/**dependencies.yml** - Alternative format |
| 648 | 676 | - **pkgx.yaml**/**pkgx.yml** - pkgx-specific files |
| 649 | 677 | - **.deps.yaml**/**.deps.yml** - Hidden configuration files |
| 650 | - Managed via `ts-pkgx` library integration | |
| 678 | - Managed via `ts-pantry` library integration | |
| 651 | 679 | |
| 652 | 680 | ### GitHub Actions |
| 653 | 681 | |
| @@ -702,6 +730,19 @@ const config: BuddyConfig = { | ||
| 702 | 730 | } |
| 703 | 731 | ``` |
| 704 | 732 | |
| 733 | Every entry is an exact package name. To exclude a whole family, match it with | |
| 734 | a rule instead: | |
| 735 | ||
| 736 | ```typescript | |
| 737 | const config: BuddyConfig = { | |
| 738 | packages: { | |
| 739 | rules: [ | |
| 740 | { matchPackages: ['@types/*'], enabled: false }, | |
| 741 | ], | |
| 742 | }, | |
| 743 | } | |
| 744 | ``` | |
| 745 | ||
| 705 | 746 | #### Strategy Application |
| 706 | 747 | |
| 707 | 748 | Update strategies apply to all dependency types: |
| @@ -709,7 +750,7 @@ Update strategies apply to all dependency types: | ||
| 709 | 750 | ```typescript |
| 710 | 751 | const config: BuddyConfig = { |
| 711 | 752 | packages: { |
| 712 | strategy: 'patch', // Applies to npm, pkgx, AND GitHub Actions | |
| 753 | strategy: 'patch', // Patch updates only, across npm, pkgx, AND GitHub Actions | |
| 713 | 754 | }, |
| 714 | 755 | } |
| 715 | 756 | ``` |
| @@ -31,9 +31,11 @@ A PR qualifies when **any** listed condition accepts it. | ||
| 31 | 31 | |---|---| |
| 32 | 32 | | `patch-only` | Every update in the PR is a patch bump | |
| 33 | 33 | | `minor-only` | Every update is minor or patch (no majors) | |
| 34 | | `security-only` | The PR carries the configured `security.label` | | |
| 34 | | `security-only` | The PR carries the configured `security.label` (default `security`) | | |
| 35 | 35 | | `all` | Any Buddy PR, including major upgrades | |
| 36 | 36 | |
| 37 | `security-only` reads a label, and Buddy does not apply that label on its own — a PR gets it because you put it there, either through `pullRequest.labels` or a package rule. Configure `security-only` without arranging for the label and nothing will ever match it. | |
| 38 | ||
| 37 | 39 | Unknown condition names are rejected by config validation rather than ignored, so a typo like `patch_only` fails loudly instead of widening what merges unreviewed. |
| 38 | 40 | |
| 39 | 41 | Update types are read from the metadata manifest embedded in each PR body, not from the PR title. A retitled or hand-edited PR therefore cannot talk its way past a `patch-only` policy. A PR whose manifest is missing (opened before manifests existed) or truncated (a very large group whose manifest had to drop rows) is never auto-merged, because neither case proves what the PR actually changes. |
| @@ -183,7 +183,7 @@ name: Dependency Dashboard | ||
| 183 | 183 | on: |
| 184 | 184 | schedule: |
| 185 | 185 | |
| 186 | - cron: '0 9 _ _ 1,3,5' # Monday, Wednesday, Friday at 9 AM UTC | |
| 186 | - cron: '0 9 * * 1,3,5' # Monday, Wednesday, Friday at 9 AM UTC | |
| 187 | 187 | |
| 188 | 188 | jobs: |
| 189 | 189 | update-dashboard: |
| @@ -200,7 +200,7 @@ jobs: | ||
| 200 | 200 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 201 | 201 | ``` |
| 202 | 202 | |
| 203 | **�� Ready-to-use workflow**: Buddy includes a pre-built dashboard workflow at `.github/workflows/buddy-dashboard.yml` that you can use directly. It includes manual triggering, dry-run mode, and customizable options. | |
| 203 | **�� Ready-to-use workflow**: you rarely need the workflow above. `buddy setup` writes a single `.github/workflows/buddy.yml` whose dashboard job already refreshes the issue on the `15 */2 * * *` schedule, and it can be run on demand from the Actions tab — pick **Buddy**, then **Run workflow**, then set **Which job to run** to `dashboard`. The same dispatch takes a custom title, a specific issue number and the pin toggle. | |
| 204 | 204 | |
| 205 | 205 | ### Auto-Update |
| 206 | 206 | |
| @@ -19,7 +19,7 @@ Buddy automatically detects and updates the following dependency file formats: | ||
| 19 | 19 | |
| 20 | 20 | ## How It Works |
| 21 | 21 | |
| 22 | Buddy uses the `ts-pkgx` library to parse and resolve dependency files, ensuring full compatibility with the pkgx registry ecosystem while supporting tools like Launchpad that reuse the same registry format. | |
| 22 | Buddy uses the `ts-pantry` library to parse and resolve dependency files, ensuring full compatibility with the pkgx registry ecosystem while supporting tools like Launchpad that reuse the same registry format. | |
| 23 | 23 | |
| 24 | 24 | ### Automatic Detection |
| 25 | 25 | |
| @@ -260,7 +260,7 @@ export default { | ||
| 260 | 260 | packages: { |
| 261 | 261 | rules: [ |
| 262 | 262 | { matchEcosystems: ['npm'], groupName: 'npm dependencies' }, |
| 263 | { matchEcosystems: ['launchpad'], groupName: 'pkgx tools' }, | |
| 263 | { matchEcosystems: ['pkgx'], groupName: 'pkgx tools' }, | |
| 264 | 264 | { matchEcosystems: ['github-actions'], groupName: 'GitHub Actions' } |
| 265 | 265 | ] |
| 266 | 266 | }, |
| @@ -325,32 +325,46 @@ export default { | ||
| 325 | 325 | |
| 326 | 326 | ## CLI Commands |
| 327 | 327 | |
| 328 | ### Scan Specific File Types | |
| 328 | ### Scanning | |
| 329 | ||
| 330 | Every manifest in the repository is scanned in one pass; there is no flag that | |
| 331 | narrows a run to one file type. What the CLI does take is a package filter and | |
| 332 | a strategy: | |
| 329 | 333 | |
| 330 | 334 | ```bash |
| 331 | # Scan only package.json files | |
| 332 | buddy scan --file-type package.json | |
| 335 | # Scan every dependency file Buddy supports | |
| 336 | buddy scan | |
| 333 | 337 | |
| 334 | # Scan only dependency files | |
| 335 | buddy scan --file-type deps.yaml | |
| 338 | # Scan named packages only | |
| 339 | buddy scan --packages "bun,typescript" | |
| 336 | 340 | |
| 337 | # Scan specific files | |
| 338 | buddy scan --files "deps.yaml,package.json" | |
| 339 | ``` | |
| 341 | # Scan a family of packages by pattern | |
| 342 | buddy scan --pattern "@types/*" | |
| 340 | 343 | |
| 341 | ### Update Specific Formats | |
| 344 | # Scan with a specific strategy | |
| 345 | buddy scan --strategy patch | |
| 346 | ``` | |
| 342 | 347 | |
| 343 | ```bash | |
| 344 | # Update only npm dependencies | |
| 345 | buddy update --package-manager npm | |
| 348 | ### Restricting Formats | |
| 346 | 349 | |
| 347 | # Update only pkgx dependencies | |
| 348 | buddy update --package-manager pkgx | |
| 350 | Narrowing by file or ecosystem is config, not a flag. A rule with | |
| 351 | `enabled: false` drops matching updates entirely, so the run only proposes what | |
| 352 | is left: | |
| 349 | 353 | |
| 350 | # Update with different strategies per type | |
| 351 | buddy update --strategy package.json:minor,deps.yaml:patch | |
| 354 | ```typescript | |
| 355 | export default { | |
| 356 | packages: { | |
| 357 | rules: [ | |
| 358 | // Leave the pkgx/Launchpad files alone; npm only | |
| 359 | { matchEcosystems: ['pkgx'], enabled: false } | |
| 360 | ] | |
| 361 | } | |
| 362 | } satisfies BuddyConfig | |
| 352 | 363 | ``` |
| 353 | 364 | |
| 365 | Per-format strategies work the same way — see | |
| 366 | [file-specific configuration](#file-specific-configuration) above. | |
| 367 | ||
| 354 | 368 | ## Troubleshooting |
| 355 | 369 | |
| 356 | 370 | ### Common Issues |
| @@ -366,8 +380,8 @@ cat deps.yaml | ||
| 366 | 380 | |
| 367 | 381 | **pkgx resolution errors:** |
| 368 | 382 | ```bash |
| 369 | # Verify ts-pkgx can parse the file | |
| 370 | bunx ts-pkgx resolve deps.yaml | |
| 383 | # Verify ts-pantry can parse the file | |
| 384 | bunx ts-pantry resolve-deps deps.yaml | |
| 371 | 385 | |
| 372 | 386 | # Check for syntax errors |
| 373 | 387 | yamllint deps.yaml |
| @@ -380,14 +394,11 @@ yamllint deps.yaml | ||
| 380 | 394 | # ❌ Avoid: 1.*, ^1.0, ~2 |
| 381 | 395 | ``` |
| 382 | 396 | |
| 383 | ### Debug Mode | |
| 397 | ### Verbose Mode | |
| 384 | 398 | |
| 385 | 399 | ```bash |
| 386 | # Enable verbose logging for dependency files | |
| 387 | buddy scan --verbose --debug dependency-files | |
| 388 | ||
| 389 | # Show file detection process | |
| 390 | buddy scan --show-files | |
| 400 | # Log the file detection and resolution process | |
| 401 | buddy scan --verbose | |
| 391 | 402 | ``` |
| 392 | 403 | |
| 393 | 404 | ## Best Practices |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | --- |
| 2 | 2 | layout: home |
| 3 | 3 | title: Dependency Updates |
| 4 | description: Buddy replaces Renovate and Dependabot — scanning, grouping, real changelogs, OSV advisories, a pinned dashboard, interactive rebase and auto-merge across eleven ecosystems. | |
| 4 | description: Buddy replaces Renovate and Dependabot — scanning, grouping, real changelogs, OSV advisories, a pinned dashboard, interactive rebase and auto-merge across ten ecosystems. | |
| 5 | 5 | |
| 6 | 6 | hero: |
| 7 | 7 | name: "dependency updates" |
| @@ -91,7 +91,7 @@ hero: | ||
| 91 | 91 | } satisfies BuddyConfig |
| 92 | 92 | |
| 93 | 93 | features: |
| 94 | - title: "Eleven ecosystems" | |
| 94 | - title: "Ten ecosystems" | |
| 95 | 95 | icon: "🌍" |
| 96 | 96 | span: 2 |
| 97 | 97 | details: "npm, Bun, yarn and pnpm; Composer; GitHub Actions; Docker; pkgx and Launchpad; Zig; and — through the adapter interface — Python, Rust, Go and Ruby. Every lock file that has one is regenerated with the right tool, not hand-edited." |
| @@ -133,8 +133,8 @@ Then the maintenance commands: `buddy dashboard` refreshes the pinned issue, `bu | ||
| 133 | 133 | |
| 134 | 134 | | Strategy | Updates it proposes | |
| 135 | 135 | | --- | --- | |
| 136 | | `patch` | Everything, patch first — the safest default to automate | | |
| 137 | | `minor` | Major and minor, no patch-only churn | | |
| 136 | | `patch` | Patch only — the safest default to automate | | |
| 137 | | `minor` | Minor and patch, no majors | | |
| 138 | 138 | | `major` | Major versions only | |
| 139 | 139 | | `all` | Everything, regardless of semver impact | |
| 140 | 140 | |
| @@ -119,8 +119,20 @@ buddy update | ||
| 119 | 119 | # Dry run to preview action updates |
| 120 | 120 | buddy update --dry-run |
| 121 | 121 | |
| 122 | # Assign action updates to specific team | |
| 123 | buddy update --assignee devops-team | |
| 122 | # Keep the run to minor and patch updates | |
| 123 | buddy update --strategy minor | |
| 124 | ``` | |
| 125 | ||
| 126 | Reviewers, assignees and labels are not flags — they are set once in `buddy.config.ts` and applied to every PR Buddy opens: | |
| 127 | ||
| 128 | ```typescript | |
| 129 | // buddy.config.ts | |
| 130 | export default { | |
| 131 | pullRequest: { | |
| 132 | teamReviewers: ['devops'], | |
| 133 | labels: ['dependencies', 'github-actions'], | |
| 134 | }, | |
| 135 | } | |
| 124 | 136 | ``` |
| 125 | 137 | |
| 126 | 138 | ## Best Practices |
| @@ -1,327 +1,227 @@ | ||
| 1 | 1 | # Labeling & Assignment |
| 2 | 2 | |
| 3 | Buddy provides intelligent labeling and team assignment features to ensure proper pull request categorization and review workflows. | |
| 3 | Every pull request Buddy opens arrives already labelled, and — when you ask for | |
| 4 | it — already carrying the reviewers and assignees the change deserves. Labels | |
| 5 | come from two places: a set Buddy derives from the update itself, and whatever | |
| 6 | your `packages.rules` attach to the packages that matched. Reviewers and | |
| 7 | assignees come from your repository-wide `pullRequest` settings, unioned with | |
| 8 | the same rules. | |
| 9 | ||
| 10 | ## Automatic Labels | |
| 11 | ||
| 12 | Buddy derives these from the group it is about to open a PR for. They need no | |
| 13 | configuration and are always present. | |
| 14 | ||
| 15 | | Label | Applied when | | |
| 16 | |---|---| | |
| 17 | | `dependencies` | Always | | |
| 18 | | `major` / `minor` / `patch` | The greatest semver impact in the PR | | |
| 19 | | `npm` | The PR touches a `package.json` | | |
| 20 | | `composer` | It touches `composer.json` or `composer.lock` | | |
| 21 | | `zig` | It touches `build.zig.zon` | | |
| 22 | | `system` | It touches a `deps.yaml`-style dependency file | | |
| 23 | | `github-actions` | It touches a workflow under `.github/workflows/` | | |
| 24 | | *the package name* | The PR updates exactly one package | | |
| 25 | ||
| 26 | A PR bumping `react` on its own therefore opens with `dependencies`, `minor`, | |
| 27 | `npm` and `react` before any rule of yours is consulted. | |
| 28 | ||
| 29 | Labels that do not exist on the repository are retried one at a time and skipped | |
| 30 | with a warning rather than failing the pull request, so a typo'd label costs you | |
| 31 | a label, not a PR. | |
| 32 | ||
| 33 | ## Per-Package Labels, Reviewers and Assignees | |
| 34 | ||
| 35 | `packages.rules` is where targeting happens. A rule matches on any combination of | |
| 36 | package name, ecosystem, dependency type, update type, file path, installed | |
| 37 | version and schedule, and attaches `labels`, `reviewers` and `assignees` to | |
| 38 | whatever it matched. | |
| 4 | 39 | |
| 5 | ## Dynamic Labeling | |
| 40 | ```typescript | |
| 41 | // buddy.config.ts | |
| 42 | import type { BuddyConfig } from '@buddysh/buddy' | |
| 43 | ||
| 44 | const config: BuddyConfig = { | |
| 45 | packages: { | |
| 46 | strategy: 'all', | |
| 47 | rules: [ | |
| 48 | { | |
| 49 | matchEcosystems: ['npm'], | |
| 50 | labels: ['javascript'], | |
| 51 | reviewers: ['platform-team'], | |
| 52 | }, | |
| 53 | { | |
| 54 | matchPackages: ['react', 'react-dom', '@types/react*'], | |
| 55 | labels: ['frontend'], | |
| 56 | reviewers: ['ui-lead'], | |
| 57 | assignees: ['ui-lead'], | |
| 58 | }, | |
| 59 | ], | |
| 60 | }, | |
| 61 | } | |
| 6 | 62 | |
| 7 | Buddy automatically applies contextual labels based on package characteristics, update types, and change scope. | |
| 63 | export default config | |
| 64 | ``` | |
| 8 | 65 | |
| 9 | ### Default Label Categories | |
| 66 | ### Effects Accumulate | |
| 10 | 67 | |
| 11 | #### Update Type Labels | |
| 68 | This is the part worth understanding, because it is what makes narrow rules safe | |
| 69 | to add: **list effects union, they do not override.** | |
| 12 | 70 | |
| 13 | - `patch-update` - Patch version updates (bug fixes) | |
| 14 | - `minor-update` - Minor version updates (new features) | |
| 15 | - `major-update` - Major version updates (breaking changes) | |
| 16 | - `security-update` - Security-related updates | |
| 17 | - `dependencies` - General dependency label | |
| 71 | A `react` bump in `package.json` matches *both* rules above. It does not take the | |
| 72 | last one and discard the first — it carries everything both rules asked for: | |
| 18 | 73 | |
| 19 | #### Package Ecosystem Labels | |
| 74 | | | Rule 1 (`npm`) | Rule 2 (`react*`) | Resolved | | |
| 75 | |---|---|---|---| | |
| 76 | | Labels | `javascript` | `frontend` | `javascript`, `frontend` | | |
| 77 | | Reviewers | `platform-team` | `ui-lead` | `platform-team`, `ui-lead` | | |
| 78 | | Assignees | — | `ui-lead` | `ui-lead` | | |
| 20 | 79 | |
| 21 | - `react-ecosystem` - React and related packages | |
| 22 | - `vue-ecosystem` - Vue.js and related packages | |
| 23 | - `angular-ecosystem` - Angular framework packages | |
| 24 | - `typescript` - TypeScript and type definitions | |
| 25 | - `testing` - Testing frameworks and utilities | |
| 26 | - `build-tools` - Build and bundling tools | |
| 27 | - `dev-dependencies` - Development-only packages | |
| 80 | Combined with the automatic labels, the pull request opens carrying | |
| 81 | `dependencies`, `minor`, `npm`, `react`, `javascript` and `frontend`, assigned to | |
| 82 | `ui-lead`, with review requested from `platform-team` and `ui-lead`. Duplicates | |
| 83 | are collapsed, so a name listed by three rules is requested once. | |
| 28 | 84 | |
| 29 | #### Scope Labels | |
| 85 | The non-list effects behave the opposite way. `enabled`, `strategy`, | |
| 86 | `groupName`, `autoMerge`, `minimumReleaseAge`, `prPriority` and `autoMigrate` | |
| 87 | are single values, so a later matching rule overrides an earlier one per field — | |
| 88 | which is what lets a broad rule set a default and a narrow one refine it. | |
| 30 | 89 | |
| 31 | - `single-package` - Updates affecting one package | |
| 32 | - `multi-package` - Updates affecting multiple packages | |
| 33 | - `monorepo-update` - Monorepo workspace updates | |
| 34 | - `breaking-changes` - Updates with breaking changes | |
| 90 | ### Matchers | |
| 35 | 91 | |
| 36 | ### Configuration | |
| 92 | All matchers present on one rule must match (AND within a rule). Add rules for | |
| 93 | OR. | |
| 37 | 94 | |
| 38 | ```typescript | |
| 39 | export default { | |
| 40 | pullRequest: { | |
| 41 | labels: { | |
| 42 | // Static labels (always applied) | |
| 43 | static: ['dependencies', 'automated'], | |
| 44 | ||
| 45 | // Dynamic labeling rules | |
| 46 | dynamic: { | |
| 47 | enabled: true, | |
| 48 | ||
| 49 | // Update type labeling | |
| 50 | updateType: { | |
| 51 | patch: 'patch-update', | |
| 52 | minor: 'minor-update', | |
| 53 | major: 'major-update', | |
| 54 | security: 'security-update' | |
| 55 | }, | |
| 56 | ||
| 57 | // Package ecosystem detection | |
| 58 | ecosystems: { | |
| 59 | react: ['react*', '@types/react*'], | |
| 60 | vue: ['vue*', '@vue/*'], | |
| 61 | angular: ['@angular/*'], | |
| 62 | typescript: ['typescript', '@types/*'], | |
| 63 | testing: ['jest', 'vitest', '@testing-library/*'] | |
| 64 | }, | |
| 65 | ||
| 66 | // Custom label rules | |
| 67 | rules: [ | |
| 68 | { | |
| 69 | condition: 'packages.includes("@types/")', | |
| 70 | label: 'type-definitions' | |
| 71 | }, | |
| 72 | { | |
| 73 | condition: 'packageCount > 5', | |
| 74 | label: 'large-update' | |
| 75 | }, | |
| 76 | { | |
| 77 | condition: 'hasBreakingChanges', | |
| 78 | label: 'breaking-changes' | |
| 79 | } | |
| 80 | ] | |
| 81 | } | |
| 82 | } | |
| 83 | } | |
| 84 | } satisfies BuddyConfig | |
| 85 | ``` | |
| 95 | | Matcher | Matches on | | |
| 96 | |---|---| | |
| 97 | | `matchPackages` | Package names or globs (`@types/*`) | | |
| 98 | | `matchEcosystems` | `npm`, `composer`, `github-actions`, `docker`, `pkgx`, `zig`, `python`, `rust`, `go`, `ruby` | | |
| 99 | | `matchDepTypes` | `dependencies`, `devDependencies`, `peerDependencies`, … | | |
| 100 | | `matchUpdateTypes` | `major`, `minor`, `patch` | | |
| 101 | | `matchFiles` | Globs on the manifest path, for monorepo directories | | |
| 102 | | `matchCurrentVersion` | Semver range the *installed* version must satisfy | | |
| 103 | | `schedule` | Cron window during which the rule applies | | |
| 86 | 104 | |
| 87 | ### Custom Label Rules | |
| 105 | A rule with no matchers at all applies to everything, and configuration | |
| 106 | validation rejects it on the grounds that it is more often a misspelled matcher | |
| 107 | than an intention — a typo does not disable a rule, it widens it. | |
| 88 | 108 | |
| 89 | #### Pattern-Based Labeling | |
| 109 | Glob `*` stops at `/`, so it does not match a scoped package: use `**` for | |
| 110 | "every package", or `@scope/*` for one scope. | |
| 90 | 111 | |
| 91 | 112 | ```typescript |
| 92 | const patternLabeling = { | |
| 93 | pullRequest: { | |
| 94 | labels: { | |
| 95 | patterns: { | |
| 96 | '@types/*': ['type-definitions', 'typescript'], | |
| 97 | 'eslint*': ['linting', 'code-quality'], | |
| 98 | 'babel*': ['build-tools', 'transpilation'], | |
| 99 | '*test*': ['testing'], | |
| 100 | '*security*': ['security'] | |
| 101 | } | |
| 102 | } | |
| 103 | } | |
| 104 | } | |
| 105 | ``` | |
| 113 | rules: [ | |
| 114 | // Repository-wide labels, applied to every update | |
| 115 | { matchPackages: ['**'], labels: ['dependencies-bot'] }, | |
| 106 | 116 | |
| 107 | #### Conditional Labeling | |
| 117 | // Per-workspace ownership in a monorepo | |
| 118 | { matchFiles: ['packages/api/**'], reviewers: ['backend-team'] }, | |
| 119 | { matchFiles: ['packages/web/**'], reviewers: ['frontend-team'] }, | |
| 108 | 120 | |
| 109 | ```typescript | |
| 110 | const conditionalLabeling = { | |
| 111 | pullRequest: { | |
| 112 | labels: { | |
| 113 | conditions: [ | |
| 114 | { | |
| 115 | when: pr => pr.packages.length === 1, | |
| 116 | apply: ['single-package'] | |
| 117 | }, | |
| 118 | { | |
| 119 | when: pr => pr.packages.some(p => p.hasBreakingChanges), | |
| 120 | apply: ['breaking-changes', 'requires-review'] | |
| 121 | }, | |
| 122 | { | |
| 123 | when: pr => pr.updateType === 'security', | |
| 124 | apply: ['security', 'high-priority'] | |
| 125 | }, | |
| 126 | { | |
| 127 | when: pr => pr.packages.every(p => p.isDevDependency), | |
| 128 | apply: ['dev-only', 'low-risk'] | |
| 129 | } | |
| 130 | ] | |
| 131 | } | |
| 132 | } | |
| 133 | } | |
| 134 | ``` | |
| 135 | ||
| 136 | ## Team Assignment | |
| 137 | ||
| 138 | Intelligent assignment of reviewers and assignees based on package ownership and team structure. | |
| 139 | ||
| 140 | ### Reviewer Assignment | |
| 141 | ||
| 142 | #### Global Reviewers | |
| 143 | ||
| 144 | ```typescript | |
| 145 | export default { | |
| 146 | pullRequest: { | |
| 147 | reviewers: ['tech-lead', 'senior-dev'], | |
| 148 | ||
| 149 | // GitHub teams, requested alongside individual reviewers | |
| 150 | teamReviewers: ['platform'], | |
| 121 | // Type definitions go to whoever maintains the types | |
| 122 | { matchPackages: ['@types/*'], labels: ['types'], assignees: ['types-owner'] }, | |
| 151 | 123 | |
| 152 | assignees: ['maintainer'] | |
| 153 | } | |
| 154 | } satisfies BuddyConfig | |
| 124 | // Majors get a second pair of eyes, whatever else matched | |
| 125 | { matchUpdateTypes: ['major'], labels: ['breaking-risk'], reviewers: ['tech-lead'] }, | |
| 126 | ] | |
| 155 | 127 | ``` |
| 156 | 128 | |
| 157 | How many approvals a merge requires is a GitHub branch-protection setting, not | |
| 158 | a Buddy one — Buddy requests reviewers, and the repository decides what | |
| 159 | counts. | |
| 129 | ### Grouped Updates | |
| 160 | 130 | |
| 161 | #### Package-Based Assignment | |
| 131 | When several updates travel in one PR, their resolved effects merge the same | |
| 132 | way: labels, reviewers and assignees union across every update in the group. A | |
| 133 | group containing one `@types/*` bump and one `react` bump carries the labels and | |
| 134 | people from both rules, because the PR genuinely touches both. | |
| 162 | 135 | |
| 163 | ```typescript | |
| 164 | const packageBasedAssignment = { | |
| 165 | pullRequest: { | |
| 166 | packageOwners: { | |
| 167 | 'react': ['frontend-team', 'react-expert'], | |
| 168 | 'vue': ['vue-team'], | |
| 169 | '@types/*': ['typescript-team'], | |
| 170 | 'eslint*': ['code-quality-team'], | |
| 171 | 'jest': ['testing-team'], | |
| 172 | 'webpack': ['build-team'], | |
| 173 | '@company/*': ['platform-team'] | |
| 174 | }, | |
| 136 | `autoMerge` resolves conservatively across a group instead — every update must | |
| 137 | allow it, so one package that must not merge unattended holds back the whole PR | |
| 138 | containing it. | |
| 175 | 139 | |
| 176 | // Fallback reviewers | |
| 177 | fallbackReviewers: ['tech-lead', 'senior-dev'] | |
| 178 | } | |
| 179 | } | |
| 180 | ``` | |
| 140 | ## Repository-Wide Reviewers and Assignees | |
| 181 | 141 | |
| 182 | #### Team-Based Assignment | |
| 183 | ||
| 184 | ```typescript | |
| 185 | const teamBasedAssignment = { | |
| 186 | pullRequest: { | |
| 187 | teams: { | |
| 188 | frontend: { | |
| 189 | members: ['alice', 'bob', 'charlie'], | |
| 190 | packages: ['react*', 'vue*', '@types/react*'], | |
| 191 | requiredReviews: 2 | |
| 192 | }, | |
| 193 | backend: { | |
| 194 | members: ['david', 'eve'], | |
| 195 | packages: ['express*', '@types/node*'], | |
| 196 | requiredReviews: 1 | |
| 197 | }, | |
| 198 | devtools: { | |
| 199 | members: ['frank', 'grace'], | |
| 200 | packages: ['eslint*', 'prettier*', 'webpack*'], | |
| 201 | autoAssign: true | |
| 202 | } | |
| 203 | } | |
| 204 | } | |
| 205 | } | |
| 206 | ``` | |
| 207 | ||
| 208 | ### Assignee Management | |
| 209 | ||
| 210 | #### Automatic Assignment | |
| 142 | Names that should be on every Buddy PR regardless of what changed belong in | |
| 143 | `pullRequest`. All three are plain string arrays. | |
| 211 | 144 | |
| 212 | 145 | ```typescript |
| 213 | 146 | export default { |
| 214 | 147 | pullRequest: { |
| 215 | assignees: { | |
| 216 | // Static assignees | |
| 217 | static: ['maintainer'], | |
| 218 | ||
| 219 | // Dynamic assignment rules | |
| 220 | rules: [ | |
| 221 | { | |
| 222 | condition: 'updateType === "security"', | |
| 223 | assignees: ['security-team'] | |
| 224 | }, | |
| 225 | { | |
| 226 | condition: 'packages.includes("react")', | |
| 227 | assignees: ['frontend-lead'] | |
| 228 | }, | |
| 229 | { | |
| 230 | condition: 'packageCount > 10', | |
| 231 | assignees: ['tech-lead'] | |
| 232 | } | |
| 233 | ], | |
| 234 | ||
| 235 | // Assignment limits | |
| 236 | maxAssignees: 3, | |
| 237 | requiresAssignee: true | |
| 238 | } | |
| 239 | } | |
| 148 | reviewers: ['tech-lead'], | |
| 149 | teamReviewers: ['platform'], | |
| 150 | assignees: ['maintainer'], | |
| 151 | }, | |
| 240 | 152 | } satisfies BuddyConfig |
| 241 | 153 | ``` |
| 242 | 154 | |
| 243 | ## CLI Label Management | |
| 244 | ||
| 245 | Manage labels and assignments via CLI: | |
| 155 | | Option | Type | Description | | |
| 156 | |---|---|---| | |
| 157 | | `reviewers` | `string[]` | GitHub usernames to request review from | | |
| 158 | | `teamReviewers` | `string[]` | GitHub team **slugs**, without the organisation prefix | | |
| 159 | | `assignees` | `string[]` | GitHub usernames to assign | | |
| 246 | 160 | |
| 247 | ```bash | |
| 248 | # List current labels | |
| 249 | buddy labels list | |
| 161 | `reviewers` and `assignees` are unioned with whatever the matching rules | |
| 162 | contributed, so the two mechanisms compose rather than compete — the repository | |
| 163 | default is a floor, not a ceiling. When neither the config nor a rule names | |
| 164 | anybody, Buddy sends no reviewer request at all rather than an empty one, which | |
| 165 | GitHub would read as a deliberate request for nobody. | |
| 250 | 166 | |
| 251 | # Create custom label | |
| 252 | buddy labels create "custom-label" --color "ff0000" --description "Custom label" | |
| 167 | Team reviewers are requested in the same API call as individual reviewers, so a | |
| 168 | config listing `teamReviewers` and no `reviewers` never sends the request. Name | |
| 169 | at least one individual reviewer alongside the team, or let a rule supply one. | |
| 253 | 170 | |
| 254 | # Assign reviewers to PR | |
| 255 | buddy assign 123 --reviewers alice,bob --assignees charlie | |
| 256 | ||
| 257 | # Update PR labels | |
| 258 | buddy labels update 123 --add security --remove low-priority | |
| 259 | ``` | |
| 171 | How many approvals a merge actually requires is a GitHub branch-protection | |
| 172 | setting, not a Buddy one. Buddy requests reviewers; the repository decides what | |
| 173 | counts. | |
| 260 | 174 | |
| 261 | ## Automation Examples | |
| 175 | ## Holding a PR Back With a Label | |
| 262 | 176 | |
| 263 | ### Security-First Assignment | |
| 177 | One label has behaviour attached to it. `pullRequest.autoMerge.optOutLabel` — | |
| 178 | `no-auto-merge` by default — suppresses auto-merge on any PR carrying it, checked | |
| 179 | both at the moment Buddy opens the PR and again when `buddy update-check` | |
| 180 | re-evaluates open ones. | |
| 264 | 181 | |
| 265 | 182 | ```typescript |
| 266 | 183 | export default { |
| 267 | 184 | pullRequest: { |
| 268 | labels: { | |
| 269 | rules: [ | |
| 270 | { | |
| 271 | condition: 'isSecurityUpdate', | |
| 272 | labels: ['security', 'high-priority', 'auto-merge-approved'] | |
| 273 | } | |
| 274 | ] | |
| 185 | autoMerge: { | |
| 186 | enabled: true, | |
| 187 | strategy: 'squash', | |
| 188 | conditions: ['patch-only'], | |
| 189 | optOutLabel: 'needs-human', | |
| 275 | 190 | }, |
| 276 | ||
| 277 | assignees: { | |
| 278 | rules: [ | |
| 279 | { | |
| 280 | condition: 'isSecurityUpdate', | |
| 281 | assignees: ['security-team'], | |
| 282 | reviewers: ['security-lead', 'tech-lead'], | |
| 283 | urgency: 'high' | |
| 284 | } | |
| 285 | ] | |
| 286 | } | |
| 287 | } | |
| 191 | }, | |
| 288 | 192 | } satisfies BuddyConfig |
| 289 | 193 | ``` |
| 290 | 194 | |
| 291 | ### Development Workflow | |
| 195 | Because rule labels are resolved before the PR is opened, a rule can mark a | |
| 196 | package as never-unattended and the PR arrives already held back: | |
| 292 | 197 | |
| 293 | 198 | ```typescript |
| 294 | export default { | |
| 295 | pullRequest: { | |
| 296 | labels: { | |
| 297 | rules: [ | |
| 298 | { | |
| 299 | condition: 'isDevDependency && updateType === "patch"', | |
| 300 | labels: ['dev-only', 'auto-merge', 'low-risk'] | |
| 301 | }, | |
| 302 | { | |
| 303 | condition: 'isProductionDependency && updateType === "major"', | |
| 304 | labels: ['production', 'breaking-changes', 'requires-testing'] | |
| 305 | } | |
| 306 | ] | |
| 307 | }, | |
| 308 | ||
| 309 | assignees: { | |
| 310 | rules: [ | |
| 311 | { | |
| 312 | condition: 'isDevDependency', | |
| 313 | assignees: ['dev-lead'], | |
| 314 | reviewers: ['senior-dev'] | |
| 315 | }, | |
| 316 | { | |
| 317 | condition: 'isProductionDependency', | |
| 318 | assignees: ['tech-lead'], | |
| 319 | reviewers: ['tech-lead', 'senior-dev-1', 'senior-dev-2'] | |
| 320 | } | |
| 321 | ] | |
| 322 | } | |
| 323 | } | |
| 324 | } satisfies BuddyConfig | |
| 199 | rules: [ | |
| 200 | { matchPackages: ['@company/auth*'], labels: ['no-auto-merge'] }, | |
| 201 | ] | |
| 325 | 202 | ``` |
| 326 | 203 | |
| 327 | See [Pull Request Generation](/features/pull-requests) for more details on how labeling and assignment integrate with the overall PR workflow. | |
| 204 | Setting `enabled: false` or a narrower `strategy` on the rule is the stronger | |
| 205 | form of the same intent: the update is never proposed at all rather than proposed | |
| 206 | and held. See [Auto-Merge](/features/auto-merge) for what qualifies in the first | |
| 207 | place. | |
| 208 | ||
| 209 | ## Labels Are Configuration, Not Commands | |
| 210 | ||
| 211 | There is no CLI for managing labels or assignees. Buddy resolves them at the | |
| 212 | moment it opens a pull request, so the way to change them is to change | |
| 213 | `buddy.config.ts` and let the next run pick it up. | |
| 214 | ||
| 215 | A rule you add now therefore shows up on the next PR for that group rather than | |
| 216 | on one already open. When a later run finds an existing open Buddy PR for that | |
| 217 | group it refreshes the PR in place, rewriting its labels to the automatically | |
| 218 | derived set and its reviewers and assignees to the repository-wide | |
| 219 | `pullRequest` names. A label added | |
| 220 | by hand on an open PR is therefore not guaranteed to survive the next refresh, | |
| 221 | and neither is one a rule contributed when the PR was opened. Close the PR and | |
| 222 | let the next run open it again when you need the current rules applied from | |
| 223 | scratch. | |
| 224 | ||
| 225 | See [Package Rules](/config#package-rules) for the full effect list and | |
| 226 | [Pull Request Generation](/features/pull-requests) for how labelling fits into | |
| 227 | the rest of the PR workflow. | |
| @@ -38,7 +38,7 @@ hero: | ||
| 38 | 38 | ✔ tests-updated behaviour change covered |
| 39 | 39 | |
| 40 | 40 | error · 1 failing gate |
| 41 | check run published: buddy/gate | |
| 41 | check run published: buddy/gates | |
| 42 | 42 | - file: "buddy.config.ts" |
| 43 | 43 | lang: "ts" |
| 44 | 44 | content: | |
| @@ -113,7 +113,7 @@ jobs: | ||
| 113 | 113 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 114 | 114 | ``` |
| 115 | 115 | |
| 116 | Then mark `buddy/gate` as a required check in your branch protection rules. That is the whole enforcement story: GitHub blocks the merge, Buddy just reports the truth. | |
| 116 | Then mark `buddy/gates` as a required check in your branch protection rules. That is the whole enforcement story: GitHub blocks the merge, Buddy just reports the truth. | |
| 117 | 117 | |
| 118 | 118 | ## Deterministic first {#deterministic} |
| 119 | 119 | |
| @@ -108,7 +108,7 @@ jobs: | ||
| 108 | 108 | run: bun test |
| 109 | 109 | ``` |
| 110 | 110 | |
| 111 | All dependency files are parsed using the `ts-pkgx` library to ensure compatibility with the pkgx registry ecosystem. GitHub Actions are detected by parsing `uses:` statements in workflow files and checking for updates via the GitHub releases API. | |
| 111 | All dependency files are parsed using the `ts-pantry` library to ensure compatibility with the pkgx registry ecosystem. GitHub Actions are detected by parsing `uses:` statements in workflow files and checking for updates via the GitHub releases API. | |
| 112 | 112 | |
| 113 | 113 | ### Project Structure Detection |
| 114 | 114 | |
| @@ -297,28 +297,45 @@ Platform requirements are automatically excluded from updates: | ||
| 297 | 297 | |
| 298 | 298 | Control which packages are managed by buddy. |
| 299 | 299 | |
| 300 | ### Ignore Patterns | |
| 300 | ### Ignore List | |
| 301 | 301 | |
| 302 | 302 | ```typescript |
| 303 | 303 | export default { |
| 304 | 304 | packages: { |
| 305 | // Global ignore list | |
| 305 | // Global ignore list — exact package names | |
| 306 | 306 | ignore: [ |
| 307 | 307 | '@types/node', // Keep Node types stable |
| 308 | 308 | 'react', // Manual React updates |
| 309 | 'vue', // Manual Vue updates | |
| 310 | '@internal/*', // Internal packages | |
| 311 | '@types/*', // All type definitions | |
| 312 | 'eslint-*', // All ESLint packages | |
| 313 | 'babel-*' // All Babel packages | |
| 309 | 'vue' // Manual Vue updates | |
| 314 | 310 | ] |
| 315 | 311 | } |
| 316 | 312 | } satisfies BuddyConfig |
| 317 | 313 | ``` |
| 318 | 314 | |
| 319 | `ignore` entries are matched as globs against the package name, so one list | |
| 320 | covers both exact names and whole families. To exclude by file path instead, | |
| 321 | use `ignorePaths`. | |
| 315 | `ignore` entries are compared by **exact name equality**. A glob such as | |
| 316 | `@types/*` matches no package at all, so it silently ignores nothing rather | |
| 317 | than failing loudly. | |
| 318 | ||
| 319 | ### Ignore Patterns | |
| 320 | ||
| 321 | For whole families, use a rule: `matchPackages` accepts globs, and | |
| 322 | `enabled: false` drops every update it matches. | |
| 323 | ||
| 324 | ```typescript | |
| 325 | export default { | |
| 326 | packages: { | |
| 327 | rules: [ | |
| 328 | { matchPackages: ['@internal/*'], enabled: false }, | |
| 329 | { matchPackages: ['@types/*'], enabled: false }, | |
| 330 | { matchPackages: ['eslint-*', 'babel-*'], enabled: false } | |
| 331 | ] | |
| 332 | } | |
| 333 | } satisfies BuddyConfig | |
| 334 | ``` | |
| 335 | ||
| 336 | The two lists behave differently on purpose, and the difference is easy to trip | |
| 337 | over: `ignore` is exact names, while the adjacent `ignorePaths` **does** take | |
| 338 | globs, because it matches file paths rather than package names. | |
| 322 | 339 | |
| 323 | 340 | ### Include/Exclude by Scope |
| 324 | 341 | |
| @@ -360,9 +377,8 @@ export default { | ||
| 360 | 377 | }, |
| 361 | 378 | { |
| 362 | 379 | name: 'Build Tools', |
| 363 | packages: ['webpack', 'webpack-cli', 'webpack-dev-server'], | |
| 364 | strategy: 'major', | |
| 365 | reviewers: ['build-team'] | |
| 380 | patterns: ['webpack', 'webpack-cli', 'webpack-dev-server'], | |
| 381 | strategy: 'major' | |
| 366 | 382 | } |
| 367 | 383 | ] |
| 368 | 384 | } |
| @@ -377,18 +393,17 @@ const patternGroupsConfig = { | ||
| 377 | 393 | groups: [ |
| 378 | 394 | { |
| 379 | 395 | name: 'Type Definitions', |
| 380 | pattern: '@types/*', | |
| 381 | strategy: 'minor', | |
| 382 | autoMerge: true | |
| 396 | patterns: ['@types/*'], | |
| 397 | strategy: 'minor' | |
| 383 | 398 | }, |
| 384 | 399 | { |
| 385 | 400 | name: 'ESLint Ecosystem', |
| 386 | pattern: 'eslint*', | |
| 401 | patterns: ['eslint*'], | |
| 387 | 402 | strategy: 'patch' |
| 388 | 403 | }, |
| 389 | 404 | { |
| 390 | 405 | name: 'Babel Plugins', |
| 391 | pattern: 'babel-*', | |
| 406 | patterns: ['babel-*'], | |
| 392 | 407 | strategy: 'minor' |
| 393 | 408 | } |
| 394 | 409 | ] |
| @@ -638,26 +653,49 @@ All package management features are available via CLI. | ||
| 638 | 653 | buddy check react vue typescript |
| 639 | 654 | |
| 640 | 655 | # Get package information |
| 641 | buddy info @types/node --detailed | |
| 656 | buddy info @types/node | |
| 657 | ||
| 658 | # Machine-readable package information | |
| 659 | buddy info @types/node --json | |
| 642 | 660 | |
| 643 | 661 | # Search packages |
| 644 | 662 | buddy search "ui component" --limit 10 |
| 645 | 663 | |
| 646 | 664 | # Analyze dependencies |
| 647 | buddy deps react --depth 2 | |
| 665 | buddy deps react | |
| 666 | ||
| 667 | # Include dev and peer dependencies | |
| 668 | buddy deps react --all | |
| 648 | 669 | ``` |
| 649 | 670 | |
| 650 | 671 | ### Batch Operations |
| 651 | 672 | |
| 673 | `buddy update` runs over everything the scan found; it has no package or group | |
| 674 | filter of its own. Narrow it with a strategy, an ignore list, or a preview run: | |
| 675 | ||
| 652 | 676 | ```bash |
| 653 | # Update multiple packages | |
| 654 | buddy update --packages react,vue,typescript | |
| 677 | # Preview the pull requests without opening them | |
| 678 | buddy update --dry-run | |
| 679 | ||
| 680 | # Restrict this run to patch updates | |
| 681 | buddy update --strategy patch | |
| 682 | ||
| 683 | # Skip named packages for this run | |
| 684 | buddy update --ignore react,vue | |
| 685 | ``` | |
| 655 | 686 | |
| 656 | # Update by pattern | |
| 657 | buddy update --pattern "@types/_" | |
| 687 | To scope a run to a group or a pattern, express it in config as a rule and let | |
| 688 | `buddy update` honour it: | |
| 658 | 689 | |
| 659 | # Update by group | |
| 660 | buddy update --group "React Ecosystem" | |
| 690 | ```typescript | |
| 691 | export default { | |
| 692 | packages: { | |
| 693 | rules: [ | |
| 694 | { matchPackages: ['@types/*'], groupName: 'Type Definitions' }, | |
| 695 | { matchEcosystems: ['docker'], enabled: false } | |
| 696 | ] | |
| 697 | } | |
| 698 | } satisfies BuddyConfig | |
| 661 | 699 | ``` |
| 662 | 700 | |
| 663 | 701 | See [CLI Package Commands](/cli/package) for complete CLI reference. |
| @@ -27,7 +27,7 @@ Every Buddy pull request includes an interactive checkbox: | ||
| 27 | 27 | |
| 28 | 28 | ### 2. Automatic Detection |
| 29 | 29 | |
| 30 | A GitHub Actions workflow (`.github/workflows/buddy-check.yml`) runs every minute and: | |
| 30 | Ticking the box edits the pull request body, and that edit is the trigger. The unified workflow (`.github/workflows/buddy.yml`) listens on `pull_request: [edited]` — and on `issues: [edited]` for the same checkboxes on the dashboard — so nothing is polling and nothing waits for a schedule. The run then: | |
| 31 | 31 | |
| 32 | 32 | 1. Scans all open pull requests |
| 33 | 33 | 2. Identifies Buddy PRs with checked rebase boxes |
| @@ -52,7 +52,7 @@ During rebase, Buddy: | ||
| 52 | 52 | 1. **Open any Buddy PR** |
| 53 | 53 | 2. **Scroll to the bottom** of the PR description |
| 54 | 54 | 3. **Check the rebase checkbox**: `- [x] If you want to update/retry this PR, check this box` |
| 55 | 4. **Wait for automation**: The workflow will detect and process the request within 1 minute | |
| 55 | 4. **Wait for automation**: The edit fires the workflow straight away — no scheduled tick to wait for | |
| 56 | 56 | 5. **Review updates**: PR will be refreshed with latest dependency versions |
| 57 | 57 | |
| 58 | 58 | ### Manual Rebase via CLI |
| @@ -74,9 +74,10 @@ buddy update-check --dry-run --verbose | ||
| 74 | 74 | ### Manual Trigger via GitHub Actions |
| 75 | 75 | |
| 76 | 76 | 1. Go to **Actions** tab in your repository |
| 77 | 2. Select **"Buddy Check"** workflow | |
| 77 | 2. Select the **"Buddy"** workflow | |
| 78 | 78 | 3. Click **"Run workflow"** |
| 79 | 79 | 4. Choose options: |
| 80 | - **Which job to run**: pick `check` to process rebase requests only | |
| 80 | 81 | - **Dry run**: Preview changes without applying them |
| 81 | 82 | 5. Click **"Run workflow"** to execute |
| 82 | 83 | |
| @@ -84,19 +85,39 @@ buddy update-check --dry-run --verbose | ||
| 84 | 85 | |
| 85 | 86 | ### Workflow Setup |
| 86 | 87 | |
| 87 | The rebase workflow is automatically created when you run `buddy setup`. It includes: | |
| 88 | The rebase handling lives in the unified workflow `buddy setup` writes to `.github/workflows/buddy.yml`. The parts that matter for rebasing: | |
| 88 | 89 | |
| 89 | 90 | ```yaml |
| 90 | name: Buddy Check | |
| 91 | name: Buddy | |
| 91 | 92 | |
| 92 | 93 | on: |
| 93 | schedule: | |
| 94 | # Ticking the checkbox edits the PR body, which fires this event | |
| 95 | pull_request: | |
| 96 | types: [edited, opened, ready_for_review, synchronize, closed] | |
| 97 | ||
| 98 | # The dashboard's checkboxes are the same request, made on an issue | |
| 99 | issues: | |
| 100 | types: [edited, opened] | |
| 94 | 101 | |
| 95 | - cron: '*/1 * * * *' # Every minute | |
| 102 | schedule: | |
| 103 | - cron: '0 */2 * * *' # Dependency updates | |
| 104 | - cron: '15 */2 * * *' # Dashboard refresh | |
| 105 | - cron: '0 4 * * *' # Daily cleanup of orphaned branches and obsolete PRs | |
| 106 | - cron: '0 9 * * 1' # Weekly dependency-health report | |
| 96 | 107 | |
| 97 | workflow*dispatch: # Manual trigger | |
| 108 | workflow_dispatch: # Manual trigger | |
| 98 | 109 | inputs: |
| 99 | dry*run: | |
| 110 | job: | |
| 111 | description: Which job to run | |
| 112 | required: false | |
| 113 | default: all | |
| 114 | type: choice | |
| 115 | options: | |
| 116 | - all | |
| 117 | - check | |
| 118 | - update | |
| 119 | - dashboard | |
| 120 | dry_run: | |
| 100 | 121 | description: Dry run (preview only) |
| 101 | 122 | required: false |
| 102 | 123 | default: false |
| @@ -107,8 +128,12 @@ permissions: | ||
| 107 | 128 | pull-requests: write |
| 108 | 129 | issues: write |
| 109 | 130 | actions: write # Required for workflow file updates |
| 131 | checks: read | |
| 132 | statuses: read | |
| 110 | 133 | ``` |
| 111 | 134 | |
| 135 | None of those schedules drives rebase detection — the edit event covers that. They exist for the periodic jobs: dependency updates, the dashboard refresh, cleanup and the weekly report. | |
| 136 | ||
| 112 | 137 | ### Token Configuration |
| 113 | 138 | |
| 114 | 139 | #### Option 1: Personal Access Token (Full Features) |
| @@ -195,13 +220,9 @@ During rebase, Buddy updates: | ||
| 195 | 220 | |
| 196 | 221 | **Error**: `No buddy PRs found` |
| 197 | 222 | |
| 198 | **Cause**: Workflow looks for PRs created by: | |
| 199 | ||
| 200 | - Branch names starting with `buddy/` | |
| 201 | - Author `github-actions[bot]` | |
| 202 | - Author containing `buddy` | |
| 223 | **Cause**: `buddy update-check` only considers open pull requests whose head branch starts with `buddy/`. The author is never inspected. The workflow adds one condition of its own on the edit trigger: an edit made by a bot account is ignored, so Buddy's own untick cannot re-trigger the run. | |
| 203 | 224 | |
| 204 | **Solution**: Ensure PRs were created by Buddy | |
| 225 | **Solution**: Ensure the PR was created by Buddy — a hand-made PR on a branch outside `buddy/` is never picked up — and tick the box from your own account rather than through another bot | |
| 205 | 226 | |
| 206 | 227 | #### 4. Rebase Not Triggered |
| 207 | 228 | |
| @@ -213,22 +234,20 @@ During rebase, Buddy updates: | ||
| 213 | 234 | |
| 214 | 235 | ## Advanced Usage |
| 215 | 236 | |
| 216 | ### Custom Rebase Logic | |
| 237 | ### Rebasing One PR Directly | |
| 217 | 238 | |
| 218 | You can customize the rebase behavior by modifying the workflow: | |
| 239 | `update-check` sweeps every open Buddy PR for ticked boxes. To act on a single PR without touching the checkbox at all, address it by number: | |
| 219 | 240 | |
| 220 | ```yaml | |
| 221 | # Custom rebase frequency | |
| 222 | on: | |
| 223 | schedule: | |
| 224 | ||
| 225 | - cron: '*/5 * * * *' # Every 5 minutes instead of 1 | |
| 241 | ```bash | |
| 242 | # Recreate PR #17 with the latest versions | |
| 243 | buddy rebase 17 | |
| 226 | 244 | |
| 227 | # Custom PR detection | |
| 228 | env: | |
| 229 | CUSTOM_AUTHOR_FILTER: 'my-custom-bot' | |
| 245 | # Rebase even when the PR already looks up to date | |
| 246 | buddy rebase 17 --force | |
| 230 | 247 | ``` |
| 231 | 248 | |
| 249 | A PR that is already current is skipped unless you pass `--force`, so this is safe to run from a script or from your own workflow step. | |
| 250 | ||
| 232 | 251 | ### Integration with Other Tools |
| 233 | 252 | |
| 234 | 253 | The rebase functionality works seamlessly with: |
| @@ -265,7 +284,7 @@ Track rebase operations via: | ||
| 265 | 284 | |
| 266 | 285 | ### Performance Considerations |
| 267 | 286 | |
| 268 | - **Frequency**: Every minute is optimal for responsiveness | |
| 287 | - **Frequency**: Detection costs nothing while idle — the run starts on the edit, not on a clock | |
| 269 | 288 | - **Rate limits**: GitHub API rate limits apply |
| 270 | 289 | - **Resource usage**: Minimal overhead per execution |
| 271 | 290 | - **Parallel execution**: Multiple rebase requests handled sequentially |
| @@ -15,7 +15,7 @@ Buddy uses multiple scanning approaches depending on the file type: | ||
| 15 | 15 | |
| 16 | 16 | ### Dependency File Scanning |
| 17 | 17 | |
| 18 | - **pkgx Integration**: Uses `ts-pkgx` library for parsing dependency files | |
| 18 | - **pkgx Integration**: Uses `ts-pantry` library for parsing dependency files | |
| 19 | 19 | - **Registry Compatibility**: Full compatibility with pkgx registry ecosystem |
| 20 | 20 | - **Format Support**: Handles multiple YAML formats (`.yaml`, `.yml`) |
| 21 | 21 | - **Launchpad Support**: Compatible with Launchpad dependency files |
| @@ -67,20 +67,33 @@ export default { | ||
| 67 | 67 | |
| 68 | 68 | #### Ignore Packages |
| 69 | 69 | |
| 70 | Skip specific packages from scanning: | |
| 70 | Skip specific packages from scanning. Entries are compared by exact name — no | |
| 71 | globs: | |
| 71 | 72 | |
| 72 | 73 | ```typescript |
| 73 | 74 | export default { |
| 74 | 75 | packages: { |
| 75 | 76 | ignore: [ |
| 76 | '@types/node', // Specific package | |
| 77 | '@types/*', // Glob patterns | |
| 77 | '@types/node', // Exact package name | |
| 78 | 78 | 'react', // Dependencies you want to control manually |
| 79 | 79 | ] |
| 80 | 80 | } |
| 81 | 81 | } |
| 82 | 82 | ``` |
| 83 | 83 | |
| 84 | To skip a whole family, use a rule with `matchPackages`, which does take | |
| 85 | patterns: | |
| 86 | ||
| 87 | ```typescript | |
| 88 | export default { | |
| 89 | packages: { | |
| 90 | rules: [ | |
| 91 | { matchPackages: ['@types/*'], enabled: false } | |
| 92 | ] | |
| 93 | } | |
| 94 | } | |
| 95 | ``` | |
| 96 | ||
| 84 | 97 | #### Pin Specific Versions |
| 85 | 98 | |
| 86 | 99 | Lock packages to specific versions: |
| @@ -58,9 +58,10 @@ export default { | ||
| 58 | 58 | - `typescript@5.1.0` → `typescript@5.2.0` ✅ (minor) |
| 59 | 59 | - `typescript@5.1.0` → `typescript@6.0.0` ❌ (major) |
| 60 | 60 | |
| 61 | ### `major` - Latest Stable | |
| 61 | ### `major` - Breaking Changes Only | |
| 62 | 62 | |
| 63 | Updates to the latest stable version, including major versions with breaking changes. | |
| 63 | Updates major versions and nothing else. Minor and patch bumps are left for a | |
| 64 | run configured to take them. | |
| 64 | 65 | |
| 65 | 66 | ```typescript |
| 66 | 67 | // Example: 1.2.3 → 2.0.0 |
| @@ -73,18 +74,20 @@ export default { | ||
| 73 | 74 | |
| 74 | 75 | **When to use:** |
| 75 | 76 | |
| 76 | - Development environments | |
| 77 | - Regular maintenance windows | |
| 77 | - A dedicated maintenance window for breaking changes | |
| 78 | - Keeping major upgrades in their own pull requests | |
| 78 | 79 | - Teams comfortable with handling breaking changes |
| 79 | 80 | |
| 80 | 81 | **Example updates:** |
| 81 | 82 | |
| 82 | - `vue@2.7.0` → `vue@2.7.16` ✅ (patch) | |
| 83 | 83 | - `vue@2.7.0` → `vue@3.4.0` ✅ (major) |
| 84 | - `vue@2.7.0` → `vue@2.8.0` ❌ (minor) | |
| 85 | - `vue@2.7.0` → `vue@2.7.16` ❌ (patch) | |
| 84 | 86 | |
| 85 | ### `all` - Most Aggressive | |
| 87 | ### `all` - Everything | |
| 86 | 88 | |
| 87 | Updates to the absolute latest version available, including pre-releases when no stable version exists. | |
| 89 | Updates everything available, regardless of semver impact — major, minor and | |
| 90 | patch together. This is the default. | |
| 88 | 91 | |
| 89 | 92 | ```typescript |
| 90 | 93 | export default { |
| @@ -98,12 +101,26 @@ export default { | ||
| 98 | 101 | |
| 99 | 102 | - Experimental projects |
| 100 | 103 | - Early adoption teams |
| 101 | - Testing latest features | |
| 104 | - Staying current across the whole dependency tree | |
| 102 | 105 | |
| 103 | 106 | **Example updates:** |
| 104 | 107 | |
| 105 | - `next@14.0.0` → `next@15.0.0-rc.1` ✅ (pre-release) | |
| 106 | - `react@18.2.0` → `react@19.0.0-beta.1` ✅ (beta) | |
| 108 | - `react@18.2.0` → `react@18.2.1` ✅ (patch) | |
| 109 | - `react@18.2.0` → `react@18.3.0` ✅ (minor) | |
| 110 | - `react@18.2.0` → `react@19.0.0` ✅ (major) | |
| 111 | ||
| 112 | Pre-release versions are a separate switch, not part of the strategy: set | |
| 113 | `packages.includePrerelease` if you want alphas, betas and release candidates | |
| 114 | considered. | |
| 115 | ||
| 116 | ### At a Glance | |
| 117 | ||
| 118 | | Strategy | Updates it proposes | | |
| 119 | | --- | --- | | |
| 120 | | `all` | Everything, regardless of semver impact | | |
| 121 | | `major` | Major versions only | | |
| 122 | | `minor` | Minor and patch | | |
| 123 | | `patch` | Patch only | | |
| 107 | 124 | |
| 108 | 125 | ## Strategy Configuration |
| 109 | 126 | |
| @@ -137,11 +154,11 @@ export default { | ||
| 137 | 154 | { |
| 138 | 155 | name: 'Development Tools', |
| 139 | 156 | patterns: ['eslint', 'prettier', 'typescript'], |
| 140 | strategy: 'major' // More aggressive for dev tools | |
| 157 | strategy: 'major' // Dev-tool majors, batched on their own | |
| 141 | 158 | }, |
| 142 | 159 | { |
| 143 | 160 | name: 'Testing Libraries', |
| 144 | packages: ['jest', 'vitest', '@testing-library/*'], | |
| 161 | patterns: ['jest', 'vitest', '@testing-library/*'], | |
| 145 | 162 | strategy: 'minor' |
| 146 | 163 | } |
| 147 | 164 | ] |
| @@ -159,7 +176,7 @@ export default { | ||
| 159 | 176 | strategy: 'minor', |
| 160 | 177 | rules: [ |
| 161 | 178 | { matchPackages: ['react'], strategy: 'patch' }, // Keep React very stable |
| 162 | { matchPackages: ['typescript'], strategy: 'major' }, // Always latest TypeScript | |
| 179 | { matchPackages: ['typescript'], strategy: 'major' }, // TypeScript majors only | |
| 163 | 180 | { matchPackages: ['@types/*'], strategy: 'all' } // Types can be aggressive |
| 164 | 181 | ] |
| 165 | 182 | } |
| @@ -228,7 +245,7 @@ const week1Config = { strategy: 'patch' } | ||
| 228 | 245 | // Week 2: Add minor updates |
| 229 | 246 | const week2Config = { strategy: 'minor' } |
| 230 | 247 | |
| 231 | // Week 3: Add major updates for dev dependencies | |
| 248 | // Week 3: minor everywhere, plus a group that takes dev-tool majors | |
| 232 | 249 | const week3Config = { |
| 233 | 250 | strategy: 'minor', |
| 234 | 251 | groups: [ |
| @@ -253,7 +270,7 @@ export default { | ||
| 253 | 270 | packages: { |
| 254 | 271 | strategy: isProduction |
| 255 | 272 | ? (isCorporate ? 'patch' : 'minor') |
| 256 | : 'major' | |
| 273 | : 'all' | |
| 257 | 274 | } |
| 258 | 275 | } satisfies BuddyConfig |
| 259 | 276 | ``` |
| @@ -279,8 +296,8 @@ const config = { | ||
| 279 | 296 | }, |
| 280 | 297 | { |
| 281 | 298 | name: 'Build Tools', |
| 282 | packages: ['vite', 'rollup', 'esbuild'], | |
| 283 | strategy: 'major' // Build tools are less breaking | |
| 299 | patterns: ['vite', 'rollup', 'esbuild'], | |
| 300 | strategy: 'major' // Build tools get their majors in a PR of their own | |
| 284 | 301 | } |
| 285 | 302 | ] |
| 286 | 303 | } |
| @@ -295,13 +312,16 @@ Override configuration strategies via CLI: | ||
| 295 | 312 | # Force patch strategy regardless of config |
| 296 | 313 | buddy update --strategy patch |
| 297 | 314 | |
| 298 | # Use major strategy for specific packages | |
| 299 | buddy update --strategy major --packages react,vue | |
| 315 | # Take the major bumps on their own, in a preview run first | |
| 316 | buddy update --strategy major --dry-run | |
| 300 | 317 | |
| 301 | # Mixed strategies | |
| 302 | buddy update --patch typescript --minor react --major eslint | |
| 318 | # Take the majors, but leave two packages behind | |
| 319 | buddy update --strategy major --ignore react,vue | |
| 303 | 320 | ``` |
| 304 | 321 | |
| 322 | `--strategy` is a whole-run switch. Per-package strategies are config only — | |
| 323 | use `rules` with `matchPackages`, as above. | |
| 324 | ||
| 305 | 325 | ## Monitoring Strategy Effectiveness |
| 306 | 326 | |
| 307 | 327 | Track how strategies perform: |
| @@ -359,7 +379,7 @@ export default { | ||
| 359 | 379 | { |
| 360 | 380 | name: 'Development Tools', |
| 361 | 381 | patterns: ['typescript', 'webpack', 'vite'], |
| 362 | strategy: 'major' | |
| 382 | strategy: 'all' | |
| 363 | 383 | } |
| 364 | 384 | ] |
| 365 | 385 | } |
| @@ -371,7 +391,7 @@ export default { | ||
| 371 | 391 | ```typescript |
| 372 | 392 | export default { |
| 373 | 393 | packages: { |
| 374 | strategy: 'major', | |
| 394 | strategy: 'all', | |
| 375 | 395 | groups: [ |
| 376 | 396 | { |
| 377 | 397 | name: 'Database & Infrastructure', |
| @@ -50,8 +50,8 @@ Configure how Buddy interacts with your repository: | ||
| 50 | 50 | |
| 51 | 51 | ```typescript |
| 52 | 52 | repository: { |
| 53 | // Git provider | |
| 54 | provider: 'github', // 'github' | 'gitlab' | 'bitbucket' | |
| 53 | // Git provider — only 'github' is implemented today | |
| 54 | provider: 'github', | |
| 55 | 55 | |
| 56 | 56 | // Repository owner (organization or user) |
| 57 | 57 | owner: 'stacksjs', |
| @@ -203,7 +203,7 @@ Choose from predefined workflow configurations: | ||
| 203 | 203 | ### Standard (Default) |
| 204 | 204 | |
| 205 | 205 | ```bash |
| 206 | buddy setup --preset standard | |
| 206 | buddy setup --non-interactive --preset standard | |
| 207 | 207 | ``` |
| 208 | 208 | |
| 209 | 209 | - Dashboard updates 3x/week |
| @@ -212,7 +212,7 @@ buddy setup --preset standard | ||
| 212 | 212 | ### High Frequency |
| 213 | 213 | |
| 214 | 214 | ```bash |
| 215 | buddy setup --preset high-frequency | |
| 215 | buddy setup --non-interactive --preset high-frequency | |
| 216 | 216 | ``` |
| 217 | 217 | |
| 218 | 218 | - Updates multiple times per day |
| @@ -221,7 +221,7 @@ buddy setup --preset high-frequency | ||
| 221 | 221 | ### Security Focused |
| 222 | 222 | |
| 223 | 223 | ```bash |
| 224 | buddy setup --preset security | |
| 224 | buddy setup --non-interactive --preset security | |
| 225 | 225 | ``` |
| 226 | 226 | |
| 227 | 227 | - Frequent security patches |
| @@ -230,7 +230,7 @@ buddy setup --preset security | ||
| 230 | 230 | ### Minimal |
| 231 | 231 | |
| 232 | 232 | ```bash |
| 233 | buddy setup --preset minimal | |
| 233 | buddy setup --non-interactive --preset minimal | |
| 234 | 234 | ``` |
| 235 | 235 | |
| 236 | 236 | - Weekly checks only |
| @@ -239,11 +239,11 @@ buddy setup --preset minimal | ||
| 239 | 239 | ### Testing |
| 240 | 240 | |
| 241 | 241 | ```bash |
| 242 | buddy setup --preset testing | |
| 242 | buddy setup --non-interactive --preset testing | |
| 243 | 243 | ``` |
| 244 | 244 | |
| 245 | - Every 5 minutes | |
| 246 | - Dry run by default | |
| 245 | - Manual dashboard trigger, frequent update checks | |
| 246 | - Patch updates only, no auto-merge | |
| 247 | 247 | - For development/testing |
| 248 | 248 | |
| 249 | 249 | ## Migration from Other Tools |
| @@ -313,7 +313,7 @@ Create custom integrations in `.buddy/plugins/`: | ||
| 313 | 313 | "enabled": true, |
| 314 | 314 | "triggers": [ |
| 315 | 315 | { "event": "setup_complete" }, |
| 316 | { "event": "pr_created" } | |
| 316 | { "event": "validation_error" } | |
| 317 | 317 | ], |
| 318 | 318 | "configuration": { |
| 319 | 319 | "webhook_url": "https://your-webhook.com/notify" |
| @@ -105,8 +105,8 @@ buddy update-check --verbose | ||
| 105 | 105 | |----------|-------------| |
| 106 | 106 | | `all` | All updates regardless of semver impact | |
| 107 | 107 | | `major` | Only major version updates | |
| 108 | | `minor` | Major and minor updates (no patch-only) | | |
| 109 | | `patch` | All updates (most conservative) | | |
| 108 | | `minor` | Minor and patch updates (no majors) | | |
| 109 | | `patch` | Only patch updates (most conservative) | | |
| 110 | 110 | |
| 111 | 111 | ## Supported Ecosystems |
| 112 | 112 | |
| @@ -134,31 +134,24 @@ Buddy automatically detects and updates: | ||
| 134 | 134 | |
| 135 | 135 | ## Generated Workflows |
| 136 | 136 | |
| 137 | After setup, Buddy creates three workflows: | |
| 137 | After setup, Buddy creates two workflows: | |
| 138 | 138 | |
| 139 | ### `buddy-dashboard.yml` | |
| 139 | ### `buddy.yml` | |
| 140 | 140 | |
| 141 | Maintains the dependency dashboard issue: | |
| 141 | One unified workflow covering checks, updates and the dashboard: | |
| 142 | 142 | |
| 143 | - Runs Monday, Wednesday, Friday at 9 AM UTC | |
| 144 | - Shows all open PRs and detected dependencies | |
| 145 | - Interactive checkbox controls | |
| 143 | - Scans for updates every 2 hours, refreshing the dashboard 15 minutes later | |
| 144 | - Rebase and dashboard checkboxes are event-driven, so ticking a box triggers a run immediately | |
| 145 | - Runs a daily cleanup pass at 4 AM UTC and a weekly dependency report Monday at 9 AM UTC | |
| 146 | - Answers `@buddy` comments and supports manual triggers | |
| 146 | 147 | |
| 147 | ### `buddy-check.yml` | |
| 148 | ### `buddy-security.yml` | |
| 148 | 149 | |
| 149 | Handles PR rebase requests: | |
| 150 | Audits your GitHub Actions workflows: | |
| 150 | 151 | |
| 151 | - Runs every minute | |
| 152 | - Detects checked rebase boxes | |
| 153 | - Updates PR content automatically | |
| 154 | ||
| 155 | ### `buddy-update.yml` | |
| 156 | ||
| 157 | Creates dependency update PRs: | |
| 158 | ||
| 159 | - Schedule varies by preset | |
| 152 | - Runs on pushes and PRs that touch `.github/workflows/**` | |
| 153 | - Weekly drift check Monday at 6 AM UTC | |
| 160 | 154 | - Supports manual triggers |
| 161 | - Configurable update strategy | |
| 162 | 155 | |
| 163 | 156 | ## CLI Reference |
| 164 | 157 | |
| @@ -181,7 +174,7 @@ buddy update-check # Process rebase requests | ||
| 181 | 174 | buddy dashboard # Update dashboard issue |
| 182 | 175 | |
| 183 | 176 | # Help |
| 184 | buddy help | |
| 177 | buddy --help | |
| 185 | 178 | buddy --version |
| 186 | 179 | ``` |
| 187 | 180 | |
| @@ -64,10 +64,14 @@ pullRequest: { | ||
| 64 | 64 | | Variable | Description | Example | |
| 65 | 65 | |----------|-------------|---------| |
| 66 | 66 | | `{title}` | Generated title | "update typescript to 5.8.3" | |
| 67 | | `{package}` | Package name | "typescript" | | |
| 68 | | `{from}` | Current version | "5.8.2" | | |
| 69 | | `{to}` | New version | "5.8.3" | | |
| 70 | | `{type}` | Update type | "patch" | | |
| 67 | | `{group}` | Update group name | "Non-Major Updates" | | |
| 68 | | `{packages}` | Comma-separated package names | "typescript, vitest" | | |
| 69 | | `{count}` | Number of packages in the PR | "2" | | |
| 70 | | `{update_type}` | Highest semver impact in the group | "patch" | | |
| 71 | | `{strategy}` | Configured update strategy | "minor" | | |
| 72 | ||
| 73 | Unknown tokens are left in place rather than blanked, so a typo shows up in the | |
| 74 | title instead of silently disappearing. | |
| 71 | 75 | |
| 72 | 76 | ### Examples |
| 73 | 77 | |
| @@ -76,12 +80,12 @@ pullRequest: { | ||
| 76 | 80 | titleFormat: 'chore(deps): {title}' |
| 77 | 81 | // Result: "chore(deps): update typescript to 5.8.3" |
| 78 | 82 | |
| 79 | // Simple style | |
| 80 | titleFormat: 'Update {package} to {to}' | |
| 81 | // Result: "Update typescript to 5.8.3" | |
| 83 | // Group style | |
| 84 | titleFormat: 'Update {group} ({count} packages)' | |
| 85 | // Result: "Update Non-Major Updates (2 packages)" | |
| 82 | 86 | |
| 83 | // With type | |
| 84 | titleFormat: '[{type}] {title}' | |
| 87 | // With update type | |
| 88 | titleFormat: '[{update_type}] {title}' | |
| 85 | 89 | // Result: "[patch] update typescript to 5.8.3" |
| 86 | 90 | ``` |
| 87 | 91 | |
| @@ -111,11 +115,14 @@ Buddy automatically adds contextual labels: | ||
| 111 | 115 | |
| 112 | 116 | | Label | Condition | |
| 113 | 117 | |-------|-----------| |
| 114 | | `major-update` | Major version change | | |
| 115 | | `minor-update` | Minor version change | | |
| 116 | | `patch-update` | Patch version change | | |
| 117 | | `security` | Security vulnerability fix | | |
| 118 | | `dependencies` | Always applied | | |
| 119 | | `major` | Major version change | | |
| 120 | | `minor` | Minor version change | | |
| 121 | | `patch` | Patch version change | | |
| 122 | | `security` | Resolves a published advisory | | |
| 118 | 123 | | `npm` | npm package update | |
| 124 | | `composer` | Composer package update | | |
| 125 | | `zig` | Zig package update | | |
| 119 | 126 | | `github-actions` | Workflow update | |
| 120 | 127 | |
| 121 | 128 | ## Reviewers and Assignees |
| @@ -183,10 +190,14 @@ pullRequest: { | ||
| 183 | 190 | |
| 184 | 191 | | Condition | Description | |
| 185 | 192 | |-----------|-------------| |
| 186 | | `patch-only` | Only patch updates | | |
| 187 | | `minor-and-patch` | Minor and patch updates | | |
| 193 | | `patch-only` | Every update in the PR is a patch | | |
| 194 | | `minor-only` | Every update is minor or patch | | |
| 195 | | `security-only` | The PR resolves a security advisory | | |
| 188 | 196 | | `all` | All updates (use cautiously) | |
| 189 | 197 | |
| 198 | A PR qualifies when any listed condition accepts it. An empty or missing list | |
| 199 | means nothing auto-merges. | |
| 200 | ||
| 190 | 201 | ## Rebase Feature |
| 191 | 202 | |
| 192 | 203 | Every PR includes a rebase checkbox: |
| @@ -202,7 +213,7 @@ Every PR includes a rebase checkbox: | ||
| 202 | 213 | ### How It Works |
| 203 | 214 | |
| 204 | 215 | 1. Check the box in the PR description |
| 205 | 2. `buddy-check.yml` workflow detects checked boxes | |
| 216 | 2. Editing the PR body triggers the `buddy.yml` workflow, which detects checked boxes | |
| 206 | 217 | 3. PR is automatically updated with latest versions |
| 207 | 218 | 4. Checkbox is unchecked after successful update |
| 208 | 219 | |
| @@ -47,11 +47,9 @@ hero: | ||
| 47 | 47 | @buddy review new changes since last time |
| 48 | 48 | @buddy full-review re-read the whole diff |
| 49 | 49 | @buddy summary a summary, no inline notes |
| 50 | @buddy resolve resolve the threads it opened | |
| 51 | 50 | @buddy pause stop reviewing this PR |
| 52 | 51 | @buddy resume start again |
| 53 | 52 | @buddy fix-ci diagnose the failing checks |
| 54 | @buddy plan turn an issue into a plan | |
| 55 | 53 | @buddy rebase rebase a dependency update |
| 56 | 54 | @buddy merge re-check auto-merge now |
| 57 | 55 | @buddy remember ... keep a note for future runs |
| @@ -92,7 +90,7 @@ features: | ||
| 92 | 90 | details: "Inline findings anchored to the lines you actually changed, each with the failure it causes rather than a style opinion. Buddy remembers what it already said, so a second push gets new findings — not the same ones again." |
| 93 | 91 | - title: "Talks back in the thread" |
| 94 | 92 | icon: "💬" |
| 95 | details: "Mention @buddy to re-review, summarise, resolve its own threads, pause on a noisy PR, or just ask a question about the diff." | |
| 93 | details: "Mention @buddy to re-review, summarise, pause on a noisy PR, or just ask a question about the diff." | |
| 96 | 94 | - title: "Works without an API key" |
| 97 | 95 | icon: "🦴" |
| 98 | 96 | details: "buddy review --light runs secret scanning, actionlint, shellcheck, hadolint and syntax checks with no model and no network. Fast enough for a pre-commit hook." |
| @@ -104,7 +102,7 @@ features: | ||
| 104 | 102 | details: "buddy fix-ci reads a failing workflow run, classifies the failure, and opens the repair when the fix is unambiguous." |
| 105 | 103 | - title: "Also minds the dependencies" |
| 106 | 104 | icon: "📦" |
| 107 | details: "The whole Renovate/Dependabot job — scanning, grouping, changelogs, a pinned dashboard, auto-merge — across npm, Composer, Docker, Actions, Go, Rust, Python and Ruby." | |
| 105 | details: "The whole Renovate/Dependabot job — scanning, grouping, changelogs, a pinned dashboard, auto-merge — across npm, Composer, Docker, Actions, pkgx, Zig, Go, Rust, Python and Ruby." | |
| 108 | 106 | - title: "Your CI, your keys, your model" |
| 109 | 107 | icon: "🏠" |
| 110 | 108 | span: 2 |
| @@ -191,6 +189,7 @@ Underneath sits the release notes for every version in the range, a compare link | ||
| 191 | 189 | | pkgx / Launchpad | `deps.yaml`, `dependencies.yaml`, `pkgx.yaml` | `pantry.lock` | |
| 192 | 190 | | GitHub Actions | `.github/workflows/*.yml` | — | |
| 193 | 191 | | Docker | `Dockerfile` | — | |
| 192 | | Zig | `build.zig.zon` | — | | |
| 194 | 193 | | Go, Rust, Python, Ruby | `go.mod`, `Cargo.toml`, `pyproject.toml`, `Gemfile` | `go.sum`, `Cargo.lock`, `poetry.lock`, `Gemfile.lock` | |
| 195 | 194 | |
| 196 | 195 | More in [pull request generation](/features/pull-requests), [the dashboard](/features/dependency-dashboard) and [ecosystems](/advanced/ecosystems). |
| @@ -204,7 +203,7 @@ More in [pull request generation](/features/pull-requests), [the dashboard](/fea | ||
| 204 | 203 | | Runs on | Your CI, your keys | Hosted app | Hosted or self-hosted | GitHub-hosted | |
| 205 | 204 | | Works with no API key | Analyzers only | — | n/a | n/a | |
| 206 | 205 | | Local pre-push review | Yes | — | — | — | |
| 207 | | Config | TypeScript, JSON or YAML | YAML | JSON / JS | YAML | | |
| 206 | | Config | TypeScript, JavaScript or JSON | YAML | JSON / JS | YAML | | |
| 208 | 207 | | Migration in | From Renovate and Dependabot | — | — | — | |
| 209 | 208 | |
| 210 | 209 | The full matrix — including Greptile, Qodo Merge, Graphite, Sourcery and Snyk — |
| @@ -17,9 +17,9 @@ npm i -g @buddysh/buddy | ||
| 17 | 17 | ``` |
| 18 | 18 | |
| 19 | 19 | ```sh [bun] |
| 20 | bun install --dev buddy | |
| 20 | bun install --dev @buddysh/buddy | |
| 21 | 21 | # bun add --dev @buddysh/buddy |
| 22 | # bun i -d buddy | |
| 22 | # bun i -d @buddysh/buddy | |
| 23 | 23 | |
| 24 | 24 | # or, install globally via |
| 25 | 25 | bun add --global @buddysh/buddy |
| @@ -35,10 +35,10 @@ pnpm add --global @buddysh/buddy | ||
| 35 | 35 | |
| 36 | 36 | ```sh [yarn] |
| 37 | 37 | yarn add --dev @buddysh/buddy |
| 38 | # yarn i -d buddy | |
| 38 | # yarn i -d @buddysh/buddy | |
| 39 | 39 | |
| 40 | 40 | # or, install globally via |
| 41 | yarn global add buddy | |
| 41 | yarn global add @buddysh/buddy | |
| 42 | 42 | ``` |
| 43 | 43 | |
| 44 | 44 | ```sh [brew] |
| @@ -90,61 +90,82 @@ Choose the binary that matches your platform and architecture: | ||
| 90 | 90 | ::: code-group |
| 91 | 91 | |
| 92 | 92 | ```sh [macOS (arm64)] |
| 93 | # Download the binary | |
| 94 | curl -L https://github.com/stacksjs/buddy/releases/download/v0.9.1/buddy-darwin-arm64 -o buddy | |
| 93 | # Download the archive | |
| 94 | curl -L https://github.com/stacksjs/buddy/releases/latest/download/buddy-darwin-arm64.zip -o buddy-darwin-arm64.zip | |
| 95 | ||
| 96 | # Unpack it | |
| 97 | unzip buddy-darwin-arm64.zip | |
| 95 | 98 | |
| 96 | 99 | # Make it executable |
| 97 | chmod +x buddy | |
| 100 | chmod +x buddy-darwin-arm64 | |
| 98 | 101 | |
| 99 | 102 | # Move it to your PATH |
| 100 | mv buddy /usr/local/bin/buddy | |
| 103 | mv buddy-darwin-arm64 /usr/local/bin/buddy | |
| 101 | 104 | ``` |
| 102 | 105 | |
| 103 | 106 | ```sh [macOS (x64)] |
| 104 | # Download the binary | |
| 105 | curl -L https://github.com/stacksjs/buddy/releases/download/v0.9.1/buddy-darwin-x64 -o buddy | |
| 107 | # Download the archive | |
| 108 | curl -L https://github.com/stacksjs/buddy/releases/latest/download/buddy-darwin-x64.zip -o buddy-darwin-x64.zip | |
| 109 | ||
| 110 | # Unpack it | |
| 111 | unzip buddy-darwin-x64.zip | |
| 106 | 112 | |
| 107 | 113 | # Make it executable |
| 108 | chmod +x buddy | |
| 114 | chmod +x buddy-darwin-x64 | |
| 109 | 115 | |
| 110 | 116 | # Move it to your PATH |
| 111 | mv buddy /usr/local/bin/buddy | |
| 117 | mv buddy-darwin-x64 /usr/local/bin/buddy | |
| 112 | 118 | ``` |
| 113 | 119 | |
| 114 | 120 | ```sh [Linux (arm64)] |
| 115 | # Download the binary | |
| 116 | curl -L https://github.com/stacksjs/buddy/releases/download/v0.9.1/buddy-linux-arm64 -o buddy | |
| 121 | # Download the archive | |
| 122 | curl -L https://github.com/stacksjs/buddy/releases/latest/download/buddy-linux-arm64.zip -o buddy-linux-arm64.zip | |
| 123 | ||
| 124 | # Unpack it | |
| 125 | unzip buddy-linux-arm64.zip | |
| 117 | 126 | |
| 118 | 127 | # Make it executable |
| 119 | chmod +x buddy | |
| 128 | chmod +x buddy-linux-arm64 | |
| 120 | 129 | |
| 121 | 130 | # Move it to your PATH |
| 122 | mv buddy /usr/local/bin/buddy | |
| 131 | mv buddy-linux-arm64 /usr/local/bin/buddy | |
| 123 | 132 | ``` |
| 124 | 133 | |
| 125 | 134 | ```sh [Linux (x64)] |
| 126 | # Download the binary | |
| 127 | curl -L https://github.com/stacksjs/buddy/releases/download/v0.9.1/buddy-linux-x64 -o buddy | |
| 135 | # Download the archive | |
| 136 | curl -L https://github.com/stacksjs/buddy/releases/latest/download/buddy-linux-x64.zip -o buddy-linux-x64.zip | |
| 137 | ||
| 138 | # Unpack it | |
| 139 | unzip buddy-linux-x64.zip | |
| 128 | 140 | |
| 129 | 141 | # Make it executable |
| 130 | chmod +x buddy | |
| 142 | chmod +x buddy-linux-x64 | |
| 131 | 143 | |
| 132 | 144 | # Move it to your PATH |
| 133 | mv buddy /usr/local/bin/buddy | |
| 145 | mv buddy-linux-x64 /usr/local/bin/buddy | |
| 134 | 146 | ``` |
| 135 | 147 | |
| 136 | 148 | ```sh [Windows (x64)] |
| 137 | # Download the binary | |
| 138 | curl -L https://github.com/stacksjs/buddy/releases/download/v0.9.1/buddy-windows-x64.exe -o buddy.exe | |
| 149 | # Download the archive | |
| 150 | curl -L https://github.com/stacksjs/buddy/releases/latest/download/buddy-windows-x64.zip -o buddy-windows-x64.zip | |
| 151 | ||
| 152 | # Unpack it | |
| 153 | tar -xf buddy-windows-x64.zip | |
| 139 | 154 | |
| 140 | 155 | # Move it to your PATH (adjust the path as needed) |
| 141 | move buddy.exe C:\Windows\System32\buddy.exe | |
| 156 | move buddy-windows-x64.exe C:\Windows\System32\buddy.exe | |
| 142 | 157 | ``` |
| 143 | 158 | |
| 144 | 159 | ::: |
| 145 | 160 | |
| 146 | 161 | ::: tip |
| 147 | You can also find the `buddy` binaries in GitHub [releases](https://github.com/stacksjs/buddy/releases). | |
| 162 | You can also find the `buddy` archives in GitHub [releases](https://github.com/stacksjs/buddy/releases). Every release publishes a `checksums.txt` alongside them, so you can verify a download before unpacking it: | |
| 163 | ||
| 164 | ```sh | |
| 165 | curl -L https://github.com/stacksjs/buddy/releases/latest/download/checksums.txt -o checksums.txt | |
| 166 | shasum -a 256 -c checksums.txt --ignore-missing | |
| 167 | ``` | |
| 168 | ||
| 148 | 169 | ::: |
| 149 | 170 | |
| 150 | 171 | ## GitHub Setup |
| @@ -216,8 +237,8 @@ buddy --version | ||
| 216 | 237 | # Test GitHub authentication |
| 217 | 238 | buddy scan --verbose |
| 218 | 239 | |
| 219 | # Generate sample configuration | |
| 220 | buddy init | |
| 240 | # Diagnose credentials, git state and analyzer tooling | |
| 241 | buddy doctor | |
| 221 | 242 | ``` |
| 222 | 243 | |
| 223 | 244 | ## IDE Integration |
| @@ -250,7 +271,7 @@ COPY package.json bun.lockb ./ | ||
| 250 | 271 | RUN bun install |
| 251 | 272 | |
| 252 | 273 | COPY . . |
| 253 | RUN bun install -g buddy | |
| 274 | RUN bun install -g @buddysh/buddy | |
| 254 | 275 | |
| 255 | 276 | CMD ["buddy", "scan"] |
| 256 | 277 | ``` |
| @@ -16,7 +16,7 @@ Neither half depends on the other. Run the reviewer alone, run the updater alone | ||
| 16 | 16 | |
| 17 | 17 | - **�� Inline Findings** - Anchored to changed lines, stating the failure rather than a preference |
| 18 | 18 | - **♻️ Incremental** - A second push gets new findings, not the ones you already read |
| 19 | - **�� Conversational** - `@buddy review`, `full-review`, `summary`, `resolve`, `pause`, `resume`, `plan`, `remember`, or a plain question | |
| 19 | - **�� Conversational** - `@buddy review`, `full-review`, `summary`, `pause`, `resume`, `ignore`, `rebase`, `merge`, `fix-ci`, `remember`, or a plain question | |
| 20 | 20 | - **�� Local Review** - `buddy review` reads the working tree, so problems surface before the PR exists |
| 21 | 21 | - **�� No Key Required** - `--light` runs secret scanning, actionlint, shellcheck, hadolint, markdownlint and syntax checks offline |
| 22 | 22 | - **�� Merge Gates** - Title format, description quality, linked issue and dependency policy, published as a check run |
| @@ -26,7 +26,7 @@ Neither half depends on the other. Run the reviewer alone, run the updater alone | ||
| 26 | 26 | |
| 27 | 27 | ## Dependency Features |
| 28 | 28 | |
| 29 | - **�� Smart Scanning** - Lightning-fast dependency detection using Bun, ts-pkgx, and GitHub API | |
| 29 | - **�� Smart Scanning** - Lightning-fast dependency detection using Bun, ts-pantry, and GitHub API | |
| 30 | 30 | - **�� Automated PRs** - Professional pull requests with three separate dependency tables |
| 31 | 31 | - **�� Multi-Format Support** - Handles package.json, pkgx, Launchpad dependency files, and GitHub Actions |
| 32 | 32 | - **��️ Dynamic Labeling** - Contextual labels based on update type and package ecosystem |
| @@ -96,15 +96,14 @@ Choose from carefully crafted presets: | ||
| 96 | 96 | |
| 97 | 97 | #### 📝 Step 5: Configuration Generation |
| 98 | 98 | |
| 99 | - Creates `buddy.config.json` with your repository settings | |
| 99 | - Creates `buddy.config.ts` with your repository settings | |
| 100 | 100 | - Includes sensible defaults and customization options |
| 101 | 101 | |
| 102 | 102 | **�� Step 6: Workflow Generation** |
| 103 | Generates three core GitHub Actions workflows: | |
| 103 | Generates two GitHub Actions workflows: | |
| 104 | 104 | |
| 105 | - `buddy-dashboard.yml` - Dependency Dashboard Management | |
| 106 | - `buddy-check.yml` - Auto-rebase PR checker | |
| 107 | - `buddy-update.yml` - Scheduled dependency updates | |
| 105 | - `buddy.yml` - Unified workflow covering checks, updates and the dashboard | |
| 106 | - `buddy-security.yml` - Workflow security audit, on its own path filters | |
| 108 | 107 | |
| 109 | 108 | #### 🎯 Step 7: Final Instructions |
| 110 | 109 | |
| @@ -116,7 +115,7 @@ Generates three core GitHub Actions workflows: | ||
| 116 | 115 | |
| 117 | 116 | After the enhanced setup completes, you'll have: |
| 118 | 117 | |
| 119 | - ✅ **Complete automation** - Three production-ready workflows with validation | |
| 118 | - ✅ **Complete automation** - Two production-ready workflows with validation | |
| 120 | 119 | - ✅ **Professional dashboard** - Single issue tracking all dependencies |
| 121 | 120 | - ✅ **Interactive rebasing** - Checkbox-based PR updates with conflict resolution |
| 122 | 121 | - ✅ **Smart scheduling** - Optimized update frequency based on project analysis |
| @@ -232,15 +231,17 @@ jobs: | ||
| 232 | 231 | |
| 233 | 232 | ```bash |
| 234 | 233 | # Daily security patches |
| 235 | buddy update --strategy patch --auto-merge | |
| 234 | buddy update --strategy patch | |
| 236 | 235 | |
| 237 | 236 | # Weekly minor updates |
| 238 | buddy update --strategy minor --reviewers team-lead | |
| 237 | buddy update --strategy minor | |
| 239 | 238 | |
| 240 | # Monthly major updates | |
| 241 | buddy update --strategy major --assignees senior-dev | |
| 239 | # Monthly major updates, holding back one package | |
| 240 | buddy update --strategy major --ignore legacy-package | |
| 242 | 241 | ``` |
| 243 | 242 | |
| 243 | Reviewers, assignees, labels and auto-merge are not command line flags — set them once under `pullRequest` in `buddy.config.ts` and every run picks them up. | |
| 244 | ||
| 244 | 245 | ## 🏗️ Architecture |
| 245 | 246 | |
| 246 | 247 | Buddy is built with modern tools and best practices: |
| @@ -257,7 +258,7 @@ Buddy is built with modern tools and best practices: | ||
| 257 | 258 | |---------|-------|------------|----------| |
| 258 | 259 | | **Speed** | ⚡ Bun-native | �� Slower | �� Slower | |
| 259 | 260 | | **Package Managers** | Bun, npm, yarn, pnpm, pkgx, Launchpad | Limited | Limited | |
| 260 | | **Configuration** | TypeScript, YAML, JSON/JS, package.json | YAML | JSON/JS | | |
| 261 | | **Configuration** | TypeScript, JS, JSON | YAML | JSON/JS | | |
| 261 | 262 | | **Grouping** | ✅ Flexible | ✅ Basic | ✅ Advanced | |
| 262 | 263 | | **Zero Config** | ✅ Yes | ✅ Yes | ❌ Complex | |
| 263 | 264 | | **Self-hosted** | ✅ Yes | ❌ GitHub only | ✅ Yes | |
| @@ -87,16 +87,20 @@ buddy scan --strategy patch | ||
| 87 | 87 | # Create update pull requests |
| 88 | 88 | buddy update |
| 89 | 89 | buddy update --dry-run |
| 90 | buddy update --assignee username | |
| 90 | buddy update --strategy patch | |
| 91 | 91 | |
| 92 | 92 | # Rebase/retry a specific PR |
| 93 | 93 | buddy rebase 123 |
| 94 | 94 | buddy rebase 123 --force |
| 95 | 95 | |
| 96 | # Check if PR has rebase checkbox | |
| 97 | buddy update-check 123 | |
| 96 | # Auto-rebase every open buddy PR with a checked rebase box | |
| 97 | buddy update-check | |
| 98 | buddy update-check --dry-run | |
| 98 | 99 | ``` |
| 99 | 100 | |
| 101 | Reviewers, assignees, labels and auto-merge are configured under `pullRequest` in | |
| 102 | `buddy.config.ts` — `buddy update` has no flags for them. | |
| 103 | ||
| 100 | 104 | ### Package Analysis |
| 101 | 105 | |
| 102 | 106 | ```bash |
| @@ -118,16 +122,15 @@ buddy search "ui library" | ||
| 118 | 122 | ### Configuration & Utilities |
| 119 | 123 | |
| 120 | 124 | ```bash |
| 121 | # Generate configuration file | |
| 122 | buddy init | |
| 123 | buddy init --template comprehensive | |
| 125 | # Generate the configuration file and GitHub Actions workflows | |
| 126 | buddy setup | |
| 127 | buddy setup --non-interactive --preset security | |
| 124 | 128 | |
| 125 | # Generate GitHub Actions workflows | |
| 126 | buddy workflow daily | |
| 127 | buddy workflow security | |
| 129 | # Diagnose credentials, git state and tooling | |
| 130 | buddy doctor | |
| 128 | 131 | |
| 129 | 132 | # Utility commands |
| 130 | buddy help | |
| 133 | buddy --help | |
| 131 | 134 | buddy --version |
| 132 | 135 | ``` |
| 133 | 136 | |
| @@ -166,7 +169,7 @@ steps: | ||
| 166 | 169 | |
| 167 | 170 | - **npm packages**: Uses `bun outdated` for accurate detection |
| 168 | 171 | - **Composer packages**: Uses `composer outdated` and Packagist API |
| 169 | - **pkgx/Launchpad packages**: Uses `ts-pkgx` library integration | |
| 172 | - **pkgx/Launchpad packages**: Uses `ts-pantry` library integration | |
| 170 | 173 | - **GitHub Actions**: Fetches latest releases via GitHub API |
| 171 | 174 | |
| 172 | 175 | ## Library Usage |
| @@ -189,12 +192,11 @@ const buddy = new Buddy({ | ||
| 189 | 192 | }) |
| 190 | 193 | |
| 191 | 194 | // Scan for updates |
| 192 | const updates = await buddy.scanForUpdates() | |
| 193 | console.log(`Found ${updates.length} package updates`) | |
| 195 | const scanResult = await buddy.scanForUpdates() | |
| 196 | console.log(`Found ${scanResult.updates.length} package updates`) | |
| 194 | 197 | |
| 195 | 198 | // Create pull requests |
| 196 | const prs = await buddy.createPullRequests() | |
| 197 | console.log(`Created ${prs.length} pull requests`) | |
| 199 | await buddy.createPullRequests(scanResult) | |
| 198 | 200 | ``` |
| 199 | 201 | |
| 200 | 202 | ### Advanced Configuration |
| @@ -261,15 +263,15 @@ await buddy.run() | ||
| 261 | 263 | ```typescript |
| 262 | 264 | try { |
| 263 | 265 | const buddy = new Buddy(config) |
| 264 | const updates = await buddy.scanForUpdates() | |
| 266 | const scanResult = await buddy.scanForUpdates() | |
| 265 | 267 | |
| 266 | if (updates.length === 0) { | |
| 268 | if (scanResult.updates.length === 0) { | |
| 267 | 269 | console.log('All packages are up to date!') |
| 268 | 270 | return |
| 269 | 271 | } |
| 270 | 272 | |
| 271 | const prs = await buddy.createPullRequests() | |
| 272 | console.log(`Successfully created ${prs.length} PRs`) | |
| 273 | await buddy.createPullRequests(scanResult) | |
| 274 | console.log(`Opened pull requests for ${scanResult.updates.length} updates`) | |
| 273 | 275 | } |
| 274 | 276 | catch (error) { |
| 275 | 277 | if (error.code === 'GITHUB_TOKEN_MISSING') { |
| @@ -401,15 +403,14 @@ jobs: | ||
| 401 | 403 | - run: bun install |
| 402 | 404 | - name: Security updates only |
| 403 | 405 | |
| 404 | run: | | |
| 405 | bunx @buddysh/buddy update \ | |
| 406 | --strategy patch \ | |
| 407 | --labels security,dependencies \ | |
| 408 | --auto-merge | |
| 406 | run: bunx @buddysh/buddy update --strategy patch --verbose | |
| 409 | 407 | env: |
| 410 | 408 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 411 | 409 | ``` |
| 412 | 410 | |
| 411 | Labels and auto-merge for these PRs come from the `pullRequest` block in | |
| 412 | `buddy.config.ts`. | |
| 413 | ||
| 413 | 414 | ### Matrix Strategy |
| 414 | 415 | |
| 415 | 416 | ```yaml |
| @@ -433,10 +434,7 @@ jobs: | ||
| 433 | 434 | - run: bun install |
| 434 | 435 | - name: Update ${{ matrix.strategy }} |
| 435 | 436 | |
| 436 | run: | | |
| 437 | bunx @buddysh/buddy update \ | |
| 438 | --strategy ${{ matrix.strategy }} \ | |
| 439 | --labels ${{ matrix.strategy }}-updates | |
| 437 | run: bunx @buddysh/buddy update --strategy ${{ matrix.strategy }} | |
| 440 | 438 | env: |
| 441 | 439 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 442 | 440 | ``` |
| @@ -498,53 +496,83 @@ GITHUB_TOKEN=$ | ||
| 498 | 496 | export GITHUB_TOKEN=ghp_xxxxxxxxxxxx |
| 499 | 497 | |
| 500 | 498 | # Optional: Custom registry |
| 501 | export NPM_REGISTRY_URL=https://registry.npmjs.org | |
| 502 | ||
| 503 | # Optional: Bun configuration | |
| 504 | export BUN_CONFIG_NO_CACHE=false | |
| 499 | export NPM_CONFIG_REGISTRY=https://registry.npmjs.org | |
| 505 | 500 | |
| 506 | # Optional: Debug mode | |
| 507 | export DEBUG=buddy:_ | |
| 501 | # Optional: Log verbosity (silent | error | warn | info | debug) | |
| 502 | export BUDDY_LOG_LEVEL=debug | |
| 508 | 503 | ``` |
| 509 | 504 | |
| 510 | 505 | ## Workflow Examples |
| 511 | 506 | |
| 507 | `buddy update` accepts `--strategy`, `--ignore`, `--dry-run`, `--respect-latest`, | |
| 508 | `--no-respect-latest` and `--verbose`. Everything about the pull request itself — | |
| 509 | reviewers, assignees, labels, auto-merge — is read from `buddy.config.ts`, so each | |
| 510 | example below pairs the config with the script that runs it. | |
| 511 | ||
| 512 | 512 | ### Daily Patch Updates |
| 513 | 513 | |
| 514 | ```typescript | |
| 515 | // buddy.config.ts | |
| 516 | export default { | |
| 517 | pullRequest: { | |
| 518 | labels: ['security', 'patch-updates'], | |
| 519 | autoMerge: { | |
| 520 | enabled: true, | |
| 521 | strategy: 'squash', | |
| 522 | conditions: ['patch-only'], | |
| 523 | }, | |
| 524 | }, | |
| 525 | } satisfies BuddyConfig | |
| 526 | ``` | |
| 527 | ||
| 514 | 528 | ```bash |
| 515 | 529 | # !/bin/bash |
| 516 | 530 | # daily-updates.sh |
| 517 | 531 | |
| 518 | buddy update \ | |
| 519 | --strategy patch \ | |
| 520 | --auto-merge \ | |
| 521 | --labels security,patch-updates | |
| 532 | buddy update --strategy patch | |
| 522 | 533 | ``` |
| 523 | 534 | |
| 524 | 535 | ### Weekly Comprehensive Updates |
| 525 | 536 | |
| 537 | ```typescript | |
| 538 | // buddy.config.ts | |
| 539 | export default { | |
| 540 | pullRequest: { | |
| 541 | reviewers: ['team-lead', 'senior-dev'], | |
| 542 | assignees: ['maintainer'], | |
| 543 | labels: ['dependencies', 'weekly-update'], | |
| 544 | }, | |
| 545 | } satisfies BuddyConfig | |
| 546 | ``` | |
| 547 | ||
| 526 | 548 | ```bash |
| 527 | 549 | # !/bin/bash |
| 528 | 550 | # weekly-updates.sh |
| 529 | 551 | |
| 530 | buddy update \ | |
| 531 | --strategy all \ | |
| 532 | --reviewers team-lead,senior-dev \ | |
| 533 | --assignees maintainer \ | |
| 534 | --labels dependencies,weekly-update | |
| 552 | buddy update --strategy all | |
| 535 | 553 | ``` |
| 536 | 554 | |
| 537 | 555 | ### Emergency Security Update |
| 538 | 556 | |
| 557 | ```typescript | |
| 558 | // buddy.config.ts | |
| 559 | export default { | |
| 560 | pullRequest: { | |
| 561 | labels: ['security', 'urgent'], | |
| 562 | autoMerge: { | |
| 563 | enabled: true, | |
| 564 | strategy: 'squash', | |
| 565 | conditions: ['security-only'], | |
| 566 | }, | |
| 567 | }, | |
| 568 | } satisfies BuddyConfig | |
| 569 | ``` | |
| 570 | ||
| 539 | 571 | ```bash |
| 540 | 572 | # !/bin/bash |
| 541 | 573 | # security-update.sh |
| 542 | 574 | |
| 543 | buddy update \ | |
| 544 | --strategy patch \ | |
| 545 | --packages-only security \ | |
| 546 | --auto-merge \ | |
| 547 | --labels security,urgent | |
| 575 | buddy update --strategy patch --verbose | |
| 548 | 576 | ``` |
| 549 | 577 | |
| 550 | 578 | ## Dependency File Support |
| @@ -640,10 +668,10 @@ by path, use a rule with `matchFiles` as above. See | ||
| 640 | 668 | ## Testing |
| 641 | 669 | |
| 642 | 670 | ```bash |
| 643 | # Test configuration | |
| 644 | buddy scan --dry-run --verbose | |
| 671 | # Test configuration, credentials and git state | |
| 672 | buddy doctor --verbose | |
| 645 | 673 | |
| 646 | # Test GitHub authentication | |
| 674 | # Test scanning and GitHub authentication | |
| 647 | 675 | buddy scan --verbose |
| 648 | 676 | |
| 649 | 677 | # Test package detection |