@@ -9,6 +9,26 @@ const semver = require("semver");
9
9
const RELEASE_BRANCH = "release" ;
10
10
const MAIN_BRANCH = "main" ;
11
11
12
+ /**
13
+ * Handles execSync errors and logs them in a readable format.
14
+ * @param {string } command
15
+ * @param {{ doNotExit?: boolean } } [options] - Optional configuration
16
+ * @param {boolean } [options.doNotExit] - Whether or not to exit the process on error
17
+ */
18
+ function execSyncWithErrorHandling ( command , options = { } ) {
19
+ try {
20
+ execSync (
21
+ command ,
22
+ { stdio : "inherit" } // This will stream output in real-time
23
+ ) ;
24
+ } catch ( error ) {
25
+ console . error ( error . message ) ;
26
+ if ( ! options . doNotExit ) {
27
+ process . exit ( 1 ) ;
28
+ }
29
+ }
30
+ }
31
+
12
32
/**
13
33
* Get the version of a workspace inside a directory.
14
34
*
@@ -131,33 +151,22 @@ async function runYarnRelease(packageDirectory, npm2FACode, tag) {
131
151
132
152
console . log ( `Running command: "yarn ${ args . join ( " " ) } "` ) ;
133
153
134
- const yarnReleaseProcess = spawn ( "yarn" , args , { cwd : workingDirectory } ) ;
135
-
136
- let stdout = "" ;
137
- let stderr = "" ;
138
-
139
- yarnReleaseProcess . stdout . on ( "data" , ( data ) => {
140
- stdout += data ;
141
- // Still show output in real-time
142
- process . stdout . write ( data ) ;
143
- } ) ;
144
-
145
- yarnReleaseProcess . stderr . on ( "data" , ( data ) => {
146
- stderr += data ;
147
- // Still show errors in real-time
148
- process . stderr . write ( data ) ;
154
+ // Use 'inherit' for stdio to allow direct CLI interaction
155
+ const yarnReleaseProcess = spawn ( "yarn" , args , {
156
+ stdio : "inherit" ,
157
+ cwd : workingDirectory ,
149
158
} ) ;
150
159
151
160
yarnReleaseProcess . on ( "close" , ( code ) => {
152
161
if ( code === 0 ) {
153
162
resolve ( ) ;
154
163
} else {
155
- reject ( `Process exited with code ${ code } .\nError: ${ stderr } ` ) ;
164
+ reject ( `Process exited with code ${ code } ` ) ;
156
165
}
157
166
} ) ;
158
167
159
168
yarnReleaseProcess . on ( "error" , ( err ) => {
160
- reject ( `Failed to start process: ${ err . message } \nError: ${ stderr } ` ) ;
169
+ reject ( `Failed to start process: ${ err . message } ` ) ;
161
170
} ) ;
162
171
} ) ;
163
172
}
@@ -194,7 +203,7 @@ function bumpDeps(
194
203
console . log (
195
204
"Updated version is not greater than the pre-release version. Pulling from github and checking again."
196
205
) ;
197
- execSync ( `git pull origin ${ RELEASE_BRANCH } ` ) ;
206
+ execSyncWithErrorHandling ( `git pull origin ${ RELEASE_BRANCH } ` ) ;
198
207
updatedWorkspaceVersion = getWorkspaceVersion ( workspaceDirectory ) ;
199
208
if ( ! semver . gt ( updatedWorkspaceVersion , preReleaseVersion ) ) {
200
209
console . warn (
@@ -213,10 +222,10 @@ function bumpDeps(
213
222
versionString = `${ updatedWorkspaceVersion } -${ tag } ` ;
214
223
}
215
224
216
- execSync ( `git checkout ${ MAIN_BRANCH } ` ) ;
225
+ execSyncWithErrorHandling ( `git checkout ${ MAIN_BRANCH } ` ) ;
217
226
const newBranchName = `bump-${ workspaceName } -to-${ versionString } ` ;
218
227
console . log ( `Checking out new branch: ${ newBranchName } ` ) ;
219
- execSync ( `git checkout -b ${ newBranchName } ` ) ;
228
+ execSyncWithErrorHandling ( `git checkout -b ${ newBranchName } ` ) ;
220
229
221
230
const allWorkspacesWhichDependOn = allWorkspaces . filter ( ( { packageJSON } ) =>
222
231
Object . keys ( packageJSON . dependencies ?? { } ) . includes ( workspaceName )
@@ -268,7 +277,7 @@ Workspaces:
268
277
console . log ( "Updated package.json's! Running yarn install." ) ;
269
278
270
279
try {
271
- execSync ( `yarn install` ) ;
280
+ execSyncWithErrorHandling ( `yarn install` ) ;
272
281
} catch ( _ ) {
273
282
console . log (
274
283
"Yarn install failed. Likely because NPM has not finished publishing the new version. Continuing."
@@ -277,12 +286,12 @@ Workspaces:
277
286
278
287
// Add all current changes, commit, push and log branch URL.
279
288
console . log ( "Adding and committing all changes." ) ;
280
- execSync ( `git add -A` ) ;
281
- execSync (
289
+ execSyncWithErrorHandling ( `git add -A` ) ;
290
+ execSyncWithErrorHandling (
282
291
`git commit -m "all[minor]: bump deps on ${ workspaceName } to ${ versionString } "`
283
292
) ;
284
293
console . log ( "Pushing changes." ) ;
285
- execSync ( `git push -u origin ${ newBranchName } ` ) ;
294
+ execSyncWithErrorHandling ( `git push -u origin ${ newBranchName } ` ) ;
286
295
console . log (
287
296
"🔗 Open %s and merge the bump-deps PR." ,
288
297
`\x1b[34mhttps://github.com/langchain-ai/langchainjs/compare/${ newBranchName } ?expand=1\x1b[0m`
@@ -299,23 +308,37 @@ Workspaces:
299
308
* @param {string } version
300
309
*/
301
310
function createCommitMessage ( workspaceName , version ) {
302
- return `release(${ workspaceName } ): ${ version } ` ;
311
+ const cleanedWorkspaceName = workspaceName . replace ( "@langchain/" , "" ) ;
312
+ return `release(${ cleanedWorkspaceName } ): ${ version } ` ;
303
313
}
304
314
305
315
/**
306
316
* Commits all changes and pushes to the current branch.
307
317
*
308
318
* @param {string } workspaceName The name of the workspace being released
309
319
* @param {string } version The new version being released
320
+ * @param {boolean } onlyPush Whether or not to only push the changes, and not commit
310
321
* @returns {void }
311
322
*/
312
- function commitAndPushChanges ( workspaceName , version ) {
313
- console . log ( "Committing and pushing changes..." ) ;
314
- const commitMsg = createCommitMessage ( workspaceName , version ) ;
315
- execSync ( "git add -A" ) ;
316
- execSync ( `git commit -m "${ commitMsg } "` ) ;
323
+ function commitAndPushChanges ( workspaceName , version , onlyPush ) {
324
+ if ( ! onlyPush ) {
325
+ console . log ( "Committing changes..." ) ;
326
+ const commitMsg = createCommitMessage ( workspaceName , version ) ;
327
+ try {
328
+ execSyncWithErrorHandling ( "git add -A" , { doNotExit : true } ) ;
329
+ execSyncWithErrorHandling ( `git commit -m "${ commitMsg } "` , {
330
+ doNotExit : true ,
331
+ } ) ;
332
+ } catch ( _ ) {
333
+ // No-op. Likely erroring because there are no unstaged changes.
334
+ }
335
+ }
336
+
337
+ console . log ( "Pushing changes..." ) ;
317
338
// Pushes to the current branch
318
- execSync ( "git push -u origin $(git rev-parse --abbrev-ref HEAD)" ) ;
339
+ execSyncWithErrorHandling (
340
+ "git push -u origin $(git rev-parse --abbrev-ref HEAD)"
341
+ ) ;
319
342
console . log ( "Successfully committed and pushed changes." ) ;
320
343
}
321
344
@@ -330,8 +353,8 @@ function checkoutReleaseBranch() {
330
353
const currentBranch = execSync ( "git branch --show-current" ) . toString ( ) . trim ( ) ;
331
354
if ( currentBranch === MAIN_BRANCH || currentBranch === RELEASE_BRANCH ) {
332
355
console . log ( `Checking out '${ RELEASE_BRANCH } ' branch.` ) ;
333
- execSync ( `git checkout -B ${ RELEASE_BRANCH } ` ) ;
334
- execSync ( `git push -u origin ${ RELEASE_BRANCH } ` ) ;
356
+ execSyncWithErrorHandling ( `git checkout -B ${ RELEASE_BRANCH } ` ) ;
357
+ execSyncWithErrorHandling ( `git push -u origin ${ RELEASE_BRANCH } ` ) ;
335
358
} else {
336
359
throw new Error (
337
360
`Current branch is not ${ MAIN_BRANCH } or ${ RELEASE_BRANCH } . Current branch: ${ currentBranch } `
@@ -361,15 +384,34 @@ async function getUserInput(question) {
361
384
}
362
385
363
386
/**
364
- * Checks if there are any uncommitted changes in the git repository
387
+ * Checks if there are any uncommitted changes in the git repository.
365
388
*
366
389
* @returns {boolean } True if there are uncommitted changes, false otherwise
367
390
*/
368
391
function hasUncommittedChanges ( ) {
369
392
try {
370
- // This command returns empty string if no changes, or a string with changes if there are any
371
- const output = execSync ( "git status --porcelain" ) . toString ( ) ;
372
- return output . length > 0 ;
393
+ // Check for uncommitted changes (both staged and unstaged)
394
+ const uncommittedOutput = execSync ( "git status --porcelain" ) . toString ( ) ;
395
+
396
+ return uncommittedOutput . length > 0 ;
397
+ } catch ( error ) {
398
+ console . error ( "Error checking git status:" , error ) ;
399
+ // If we can't check, better to assume there are changes
400
+ return true ;
401
+ }
402
+ }
403
+
404
+ /**
405
+ * Checks if there are any staged commits in the git repository.
406
+ *
407
+ * @returns {boolean } True if there are staged changes, false otherwise
408
+ */
409
+ function hasStagedChanges ( ) {
410
+ try {
411
+ // Check for staged but unpushed changes
412
+ const unPushedOutput = execSync ( "git log '@{u}..'" ) . toString ( ) ;
413
+
414
+ return unPushedOutput . length > 0 ;
373
415
} catch ( error ) {
374
416
console . error ( "Error checking git status:" , error ) ;
375
417
// If we can't check, better to assume there are changes
@@ -419,7 +461,7 @@ async function main() {
419
461
420
462
// Run build, lint, tests
421
463
console . log ( "Running build, lint, and tests." ) ;
422
- execSync (
464
+ execSyncWithErrorHandling (
423
465
`yarn turbo:command run --filter ${ options . workspace } build lint test --concurrency 1`
424
466
) ;
425
467
console . log ( "Successfully ran build, lint, and tests." ) ;
@@ -433,9 +475,13 @@ async function main() {
433
475
// Run `release-it` on workspace
434
476
await runYarnRelease ( matchingWorkspace . dir , npm2FACode , options . tag ) ;
435
477
436
- if ( hasUncommittedChanges ( ) ) {
478
+ const hasStaged = hasStagedChanges ( ) ;
479
+ const hasUnCommitted = hasUncommittedChanges ( ) ;
480
+ if ( hasStaged || hasUnCommitted ) {
437
481
const updatedVersion = getWorkspaceVersion ( matchingWorkspace . dir ) ;
438
- commitAndPushChanges ( options . workspace , updatedVersion ) ;
482
+ // Only push and do not commit if there are staged changes and no uncommitted changes
483
+ const onlyPush = hasStaged && ! hasUnCommitted ;
484
+ commitAndPushChanges ( options . workspace , updatedVersion , onlyPush ) ;
439
485
}
440
486
441
487
// Log release branch URL
@@ -458,4 +504,7 @@ async function main() {
458
504
}
459
505
}
460
506
461
- main ( ) ;
507
+ main ( ) . catch ( ( error ) => {
508
+ console . error ( error ) ;
509
+ process . exit ( 1 ) ;
510
+ } ) ;
0 commit comments