Skip to content
Open
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
1 change: 0 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ jobs:
strategy:
matrix:
node-version:
- 20.8.1
- 22.0.0
os:
- ubuntu-latest
Expand Down
4 changes: 2 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { format } from "url";
import { find, merge } from "lodash-es";
import { CommitParser } from "conventional-commits-parser";
import writer from "./wrappers/conventional-changelog-writer.js";
import { filterRevertedCommitsSync } from "conventional-commits-filter";
import { readPackageUp } from "read-package-up";
import debugFactory from "debug";
import loadChangelogConfig from "./lib/load-changelog-config.js";
import HOSTS_CONFIG from "./lib/hosts-config.js";
import selectWriter from "./lib/select-writer.js";

const debug = debugFactory("semantic-release:release-notes-generator");

Expand Down Expand Up @@ -92,5 +92,5 @@ export async function generateNotes(pluginConfig, context) {
debug("issue: %o", changelogContext.issue);
debug("commit: %o", changelogContext.commit);

return writer(parsedCommits, changelogContext, writerOpts);
return selectWriter(writerOpts)(parsedCommits, changelogContext, writerOpts);
}
14 changes: 14 additions & 0 deletions lib/select-writer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import writerV8 from "../wrappers/conventional-changelog-writer.js";
import writerV9 from "../wrappers/conventional-changelog-writer-v9.js";

/**
* Select the `conventional-changelog-writer` version compatible with the loaded preset's `writerOpts`.
*
* `conventional-changelog-writer@9` replaced its Handlebars-string templates (`mainTemplate`, `headerPartial`, etc.) with plain render functions, and renamed the root template option from `mainTemplate` to `template`. Presets built against the old writer (e.g. `conventional-changelog-angular@8`) never set `writerOpts.template`; presets built against the new writer (e.g. `conventional-changelog-conventionalcommits@10`) always do, as a function. The two are mutually exclusive, so this is a reliable dispatch key without needing the preset to declare its own writer version explicitly.
*
* @param {Object} writerOpts The resolved writer options from `loadChangelogConfig`.
* @return {Function} The `writeChangelogString` implementation matching `writerOpts`' own template architecture.
*/
export default function selectWriter(writerOpts) {
return typeof writerOpts.template === "function" ? writerV9 : writerV8;
}
80 changes: 79 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"dependencies": {
"conventional-changelog-angular": "^8.0.0",
"conventional-changelog-writer": "^8.0.0",
"conventional-changelog-writer-v9": "npm:conventional-changelog-writer@^9.0.0",
"conventional-commits-filter": "^5.0.0",
"conventional-commits-parser": "^6.0.0",
"debug": "^4.0.0",
Expand All @@ -25,6 +26,7 @@
"c8": "11.0.0",
"conventional-changelog-atom": "5.1.0",
"conventional-changelog-conventionalcommits": "9.3.1",
"conventional-changelog-conventionalcommits-v10": "npm:conventional-changelog-conventionalcommits@10.2.1",
"conventional-changelog-ember": "5.1.0",
"conventional-changelog-eslint": "6.1.0",
"conventional-changelog-express": "5.1.0",
Expand All @@ -42,7 +44,7 @@
"testdouble": "3.20.2"
},
"engines": {
"node": ">=20.8.1"
"node": ">=22.0.0"
},
"files": [
"lib",
Expand Down
37 changes: 37 additions & 0 deletions test/integration.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,43 @@ test.serial('Use "conventional-changelog-angular" by default', async (t) => {
);
});

test.serial(
'Use "conventional-changelog-conventionalcommits-v10" (render-function writer templates) end to end',
async (t) => {
const { generateNotes } = await import("../index.js");
const commits = [
{ hash: "111", message: "fix(scope1): First fix" },
{ hash: "222", message: "feat(scope2): Second feature" },
];
const changelog = await generateNotes(
{ config: "conventional-changelog-conventionalcommits-v10" },
{ cwd, options: { repositoryUrl }, lastRelease, nextRelease, commits }
);

t.regex(changelog, /### Bug Fixes/);
t.regex(changelog, new RegExp(escape("First fix ([111](https://github.com/owner/repo/commit/111))")));
t.regex(changelog, /### Features/);
t.regex(changelog, new RegExp(escape("Second feature ([222](https://github.com/owner/repo/commit/222))")));
}
);

test.serial("Dispatch to the v9 writer when writerOpts.template is a render function", async (t) => {
const writerV8Double = td.func();
const writerV9Double = td.func();
await td.replaceEsm("../wrappers/conventional-changelog-writer.js", {}, writerV8Double);
await td.replaceEsm("../wrappers/conventional-changelog-writer-v9.js", {}, writerV9Double);
const { generateNotes } = await import("../index.js");

const commits = [{ hash: "111", message: "fix(scope1): First fix" }];
await generateNotes(
{ writerOpts: { template: () => "" } },
{ cwd, options: { repositoryUrl }, lastRelease, nextRelease, commits }
);

td.verify(writerV9Double(td.matchers.anything(), td.matchers.anything(), td.matchers.anything()));
t.throws(() => td.verify(writerV8Double(td.matchers.anything(), td.matchers.anything(), td.matchers.anything())));
});

test.serial("Set conventional-changelog-writer context", async (t) => {
const cwd = temporaryDirectory();
const writerDouble = td.func();
Expand Down
9 changes: 9 additions & 0 deletions test/load-changelog-config.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,15 @@ test('Throw error if "preset" doesn`t exist', async (t) => {
await t.throwsAsync(loadChangelogConfig({ preset: "unknown-preset" }, { cwd }), { code: "MODULE_NOT_FOUND" });
});

test('Load "conventional-changelog-conventionalcommits-v10" config with the new render-function writer template', async (t) => {
const changelogConfig = await loadChangelogConfig(
{ config: "conventional-changelog-conventionalcommits-v10", presetConfig: {} },
{ cwd }
);

t.is(typeof changelogConfig.writerOpts.template, "function");
});

test.serial("Load preset and config correctly when importFrom.silent fails", async (t) => {
sinon.stub(importFrom, "silent").returns(undefined);

Expand Down
3 changes: 3 additions & 0 deletions wrappers/conventional-changelog-writer-v9.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { writeChangelogString as writer } from "conventional-changelog-writer-v9";

export default writer;
3 changes: 1 addition & 2 deletions wrappers/conventional-changelog-writer.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { writeChangelogString as writer } from 'conventional-changelog-writer';
import { writeChangelogString as writer } from "conventional-changelog-writer";

export default writer;