Skip to content

Commit 4b5f8dd

Browse files
committed
chore: wip
chore: wip chore: wip chore: wip chore: wip chore: wip chore: wip chore: wip 🐛 CRITICAL FIX: Fix composer update detection - Fixed bug where composer show versions array was incorrectly parsed as object keys - Now properly detects all available composer package versions - Enhanced detection finds best patch, minor, and major updates per package - Fixes issue where 0 composer updates were found despite packages being available - Clean up debug logging chore: wip Add composer dependencies for testing composer update detection chore: wip Clean up debug logging after successful fixes MAJOR ENHANCEMENT: Add support for detecting minor/patch composer updates in addition to major updates - Enhanced composer outdated detection to find best patch, minor, and major updates per package - Uses 'composer show --available' to get all versions instead of just latest - Now composer packages will appear in non-major PRs when safe updates are available - Fixes the issue where only major updates were detected, missing safer bug fixes CRITICAL FIX: Reset to clean main state before generating file updates to prevent cross-contamination between PRs Add extensive debug logging to trace composer update issue Fix variable name mismatch: duration -> scanDuration Fix generateAllFileUpdates to prevent cross-contamination between update groups and add debug logging for grouping Add debug logging for update grouping chore: wip chore: wip chore: wip fix: remove overly restrictive Composer constraint filtering The previous approach was filtering out ALL updates that didn't match version constraints, including major updates that users want to see as individual PRs. Now including all available Composer updates and letting the grouping logic handle separation of major vs non-major updates naturally: - Major updates → Individual PRs (even if beyond constraints) - Minor/patch updates → Grouped PR (naturally respect constraints) This matches user expectations and fixes the issue where 0 Composer packages were being found due to overly strict constraint filtering. fix: remove debug test files Cleaning up test files that were created during debugging. The core constraint logic fix has been applied to the registry client. fix: improve tilde constraint handling in Composer Fixed the tilde constraint logic to properly handle different constraint levels: - ~1.2.3 allows only patch updates within 1.2.x - ~1.2 allows minor/patch updates within 1.x.x - ~1 allows minor/patch updates within 1.x.x This matches the test logic and ensures correct constraint-based filtering. debug: add comprehensive logging to Composer scanning Added detailed debug logging to understand why 0 Composer updates are found: - Log composer outdated command execution - Log raw output from composer outdated - Log parsed JSON data structure - Log composer.json file path and existence - Log packages found in composer.json require/require-dev This will help identify if the issue is: 1. composer outdated returning no packages 2. composer.json not being found/read 3. packages not matching between outdated and composer.json debug: add logging to Composer constraint filtering Added debug logs to understand why constraint filtering is excluding all updates: - Log number of outdated packages found - Log each package being processed with versions - Log constraints found in composer.json - Log why packages are being skipped or accepted This will help identify the issue with overly restrictive filtering. chore: wip fix: implement proper version constraint filtering for Composer updates Replaced invalid --strict flag with proper constraint-aware filtering: - Parse version constraints from composer.json (^, ~, etc.) - Filter composer outdated results to respect constraint boundaries - For ^ constraints: only allow minor/patch updates within same major - For ~ constraints: respect tilde semantics (~1.2 vs ~1) - Skip packages not found in composer.json This ensures Composer updates respect version constraints like Renovate does: - laravel/framework ^10.0 → shows 10.48.29 (not v12.x) - symfony/console ^6.0 → shows 6.4.23 (not v7.x) Fixes composer command failing with code 1 due to invalid --strict flag. fix: use composer outdated --strict to respect version constraints Changed from 'composer outdated' to 'composer outdated --strict' which: - Respects version constraints in composer.json (e.g., ^10.0, ^6.0) - Shows minor/patch updates within allowed ranges instead of major updates - Matches Renovate behavior for constraint-aware updates This should fix the issue where: - laravel/framework shows 10.48.29 (minor) instead of v12.21.0 (major) - symfony/console shows 6.4.23 (minor) instead of v7.3.1 (major) - All Composer packages now properly appear in non-major grouped PRs fix: ensure clean working directory between individual major update PRs Added git reset --hard and git clean -fd to ensure each PR branch starts from a completely clean state. This prevents individual major update PRs from inheriting file changes from previous PRs in the same workflow run. Also added comprehensive tests for Composer updates in non-major grouped PRs. This resolves the issue where: - Individual major PRs were applying all major updates instead of just the target package - Ensures proper isolation between PR creations chore: wip debug: show ALL package versions in composer.json during PR creation This will help identify if the composer.json file being read already contains updates from other PRs, which would explain why individual major update PRs are applying all changes instead of just the target package. debug: add detailed logging to generateComposerUpdates to trace file reading This will help identify what composer.json content is being read and which packages are being updated for individual major update PRs. The debug output will show current versions and target updates for each file. chore: wip debug: add logging to trace what updates are passed to each PR group This will help identify why individual major update PRs are applying all Composer updates instead of just the target package. The logs will show exactly what updates each group contains when creating PRs. chore: wip fix: treat GitHub Actions updates same as regular dependencies + handle workflow permissions Major changes: - Reverted GitHub Actions artificial separation - they now follow same rules as regular deps - Major GitHub Actions updates get individual PRs: 'chore(deps): update dependency X to Y' - Non-major GitHub Actions updates grouped with other non-major: 'chore(deps): update all non-major dependencies' Workflow permission handling: - Added filtering logic to exclude workflow files when GitHub App lacks 'workflows' permission - Gracefully handles mixed updates by committing non-workflow files and warning about workflow files - Prevents complete PR failure when only some files have permission issues This resolves the 403 Forbidden error while maintaining proper dependency grouping. fix: separate GitHub Actions updates to avoid workflow permission issues - GitHub Actions updates now get their own PR: 'chore(ci): update GitHub Actions dependencies' - Regular non-major updates stay grouped: 'chore(deps): update all non-major dependencies' - This prevents GitHub App workflow permission errors when updating .github/workflows/ files - Filters based on file path (.github/workflows/) and action names (actions/, oven-sh/, shivammathur/) This should resolve the '403 Forbidden' error for non-major updates containing workflow files. chore: wip chore: wip chore: wip fix: create individual PRs for each major update instead of grouping them - Major updates now get individual PRs: 'chore(deps): update dependency X to Y' - Non-major updates stay grouped: 'chore(deps): update all non-major dependencies' - Improved PR title matching to prevent incorrect PR overwrites - This ensures major updates get proper individual review Example: doctrine/dbal, laravel/framework, symfony/console each get separate PRs chore: wip chore: wip fix: add git configuration to workflow to prevent commit failures Adds git user.name and user.email configuration to prevent the 'Author identity unknown' error that was causing git CLI commits to fail. fix: improve version classification to handle v-prefixed versions This fixes the issue where Composer packages like laravel/framework v10.48.29→v12.21.0 and symfony/console v6.4.23→v7.3.1 were incorrectly classified as patch updates instead of major updates. The regex now includes 'v' prefix in the version cleaning pattern. chore: wip fix: restore proper rebase matching logic and cleanup empty files - Remove dangerous fallback to first group that was causing PR overwrites - Add bidirectional package matching for exact group identification - Add detailed logging when no matching group found - Remove accidentally committed empty files This ensures PR #20 type incidents won't happen again by making rebase operations fail safely instead of overwriting wrong PRs. chore: wip fix: improve rebase PR matching logic to prevent incorrect overwrites - Remove dangerous fallback to first group that caused wrong PR overwrites - Add bidirectional package matching to ensure exact group matches - Add detailed logging when no matching group is found - Prevent future incidents like PR #20 being overwritten with wrong updates This fixes the issue where the non-major updates PR was incorrectly overwritten with a major Composer update during rebase. fix: update package extraction regex to handle Composer PR format The regex now correctly extracts package updates from both npm and Composer PR tables, fixing the issue where 'Could not extract package updates from PR body' was preventing rebase functionality from working on Composer PRs. Before: Only handled npm format | [package] | [`version` -> `version`] | After: Handles both npm and Composer formats including | [package](link) | `version` -> `version` | file | status | fix: properly separate major and non-major dependency updates - Major updates (e.g. doctrine/dbal v3→v4) get individual PRs for careful review - Non-major updates (minor/patch) get grouped into a single PR - Uses default grouping behavior instead of custom groups fix: group all package updates together regardless of version type This ensures that major updates (like doctrine/dbal v3→v4) are grouped with other dependency updates instead of being separated into individual PRs.
1 parent 334ae34 commit 4b5f8dd

