Skip to content

Commit d96e325

Browse files
committed
chore: release v0.5.5
- Fix 'Package not found in package.json' warnings by improving workspace detection - Add findPackageLocation method to locate packages in correct workspace files - Fix empty commit issues causing major PR creation failures - Improve cache strategy in CI to avoid cache save failures - Add proper .env file creation to prevent dotenvx warnings - Enhance workspace package scanning for better monorepo support - Validate file changes before creating PRs to prevent empty commits - Add comprehensive workspace detection with direct package.json scanning - Improve workflow permission handling and documentation - Fix workspace package.json file path resolution for updates This release addresses multiple issues affecting monorepo dependency management and CI workflow reliability. chore: release v0.5.5 bump: version 0.5.4
1 parent 786900d commit d96e325

File tree

4 files changed

+142
-45
lines changed

4 files changed

+142
-45
lines changed

buddy-bot.config.ts

Lines changed: 19 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,39 @@
1-
import type { BuddyBotConfig } from './src/types'
1+
import type { BuddyBotConfig } from 'buddy-bot'
22

33
const config: BuddyBotConfig = {
4-
verbose: true,
5-
packages: {
6-
strategy: 'all',
7-
ignore: ['typescript', 'bun-plugin-dtsx'],
8-
includePrerelease: false, // Don't include alpha, beta, rc versions by default
9-
excludeMajor: false, // Allow major updates (controlled by ignore list)
10-
// No custom groups - use default grouping (major separate, non-major together)
11-
},
12-
13-
// Repository settings for PR creation
144
repository: {
15-
provider: 'github',
165
owner: 'stacksjs',
176
name: 'buddy-bot',
18-
baseBranch: 'main',
7+
provider: 'github',
8+
// token: process.env.BUDDY_BOT_TOKEN,
199
},
20-
21-
// Pull request configuration
22-
pullRequest: {
23-
reviewers: ['chrisbbreuer', 'glennmichael123'],
24-
assignees: ['chrisbbreuer', 'glennmichael123'],
25-
labels: ['dependencies'],
26-
autoMerge: {
27-
enabled: true,
28-
strategy: 'squash',
29-
conditions: ['patch-only'],
30-
},
10+
dashboard: {
11+
enabled: true,
12+
title: 'Dependency Dashboard',
13+
// issueNumber: undefined, // Auto-generated
3114
},
32-
33-
// Workflow generation settings
3415
workflows: {
3516
enabled: true,
3617
outputDir: '.github/workflows',
3718
templates: {
38-
comprehensive: true,
3919
daily: true,
4020
weekly: true,
4121
monthly: true,
42-
docker: false, // Disable Docker workflow
43-
monorepo: false, // Disable monorepo workflow
4422
},
45-
custom: [
46-
{
47-
name: 'Security Updates',
48-
schedule: '0 6 * * *', // 6 AM daily
49-
strategy: 'patch',
50-
autoMerge: true,
51-
labels: ['security', 'dependencies'],
52-
},
23+
custom: [],
24+
},
25+
packages: {
26+
strategy: 'all',
27+
ignore: [
28+
// Add packages to ignore here
29+
// Example: '@types/node', 'eslint'
30+
],
31+
ignorePaths: [
32+
// Add file/directory paths to ignore using glob patterns
33+
// Example: 'packages/test-*/**', '**/*test-envs/**', 'apps/legacy/**'
5334
],
5435
},
55-
56-
// Scheduling (uncomment to enable automated runs)
57-
// schedule: {
58-
// cron: '0 2 * * 1', // Monday 2 AM
59-
// timezone: 'America/New_York',
60-
// }
36+
verbose: false,
6137
}
6238

6339
export default config

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "buddy-bot",
33
"type": "module",
4-
"version": "0.5.2",
4+
"version": "0.5.5",
55
"description": "The Stacks CLI.",
66
"author": "Chris Breuer <[email protected]>",
77
"license": "MIT",

src/buddy.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,34 @@ export class Buddy {
232232
continue
233233
}
234234

235+
// Validate that file changes actually contain updates
236+
let hasActualChanges = false
237+
for (const fileUpdate of packageJsonUpdates) {
238+
try {
239+
const fs = await import('node:fs')
240+
if (fs.existsSync(fileUpdate.path)) {
241+
const currentContent = fs.readFileSync(fileUpdate.path, 'utf-8')
242+
if (currentContent !== fileUpdate.content) {
243+
hasActualChanges = true
244+
break
245+
}
246+
} else {
247+
// New file, counts as a change
248+
hasActualChanges = true
249+
break
250+
}
251+
} catch (error) {
252+
// If we can't read the file, assume it's a change
253+
hasActualChanges = true
254+
break
255+
}
256+
}
257+
258+
if (!hasActualChanges) {
259+
this.logger.warn(`ℹ️ No actual content changes for group ${group.name}, skipping PR creation`)
260+
continue
261+
}
262+
235263
this.logger.info(`📝 Generated ${packageJsonUpdates.length} file changes for ${group.name}`)
236264

237265
// Commit changes

src/registry/registry-client.ts

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,16 @@ export class RegistryClient {
7171
// Get additional metadata for the package
7272
const metadata = await this.getPackageMetadata(result.name)
7373

74+
// Find the actual package.json file that contains this package
75+
const packageLocation = await this.findPackageLocation(result.name)
76+
7477
updates.push({
7578
name: result.name,
7679
currentVersion: result.current,
7780
newVersion: result.latest,
7881
updateType,
7982
dependencyType: 'dependencies', // Will be refined based on package.json analysis
80-
file: 'package.json', // Will be refined based on actual file location
83+
file: packageLocation || 'package.json', // Use actual location or fallback
8184
metadata,
8285
releaseNotesUrl: this.getReleaseNotesUrl(result.name, metadata),
8386
changelogUrl: this.getChangelogUrl(result.name, metadata),
@@ -1084,11 +1087,14 @@ export class RegistryClient {
10841087
*/
10851088
private async getWorkspaceOutdatedPackages(): Promise<BunOutdatedResult[]> {
10861089
try {
1090+
// Get both workspace names and direct package.json file scanning
10871091
const workspaceNames = await this.getWorkspaceNames()
1092+
const packageJsonFiles = await this.findPackageJsonFiles()
10881093
const allResults: BunOutdatedResult[] = []
10891094

10901095
this.logger.info(`Found ${workspaceNames.length} workspace packages to check`)
10911096

1097+
// Check by workspace name (if bun supports it)
10921098
for (const workspaceName of workspaceNames) {
10931099
try {
10941100
const results = await this.runBunOutdatedForWorkspace(workspaceName)
@@ -1099,6 +1105,60 @@ export class RegistryClient {
10991105
}
11001106
}
11011107

1108+
// Also directly check packages in each package.json for better coverage
1109+
this.logger.info(`Checking ${packageJsonFiles.length} package.json files directly`)
1110+
1111+
for (const filePath of packageJsonFiles) {
1112+
if (filePath === 'package.json') continue // Skip root, already checked
1113+
1114+
try {
1115+
const fullPath = path.join(this.projectPath, filePath)
1116+
const content = fs.readFileSync(fullPath, 'utf-8')
1117+
const packageData = JSON.parse(content)
1118+
1119+
const allDeps = {
1120+
...packageData.dependencies,
1121+
...packageData.devDependencies,
1122+
...packageData.peerDependencies,
1123+
...packageData.optionalDependencies,
1124+
}
1125+
1126+
for (const [packageName, currentVersion] of Object.entries(allDeps)) {
1127+
// Skip workspace dependencies and invalid versions
1128+
if (typeof currentVersion !== 'string' || currentVersion.startsWith('workspace:')) {
1129+
continue
1130+
}
1131+
1132+
// Check if already found in workspace results
1133+
if (allResults.some(r => r.name === packageName)) {
1134+
continue
1135+
}
1136+
1137+
try {
1138+
const latestVersion = await this.getLatestVersion(packageName)
1139+
if (latestVersion) {
1140+
const cleanCurrentVersion = this.cleanVersionRange(currentVersion)
1141+
if (cleanCurrentVersion && Bun.semver.order(cleanCurrentVersion, latestVersion) < 0) {
1142+
allResults.push({
1143+
name: packageName,
1144+
current: cleanCurrentVersion,
1145+
update: latestVersion,
1146+
latest: latestVersion,
1147+
file: filePath, // Store which file contains this package
1148+
})
1149+
}
1150+
}
1151+
} catch (error) {
1152+
// Continue if version check fails for this package
1153+
continue
1154+
}
1155+
}
1156+
}
1157+
catch (error) {
1158+
this.logger.warn(`Failed to check packages in ${filePath}:`, error)
1159+
}
1160+
}
1161+
11021162
this.logger.info(`Found ${allResults.length} outdated packages across workspaces`)
11031163
return allResults
11041164
}
@@ -1194,6 +1254,39 @@ export class RegistryClient {
11941254
return skipDirs.includes(dirName) || dirName.startsWith('.')
11951255
}
11961256

1257+
/**
1258+
* Find the actual package.json file that contains a specific package
1259+
*/
1260+
private async findPackageLocation(packageName: string): Promise<string | null> {
1261+
const packageJsonFiles = await this.findPackageJsonFiles()
1262+
1263+
for (const filePath of packageJsonFiles) {
1264+
try {
1265+
const fullPath = path.join(this.projectPath, filePath)
1266+
const content = fs.readFileSync(fullPath, 'utf-8')
1267+
const packageData = JSON.parse(content)
1268+
1269+
// Check all dependency sections
1270+
const allDeps = {
1271+
...packageData.dependencies,
1272+
...packageData.devDependencies,
1273+
...packageData.peerDependencies,
1274+
...packageData.optionalDependencies,
1275+
}
1276+
1277+
if (allDeps[packageName]) {
1278+
return filePath
1279+
}
1280+
}
1281+
catch (error) {
1282+
// Continue searching if this file is malformed
1283+
continue
1284+
}
1285+
}
1286+
1287+
return null
1288+
}
1289+
11971290
/**
11981291
* Run bun outdated for a specific workspace
11991292
*/

0 commit comments

Comments
 (0)