Skip to content

Commit

Permalink
fix(core): various release fixes (#20478)
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesHenry authored Nov 29, 2023
1 parent a012e4d commit b3e8fcd
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 58 deletions.
6 changes: 3 additions & 3 deletions e2e/release/src/release.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,7 @@ describe('nx release', () => {
> NX Previewing a Github release and an entry in {project-name}/CHANGELOG.md for v1000.0.0-next.0
> NX Previewing a GitHub release and an entry in {project-name}/CHANGELOG.md for v1000.0.0-next.0
+ ## 1000.0.0-next.0
Expand All @@ -690,7 +690,7 @@ describe('nx release', () => {
+ - an awesome new feature ([{COMMIT_SHA}](https://github.com/nrwl/fake-repo/commit/{COMMIT_SHA}))
> NX Previewing a Github release and an entry in {project-name}/CHANGELOG.md for v1000.0.0-next.0
> NX Previewing a GitHub release and an entry in {project-name}/CHANGELOG.md for v1000.0.0-next.0
+ ## 1000.0.0-next.0
Expand All @@ -701,7 +701,7 @@ describe('nx release', () => {
+ - an awesome new feature ([{COMMIT_SHA}](https://github.com/nrwl/fake-repo/commit/{COMMIT_SHA}))
> NX Previewing a Github release and an entry in {project-name}/CHANGELOG.md for v1000.0.0-next.0
> NX Previewing a GitHub release and an entry in {project-name}/CHANGELOG.md for v1000.0.0-next.0
+ ## 1000.0.0-next.0
Expand Down
44 changes: 39 additions & 5 deletions packages/nx/changelog-renderer/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,33 @@
import type { GitCommit } from '../src/command-line/release/utils/git';
import defaultChangelogRenderer from './index';

jest.mock('../src/project-graph/file-map-utils', () => ({
createFileMapUsingProjectGraph: jest.fn().mockImplementation(() => {
return Promise.resolve({
allWorkspaceFiles: [],
fileMap: {
nonProjectFiles: [],
projectFileMap: {
'pkg-a': [
{
file: 'packages/pkg-a/src/index.ts',
},
],
'pkg-b': [
{
file: 'packages/pkg-b/src/index.ts',
},
],
},
},
});
}),
}));

describe('defaultChangelogRenderer()', () => {
const projectGraph = {
nodes: {},
} as any;
const commits: GitCommit[] = [
{
message: 'fix: all packages fixed',
Expand All @@ -27,7 +53,10 @@ describe('defaultChangelogRenderer()', () => {
},
],
isBreaking: false,
affectedFiles: [],
affectedFiles: [
'packages/pkg-a/src/index.ts',
'packages/pkg-b/src/index.ts',
],
},
{
message: 'feat(pkg-b): and another new capability',
Expand All @@ -53,7 +82,7 @@ describe('defaultChangelogRenderer()', () => {
},
],
isBreaking: false,
affectedFiles: [],
affectedFiles: ['packages/pkg-b/src/index.ts'],
},
{
message: 'feat(pkg-a): new hotness',
Expand All @@ -79,7 +108,7 @@ describe('defaultChangelogRenderer()', () => {
},
],
isBreaking: false,
affectedFiles: [],
affectedFiles: ['packages/pkg-a/src/index.ts'],
},
{
message: 'feat(pkg-b): brand new thing',
Expand All @@ -105,7 +134,7 @@ describe('defaultChangelogRenderer()', () => {
},
],
isBreaking: false,
affectedFiles: [],
affectedFiles: ['packages/pkg-b/src/index.ts'],
},
{
message: 'fix(pkg-a): squashing bugs',
Expand All @@ -131,13 +160,14 @@ describe('defaultChangelogRenderer()', () => {
},
],
isBreaking: false,
affectedFiles: [],
affectedFiles: ['packages/pkg-a/src/index.ts'],
},
];

describe('workspaceChangelog', () => {
it('should generate markdown for all projects by organizing commits by type, then grouped by scope within the type (sorted alphabetically), then chronologically within the scope group', async () => {
const markdown = await defaultChangelogRenderer({
projectGraph,
commits,
releaseVersion: 'v1.1.0',
project: null,
Expand Down Expand Up @@ -169,6 +199,7 @@ describe('defaultChangelogRenderer()', () => {

it('should not generate a Thank You section when changelogRenderOptions.includeAuthors is false', async () => {
const markdown = await defaultChangelogRenderer({
projectGraph,
commits,
releaseVersion: 'v1.1.0',
project: null,
Expand Down Expand Up @@ -198,6 +229,7 @@ describe('defaultChangelogRenderer()', () => {
describe('project level configs', () => {
it('should generate markdown for the given project by organizing commits by type, then chronologically', async () => {
const otherOpts = {
projectGraph,
commits,
releaseVersion: 'v1.1.0',
entryWhenNoChanges: false as const,
Expand Down Expand Up @@ -288,6 +320,7 @@ describe('defaultChangelogRenderer()', () => {
describe('entryWhenNoChanges', () => {
it('should respect the entryWhenNoChanges option for the workspace changelog', async () => {
const otherOpts = {
projectGraph,
commits: [],
releaseVersion: 'v1.1.0',
project: null, // workspace changelog
Expand Down Expand Up @@ -317,6 +350,7 @@ describe('defaultChangelogRenderer()', () => {

it('should respect the entryWhenNoChanges option for project changelogs', async () => {
const otherOpts = {
projectGraph,
commits: [],
releaseVersion: 'v1.1.0',
project: 'pkg-a',
Expand Down
21 changes: 14 additions & 7 deletions packages/nx/changelog-renderer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
RepoSlug,
formatReferences,
} from '../src/command-line/release/utils/github';
import { getCommitsRelevantToProjects } from '../src/command-line/release/utils/shared';
import type { ProjectGraph } from '../src/config/project-graph';

// axios types and values don't seem to match
import _axios = require('axios');
Expand All @@ -19,13 +21,15 @@ export type ChangelogRenderOptions = Record<string, unknown>;
* and returns a string, or a Promise of a string of changelog contents (usually markdown).
*
* @param {Object} config The configuration object for the ChangelogRenderer
* @param {ProjectGraph} config.projectGraph The project graph for the workspace
* @param {GitCommit[]} config.commits The collection of extracted commits to generate a changelog for
* @param {string} config.releaseVersion The version that is being released
* @param {string | null} config.project The name of specific project to generate a changelog for, or `null` if the overall workspace changelog
* @param {string | false} config.entryWhenNoChanges The (already interpolated) string to use as the changelog entry when there are no changes, or `false` if no entry should be generated
* @param {ChangelogRenderOptions} config.changelogRenderOptions The options specific to the ChangelogRenderer implementation
*/
export type ChangelogRenderer = (config: {
projectGraph: ProjectGraph;
commits: GitCommit[];
releaseVersion: string;
project: string | null;
Expand All @@ -51,6 +55,7 @@ export interface DefaultChangelogRenderOptions extends ChangelogRenderOptions {
* from the given commits and other metadata.
*/
const defaultChangelogRenderer: ChangelogRenderer = async ({
projectGraph,
commits,
releaseVersion,
project,
Expand Down Expand Up @@ -129,13 +134,14 @@ const defaultChangelogRenderer: ChangelogRenderer = async ({
}
} else {
// project level changelog
const scopeGroups = groupBy(commits, 'scope');

// Treat unscoped commits as "global", and therefore also relevant to include in the project level changelog
const unscopedCommits = scopeGroups[''] || [];
const relevantCommits = await getCommitsRelevantToProjects(
projectGraph,
commits,
[project]
);

// Generating for a named project, but that project has no changes in the current set of commits, exit early
if (!scopeGroups[project] && unscopedCommits.length === 0) {
// Generating for a named project, but that project has no relevant changes in the current set of commits, exit early
if (relevantCommits.length === 0) {
if (entryWhenNoChanges) {
markdownLines.push(
'',
Expand All @@ -149,7 +155,8 @@ const defaultChangelogRenderer: ChangelogRenderer = async ({
markdownLines.push('', `## ${releaseVersion}`, '');

const typeGroups = groupBy(
[...(scopeGroups[project] || []), ...unscopedCommits],
// Sort the relevant commits to have the unscoped commits first, before grouping by type
relevantCommits.sort((a, b) => (b.scope ? 1 : 0) - (a.scope ? 1 : 0)),
'type'
);
for (const type of Object.keys(commitTypes)) {
Expand Down
44 changes: 27 additions & 17 deletions packages/nx/src/command-line/release/changelog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import { valid } from 'semver';
import { dirSync } from 'tmp';
import type { ChangelogRenderer } from '../../../changelog-renderer';
import { readNxJson } from '../../config/nx-json';
import { ProjectGraphProjectNode } from '../../config/project-graph';
import {
ProjectGraph,
ProjectGraphProjectNode,
} from '../../config/project-graph';
import { FsTree, Tree } from '../../generators/tree';
import { registerTsProject } from '../../plugins/js/utils/register';
import { createProjectGraphAsync } from '../../project-graph/project-graph';
Expand Down Expand Up @@ -188,6 +191,7 @@ export async function releaseChangelog(
await generateChangelogForWorkspace(
tree,
args,
projectGraph,
nxReleaseConfig,
workspaceChangelogVersion,
commits,
Expand All @@ -206,6 +210,7 @@ export async function releaseChangelog(
await generateChangelogForProjects(
tree,
args,
projectGraph,
commits,
projectsVersionData,
postGitTasks,
Expand Down Expand Up @@ -236,6 +241,7 @@ export async function releaseChangelog(
await generateChangelogForProjects(
tree,
args,
projectGraph,
commits,
projectsVersionData,
postGitTasks,
Expand Down Expand Up @@ -404,6 +410,7 @@ function resolveChangelogRenderer(
async function generateChangelogForWorkspace(
tree: Tree,
args: ChangelogOptions,
projectGraph: ProjectGraph,
nxReleaseConfig: NxReleaseConfig,
workspaceChangelogVersion: (string | null) | undefined,
commits: GitCommit[],
Expand Down Expand Up @@ -448,11 +455,11 @@ async function generateChangelogForWorkspace(
releaseTagPattern: nxReleaseConfig.releaseTagPattern,
});

// We are either creating/previewing a changelog file, a Github release, or both
// We are either creating/previewing a changelog file, a GitHub release, or both
let logTitle = dryRun ? 'Previewing a' : 'Generating a';
switch (true) {
case interpolatedTreePath && config.createRelease === 'github':
logTitle += ` Github release and an entry in ${interpolatedTreePath} for ${chalk.white(
logTitle += ` GitHub release and an entry in ${interpolatedTreePath} for ${chalk.white(
releaseVersion.gitTag
)}`;
break;
Expand All @@ -462,7 +469,7 @@ async function generateChangelogForWorkspace(
)}`;
break;
case config.createRelease === 'github':
logTitle += ` Github release for ${chalk.white(releaseVersion.gitTag)}`;
logTitle += ` GitHub release for ${chalk.white(releaseVersion.gitTag)}`;
}

output.log({
Expand All @@ -475,6 +482,7 @@ async function generateChangelogForWorkspace(
: undefined;

let contents = await changelogRenderer({
projectGraph,
commits,
releaseVersion: releaseVersion.rawVersion,
project: null,
Expand All @@ -501,7 +509,7 @@ async function generateChangelogForWorkspace(

/**
* The exact logic we use for printing the summary/diff to the user is dependent upon whether they are creating
* a changelog file, a Github release, or both.
* a changelog file, a GitHub release, or both.
*/
let printSummary = () => {};
const noDiffInChangelogMessage = chalk.yellow(
Expand Down Expand Up @@ -544,9 +552,9 @@ async function generateChangelogForWorkspace(
if (config.createRelease === 'github') {
if (!githubRepoSlug) {
output.error({
title: `Unable to create a Github release because the Github repo slug could not be determined.`,
title: `Unable to create a GitHub release because the GitHub repo slug could not be determined.`,
bodyLines: [
`Please ensure you have a valid Github remote configured. You can run \`git remote -v\` to list your current remotes.`,
`Please ensure you have a valid GitHub remote configured. You can run \`git remote -v\` to list your current remotes.`,
],
});
process.exit(1);
Expand All @@ -567,9 +575,9 @@ async function generateChangelogForWorkspace(
} catch (err) {
if (err.response?.status === 401) {
output.error({
title: `Unable to resolve data via the Github API. You can use any of the following options to resolve this:`,
title: `Unable to resolve data via the GitHub API. You can use any of the following options to resolve this:`,
bodyLines: [
'- Set the `GITHUB_TOKEN` or `GH_TOKEN` environment variable to a valid Github token with `repo` scope',
'- Set the `GITHUB_TOKEN` or `GH_TOKEN` environment variable to a valid GitHub token with `repo` scope',
'- Have an active session via the official gh CLI tool (https://cli.github.com) in your current terminal',
],
});
Expand Down Expand Up @@ -640,6 +648,7 @@ async function generateChangelogForWorkspace(
async function generateChangelogForProjects(
tree: Tree,
args: ChangelogOptions,
projectGraph: ProjectGraph,
commits: GitCommit[],
projectsVersionData: VersionData,
postGitTasks: PostGitTask[],
Expand Down Expand Up @@ -684,11 +693,11 @@ async function generateChangelogForProjects(
projectName: project.name,
});

// We are either creating/previewing a changelog file, a Github release, or both
// We are either creating/previewing a changelog file, a GitHub release, or both
let logTitle = dryRun ? 'Previewing a' : 'Generating a';
switch (true) {
case interpolatedTreePath && config.createRelease === 'github':
logTitle += ` Github release and an entry in ${interpolatedTreePath} for ${chalk.white(
logTitle += ` GitHub release and an entry in ${interpolatedTreePath} for ${chalk.white(
releaseVersion.gitTag
)}`;
break;
Expand All @@ -698,7 +707,7 @@ async function generateChangelogForProjects(
)}`;
break;
case config.createRelease === 'github':
logTitle += ` Github release for ${chalk.white(releaseVersion.gitTag)}`;
logTitle += ` GitHub release for ${chalk.white(releaseVersion.gitTag)}`;
}

output.log({
Expand All @@ -711,6 +720,7 @@ async function generateChangelogForProjects(
: undefined;

let contents = await changelogRenderer({
projectGraph,
commits,
releaseVersion: releaseVersion.rawVersion,
project: project.name,
Expand Down Expand Up @@ -744,7 +754,7 @@ async function generateChangelogForProjects(

/**
* The exact logic we use for printing the summary/diff to the user is dependent upon whether they are creating
* a changelog file, a Github release, or both.
* a changelog file, a GitHub release, or both.
*/
let printSummary = () => {};
const noDiffInChangelogMessage = chalk.yellow(
Expand Down Expand Up @@ -794,9 +804,9 @@ async function generateChangelogForProjects(
if (config.createRelease === 'github') {
if (!githubRepoSlug) {
output.error({
title: `Unable to create a Github release because the Github repo slug could not be determined.`,
title: `Unable to create a GitHub release because the GitHub repo slug could not be determined.`,
bodyLines: [
`Please ensure you have a valid Github remote configured. You can run \`git remote -v\` to list your current remotes.`,
`Please ensure you have a valid GitHub remote configured. You can run \`git remote -v\` to list your current remotes.`,
],
});
process.exit(1);
Expand All @@ -817,9 +827,9 @@ async function generateChangelogForProjects(
} catch (err) {
if (err.response?.status === 401) {
output.error({
title: `Unable to resolve data via the Github API. You can use any of the following options to resolve this:`,
title: `Unable to resolve data via the GitHub API. You can use any of the following options to resolve this:`,
bodyLines: [
'- Set the `GITHUB_TOKEN` or `GH_TOKEN` environment variable to a valid Github token with `repo` scope',
'- Set the `GITHUB_TOKEN` or `GH_TOKEN` environment variable to a valid GitHub token with `repo` scope',
'- Have an active session via the official gh CLI tool (https://cli.github.com) in your current terminal',
],
});
Expand Down
1 change: 0 additions & 1 deletion packages/nx/src/command-line/release/utils/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* https://github.com/unjs/changelogen
*/
import { interpolate } from '../../../tasks-runner/utils';
import { output } from '../../../utils/output';
import { execCommand } from './exec-command';

export interface GitCommitAuthor {
Expand Down
Loading

1 comment on commit b3e8fcd

@vercel
Copy link

@vercel vercel bot commented on b3e8fcd Nov 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nx-dev – ./

nx-dev-nrwl.vercel.app
nx-dev-git-master-nrwl.vercel.app
nx-five.vercel.app
nx.dev

Please sign in to comment.