Skip to content

fix: update changelog format to hyperlink PR numbers and handle multiline commit messages #160

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 25 additions & 6 deletions __tests__/changelog.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ describe('changelog', () => {
const expectedChangelog = [
'## `module1/v1.0.0` (2024-11-05)',
'',
'- PR #123 - Test PR Title',
'- :twisted_rightwards_arrows:**[PR #123](https://github.com/techpivot/terraform-module-releaser/pull/123)** - Test PR Title',
'- feat: Add new feature',
'- fix: Fix bug<br>With multiple lines',
'',
'## `module2/v2.0.0` (2024-11-05)',
'',
'- PR #123 - Test PR Title',
'- :twisted_rightwards_arrows:**[PR #123](https://github.com/techpivot/terraform-module-releaser/pull/123)** - Test PR Title',
'- Another commit',
].join('\n');

Expand All @@ -85,7 +85,11 @@ describe('changelog', () => {
},
];

const expectedChangelog = ['## `module2/v2.0.0` (2024-11-05)', '', '- PR #123 - Test PR Title'].join('\n');
const expectedChangelog = [
'## `module2/v2.0.0` (2024-11-05)',
'',
'- :twisted_rightwards_arrows:**[PR #123](https://github.com/techpivot/terraform-module-releaser/pull/123)** - Test PR Title',
].join('\n');

expect(getPullRequestChangelog(terraformChangedModules)).toBe(expectedChangelog);
});
Expand Down Expand Up @@ -114,7 +118,7 @@ describe('changelog', () => {
const expectedChangelog = [
'## `module1/v1.0.0` (2024-11-05)',
'',
'- PR #123 - Test PR Title',
'- :twisted_rightwards_arrows:**[PR #123](https://github.com/techpivot/terraform-module-releaser/pull/123)** - Test PR Title',
'- Another commit',
].join('\n');

Expand Down Expand Up @@ -145,7 +149,7 @@ describe('changelog', () => {
const expectedChangelog = [
'## `1.0.0` (2024-11-05)',
'',
'- [PR #123](https://github.com/techpivot/terraform-module-releaser/pull/123) - Test PR Title',
'- :twisted_rightwards_arrows:**[PR #123](https://github.com/techpivot/terraform-module-releaser/pull/123)** - Test PR Title',
'- feat: Add new feature',
'- fix: Fix bug<br>With multiple lines',
].join('\n');
Expand All @@ -161,13 +165,28 @@ describe('changelog', () => {
const expectedChangelog = [
'## `1.0.0` (2024-11-05)',
'',
'- [PR #123](https://github.com/techpivot/terraform-module-releaser/pull/123) - Test PR Title',
'- :twisted_rightwards_arrows:**[PR #123](https://github.com/techpivot/terraform-module-releaser/pull/123)** - Test PR Title',
'- feat: Multiple<br>line<br>commit',
'- fix: Another<br>Multiline',
].join('\n');

expect(getModuleChangelog(terraformChangedModule)).toBe(expectedChangelog);
});

it('should handle trimming commit messages', () => {
const terraformChangedModule = Object.assign(baseTerraformChangedModule, {
commitMessages: ['\nfeat: message with new lines\n'],
});

const expectedChangelog = [
'## `1.0.0` (2024-11-05)',
'',
'- :twisted_rightwards_arrows:**[PR #123](https://github.com/techpivot/terraform-module-releaser/pull/123)** - Test PR Title',
'- feat: message with new lines',
].join('\n');

expect(getModuleChangelog(terraformChangedModule)).toBe(expectedChangelog);
});
});

describe('getModuleReleaseChangelog()', () => {
Expand Down
37 changes: 19 additions & 18 deletions __tests__/wiki.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,24 +155,25 @@ describe('wiki', async () => {
expect(existsSync(wikiDir)).toBe(true);
});

it('should update remote URL with set-url if origin already exists', () => {
const mockExecFileSync = vi.fn(
(command: string, args?: readonly string[] | undefined, options?: ExecFileSyncOptions) => {
// If the command is "git remote" return "origin" to simulate an existing remote
if (args?.length === 1 && args[0] === 'remote') {
return Buffer.from('origin');
}
return Buffer.from('');
},
);
vi.mocked(execFileSync).mockImplementation(mockExecFileSync);

it('should set origin url if origin exists', () => {
checkoutWiki();
expect(existsSync(wikiDir)).toBe(true);

const gitCalls = mockExecFileSync.mock.calls.map((call) => call[1]?.join(' ') || '');
expect(gitCalls).toContain('remote set-url origin https://github.com/techpivot/terraform-module-releaser.wiki');
// Reset mocks and configure remote command to return "origin"
vi.clearAllMocks();
vi.mocked(execFileSync).mockImplementation((cmd, args = []) => {
if (args[0] === 'remote') {
return Buffer.from('origin');
}
return Buffer.from('');
});

// ... Assertions for group start/end can be added if needed ...
// Second call should update existing repo without error
expect(() => checkoutWiki()).not.toThrow();
// Verify the remote set-url command was called correctly
const gitCalls = vi.mocked(execFileSync).mock.calls.map((call) => call?.[1]?.join(' ') || '');

expect(gitCalls).toContain('remote set-url origin https://github.com/techpivot/terraform-module-releaser.wiki');
});
});

Expand Down Expand Up @@ -275,7 +276,7 @@ describe('wiki', async () => {
'config --local user.name GitHub Actions',
'config --local user.email 41898282+github-actions[bot]@users.noreply.github.com',
'add .',
'commit -m PR #123 - Test PR title',
'commit -m PR #123 - Test PR title', // Note that we don't include the PR body
'push origin',
]);

Expand Down Expand Up @@ -319,12 +320,12 @@ describe('wiki', async () => {
expect(endGroup).toHaveBeenCalled();
});

it('should use complete PR information in commit message', () => {
it('should not use complete PR information in commit message', () => {
// Set up PR context with multiline body
context.set({
prBody: 'Line 1\nLine 2\nLine 3',
prNumber: 456,
prTitle: 'Complex PR title',
prTitle: 'Complex PR title\n\n',
});

// Mock git status to indicate changes exist
Expand Down
54 changes: 24 additions & 30 deletions src/changelog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,27 @@ import type { TerraformChangedModule, TerraformModule } from '@/types';
* @returns {string} A formatted changelog entry as a string.
*/
function createModuleChangelogEntry(heading: string, commits: string[]): string {
const { prNumber, prTitle, repoUrl } = context;
const currentDate = new Date().toISOString().split('T')[0]; // Format: YYYY-MM-DD
const changelogContent: string[] = [`## \`${heading}\` (${currentDate})\n`];

for (const commit of commits) {
changelogContent.push(`- ${commit}`);
// Whether to hyperlink the PR number in the changelog entry. GitHub automatically
// links the PR in the pull request comments but not automatically in the wiki markdown. In the releases section
// it will automatically link just the #9 portion but not the PR part. If we link the whole section it
// ends up being much cleaner.
changelogContent.push(`- :twisted_rightwards_arrows:**[PR #${prNumber}](${repoUrl}/pull/${prNumber})** - ${prTitle}`);

// Perform some normalization
const normalizedCommitMessages = commits
// If the PR title equals the message exactly, we'll skip it
.filter((msg) => msg.trim() !== prTitle)

// Trim the commit message and for markdown, newlines that are part of a list format
// better if they use a <br> tag instead of a newline character.
.map((commitMessage) => commitMessage.trim().replace(/(\n)/g, '<br>'));

for (const normalizedCommit of normalizedCommitMessages) {
changelogContent.push(`- ${normalizedCommit}`);
}

return changelogContent.join('\n');
Expand All @@ -24,6 +40,10 @@ function createModuleChangelogEntry(heading: string, commits: string[]): string
/**
* Retrieves the global pull request changelog.
*
* Aggregates changelog entries from all changed Terraform modules into a single view.
* This aggregated changelog is used explicitly as a comment in the pull request message,
* providing a concise summary of all module changes.
*
* @param {TerraformChangedModule[]} terraformChangedModules - An array of changed Terraform modules.
* @returns {string} The content of the global pull request changelog.
*/
Expand All @@ -32,18 +52,7 @@ export function getPullRequestChangelog(terraformChangedModules: TerraformChange
const { prNumber, prTitle } = context;

for (const { nextTag, commitMessages } of terraformChangedModules) {
const cleanedCommitMessages = commitMessages.map((commitMessage) => {
// Trim the commit message and for markdown, newlines that are part of a list format
// better if they use a <br> tag instead of a newline character.
return commitMessage.trim().replace(/(\n)/g, '<br>');
});

const commitMessagesWithPR = [
`PR #${prNumber} - ${prTitle}`,
...cleanedCommitMessages.filter((msg) => msg.trim() !== prTitle),
];

pullRequestChangelog.push(createModuleChangelogEntry(nextTag, commitMessagesWithPR));
pullRequestChangelog.push(createModuleChangelogEntry(nextTag, commitMessages));
}

return pullRequestChangelog.join('\n\n');
Expand All @@ -59,22 +68,7 @@ export function getModuleChangelog(terraformChangedModule: TerraformChangedModul
const { prNumber, prTitle, repoUrl } = context;
const { nextTagVersion, commitMessages } = terraformChangedModule;

const cleanedCommitMessages = commitMessages.map((commitMessage) => {
// Trim the commit message and for markdown, newlines that are part of a list format
// better if they use a <br> tag instead of a newline character.
return commitMessage.trim().replace(/(\n)/g, '<br>');
});

// Determine whether to hyperlink the PR #XX references in the Changelog since GitHub automatically does this
// in the Pull Request comment fields but not automatically in the wiki. In the releases, it will automatically
// find it with a link; however, recommend to hyperlink here.

const commitMessagesWithPR = [
`[PR #${prNumber}](${repoUrl}/pull/${prNumber}) - ${prTitle}`,
...cleanedCommitMessages.filter((msg) => msg.trim() !== prTitle),
];

return createModuleChangelogEntry(nextTagVersion, commitMessagesWithPR);
return createModuleChangelogEntry(nextTagVersion, commitMessages);
}

/**
Expand Down
2 changes: 2 additions & 0 deletions tf-modules/vpc-endpoint/main.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Noop

locals {
endpoints = { for k, v in var.endpoints : k => v }

Expand Down