Skip to content

Commit 5551823

Browse files
authored
feat(release): add logUnchangedProjects flag to version generator, true by default (#27231)
1 parent 40d3516 commit 5551823

File tree

2 files changed

+74
-33
lines changed

2 files changed

+74
-33
lines changed

packages/js/src/generators/release-version/release-version.ts

Lines changed: 69 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ export async function releaseVersionGenerator(
4949
tree: Tree,
5050
options: ReleaseVersionGeneratorSchema
5151
): Promise<ReleaseVersionGeneratorResult> {
52+
let logger: ProjectLogger | undefined;
53+
5254
try {
5355
const versionData: VersionData = {};
5456

@@ -126,6 +128,9 @@ Valid values are: ${validReleaseVersionPrefixes
126128
dryRun?: boolean
127129
) => Promise<string[]>)[] = [];
128130

131+
// If the user has set the logUnchangedProjects option to false, we will not print any logs for projects that have no changes.
132+
const logUnchangedProjects = options.logUnchangedProjects ?? true;
133+
129134
for (const project of projects) {
130135
const projectName = project.name;
131136
const packageRoot = projectNameToPackageRootMap.get(projectName);
@@ -136,12 +141,6 @@ Valid values are: ${validReleaseVersionPrefixes
136141
}
137142

138143
const packageJsonPath = join(packageRoot, 'package.json');
139-
140-
const color = getColor(projectName);
141-
const log = (msg: string) => {
142-
console.log(color.instance.bold(projectName) + ' ' + msg);
143-
};
144-
145144
if (!tree.exists(packageJsonPath)) {
146145
throw new Error(
147146
`The project "${projectName}" does not have a package.json available at ${packageJsonPath}.
@@ -150,14 +149,11 @@ To fix this you will either need to add a package.json file at that location, or
150149
);
151150
}
152151

153-
output.logSingleLine(
154-
`Running release version for project: ${color.instance.bold(
155-
project.name
156-
)}`
157-
);
152+
const color = getColor(projectName);
153+
logger = new ProjectLogger(projectName, color);
158154

159155
const packageJson = readJson(tree, packageJsonPath);
160-
log(
156+
logger.buffer(
161157
`🔍 Reading data for package "${packageJson.name}" from ${packageJsonPath}`
162158
);
163159

@@ -227,14 +223,14 @@ To fix this you will either need to add a package.json file at that location, or
227223

228224
spinner.stop();
229225

230-
log(
226+
logger.buffer(
231227
`📄 Resolved the current version as ${currentVersion} for tag "${tag}" from registry ${registry}`
232228
);
233229
} catch (e) {
234230
spinner.stop();
235231

236232
if (options.fallbackCurrentVersionResolver === 'disk') {
237-
log(
233+
logger.buffer(
238234
`📄 Unable to resolve the current version from the registry ${registry}. Falling back to the version on disk of ${currentVersionFromDisk}`
239235
);
240236
currentVersion = currentVersionFromDisk;
@@ -247,11 +243,11 @@ To fix this you will either need to add a package.json file at that location, or
247243
}
248244
} else {
249245
if (currentVersionResolvedFromFallback) {
250-
log(
246+
logger.buffer(
251247
`📄 Using the current version ${currentVersion} already resolved from disk fallback.`
252248
);
253249
} else {
254-
log(
250+
logger.buffer(
255251
`📄 Using the current version ${currentVersion} already resolved from the registry ${registry}`
256252
);
257253
}
@@ -265,7 +261,7 @@ To fix this you will either need to add a package.json file at that location, or
265261
`Unable to determine the current version for project "${project.name}" from ${packageJsonPath}`
266262
);
267263
}
268-
log(
264+
logger.buffer(
269265
`📄 Resolved the current version as ${currentVersion} from ${packageJsonPath}`
270266
);
271267
break;
@@ -284,7 +280,7 @@ To fix this you will either need to add a package.json file at that location, or
284280
);
285281
if (!latestMatchingGitTag) {
286282
if (options.fallbackCurrentVersionResolver === 'disk') {
287-
log(
283+
logger.buffer(
288284
`📄 Unable to resolve the current version from git tag using pattern "${releaseTagPattern}". Falling back to the version on disk of ${currentVersionFromDisk}`
289285
);
290286
currentVersion = currentVersionFromDisk;
@@ -296,17 +292,17 @@ To fix this you will either need to add a package.json file at that location, or
296292
}
297293
} else {
298294
currentVersion = latestMatchingGitTag.extractedVersion;
299-
log(
295+
logger.buffer(
300296
`📄 Resolved the current version as ${currentVersion} from git tag "${latestMatchingGitTag.tag}".`
301297
);
302298
}
303299
} else {
304300
if (currentVersionResolvedFromFallback) {
305-
log(
301+
logger.buffer(
306302
`📄 Using the current version ${currentVersion} already resolved from disk fallback.`
307303
);
308304
} else {
309-
log(
305+
logger.buffer(
310306
// In this code path we know that latestMatchingGitTag is defined, because we are not relying on the fallbackCurrentVersionResolver, so we can safely use the non-null assertion operator
311307
`📄 Using the current version ${currentVersion} already resolved from git tag "${
312308
latestMatchingGitTag!.tag
@@ -323,7 +319,9 @@ To fix this you will either need to add a package.json file at that location, or
323319
}
324320

325321
if (options.specifier) {
326-
log(`📄 Using the provided version specifier "${options.specifier}".`);
322+
logger.buffer(
323+
`📄 Using the provided version specifier "${options.specifier}".`
324+
);
327325
// The user is forcibly overriding whatever specifierSource they had otherwise set by imperatively providing a specifier
328326
options.specifierSource = 'prompt';
329327
}
@@ -385,12 +383,12 @@ To fix this you will either need to add a package.json file at that location, or
385383
if (projectToDependencyBumps.has(projectName)) {
386384
// No applicable changes to the project directly by the user, but one or more dependencies have been bumped and updateDependents is enabled
387385
specifier = updateDependentsBump;
388-
log(
386+
logger.buffer(
389387
`📄 Resolved the specifier as "${specifier}" because "release.version.generatorOptions.updateDependents" is enabled`
390388
);
391389
break;
392390
}
393-
log(
391+
logger.buffer(
394392
`🚫 No changes were detected using git history and the conventional commits standard.`
395393
);
396394
break;
@@ -402,7 +400,7 @@ To fix this you will either need to add a package.json file at that location, or
402400
// Users must manually graduate from a prerelease to a release by providing an explicit specifier.
403401
if (prerelease(currentVersion ?? '')) {
404402
specifier = 'prerelease';
405-
log(
403+
logger.buffer(
406404
`📄 Resolved the specifier as "${specifier}" since the current version is a prerelease.`
407405
);
408406
} else {
@@ -411,7 +409,7 @@ To fix this you will either need to add a package.json file at that location, or
411409
specifier = `pre${specifier}`;
412410
extraText = `, combined with your given preid "${options.preid}"`;
413411
}
414-
log(
412+
logger.buffer(
415413
`📄 Resolved the specifier as "${specifier}" using git history and the conventional commits standard${extraText}.`
416414
);
417415
}
@@ -508,15 +506,17 @@ To fix this you will either need to add a package.json file at that location, or
508506
) {
509507
// No applicable changes to the project directly by the user, but one or more dependencies have been bumped and updateDependents is enabled
510508
specifier = updateDependentsBump;
511-
log(
509+
logger.buffer(
512510
`📄 Resolved the specifier as "${specifier}" because "release.version.generatorOptions.updateDependents" is enabled`
513511
);
514512
} else {
515513
specifier = null;
516-
log(`🚫 No changes were detected within version plans.`);
514+
logger.buffer(
515+
`🚫 No changes were detected within version plans.`
516+
);
517517
}
518518
} else {
519-
log(
519+
logger.buffer(
520520
`📄 Resolved the specifier as "${specifier}" using version plans.`
521521
);
522522
}
@@ -636,7 +636,7 @@ To fix this you will either need to add a package.json file at that location, or
636636
.map((dependentProject) => `${indent}- ${dependentProject.source}`)
637637
.join('\n')}`;
638638
logMsg += `\n${indent}=> You can adjust this behavior by setting \`version.generatorOptions.updateDependents\` to "auto"`;
639-
log(logMsg);
639+
logger.buffer(logMsg);
640640
}
641641
}
642642

@@ -656,9 +656,13 @@ To fix this you will either need to add a package.json file at that location, or
656656
};
657657

658658
if (!specifier) {
659-
log(
659+
logger.buffer(
660660
`🚫 Skipping versioning "${packageJson.name}" as no changes were detected.`
661661
);
662+
// Print the buffered logs for this unchanged project, as long as the user has not explicitly disabled this behavior
663+
if (logUnchangedProjects) {
664+
logger.flush();
665+
}
662666
continue;
663667
}
664668

@@ -674,7 +678,9 @@ To fix this you will either need to add a package.json file at that location, or
674678
version: newVersion,
675679
});
676680

677-
log(`✍️ New version ${newVersion} written to ${packageJsonPath}`);
681+
logger.buffer(
682+
`✍️ New version ${newVersion} written to ${packageJsonPath}`
683+
);
678684

679685
if (allDependentProjects.length > 0) {
680686
const totalProjectsToUpdate =
@@ -685,7 +691,7 @@ To fix this you will either need to add a package.json file at that location, or
685691
circularDependencies.size / 2
686692
: dependentProjectsInCurrentBatch.length;
687693
if (totalProjectsToUpdate > 0) {
688-
log(
694+
logger.buffer(
689695
`✍️ Applying new version ${newVersion} to ${totalProjectsToUpdate} ${
690696
totalProjectsToUpdate > 1
691697
? 'packages which depend'
@@ -843,6 +849,9 @@ To fix this you will either need to add a package.json file at that location, or
843849
: updateDependentsBump,
844850
});
845851
}
852+
853+
// Print the logs that have been buffered for this project
854+
logger.flush();
846855
}
847856

848857
/**
@@ -868,6 +877,9 @@ To fix this you will either need to add a package.json file at that location, or
868877
},
869878
};
870879
} catch (e: any) {
880+
// Flush any pending logs before printing the error to make troubleshooting easier
881+
logger?.flush();
882+
871883
if (process.env.NX_VERBOSE_LOGGING === 'true') {
872884
output.error({
873885
title: e.message,
@@ -925,3 +937,27 @@ function getColor(projectName: string) {
925937

926938
return colors[colorIndex];
927939
}
940+
941+
class ProjectLogger {
942+
private logs: string[] = [];
943+
944+
constructor(
945+
private projectName: string,
946+
private color: (typeof colors)[number]
947+
) {}
948+
949+
buffer(msg: string) {
950+
this.logs.push(msg);
951+
}
952+
953+
flush() {
954+
output.logSingleLine(
955+
`Running release version for project: ${this.color.instance.bold(
956+
this.projectName
957+
)}`
958+
);
959+
this.logs.forEach((msg) => {
960+
console.log(this.color.instance.bold(this.projectName) + ' ' + msg);
961+
});
962+
}
963+
}

packages/nx/src/command-line/release/version.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ export interface ReleaseVersionGeneratorSchema {
8989
* This is only applicable to independently released projects.
9090
*/
9191
updateDependents?: 'never' | 'auto';
92+
/**
93+
* Whether or not to completely omit project logs when that project has no applicable changes. This can be useful for
94+
* large monorepos which have a large number of projects, especially when only a subset are released together.
95+
*/
96+
logUnchangedProjects?: boolean;
9297
}
9398

9499
export interface NxReleaseVersionResult {

0 commit comments

Comments
 (0)