30 files changed

+1512
-125
lines changed

.github/workflows/buddy-update-check.yml renamed to .github/workflows/buddy-check.yml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Buddy Update Check
1+
name: Buddy Check
22

33
on:
44
schedule:
@@ -41,9 +41,21 @@ jobs:
4141
with:
4242
bun-version: latest
4343

44+
- name: Setup PHP and Composer (if needed)
45+
if: ${{ hashFiles('composer.json') != '' }}
46+
uses: shivammathur/setup-php@v2
47+
with:
48+
php-version: '8.4'
49+
tools: composer
50+
coverage: none
51+
4452
- name: Install dependencies
4553
run: bun install
4654

55+
- name: Install Composer dependencies (if needed)
56+
if: ${{ hashFiles('composer.json') != '' }}
57+
run: composer install --no-dev --prefer-dist --optimize-autoloader
58+
4759
- name: Build buddy-bot
4860
run: bun run build
4961

.github/workflows/buddy-dashboard.yml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Buddy Dashboard Management
1+
name: Buddy Dashboard
22

33
on:
44
schedule:
@@ -55,9 +55,21 @@ jobs:
5555
with:
5656
bun-version: latest
5757

58+
- name: Setup PHP and Composer (if needed)
59+
if: ${{ hashFiles('composer.json') != '' }}
60+
uses: shivammathur/setup-php@v2
61+
with:
62+
php-version: '8.4'
63+
tools: composer
64+
coverage: none
65+
5866
- name: Install dependencies
5967
run: bun install
6068

