diff --git a/CHANGELOG.yml b/CHANGELOG.yml index 671d06d..e6ad922 100644 --- a/CHANGELOG.yml +++ b/CHANGELOG.yml @@ -13,6 +13,8 @@ releases: - type: feat desc: cutting a release also add a new NEXT release commit: 167f631d1fe4eadba3ed5fdadbe378b8255d4ad2 + - type: feat + desc: git-gather also filters on descs - version: 0.1.0 changes: - port the core of the Perl changelord to JavaScript. diff --git a/README.md b/README.md index 64a828d..049859e 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ Git messages are compared to the regular expression configured at `project.commit_regex`. If none is found, it defaults to - ^(?[^: ]+):(?.*?)(\[(?[^\]]+)\])?$ + ^(?[^: ]+):\s*(?.*?)(\[(?[^\]]+)\])?$ The regular expression must capture a `desc` field, and may capture a `type` and `ticket` as well. diff --git a/src/changelord.js b/src/changelord.js index a45c4ab..395af53 100755 --- a/src/changelord.js +++ b/src/changelord.js @@ -8,6 +8,7 @@ import fs from "fs-extra"; import consola from "consola"; import u from "@yanick/updeep-remeda"; import { once } from "remeda"; +import simpleGit from "simple-git"; import print from "./command/print.js"; import init from "./command/init.js"; @@ -22,6 +23,7 @@ consola.raw = (...args) => console.log(...args); yargs(hideBin(process.argv)) .middleware((config) => { + config.git = once(simpleGit); config.consola = consola; config.changelog = once(() => fs.readFile(config.source, "utf-8").then(yaml.parse) diff --git a/src/command/git-gather.js b/src/command/git-gather.js index 45b792e..aa6a78f 100644 --- a/src/command/git-gather.js +++ b/src/command/git-gather.js @@ -2,50 +2,54 @@ import simpleGit from "simple-git"; import { prop, compact, pickBy } from "remeda"; const handler = async (config) => { - const next = await config.next_release(); - const seen_sha1s = compact(next?.changes.map(prop("commit"))); + const next = await config.next_release(); + const seen_sha1s = compact(next?.changes.map(prop("commit"))); + const seen_descs = next?.changes.map((change) => + typeof change === "string" ? change : change.desc + ); - const git = simpleGit(); + const git = config.git(); - const { version } = await config.latest_version(); + const { version } = await config.latest_version(); - let { all: commits } = await git.log({ - from: "v" + version, - }); + let { all: commits } = await git.log({ + from: "v" + version, + }); - config.consola.start(`gathering changes since v${version}`); + config.consola.start(`gathering changes since v${version}`); - commits = commits.filter(({ hash }) => !seen_sha1s.includes(hash)); + commits = commits.filter(({ hash }) => !seen_sha1s.includes(hash)); - const regex = new RegExp( - (await config.changelog().project?.commit_regex) ?? - /^(?[^: ]+):(?.*?)(\[(?[^\]]+)\])?$/ + const regex = new RegExp( + (await config.changelog().project?.commit_regex) ?? + /^(?[^: ]+):\s*(?.*?)(\[(?[^\]]+)\])?$/ + ); + + const changes = commits + .map((commit) => [commit, commit.message.match(regex)]) + .filter((x) => x[1]) + .filter((x) => !seen_descs.includes(x[1].groups.desc)) + .map(([commit, res]) => + pickBy({ ...res.groups, commit: commit.hash }, (x) => x) ); - const changes = commits - .map((commit) => [commit, commit.message.match(regex)]) - .filter((x) => x[1]) - .map(([commit, res]) => - pickBy({ ...res.groups, commit: commit.hash }, (x) => x) - ); + if (changes.length === 0) { + config.consola.success("no changes detected"); + return; + } - if (changes.length === 0) { - config.consola.success("no changes detected"); - return; - } - - for (const change of changes) { - config.consola.info(`${change.type}: ${change.desc}`); - config.add_to_next(change); - } - config.consola.success("done"); + for (const change of changes) { + config.consola.info(`${change.type}: ${change.desc}`); + config.add_to_next(change); + } + config.consola.success("done"); }; export default { - command: "git-gather", - desc: "gather change entries from git commits", - builder: (yargs) => { - yargs; - }, - handler, + command: "git-gather", + desc: "gather change entries from git commits", + builder: (yargs) => { + yargs; + }, + handler, }; diff --git a/src/command/git-gather.test.js b/src/command/git-gather.test.js new file mode 100644 index 0000000..8bccd17 --- /dev/null +++ b/src/command/git-gather.test.js @@ -0,0 +1,28 @@ +import { test, expect, vi } from "vitest"; +import gather from "./git-gather.js"; + +test("no changes detected", async () => { + const changelog = { + releases: [{ version: "NEXT", changes: [] }, { version: "1.0.0" }], + }; + + const noop = () => {}; + const config = { + consola: { + start: noop, + success: vi.fn(), + }, + changelog: () => changelog, + next_release: () => ({ + changes: [], + }), + latest_version: () => ({ version: "1.2.3" }), + git: () => ({ + log: () => ({ all: [] }), + }), + }; + + await gather.handler(config); + + expect(config.consola.success).toHaveBeenCalledWith("no changes detected"); +});