@pob/version 5.2.0 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -15
- package/README.md +147 -10
- package/dist/index-node.mjs +1482 -0
- package/dist/index-node.mjs.map +1 -0
- package/package.json +78 -19
- package/src/commands/version.test.ts +120 -0
- package/src/commands/version.ts +956 -0
- package/src/index.ts +13 -0
- package/src/missing-types.d.ts +10 -0
- package/src/pm/BunPackageManager.ts +29 -0
- package/src/pm/PackageManager.ts +90 -0
- package/src/pm/PnpmPackageManager.ts +23 -0
- package/src/pm/YarnPackageManager.ts +44 -0
- package/src/utils/UsageError.ts +6 -0
- package/src/utils/bumpTypeUtils.test.ts +65 -0
- package/src/utils/bumpTypeUtils.ts +111 -0
- package/src/utils/conventionalChangelogUtils.test.ts +762 -0
- package/src/utils/conventionalChangelogUtils.ts +104 -0
- package/src/utils/conventionalCommitConfigUtils.ts +19 -0
- package/src/utils/execCommand.ts +214 -0
- package/src/utils/generatorUtils.ts +11 -0
- package/src/utils/gitUtils.ts +193 -0
- package/src/utils/githubUtils.ts +120 -0
- package/src/utils/mapUtils.ts +7 -0
- package/src/utils/mapWorkspaces.test.ts +89 -0
- package/src/utils/packageDependenciesUtils.test.ts +25 -0
- package/src/utils/packageDependenciesUtils.ts +80 -0
- package/src/utils/packageUtils.test.ts +32 -0
- package/src/utils/packageUtils.ts +129 -0
- package/src/utils/updateChangelog.ts +39 -0
- package/src/utils/workspaceUtils.ts +142 -0
- package/.editorconfig +0 -13
- package/.eslintrc.json +0 -7
- package/CHANGELOG.md +0 -125
- package/generate-index.js +0 -13
- package/lib/index.d.ts +0 -8
- package/lib/index.js +0 -5
|
@@ -0,0 +1,762 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
import { beforeAll, describe, expect, it } from "vitest";
|
|
3
|
+
import { loadPreset } from "conventional-changelog-preset-loader";
|
|
4
|
+
import { parseCommits } from "conventional-commits-parser";
|
|
5
|
+
import type { Commit } from "conventional-commits-parser";
|
|
6
|
+
import type { PackageJson } from "type-fest";
|
|
7
|
+
import type { Preset } from "./conventionalChangelogUtils.ts";
|
|
8
|
+
// import { beforeAll, describe, expect, it } from "vitest";
|
|
9
|
+
import {
|
|
10
|
+
generateChangelog,
|
|
11
|
+
recommendBump,
|
|
12
|
+
} from "./conventionalChangelogUtils.ts";
|
|
13
|
+
import type { Workspace } from "./packageUtils.ts";
|
|
14
|
+
|
|
15
|
+
const createMockCommit = (
|
|
16
|
+
type: string,
|
|
17
|
+
subject: string,
|
|
18
|
+
options: {
|
|
19
|
+
scope?: string;
|
|
20
|
+
body?: string;
|
|
21
|
+
breaking?: boolean;
|
|
22
|
+
breakingMessage?: string;
|
|
23
|
+
} = {},
|
|
24
|
+
): Commit => {
|
|
25
|
+
const header = `${type}${options.scope ? `(${options.scope})` : ""}${options.breaking ? "!" : ""}: ${subject}`;
|
|
26
|
+
const rawCommit = `${header}\n\n${options.body || ""}`.trim();
|
|
27
|
+
|
|
28
|
+
// @ts-expect-error - notes conflict
|
|
29
|
+
const commit: Commit = {
|
|
30
|
+
type,
|
|
31
|
+
scope: options.scope || null,
|
|
32
|
+
subject,
|
|
33
|
+
merge: null,
|
|
34
|
+
header,
|
|
35
|
+
body: options.body || null,
|
|
36
|
+
footer: null,
|
|
37
|
+
notes: [],
|
|
38
|
+
references: [],
|
|
39
|
+
mentions: [],
|
|
40
|
+
revert: null,
|
|
41
|
+
raw: rawCommit,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
if (options.breaking) {
|
|
45
|
+
commit.notes = [
|
|
46
|
+
{
|
|
47
|
+
title: "BREAKING CHANGE",
|
|
48
|
+
text: options.breakingMessage || "This is a breaking change",
|
|
49
|
+
},
|
|
50
|
+
];
|
|
51
|
+
commit.footer = `BREAKING CHANGE: ${options.breakingMessage || "This is a breaking change"}`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return commit;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const createMockWorkspace = (cwd: string, pkg: PackageJson): Workspace => ({
|
|
58
|
+
cwd,
|
|
59
|
+
pkg,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
let config: Preset;
|
|
63
|
+
let ccParseCommits: ReturnType<typeof parseCommits>;
|
|
64
|
+
|
|
65
|
+
beforeAll(async () => {
|
|
66
|
+
config = await loadPreset<Preset>(
|
|
67
|
+
"conventional-changelog-conventionalcommits",
|
|
68
|
+
);
|
|
69
|
+
ccParseCommits = parseCommits(config.parser);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const createMockCommits = async (commits: string[]): Promise<Commit[]> => {
|
|
73
|
+
const result: Commit[] = [];
|
|
74
|
+
for await (const commit of ccParseCommits(commits)) {
|
|
75
|
+
result.push(commit);
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
describe("recommendBump", () => {
|
|
81
|
+
describe("major bump scenarios", () => {
|
|
82
|
+
it("should recommend major bump when commit has BREAKING CHANGE", async () => {
|
|
83
|
+
const commits = [
|
|
84
|
+
createMockCommit("feat", "add new feature", {
|
|
85
|
+
breaking: true,
|
|
86
|
+
breakingMessage: "API changed completely",
|
|
87
|
+
}),
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
const result = await recommendBump(commits, config);
|
|
91
|
+
|
|
92
|
+
expect(result.releaseType).toBe("major");
|
|
93
|
+
expect(result.reason).toContain("BREAKING CHANGE");
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("should recommend major bump when multiple breaking changes exist", async () => {
|
|
97
|
+
const commits = [
|
|
98
|
+
createMockCommit("feat", "new API", {
|
|
99
|
+
breaking: true,
|
|
100
|
+
breakingMessage: "Old API removed",
|
|
101
|
+
}),
|
|
102
|
+
createMockCommit("fix", "update handler", {
|
|
103
|
+
breaking: true,
|
|
104
|
+
breakingMessage: "Handler signature changed",
|
|
105
|
+
}),
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
const result = await recommendBump(commits, config);
|
|
109
|
+
|
|
110
|
+
expect(result.releaseType).toBe("major");
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("should recommend major bump with breaking change over regular feat", async () => {
|
|
114
|
+
const commits = [
|
|
115
|
+
createMockCommit("feat", "add logging"),
|
|
116
|
+
createMockCommit("refactor", "rewrite core", {
|
|
117
|
+
breaking: true,
|
|
118
|
+
breakingMessage: "Core module API changed",
|
|
119
|
+
}),
|
|
120
|
+
];
|
|
121
|
+
|
|
122
|
+
const result = await recommendBump(commits, config);
|
|
123
|
+
|
|
124
|
+
expect(result.releaseType).toBe("major");
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe("minor bump scenarios", () => {
|
|
129
|
+
it("should recommend minor bump for single feat commit", async () => {
|
|
130
|
+
const commits = [createMockCommit("feat", "add new feature")];
|
|
131
|
+
|
|
132
|
+
const result = await recommendBump(commits, config);
|
|
133
|
+
|
|
134
|
+
expect(result.releaseType).toBe("minor");
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("should recommend minor bump for multiple feat commits", async () => {
|
|
138
|
+
const commits = [
|
|
139
|
+
createMockCommit("feat", "add feature A"),
|
|
140
|
+
createMockCommit("feat", "add feature B"),
|
|
141
|
+
];
|
|
142
|
+
|
|
143
|
+
const result = await recommendBump(commits, config);
|
|
144
|
+
|
|
145
|
+
expect(result.releaseType).toBe("minor");
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("should recommend minor bump for feat with scope", async () => {
|
|
149
|
+
const commits = [
|
|
150
|
+
createMockCommit("feat", "add validation", { scope: "api" }),
|
|
151
|
+
];
|
|
152
|
+
|
|
153
|
+
const result = await recommendBump(commits, config);
|
|
154
|
+
|
|
155
|
+
expect(result.releaseType).toBe("minor");
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it("should recommend minor bump when mixed with non-bumping commits", async () => {
|
|
159
|
+
const commits = [
|
|
160
|
+
createMockCommit("chore", "update dependencies"),
|
|
161
|
+
createMockCommit("feat", "add feature"),
|
|
162
|
+
createMockCommit("docs", "update README"),
|
|
163
|
+
];
|
|
164
|
+
|
|
165
|
+
const result = await recommendBump(commits, config);
|
|
166
|
+
|
|
167
|
+
expect(result.releaseType).toBe("minor");
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it("should recommend minor over patch when both feat and fix exist", async () => {
|
|
171
|
+
const commits = [
|
|
172
|
+
createMockCommit("fix", "fix bug"),
|
|
173
|
+
createMockCommit("feat", "add feature"),
|
|
174
|
+
];
|
|
175
|
+
|
|
176
|
+
const result = await recommendBump(commits, config);
|
|
177
|
+
|
|
178
|
+
expect(result.releaseType).toBe("minor");
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
describe("patch bump scenarios", () => {
|
|
183
|
+
it("should recommend patch bump for single fix commit", async () => {
|
|
184
|
+
const commits = [createMockCommit("fix", "fix bug")];
|
|
185
|
+
|
|
186
|
+
const result = await recommendBump(commits, config);
|
|
187
|
+
|
|
188
|
+
expect(result.releaseType).toBe("patch");
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it("should recommend patch bump for multiple fix commits", async () => {
|
|
192
|
+
const commits = [
|
|
193
|
+
createMockCommit("fix", "fix bug A"),
|
|
194
|
+
createMockCommit("fix", "fix bug B"),
|
|
195
|
+
];
|
|
196
|
+
|
|
197
|
+
const result = await recommendBump(commits, config);
|
|
198
|
+
|
|
199
|
+
expect(result.releaseType).toBe("patch");
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it("should recommend patch bump for perf commits", async () => {
|
|
203
|
+
const commits = [createMockCommit("perf", "optimize database queries")];
|
|
204
|
+
|
|
205
|
+
const result = await recommendBump(commits, config);
|
|
206
|
+
|
|
207
|
+
expect(result.releaseType).toBe("patch");
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it("should recommend patch bump for fix with scope", async () => {
|
|
211
|
+
const commits = [
|
|
212
|
+
createMockCommit("fix", "correct validation", { scope: "auth" }),
|
|
213
|
+
];
|
|
214
|
+
|
|
215
|
+
const result = await recommendBump(commits, config);
|
|
216
|
+
|
|
217
|
+
expect(result.releaseType).toBe("patch");
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it("should recommend patch bump when mixed with non-bumping commits", async () => {
|
|
221
|
+
const commits = [
|
|
222
|
+
createMockCommit("chore", "update config"),
|
|
223
|
+
createMockCommit("fix", "fix crash"),
|
|
224
|
+
createMockCommit("test", "add tests"),
|
|
225
|
+
];
|
|
226
|
+
|
|
227
|
+
const result = await recommendBump(commits, config);
|
|
228
|
+
|
|
229
|
+
expect(result.releaseType).toBe("patch");
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
describe("no bump scenarios", () => {
|
|
234
|
+
it("should recommend patch for chore commits", async () => {
|
|
235
|
+
const commits = [
|
|
236
|
+
createMockCommit("chore", "update dependencies"),
|
|
237
|
+
createMockCommit("chore", "update config"),
|
|
238
|
+
];
|
|
239
|
+
|
|
240
|
+
const result = await recommendBump(commits, config);
|
|
241
|
+
|
|
242
|
+
expect(result.releaseType).toBe("patch");
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it("should recommend patch for docs commits", async () => {
|
|
246
|
+
const commits = [createMockCommit("docs", "update documentation")];
|
|
247
|
+
|
|
248
|
+
const result = await recommendBump(commits, config);
|
|
249
|
+
|
|
250
|
+
expect(result.releaseType).toBe("patch");
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it("should recommend patch for style commits", async () => {
|
|
254
|
+
const commits = [createMockCommit("style", "format code")];
|
|
255
|
+
|
|
256
|
+
const result = await recommendBump(commits, config);
|
|
257
|
+
|
|
258
|
+
expect(result.releaseType).toBe("patch");
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it("should recommend patch for test commits", async () => {
|
|
262
|
+
const commits = [createMockCommit("test", "add unit tests")];
|
|
263
|
+
|
|
264
|
+
const result = await recommendBump(commits, config);
|
|
265
|
+
|
|
266
|
+
expect(result.releaseType).toBe("patch");
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
it("should recommend patch for build commits", async () => {
|
|
270
|
+
const commits = [createMockCommit("build", "update build script")];
|
|
271
|
+
|
|
272
|
+
const result = await recommendBump(commits, config);
|
|
273
|
+
|
|
274
|
+
expect(result.releaseType).toBe("patch");
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it("should recommend patch for ci commits", async () => {
|
|
278
|
+
const commits = [createMockCommit("ci", "update CI configuration")];
|
|
279
|
+
|
|
280
|
+
const result = await recommendBump(commits, config);
|
|
281
|
+
|
|
282
|
+
expect(result.releaseType).toBe("patch");
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it("should recommend patch for mixed non-feature commits", async () => {
|
|
286
|
+
const commits = [
|
|
287
|
+
createMockCommit("chore", "update deps"),
|
|
288
|
+
createMockCommit("docs", "update docs"),
|
|
289
|
+
createMockCommit("style", "format"),
|
|
290
|
+
createMockCommit("test", "add tests"),
|
|
291
|
+
];
|
|
292
|
+
|
|
293
|
+
const result = await recommendBump(commits, config);
|
|
294
|
+
|
|
295
|
+
expect(result.releaseType).toBe("patch");
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it("should recommend patch for empty commit list", async () => {
|
|
299
|
+
const commits: Commit[] = [];
|
|
300
|
+
|
|
301
|
+
const result = await recommendBump(commits, config);
|
|
302
|
+
|
|
303
|
+
expect(result.releaseType).toBe("patch");
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
describe("generateChangelog", () => {
|
|
309
|
+
const mockCwd = fileURLToPath(
|
|
310
|
+
new URL("../../__fixtures__/yarn-basic", import.meta.url),
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
describe("single package scenarios", () => {
|
|
314
|
+
it("should generate changelog for first release with no previousTag", async () => {
|
|
315
|
+
const workspace = createMockWorkspace(mockCwd, {
|
|
316
|
+
name: "test-package",
|
|
317
|
+
version: "1.0.0",
|
|
318
|
+
repository: "https://github.com/org/repo",
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
const rawCommits = ["feat: initial feature implementation\n"];
|
|
322
|
+
const commits = await createMockCommits(rawCommits);
|
|
323
|
+
|
|
324
|
+
const expectedChangelog =
|
|
325
|
+
"## 1.0.0 (2025-01-15)\n\n### Features\n\n* initial feature implementation\n";
|
|
326
|
+
|
|
327
|
+
const changelog = await generateChangelog(
|
|
328
|
+
workspace,
|
|
329
|
+
workspace.pkg,
|
|
330
|
+
config,
|
|
331
|
+
null,
|
|
332
|
+
"v1.0.0",
|
|
333
|
+
commits,
|
|
334
|
+
"2025-01-15",
|
|
335
|
+
);
|
|
336
|
+
|
|
337
|
+
expect(changelog.length).toBeLessThan(1000);
|
|
338
|
+
expect(changelog).toBe(expectedChangelog);
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
it("should generate changelog for subsequent release with previousTag", async () => {
|
|
342
|
+
const workspace = createMockWorkspace(mockCwd, {
|
|
343
|
+
name: "test-package",
|
|
344
|
+
version: "1.1.0",
|
|
345
|
+
repository: "https://github.com/org/repo",
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
const rawCommits = ["feat: add new feature\n\nFeature description\n"];
|
|
349
|
+
const commits = await createMockCommits(rawCommits);
|
|
350
|
+
|
|
351
|
+
const expectedChangelog =
|
|
352
|
+
"## [1.1.0](https://github.com/org/repo/compare/v1.0.0...v1.1.0) (2025-01-15)\n\n### Features\n\n* add new feature\n";
|
|
353
|
+
|
|
354
|
+
const changelog = await generateChangelog(
|
|
355
|
+
workspace,
|
|
356
|
+
workspace.pkg,
|
|
357
|
+
config,
|
|
358
|
+
"v1.0.0",
|
|
359
|
+
"v1.1.0",
|
|
360
|
+
commits,
|
|
361
|
+
"2025-01-15",
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
expect(changelog.length).toBeLessThan(1000);
|
|
365
|
+
expect(changelog).toBe(expectedChangelog);
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
it("should include breaking changes in changelog", async () => {
|
|
369
|
+
const workspace = createMockWorkspace(mockCwd, {
|
|
370
|
+
name: "test-package",
|
|
371
|
+
version: "2.0.0",
|
|
372
|
+
repository: "https://github.com/org/repo",
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
const rawCommits = [
|
|
376
|
+
"feat!: breaking API change\n\nBREAKING CHANGE: API changed\n",
|
|
377
|
+
];
|
|
378
|
+
const commits = await createMockCommits(rawCommits);
|
|
379
|
+
|
|
380
|
+
const expectedChangelog =
|
|
381
|
+
"## [2.0.0](https://github.com/org/repo/compare/v1.0.0...v2.0.0) (2025-01-15)\n\n### ⚠ BREAKING CHANGES\n\n* API changed\n\n### Features\n\n* breaking API change\n";
|
|
382
|
+
|
|
383
|
+
const changelog = await generateChangelog(
|
|
384
|
+
workspace,
|
|
385
|
+
workspace.pkg,
|
|
386
|
+
config,
|
|
387
|
+
"v1.0.0",
|
|
388
|
+
"v2.0.0",
|
|
389
|
+
commits,
|
|
390
|
+
"2025-01-15",
|
|
391
|
+
);
|
|
392
|
+
|
|
393
|
+
expect(changelog.length).toBeLessThan(1000);
|
|
394
|
+
expect(changelog).toBe(expectedChangelog);
|
|
395
|
+
});
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
describe("monorepo scenarios", () => {
|
|
399
|
+
it("should generate changelog for monorepo package for first release", async () => {
|
|
400
|
+
const workspace = createMockWorkspace(mockCwd, {
|
|
401
|
+
name: "@test/package-a",
|
|
402
|
+
version: "1.0.0",
|
|
403
|
+
repository: {
|
|
404
|
+
type: "git",
|
|
405
|
+
url: "https://github.com/org/repo",
|
|
406
|
+
directory: "@test/package-a",
|
|
407
|
+
},
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
const rawCommits = ["fix(package-a): fix issue\n\n"];
|
|
411
|
+
const commits = await createMockCommits(rawCommits);
|
|
412
|
+
|
|
413
|
+
const expectedChangelog =
|
|
414
|
+
"## 1.0.0 (2025-01-15)\n\n### Bug Fixes\n\n* **package-a:** fix issue\n";
|
|
415
|
+
|
|
416
|
+
const changelog = await generateChangelog(
|
|
417
|
+
workspace,
|
|
418
|
+
workspace.pkg,
|
|
419
|
+
config,
|
|
420
|
+
null,
|
|
421
|
+
"@test/package-a@1.0.0",
|
|
422
|
+
commits,
|
|
423
|
+
"2025-01-15",
|
|
424
|
+
);
|
|
425
|
+
|
|
426
|
+
expect(changelog.length).toBeLessThan(1000);
|
|
427
|
+
expect(changelog).toBe(expectedChangelog);
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
it("should generate changelog for monorepo package for subsequent release", async () => {
|
|
431
|
+
const workspace = createMockWorkspace(mockCwd, {
|
|
432
|
+
name: "@test/package-a",
|
|
433
|
+
version: "1.1.0",
|
|
434
|
+
repository: "https://github.com/org/repo",
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
const rawCommits = ["fix(package-a): fix issue\n\n"];
|
|
438
|
+
const commits = await createMockCommits(rawCommits);
|
|
439
|
+
|
|
440
|
+
const expectedChangelog =
|
|
441
|
+
"## [1.1.0](https://github.com/org/repo/compare/@test/package-a@1.0.0...@test/package-a@1.1.0) (2025-01-15)\n\n### Bug Fixes\n\n* **package-a:** fix issue\n";
|
|
442
|
+
|
|
443
|
+
const changelog = await generateChangelog(
|
|
444
|
+
workspace,
|
|
445
|
+
workspace.pkg,
|
|
446
|
+
config,
|
|
447
|
+
"@test/package-a@1.0.0",
|
|
448
|
+
"@test/package-a@1.1.0",
|
|
449
|
+
commits,
|
|
450
|
+
"2025-01-15",
|
|
451
|
+
);
|
|
452
|
+
|
|
453
|
+
expect(changelog.length).toBeLessThan(1000);
|
|
454
|
+
expect(changelog).toBe(expectedChangelog);
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
it("should handle breaking change", async () => {
|
|
458
|
+
const workspace = createMockWorkspace(mockCwd, {
|
|
459
|
+
name: "@test/package-b",
|
|
460
|
+
version: "2.0.0",
|
|
461
|
+
repository: {
|
|
462
|
+
type: "git",
|
|
463
|
+
url: "https://github.com/org/repo",
|
|
464
|
+
directory: "@test/package-b",
|
|
465
|
+
},
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
const rawCommits = [
|
|
469
|
+
"feat(package-b)!: API changed\n\nBREAKING CHANGE: API changed\n",
|
|
470
|
+
];
|
|
471
|
+
const commits = await createMockCommits(rawCommits);
|
|
472
|
+
|
|
473
|
+
const expectedChangelog =
|
|
474
|
+
"## [2.0.0](https://github.com/org/repo/compare/@test/package-b@1.0.0...@test/package-b@2.0.0) (2025-01-15)\n\n### ⚠ BREAKING CHANGES\n\n* **package-b:** API changed\n\n### Features\n\n* **package-b:** API changed\n";
|
|
475
|
+
|
|
476
|
+
const changelog = await generateChangelog(
|
|
477
|
+
workspace,
|
|
478
|
+
workspace.pkg,
|
|
479
|
+
config,
|
|
480
|
+
"@test/package-b@1.0.0",
|
|
481
|
+
"@test/package-b@2.0.0",
|
|
482
|
+
commits,
|
|
483
|
+
"2025-01-15",
|
|
484
|
+
);
|
|
485
|
+
|
|
486
|
+
expect(changelog.length).toBeLessThan(1000);
|
|
487
|
+
expect(changelog).toBe(expectedChangelog);
|
|
488
|
+
});
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
describe("commit type scenarios", () => {
|
|
492
|
+
it("should format feat commits in changelog", async () => {
|
|
493
|
+
const workspace = createMockWorkspace(mockCwd, {
|
|
494
|
+
name: "test-package",
|
|
495
|
+
version: "1.1.0",
|
|
496
|
+
repository: "https://github.com/org/repo",
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
const rawCommits = [
|
|
500
|
+
"feat: add authentication\n\n",
|
|
501
|
+
"feat: add logging\n\n",
|
|
502
|
+
];
|
|
503
|
+
const commits = await createMockCommits(rawCommits);
|
|
504
|
+
|
|
505
|
+
const expectedChangelog =
|
|
506
|
+
"## [1.1.0](https://github.com/org/repo/compare/v1.0.0...v1.1.0) (2025-01-15)\n\n### Features\n\n* add authentication\n* add logging\n";
|
|
507
|
+
|
|
508
|
+
const changelog = await generateChangelog(
|
|
509
|
+
workspace,
|
|
510
|
+
workspace.pkg,
|
|
511
|
+
config,
|
|
512
|
+
"v1.0.0",
|
|
513
|
+
"v1.1.0",
|
|
514
|
+
commits,
|
|
515
|
+
"2025-01-15",
|
|
516
|
+
);
|
|
517
|
+
|
|
518
|
+
expect(changelog.length).toBeLessThan(1000);
|
|
519
|
+
expect(changelog).toBe(expectedChangelog);
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
it("should format fix commits in changelog", async () => {
|
|
523
|
+
const workspace = createMockWorkspace(mockCwd, {
|
|
524
|
+
name: "test-package",
|
|
525
|
+
version: "1.0.1",
|
|
526
|
+
repository: "https://github.com/org/repo",
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
const rawCommits = [
|
|
530
|
+
"fix: fix memory leak\n\n",
|
|
531
|
+
"fix: fix validation error\n\n",
|
|
532
|
+
];
|
|
533
|
+
const commits = await createMockCommits(rawCommits);
|
|
534
|
+
|
|
535
|
+
const expectedChangelog =
|
|
536
|
+
"## [1.0.1](https://github.com/org/repo/compare/v1.0.0...v1.0.1) (2025-01-15)\n\n### Bug Fixes\n\n* fix memory leak\n* fix validation error\n";
|
|
537
|
+
|
|
538
|
+
const changelog = await generateChangelog(
|
|
539
|
+
workspace,
|
|
540
|
+
workspace.pkg,
|
|
541
|
+
config,
|
|
542
|
+
"v1.0.0",
|
|
543
|
+
"v1.0.1",
|
|
544
|
+
commits,
|
|
545
|
+
"2025-01-15",
|
|
546
|
+
);
|
|
547
|
+
|
|
548
|
+
expect(changelog.length).toBeLessThan(1000);
|
|
549
|
+
expect(changelog).toBe(expectedChangelog);
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
it("should include scopes in changelog", async () => {
|
|
553
|
+
const workspace = createMockWorkspace(mockCwd, {
|
|
554
|
+
name: "test-package",
|
|
555
|
+
version: "1.1.0",
|
|
556
|
+
repository: "https://github.com/org/repo",
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
const rawCommits = [
|
|
560
|
+
"feat(api): add endpoint\n\n",
|
|
561
|
+
"feat(auth): add OAuth support\n\n",
|
|
562
|
+
];
|
|
563
|
+
const commits = await createMockCommits(rawCommits);
|
|
564
|
+
|
|
565
|
+
const expectedChangelog =
|
|
566
|
+
"## [1.1.0](https://github.com/org/repo/compare/v1.0.0...v1.1.0) (2025-01-15)\n\n### Features\n\n* **api:** add endpoint\n* **auth:** add OAuth support\n";
|
|
567
|
+
|
|
568
|
+
const changelog = await generateChangelog(
|
|
569
|
+
workspace,
|
|
570
|
+
workspace.pkg,
|
|
571
|
+
config,
|
|
572
|
+
"v1.0.0",
|
|
573
|
+
"v1.1.0",
|
|
574
|
+
commits,
|
|
575
|
+
"2025-01-15",
|
|
576
|
+
);
|
|
577
|
+
|
|
578
|
+
expect(changelog.length).toBeLessThan(1000);
|
|
579
|
+
expect(changelog).toBe(expectedChangelog);
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
it("should handle mixed commit types", async () => {
|
|
583
|
+
const workspace = createMockWorkspace(mockCwd, {
|
|
584
|
+
name: "test-package",
|
|
585
|
+
version: "1.1.0",
|
|
586
|
+
repository: "https://github.com/org/repo",
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
const rawCommits = [
|
|
590
|
+
"feat: add feature A\n\n",
|
|
591
|
+
"fix: fix bug B\n\n",
|
|
592
|
+
"perf: optimize query\n\n",
|
|
593
|
+
];
|
|
594
|
+
const commits = await createMockCommits(rawCommits);
|
|
595
|
+
|
|
596
|
+
const expectedChangelog =
|
|
597
|
+
"## [1.1.0](https://github.com/org/repo/compare/v1.0.0...v1.1.0) (2025-01-15)\n\n### Features\n\n* add feature A\n\n### Bug Fixes\n\n* fix bug B\n\n### Performance Improvements\n\n* optimize query\n";
|
|
598
|
+
|
|
599
|
+
const changelog = await generateChangelog(
|
|
600
|
+
workspace,
|
|
601
|
+
workspace.pkg,
|
|
602
|
+
config,
|
|
603
|
+
"v1.0.0",
|
|
604
|
+
"v1.1.0",
|
|
605
|
+
commits,
|
|
606
|
+
"2025-01-15",
|
|
607
|
+
);
|
|
608
|
+
|
|
609
|
+
expect(changelog.length).toBeLessThan(1000);
|
|
610
|
+
expect(changelog).toBe(expectedChangelog);
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
it("should handle perf commits", async () => {
|
|
614
|
+
const workspace = createMockWorkspace(mockCwd, {
|
|
615
|
+
name: "test-package",
|
|
616
|
+
version: "1.0.1",
|
|
617
|
+
repository: "https://github.com/org/repo",
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
const rawCommits = ["perf: optimize database queries\n\n"];
|
|
621
|
+
const commits = await createMockCommits(rawCommits);
|
|
622
|
+
|
|
623
|
+
const expectedChangelog =
|
|
624
|
+
"## [1.0.1](https://github.com/org/repo/compare/v1.0.0...v1.0.1) (2025-01-15)\n\n### Performance Improvements\n\n* optimize database queries\n";
|
|
625
|
+
|
|
626
|
+
const changelog = await generateChangelog(
|
|
627
|
+
workspace,
|
|
628
|
+
workspace.pkg,
|
|
629
|
+
config,
|
|
630
|
+
"v1.0.0",
|
|
631
|
+
"v1.0.1",
|
|
632
|
+
commits,
|
|
633
|
+
"2025-01-15",
|
|
634
|
+
);
|
|
635
|
+
|
|
636
|
+
expect(changelog.length).toBeLessThan(1000);
|
|
637
|
+
expect(changelog).toBe(expectedChangelog);
|
|
638
|
+
});
|
|
639
|
+
|
|
640
|
+
it("should exclude chore commits from changelog", async () => {
|
|
641
|
+
const workspace = createMockWorkspace(mockCwd, {
|
|
642
|
+
name: "test-package",
|
|
643
|
+
version: "1.1.0",
|
|
644
|
+
repository: "https://github.com/org/repo",
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
const rawCommits = [
|
|
648
|
+
"feat: add feature\n\n",
|
|
649
|
+
"chore: update dependencies\n\n",
|
|
650
|
+
];
|
|
651
|
+
const commits = await createMockCommits(rawCommits);
|
|
652
|
+
|
|
653
|
+
const expectedChangelog =
|
|
654
|
+
"## [1.1.0](https://github.com/org/repo/compare/v1.0.0...v1.1.0) (2025-01-15)\n\n### Features\n\n* add feature\n";
|
|
655
|
+
|
|
656
|
+
const changelog = await generateChangelog(
|
|
657
|
+
workspace,
|
|
658
|
+
workspace.pkg,
|
|
659
|
+
config,
|
|
660
|
+
"v1.0.0",
|
|
661
|
+
"v1.1.0",
|
|
662
|
+
commits,
|
|
663
|
+
"2025-01-15",
|
|
664
|
+
);
|
|
665
|
+
|
|
666
|
+
expect(changelog.length).toBeLessThan(1000);
|
|
667
|
+
expect(changelog).toBe(expectedChangelog);
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
it("should exclude non-changelog commit types", async () => {
|
|
671
|
+
const workspace = createMockWorkspace(mockCwd, {
|
|
672
|
+
name: "test-package",
|
|
673
|
+
version: "1.1.0",
|
|
674
|
+
repository: "https://github.com/org/repo",
|
|
675
|
+
});
|
|
676
|
+
|
|
677
|
+
const rawCommits = [
|
|
678
|
+
"feat: add feature\n\n",
|
|
679
|
+
"docs: update README\n\n",
|
|
680
|
+
"test: add tests\n\n",
|
|
681
|
+
"style: format code\n\n",
|
|
682
|
+
"build: update build\n\n",
|
|
683
|
+
"ci: update CI\n\n",
|
|
684
|
+
];
|
|
685
|
+
const commits = await createMockCommits(rawCommits);
|
|
686
|
+
|
|
687
|
+
const expectedChangelog =
|
|
688
|
+
"## [1.1.0](https://github.com/org/repo/compare/v1.0.0...v1.1.0) (2025-01-15)\n\n### Features\n\n* add feature\n";
|
|
689
|
+
|
|
690
|
+
const changelog = await generateChangelog(
|
|
691
|
+
workspace,
|
|
692
|
+
workspace.pkg,
|
|
693
|
+
config,
|
|
694
|
+
"v1.0.0",
|
|
695
|
+
"v1.1.0",
|
|
696
|
+
commits,
|
|
697
|
+
"2025-01-15",
|
|
698
|
+
);
|
|
699
|
+
|
|
700
|
+
expect(changelog.length).toBeLessThan(1000);
|
|
701
|
+
expect(changelog).toBe(expectedChangelog);
|
|
702
|
+
});
|
|
703
|
+
});
|
|
704
|
+
|
|
705
|
+
describe("multi-line descriptions", () => {
|
|
706
|
+
it("should handle commits with multi-line body", async () => {
|
|
707
|
+
const workspace = createMockWorkspace(mockCwd, {
|
|
708
|
+
name: "test-package",
|
|
709
|
+
version: "1.1.0",
|
|
710
|
+
repository: "https://github.com/org/repo",
|
|
711
|
+
});
|
|
712
|
+
|
|
713
|
+
const rawCommits = [
|
|
714
|
+
"feat: add authentication\n\nThis adds comprehensive authentication support\nincluding OAuth, JWT, and session management.\n",
|
|
715
|
+
];
|
|
716
|
+
const commits = await createMockCommits(rawCommits);
|
|
717
|
+
|
|
718
|
+
const expectedChangelog =
|
|
719
|
+
"## [1.1.0](https://github.com/org/repo/compare/v1.0.0...v1.1.0) (2025-01-15)\n\n### Features\n\n* add authentication\n";
|
|
720
|
+
|
|
721
|
+
const changelog = await generateChangelog(
|
|
722
|
+
workspace,
|
|
723
|
+
workspace.pkg,
|
|
724
|
+
config,
|
|
725
|
+
"v1.0.0",
|
|
726
|
+
"v1.1.0",
|
|
727
|
+
commits,
|
|
728
|
+
"2025-01-15",
|
|
729
|
+
);
|
|
730
|
+
|
|
731
|
+
expect(changelog.length).toBeLessThan(1000);
|
|
732
|
+
expect(changelog).toBe(expectedChangelog);
|
|
733
|
+
});
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
describe("edge cases", () => {
|
|
737
|
+
it("should handle empty changelog (no commits)", async () => {
|
|
738
|
+
const workspace = createMockWorkspace(mockCwd, {
|
|
739
|
+
name: "test-package",
|
|
740
|
+
version: "1.0.0",
|
|
741
|
+
repository: "https://github.com/org/repo",
|
|
742
|
+
});
|
|
743
|
+
|
|
744
|
+
const commits = await createMockCommits([]);
|
|
745
|
+
|
|
746
|
+
const expectedChangelog = "## 1.0.0 (2025-01-15)\n";
|
|
747
|
+
|
|
748
|
+
const changelog = await generateChangelog(
|
|
749
|
+
workspace,
|
|
750
|
+
workspace.pkg,
|
|
751
|
+
config,
|
|
752
|
+
null,
|
|
753
|
+
"v1.0.0",
|
|
754
|
+
commits,
|
|
755
|
+
"2025-01-15",
|
|
756
|
+
);
|
|
757
|
+
|
|
758
|
+
expect(changelog.length).toBeLessThan(1000);
|
|
759
|
+
expect(changelog).toBe(expectedChangelog);
|
|
760
|
+
});
|
|
761
|
+
});
|
|
762
|
+
});
|