69+
- name: Install Composer dependencies (if needed)
70+
if: ${{ hashFiles('composer.json') != '' }}
71+
run: composer install --no-dev --prefer-dist --optimize-autoloader
72+
6173
- name: Build buddy-bot
6274
run: bun run build
6375

.github/workflows/buddy-update.yml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Buddy Testing Updates
1+
name: Buddy Update
22

33
on:
44
schedule:
@@ -56,7 +56,8 @@ jobs:
5656
with:
5757
bun-version: latest
5858

59-
- name: Setup PHP and Composer
59+
- name: Setup PHP and Composer (if needed)
60+
if: ${{ hashFiles('composer.json') != '' }}
6061
uses: shivammathur/setup-php@v2
6162
with:
6263
php-version: '8.4'
@@ -66,12 +67,18 @@ jobs:
6667
- name: Install dependencies
6768
run: bun install
6869

69-
- name: Install Composer dependencies
70+
- name: Install Composer dependencies (if needed)
71+
if: ${{ hashFiles('composer.json') != '' }}
7072
run: composer install --no-dev --prefer-dist --optimize-autoloader
7173

7274
- name: Build buddy-bot
7375
run: bun run build
7476

77+
- name: Configure Git
78+
run: |
79+
git config --global user.name "buddy-bot[bot]"
80+
git config --global user.email "buddy-bot[bot]@users.noreply.github.com"
81+
7582
- name: Verify Composer setup
7683
run: |
7784
echo "🔍 Verifying Composer and PHP setup..."

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ storage
1616
qjs*
1717
bin/buddy
1818
bin/buddy-*
19-
19+
vendor

bin/cli.ts

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -765,14 +765,18 @@ cli
765765
return
766766
}
767767

768-
// Find the matching update group
768+
// Find the matching update group - must match exactly
769769
const group = scanResult.groups.find(g =>
770770
g.updates.length === packageUpdates.length
771-
&& g.updates.every(u => packageUpdates.some(pu => pu.name === u.name)),
772-
) || scanResult.groups[0] // Fallback to first group
771+
&& g.updates.every(u => packageUpdates.some(pu => pu.name === u.name))
772+
&& packageUpdates.every(pu => g.updates.some(u => u.name === pu.name)),
773+
)
773774

