Skip to content

Commit

Permalink
fix(release): allow interpolating {projectName} in custom commit mess…
Browse files Browse the repository at this point in the history
…age when valid (#20613)
  • Loading branch information
JamesHenry authored Dec 7, 2023
1 parent f04ed1f commit 308eeb7
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 5 deletions.
131 changes: 131 additions & 0 deletions packages/nx/src/command-line/release/utils/shared.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { ReleaseGroupWithName } from '../config/filter-release-groups';
import { createCommitMessageValues } from './shared';

describe('shared', () => {
describe('createCommitMessageValues()', () => {
describe('userCommitMessage interpolation', () => {
it('should strip {projectName} and {version} from the main commit message if multiple release groups, and instead add all the relevant information at the end of the commit', () => {
const releaseGroups: ReleaseGroupWithName[] = [
{
name: 'one',
projectsRelationship: 'independent',
projects: ['foo'], // single project, will get flattened in the final commit message
version: {
generator: '@nx/js:version',
generatorOptions: {},
},
changelog: false,
releaseTagPattern: '{projectName}-{version}',
},
{
name: 'two',
projectsRelationship: 'fixed',
projects: ['bar', 'baz'],
version: {
generator: '@nx/js:version',
generatorOptions: {},
},
changelog: false,
releaseTagPattern: '{projectName}-{version}',
},
];
const releaseGroupToFilteredProjects = new Map()
.set(releaseGroups[0], new Set(['foo']))
.set(releaseGroups[1], new Set(['bar', 'baz']));
const versionData = {
foo: {
currentVersion: '1.0.0',
dependentProjects: [],
newVersion: '1.0.1',
},
bar: {
currentVersion: '1.0.0',
dependentProjects: [],
newVersion: '1.0.1',
},
baz: {
currentVersion: '1.0.0',
dependentProjects: [],
newVersion: '1.0.1',
},
};
const userCommitMessage =
'chore(release): publish {projectName} v{version}';
const result = createCommitMessageValues(
releaseGroups,
releaseGroupToFilteredProjects,
versionData,
userCommitMessage
);
expect(result).toMatchInlineSnapshot(`
[
"chore(release): publish",
"- project: foo 1.0.1",
"- release-group: two 1.0.1",
]
`);
});

it('should interpolate the {projectName} and {version} within the main commit message if a single project within a single independent release group is being committed', () => {
const releaseGroups: ReleaseGroupWithName[] = [
{
projectsRelationship: 'independent',
projects: [
'native-federation-typescript',
'native-federation-tests',
'storybook-addon',
'typescript',
'nextjs-mf',
'utils',
'enhanced',
'core',
'node',
],
version: {
generator: '@nx/js:release-version',
generatorOptions: {
specifierSource: 'conventional-commits',
currentVersionResolver: 'git-tag',
},
},
changelog: {
createRelease: 'github',
entryWhenNoChanges:
'This was a version bump only for {projectName} to align it with other projects, there were no code changes.',
file: '{projectRoot}/CHANGELOG.md',
renderer: 'nx/changelog-renderer',
renderOptions: { includeAuthors: true },
},
releaseTagPattern: '{projectName}-{version}',
name: '__default__',
},
];

const result = createCommitMessageValues(
releaseGroups,
new Map().set(releaseGroups[0], new Set(['core'])),
{
core: {
currentVersion: '1.0.0-canary.1',
dependentProjects: [
{
source: 'react_ts_host',
target: 'core',
type: 'static',
dependencyCollection: 'devDependencies',
},
],
newVersion: '1.0.0-canary.2',
},
},
'chore(release): Release {projectName} v{version} [skip ci]'
);
expect(result).toMatchInlineSnapshot(`
[
"chore(release): Release core v1.0.0-canary.2 [skip ci]",
]
`);
});
});
});
});
54 changes: 49 additions & 5 deletions packages/nx/src/command-line/release/utils/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,46 @@ export function createCommitMessageValues(
}

/**
* At this point we have multiple release groups for a single commit, we will not interpolate an overall {version} because that won't be appropriate
* (for any {version} value within the string, we will replace it with an empty string so that it doesn't end up in the final output).
* There is another special case for interpolation: if, after all filtering, we have a single independent release group with a single project,
* and the user has provided {projectName} within the custom message.
* In this case we will directly interpolate both {version} and {projectName} within the commit message.
*/
if (
releaseGroups.length === 1 &&
releaseGroups[0].projectsRelationship === 'independent' &&
userCommitMessage?.includes('{projectName}')
) {
const releaseGroup = releaseGroups[0];
const releaseGroupProjectNames = Array.from(
releaseGroupToFilteredProjects.get(releaseGroup)
);
if (releaseGroupProjectNames.length === 1) {
const projectVersionData = versionData[releaseGroupProjectNames[0]];
const releaseVersion = new ReleaseVersion({
version: projectVersionData.newVersion,
releaseTagPattern: releaseGroup.releaseTagPattern,
projectName: releaseGroupProjectNames[0],
});
commitMessageValues[0] = interpolate(commitMessageValues[0], {
version: releaseVersion.rawVersion,
projectName: releaseGroupProjectNames[0],
}).trim();
return commitMessageValues;
}
}

/**
* At this point we have multiple release groups for a single commit, we will not interpolate an overall {version} or {projectName} because that won't be
* appropriate (for any {version} or {projectName} value within the string, we will replace it with an empty string so that it doesn't end up in the final output).
*
* Instead for fixed groups we will add one bullet point the release group, and for independent groups we will add one bullet point per project.
*/
commitMessageValues[0] = commitMessageValues[0]
.replace('{version}', '')
.trim();
commitMessageValues[0] = stripPlaceholders(commitMessageValues[0], [
// for cleanest possible final result try and replace the common pattern of a v prefix in front of the version first
'v{version}',
'{version}',
'{projectName}',
]);

for (const releaseGroup of releaseGroups) {
const releaseGroupProjectNames = Array.from(
Expand Down Expand Up @@ -153,6 +185,18 @@ export function createCommitMessageValues(
return commitMessageValues;
}

function stripPlaceholders(str: string, placeholders: string[]): string {
for (const placeholder of placeholders) {
// for cleanest possible final result try and replace relevant spacing around placeholders first
str = str
.replace(` ${placeholder}`, '')
.replace(`${placeholder} `, '')
.replace(placeholder, '')
.trim();
}
return str;
}

export function createGitTagValues(
releaseGroups: ReleaseGroupWithName[],
releaseGroupToFilteredProjects: Map<ReleaseGroupWithName, Set<string>>,
Expand Down

0 comments on commit 308eeb7

Please sign in to comment.