774775
if (!group) {
775-
logger.error('❌ Could not find matching update group')
776+
logger.error('❌ Could not find matching update group. This likely means the package grouping has changed.')
777+
logger.info(`📋 PR packages: ${packageUpdates.map(p => p.name).join(', ')}`)
778+
logger.info(`📋 Available groups: ${scanResult.groups.map(g => `${g.name} (${g.updates.length} packages)`).join(', ')}`)
779+
logger.info(`💡 Close this PR manually and let buddy-bot create new ones with correct grouping`)
776780
return
777781
}
778782

@@ -811,8 +815,10 @@ cli
811815
async function extractPackageUpdatesFromPRBody(body: string): Promise<Array<{ name: string, currentVersion: string, newVersion: string }>> {
812816
const updates: Array<{ name: string, currentVersion: string, newVersion: string }> = []
813817

814-
// Match table rows with package updates
815-
const tableRowRegex = /\|\s*\[([^\]]+)\][^|]*\|\s*\[`\^?([^`]+)`\s*->\s*`\^?([^`]+)`\]/g
818+
// Match table rows with package updates - handles both npm and Composer formats
819+
// npm format: | [package] | [`version` -> `version`] |
820+
// Composer format: | [package](link) | `version` -> `version` | file | status |
821+
const tableRowRegex = /\|\s*\[([^\]]+)\][^|]*\|\s*\[?`\^?([^`]+)`\s*->\s*`\^?([^`]+)`\]?/g
816822

817823
let match
818824
// eslint-disable-next-line no-cond-assign
@@ -914,14 +920,18 @@ cli
914920
continue
915921
}
916922

917-
// Find the matching update group
923+
// Find the matching update group - must match exactly
918924
const group = scanResult.groups.find(g =>
919925
g.updates.length === packageUpdates.length
920-
&& g.updates.every(u => packageUpdates.some(pu => pu.name === u.name)),
921-
) || scanResult.groups[0] // Fallback to first group
926+
&& g.updates.every(u => packageUpdates.some(pu => pu.name === u.name))
927+
&& packageUpdates.every(pu => g.updates.some(u => u.name === pu.name)),
928+
)
922929

923930
if (!group) {
924-
logger.warn(`⚠️ Could not find matching update group for PR #${pr.number}, skipping`)
931+
logger.warn(`⚠️ Could not find matching update group for PR #${pr.number}. This likely means the package grouping has changed.`)
932+
logger.info(`📋 PR packages: ${packageUpdates.map(p => p.name).join(', ')}`)
933+
logger.info(`📋 Available groups: ${scanResult.groups.map(g => `${g.name} (${g.updates.length} packages)`).join(', ')}`)
934+
logger.info(`💡 Skipping rebase - close this PR manually and let buddy-bot create new ones with correct grouping`)
925935
continue
926936
}
927937

buddy-bot.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const config: BuddyBotConfig = {
77
ignore: ['typescript', 'bun-plugin-dtsx'],
88
includePrerelease: false, // Don't include alpha, beta, rc versions by default
99
excludeMajor: false, // Allow major updates (controlled by ignore list)
10+
// No custom groups - use default grouping (major separate, non-major together)
1011
},
1112

1213
// Repository settings for PR creation

debug-composer-individual.js

Whitespace-only changes.

docs/cli/setup.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ The setup process creates several files:
334334

335335
#### Dashboard Workflow
336336
```yaml
337-
name: Buddy Dashboard Management
337+
name: Buddy Dashboard
338338

339339
on:
340340
schedule:
@@ -344,7 +344,7 @@ on:
344344
345345
#### Update Check Workflow
346346
```yaml
347-
name: Buddy Update Check
347+
name: Buddy Check
348348

349349
on:
350350
schedule:

docs/features/rebase.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ buddy-bot update-check --dry-run --verbose
7272
### Manual Trigger via GitHub Actions
7373

7474
1. Go to **Actions** tab in your repository
75-
2. Select **"Buddy Update Check"** workflow
75+
2. Select **"Buddy Check"** workflow
7676
3. Click **"Run workflow"**
7777
4. Choose options:
7878
- **Dry run**: Preview changes without applying them
@@ -85,7 +85,7 @@ buddy-bot update-check --dry-run --verbose
8585
The rebase workflow is automatically created when you run `buddy-bot setup`. It includes:
8686

8787
```yaml
88-
name: Buddy Update Check
88+
name: Buddy Check
8989

9090
on:
9191
schedule:

src/buddy.ts

Lines changed: 98 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -84,17 +84,17 @@ export class Buddy {
8484
? this.groupUpdatesByConfig(updates)
8585
: groupUpdates(updates)
8686

87-
const duration = Date.now() - startTime
87+
const scanDuration = Date.now() - startTime
8888

8989
const result: UpdateScanResult = {
9090
totalPackages,
9191
updates,
9292
groups,
9393
scannedAt: new Date(),
94-
duration,
94+
duration: scanDuration,
9595
}
9696

97-
this.logger.success(`Scan completed in ${duration}ms. Found ${updates.length} updates.`)
97+
this.logger.success(`Scan completed in ${scanDuration}ms. Found ${updates.length} updates.`)
9898
return result
9999
}
100100
catch (error) {
@@ -191,6 +191,33 @@ export class Buddy {
191191
// Create branch
192192
await gitProvider.createBranch(branchName, this.config.repository.baseBranch || 'main')
193193

194+
// Ensure we're on a clean main branch before generating updates
195+
// This prevents reading modified files from previous PR generations
196+
try {
197+
const { spawn } = await import('node:child_process')
198+
const runGitCommand = (command: string, args: string[]): Promise<void> => {
199+
return new Promise((resolve, reject) => {
200+
const child = spawn(command, args, { stdio: 'pipe' })
201+
child.on('close', (code) => {
202+
if (code === 0)
203+
resolve()
204+
else reject(new Error(`Git command failed with code ${code}`))
205+
})
206+
child.on('error', reject)
207+
})
208+
}
209+
210+
// Reset to clean main state before generating file updates
211+
await runGitCommand('git', ['checkout', 'main'])
212+
await runGitCommand('git', ['reset', '--hard', 'HEAD'])
213+
await runGitCommand('git', ['clean', '-fd'])
214+
// eslint-disable-next-line no-console
215+
console.log(`🧹 Reset to clean main state before generating updates for ${group.name}`)
216+
}
217+
catch (error) {
218+
console.warn(`⚠️ Failed to reset to clean state, continuing anyway:`, error)
219+
}
220+
194221
// Update package.json with new versions
195222
const packageJsonUpdates = await this.generateAllFileUpdates(group.updates)
196223

@@ -442,36 +469,58 @@ export class Buddy {
442469
}
443470

444471
// Handle dependency file updates (deps.yaml, dependencies.yaml, etc.)
445-
try {
446-
const { generateDependencyFileUpdates } = await import('./utils/dependency-file-parser')
447-
const dependencyFileUpdates = await generateDependencyFileUpdates(updates)
448-
fileUpdates.push(...dependencyFileUpdates)
449-
}
450-
catch (error) {
451-
this.logger.error('Failed to generate dependency file updates:', error)
452-
// Continue with package.json updates even if dependency file updates fail
472+
// Only process if we have dependency file updates to avoid unnecessary processing
473+
const dependencyFileUpdates = updates.filter(update =>
474+
(update.file.includes('.yaml') || update.file.includes('.yml'))
475+
&& !update.file.includes('.github/workflows/'),
476+
)
477+
if (dependencyFileUpdates.length > 0) {
478+
try {
479+
const { generateDependencyFileUpdates } = await import('./utils/dependency-file-parser')
480+
// Pass only the dependency file updates to avoid cross-contamination
481+
const depFileUpdates = await generateDependencyFileUpdates(dependencyFileUpdates)
482+
fileUpdates.push(...depFileUpdates)
483+
}
484+
catch (error) {
485+
this.logger.error('Failed to generate dependency file updates:', error)
486+
// Continue with other updates even if dependency file updates fail
487+
}
453488
}
454489

455490
// Handle Composer updates
456-
try {
457-
const { generateComposerUpdates } = await import('./utils/composer-parser')
458-
const composerUpdates = await generateComposerUpdates(updates)
459-
fileUpdates.push(...composerUpdates)
460-
}
461-
catch (error) {
462-
this.logger.error('Failed to generate Composer updates:', error)
463-
// Continue with other updates even if Composer updates fail
491+
// Only process if we have composer updates to avoid unnecessary processing
492+
const composerUpdates = updates.filter(update =>
493+
update.file.endsWith('composer.json') || update.file.endsWith('composer.lock'),
494+
)
495+
if (composerUpdates.length > 0) {
496+
try {
497+
const { generateComposerUpdates } = await import('./utils/composer-parser')
498+
// Pass only the composer updates for this specific group to prevent cross-contamination
499+
const compUpdates = await generateComposerUpdates(composerUpdates)
500+
fileUpdates.push(...compUpdates)
501+
}
502+
catch (error) {
503+
this.logger.error('Failed to generate Composer updates:', error)
504+
// Continue with other updates even if Composer updates fail
505+
}
464506
}
465507

466508
// Handle GitHub Actions updates
467-
try {
468-
const { generateGitHubActionsUpdates } = await import('./utils/github-actions-parser')
469-
const githubActionsUpdates = await generateGitHubActionsUpdates(updates)
470-
fileUpdates.push(...githubActionsUpdates)
471-
}
472-
catch (error) {
473-
this.logger.error('Failed to generate GitHub Actions updates:', error)
474-
// Continue with other updates even if GitHub Actions updates fail
509+
// Only process if we have GitHub Actions updates to avoid unnecessary processing
510+
const githubActionsUpdates = updates.filter(update =>
511+
update.file.includes('.github/workflows/'),
512+
)
513+
if (githubActionsUpdates.length > 0) {
514+
try {
515+
const { generateGitHubActionsUpdates } = await import('./utils/github-actions-parser')
516+
// Pass only the GitHub Actions updates for this specific group
517+
const ghActionsUpdates = await generateGitHubActionsUpdates(githubActionsUpdates)
518+
fileUpdates.push(...ghActionsUpdates)
519+
}
520+
catch (error) {
521+
this.logger.error('Failed to generate GitHub Actions updates:', error)
522+
// Continue with other updates even if GitHub Actions updates fail
523+
}
475524
}
476525

477526
return fileUpdates
@@ -604,21 +653,28 @@ export class Buddy {
604653
* Check if two PR titles are similar (for dependency updates)
605654
*/
606655
private isSimilarPRTitle(existingTitle: string, newTitle: string): boolean {
607-
// Normalize titles by removing timestamps and similar variations
608-
const normalize = (title: string) =>
609-
title.toLowerCase()
610-
.replace(/\b(non-major|major|minor|patch)\b/g, '') // Remove update type words
611-
.replace(/\b\d+\b/g, '') // Remove numbers
612-
.replace(/\s+/g, ' ') // Normalize whitespace
613-
.trim()
614-
615-
const normalizedExisting = normalize(existingTitle)
616-
const normalizedNew = normalize(newTitle)
617-
618-
// Check if titles are similar (considering common dependency update patterns)
619-
return normalizedExisting === normalizedNew
620-
|| (existingTitle.includes('dependency') && newTitle.includes('dependency'))
621-
|| (existingTitle.includes('update') && newTitle.includes('update'))
656+
// Exact match is always similar
657+
if (existingTitle.toLowerCase() === newTitle.toLowerCase()) {
658+
return true
659+
}
660+
661+
// Don't match different update types (major vs non-major, individual vs grouped)
662+
const existingLower = existingTitle.toLowerCase()
663+
const newLower = newTitle.toLowerCase()
664+
665+
// If one is for "all non-major" and other is for specific dependency, they're different
666+
if ((existingLower.includes('all non-major') && newLower.includes('dependency '))
667+
|| (newLower.includes('all non-major') && existingLower.includes('dependency '))) {
668+
return false
669+
}
670+
671+
// Different specific dependencies are different PRs
672+
if (existingLower.includes('dependency ') && newLower.includes('dependency ')) {
673+
return false // Each dependency gets its own PR
674+
}
675+
676+
// Otherwise, not similar
677+
return false
622678
}
623679

624680
/**

0 commit comments

Comments
 (0)