fork-version 1.8.0 → 2.0.2
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/CHANGELOG.md +23 -0
- package/dist/{chunk-RLGF46N7.js → chunk-D2PQT6ZM.js} +806 -147
- package/dist/chunk-D2PQT6ZM.js.map +1 -0
- package/dist/{chunk-EAMGFCWC.cjs → chunk-RJRVHSEG.cjs} +808 -146
- package/dist/chunk-RJRVHSEG.cjs.map +1 -0
- package/dist/cli.cjs +14 -13
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +8 -7
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +27 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +400 -326
- package/dist/index.d.ts +400 -326
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +30 -31
- package/dist/chunk-EAMGFCWC.cjs.map +0 -1
- package/dist/chunk-RLGF46N7.js.map +0 -1
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var zod = require('zod');
|
|
4
|
+
var child_process = require('child_process');
|
|
5
|
+
var semver = require('semver');
|
|
4
6
|
var path = require('path');
|
|
5
7
|
var glob = require('glob');
|
|
6
8
|
var conventionalChangelogConfigSpec = require('conventional-changelog-config-spec');
|
|
7
|
-
var child_process = require('child_process');
|
|
8
9
|
var fs = require('fs');
|
|
9
10
|
var JoyCon = require('joycon');
|
|
10
11
|
var bundleRequire = require('bundle-require');
|
|
11
12
|
var jsoncParser = require('jsonc-parser');
|
|
12
13
|
var yaml = require('yaml');
|
|
13
14
|
var cheerio = require('cheerio/slim');
|
|
14
|
-
var semver = require('semver');
|
|
15
|
-
var conventionalRecommendedBump = require('conventional-recommended-bump');
|
|
16
15
|
var conventionalChangelog = require('conventional-changelog');
|
|
17
16
|
|
|
18
17
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -35,11 +34,10 @@ function _interopNamespace(e) {
|
|
|
35
34
|
return Object.freeze(n);
|
|
36
35
|
}
|
|
37
36
|
|
|
37
|
+
var semver__default = /*#__PURE__*/_interopDefault(semver);
|
|
38
38
|
var conventionalChangelogConfigSpec__default = /*#__PURE__*/_interopDefault(conventionalChangelogConfigSpec);
|
|
39
39
|
var JoyCon__default = /*#__PURE__*/_interopDefault(JoyCon);
|
|
40
40
|
var cheerio__namespace = /*#__PURE__*/_interopNamespace(cheerio);
|
|
41
|
-
var semver__default = /*#__PURE__*/_interopDefault(semver);
|
|
42
|
-
var conventionalRecommendedBump__default = /*#__PURE__*/_interopDefault(conventionalRecommendedBump);
|
|
43
41
|
var conventionalChangelog__default = /*#__PURE__*/_interopDefault(conventionalChangelog);
|
|
44
42
|
|
|
45
43
|
// src/config/schema.js
|
|
@@ -296,6 +294,303 @@ var ForkConfigSchema = zod.z.object({
|
|
|
296
294
|
*/
|
|
297
295
|
releaseMessageSuffix: zod.z.string().optional().describe("Add a suffix to the release commit message.")
|
|
298
296
|
});
|
|
297
|
+
var Git = class {
|
|
298
|
+
constructor(config) {
|
|
299
|
+
this.config = config;
|
|
300
|
+
this.add = this.add.bind(this);
|
|
301
|
+
this.commit = this.commit.bind(this);
|
|
302
|
+
this.tag = this.tag.bind(this);
|
|
303
|
+
this.log = this.log.bind(this);
|
|
304
|
+
this.isIgnored = this.isIgnored.bind(this);
|
|
305
|
+
this.getBranchName = this.getBranchName.bind(this);
|
|
306
|
+
this.getRemoteUrl = this.getRemoteUrl.bind(this);
|
|
307
|
+
this.getTags = this.getTags.bind(this);
|
|
308
|
+
this.getMostRecentTag = this.getMostRecentTag.bind(this);
|
|
309
|
+
this.getCleanedTags = this.getCleanedTags.bind(this);
|
|
310
|
+
this.getHighestSemverVersionFromTags = this.getHighestSemverVersionFromTags.bind(this);
|
|
311
|
+
this.getCommits = this.getCommits.bind(this);
|
|
312
|
+
}
|
|
313
|
+
async #execGit(command, args) {
|
|
314
|
+
return new Promise((onResolve, onReject) => {
|
|
315
|
+
child_process.execFile(
|
|
316
|
+
"git",
|
|
317
|
+
[command, ...args],
|
|
318
|
+
{
|
|
319
|
+
cwd: this.config.path,
|
|
320
|
+
maxBuffer: Infinity
|
|
321
|
+
},
|
|
322
|
+
(error, stdout, stderr) => {
|
|
323
|
+
if (error) {
|
|
324
|
+
onReject(error);
|
|
325
|
+
} else {
|
|
326
|
+
onResolve(stdout ? stdout : stderr);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
);
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Add file contents to the index
|
|
334
|
+
*
|
|
335
|
+
* [git-add Documentation](https://git-scm.com/docs/git-add)
|
|
336
|
+
*
|
|
337
|
+
* @example
|
|
338
|
+
* ```ts
|
|
339
|
+
* await git.add("CHANGELOG.md");
|
|
340
|
+
* ```
|
|
341
|
+
*/
|
|
342
|
+
async add(...args) {
|
|
343
|
+
if (this.config.dryRun) {
|
|
344
|
+
return "";
|
|
345
|
+
}
|
|
346
|
+
return this.#execGit("add", args.filter(Boolean));
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Record changes to the repository
|
|
350
|
+
*
|
|
351
|
+
* [git-commit Documentation](https://git-scm.com/docs/git-commit)
|
|
352
|
+
*
|
|
353
|
+
* @example
|
|
354
|
+
* ```ts
|
|
355
|
+
* await git.commit("--message", "chore(release): 1.2.3");
|
|
356
|
+
* ```
|
|
357
|
+
*/
|
|
358
|
+
async commit(...args) {
|
|
359
|
+
if (this.config.dryRun) {
|
|
360
|
+
return "";
|
|
361
|
+
}
|
|
362
|
+
return this.#execGit("commit", args.filter(Boolean));
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Create, list, delete or verify a tag object
|
|
366
|
+
*
|
|
367
|
+
* [git-tag Documentation](https://git-scm.com/docs/git-tag)
|
|
368
|
+
*
|
|
369
|
+
* @example
|
|
370
|
+
* ```ts
|
|
371
|
+
* await git.tag("--annotate", "v1.2.3", "--message", "chore(release): 1.2.3");
|
|
372
|
+
* ```
|
|
373
|
+
*/
|
|
374
|
+
async tag(...args) {
|
|
375
|
+
if (this.config.dryRun) {
|
|
376
|
+
return "";
|
|
377
|
+
}
|
|
378
|
+
return this.#execGit("tag", args.filter(Boolean));
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Show commit logs
|
|
382
|
+
*
|
|
383
|
+
* - [git-log Documentation](https://git-scm.com/docs/git-log)
|
|
384
|
+
* - [pretty-formats Documentation](https://git-scm.com/docs/pretty-formats)
|
|
385
|
+
*
|
|
386
|
+
* @example
|
|
387
|
+
* ```ts
|
|
388
|
+
* await git.log("--oneline");
|
|
389
|
+
* ```
|
|
390
|
+
*/
|
|
391
|
+
async log(...args) {
|
|
392
|
+
try {
|
|
393
|
+
return await this.#execGit("log", args.filter(Boolean));
|
|
394
|
+
} catch {
|
|
395
|
+
return "";
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Check if a file is ignored by git
|
|
400
|
+
*
|
|
401
|
+
* [git-check-ignore Documentation](https://git-scm.com/docs/git-check-ignore)
|
|
402
|
+
*
|
|
403
|
+
* @example
|
|
404
|
+
* ```ts
|
|
405
|
+
* await git.isIgnored("src/my-file.txt");
|
|
406
|
+
* ```
|
|
407
|
+
*/
|
|
408
|
+
async isIgnored(file) {
|
|
409
|
+
try {
|
|
410
|
+
await this.#execGit("check-ignore", ["--no-index", file]);
|
|
411
|
+
return true;
|
|
412
|
+
} catch (_error) {
|
|
413
|
+
return false;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Get the name of the current branch
|
|
418
|
+
*
|
|
419
|
+
* [git-rev-parse Documentation](https://git-scm.com/docs/git-rev-parse)
|
|
420
|
+
*
|
|
421
|
+
* @example
|
|
422
|
+
* ```ts
|
|
423
|
+
* await git.getBranchName(); // "main"
|
|
424
|
+
* ```
|
|
425
|
+
*/
|
|
426
|
+
async getBranchName() {
|
|
427
|
+
try {
|
|
428
|
+
const branchName = await this.#execGit("rev-parse", ["--abbrev-ref", "HEAD"]);
|
|
429
|
+
return branchName.trim();
|
|
430
|
+
} catch {
|
|
431
|
+
return "";
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Get the URL of the remote repository
|
|
436
|
+
*
|
|
437
|
+
* [git-config Documentation](https://git-scm.com/docs/git-config)
|
|
438
|
+
*
|
|
439
|
+
* @example
|
|
440
|
+
* ```ts
|
|
441
|
+
* await git.getRemoteUrl(); // "https://github.com/eglavin/fork-version"
|
|
442
|
+
* ```
|
|
443
|
+
*/
|
|
444
|
+
async getRemoteUrl() {
|
|
445
|
+
try {
|
|
446
|
+
const remoteUrl = await this.#execGit("config", ["--get", "remote.origin.url"]);
|
|
447
|
+
return remoteUrl.trim();
|
|
448
|
+
} catch (_error) {
|
|
449
|
+
return "";
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* `getTags` returns valid semver version tags in order of the commit history
|
|
454
|
+
*
|
|
455
|
+
* Using `git log` to get the commit history, we then parse the tags from the
|
|
456
|
+
* commit details which is expected to be in the following format:
|
|
457
|
+
* ```txt
|
|
458
|
+
* commit 3841b1d05750d42197fe958e3d8e06df378a842d (HEAD -> main, tag: v1.0.2, tag: v1.0.1, tag: v1.0.0)
|
|
459
|
+
* Author: Username <username@example.com>
|
|
460
|
+
* Date: Sat Nov 9 15:00:00 2024 +0000
|
|
461
|
+
*
|
|
462
|
+
* chore(release): v1.0.0
|
|
463
|
+
* ```
|
|
464
|
+
*
|
|
465
|
+
* - [Functionality extracted from the conventional-changelog - git-semver-tags project](https://github.com/conventional-changelog/conventional-changelog/blob/fac8045242099c016f5f3905e54e02b7d466bd7b/packages/git-semver-tags/index.js)
|
|
466
|
+
* - [conventional-changelog git-semver-tags MIT Licence](https://github.com/conventional-changelog/conventional-changelog/blob/fac8045242099c016f5f3905e54e02b7d466bd7b/packages/git-semver-tags/LICENSE.md)
|
|
467
|
+
*
|
|
468
|
+
* @example
|
|
469
|
+
* ```ts
|
|
470
|
+
* await git.getTags("v"); // ["v1.0.2", "v1.0.1", "v1.0.0"]
|
|
471
|
+
* ```
|
|
472
|
+
*/
|
|
473
|
+
async getTags(tagPrefix) {
|
|
474
|
+
const logOutput = await this.log("--decorate", "--no-color", "--date-order");
|
|
475
|
+
const TAG_REGEX = /tag:\s*(?<tag>.+?)[,)]/gi;
|
|
476
|
+
const tags = [];
|
|
477
|
+
let tagMatch = null;
|
|
478
|
+
while (tagMatch = TAG_REGEX.exec(logOutput)) {
|
|
479
|
+
const { tag = "" } = tagMatch.groups ?? {};
|
|
480
|
+
if (tagPrefix) {
|
|
481
|
+
if (tag.startsWith(tagPrefix)) {
|
|
482
|
+
const tagWithoutPrefix = tag.replace(new RegExp(`^${tagPrefix}`), "");
|
|
483
|
+
if (semver__default.default.valid(tagWithoutPrefix)) {
|
|
484
|
+
tags.push(tag);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
} else if (/^\d/.test(tag) && semver__default.default.valid(tag)) {
|
|
488
|
+
tags.push(tag);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return tags;
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Returns the latest git tag based on commit date
|
|
495
|
+
*
|
|
496
|
+
* @example
|
|
497
|
+
* ```ts
|
|
498
|
+
* await git.getMostRecentTag("v"); // "1.2.3"
|
|
499
|
+
* ```
|
|
500
|
+
*/
|
|
501
|
+
async getMostRecentTag(tagPrefix) {
|
|
502
|
+
const tags = await this.getTags(tagPrefix);
|
|
503
|
+
return tags[0] || void 0;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Get cleaned semver tags, with any tag prefix's removed
|
|
507
|
+
*
|
|
508
|
+
* @example
|
|
509
|
+
* ```ts
|
|
510
|
+
* await git.getCleanedTags("v"); // ["1.2.3", "1.2.2", "1.2.1"]
|
|
511
|
+
* ```
|
|
512
|
+
*/
|
|
513
|
+
async getCleanedTags(tagPrefix) {
|
|
514
|
+
const tags = await this.getTags(tagPrefix);
|
|
515
|
+
const cleanedTags = [];
|
|
516
|
+
for (const tag of tags) {
|
|
517
|
+
const tagWithoutPrefix = tag.replace(new RegExp(`^${tagPrefix}`), "");
|
|
518
|
+
const cleanedTag = semver__default.default.clean(tagWithoutPrefix);
|
|
519
|
+
if (cleanedTag) {
|
|
520
|
+
cleanedTags.push(cleanedTag);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
return cleanedTags;
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Get the highest semver version from git tags. This will return the highest
|
|
527
|
+
* semver version found for the given tag prefix, regardless of the commit date.
|
|
528
|
+
*
|
|
529
|
+
* @example
|
|
530
|
+
* ```ts
|
|
531
|
+
* await git.getHighestSemverVersionFromTags("v"); // "1.2.3"
|
|
532
|
+
* ```
|
|
533
|
+
*/
|
|
534
|
+
async getHighestSemverVersionFromTags(tagPrefix) {
|
|
535
|
+
const cleanedTags = await this.getCleanedTags(tagPrefix);
|
|
536
|
+
return cleanedTags.sort(semver__default.default.rcompare)[0] || void 0;
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Get commit history in a parsable format
|
|
540
|
+
*
|
|
541
|
+
* An array of strings with commit details is returned in the following format:
|
|
542
|
+
* ```txt
|
|
543
|
+
* subject
|
|
544
|
+
* body
|
|
545
|
+
* hash
|
|
546
|
+
* committer date
|
|
547
|
+
* committer name
|
|
548
|
+
* committer email
|
|
549
|
+
* ```
|
|
550
|
+
*
|
|
551
|
+
* @example
|
|
552
|
+
* ```ts
|
|
553
|
+
* await git.getCommits("v1.0.0", "HEAD", "src/utils");
|
|
554
|
+
* ```
|
|
555
|
+
*/
|
|
556
|
+
async getCommits(from = "", to = "HEAD", ...paths) {
|
|
557
|
+
const SCISSOR = "^----------- FORK VERSION -----------^";
|
|
558
|
+
const LOG_FORMAT = [
|
|
559
|
+
"%s",
|
|
560
|
+
// subject
|
|
561
|
+
"%b",
|
|
562
|
+
// body
|
|
563
|
+
"%H",
|
|
564
|
+
// hash
|
|
565
|
+
"%cI",
|
|
566
|
+
// committer date
|
|
567
|
+
"%cN",
|
|
568
|
+
// committer name
|
|
569
|
+
"%cE",
|
|
570
|
+
// committer email
|
|
571
|
+
SCISSOR
|
|
572
|
+
].join("%n");
|
|
573
|
+
const commits = await this.log(
|
|
574
|
+
`--format=${LOG_FORMAT}`,
|
|
575
|
+
[from, to].filter(Boolean).join(".."),
|
|
576
|
+
paths.length ? "--" : "",
|
|
577
|
+
...paths
|
|
578
|
+
);
|
|
579
|
+
const splitCommits = commits.split(`
|
|
580
|
+
${SCISSOR}
|
|
581
|
+
`);
|
|
582
|
+
if (splitCommits.length === 0) {
|
|
583
|
+
return splitCommits;
|
|
584
|
+
}
|
|
585
|
+
if (splitCommits[0] === SCISSOR) {
|
|
586
|
+
splitCommits.shift();
|
|
587
|
+
}
|
|
588
|
+
if (splitCommits[splitCommits.length - 1] === "") {
|
|
589
|
+
splitCommits.pop();
|
|
590
|
+
}
|
|
591
|
+
return splitCommits;
|
|
592
|
+
}
|
|
593
|
+
};
|
|
299
594
|
function getChangelogPresetConfig(mergedConfig, cliArguments, detectedGitHost) {
|
|
300
595
|
const preset = {
|
|
301
596
|
name: "conventionalcommits"
|
|
@@ -399,12 +694,13 @@ All notable changes to this project will be documented in this file. See [fork-v
|
|
|
399
694
|
skipTag: false,
|
|
400
695
|
changelogPresetConfig: {}
|
|
401
696
|
};
|
|
697
|
+
|
|
698
|
+
// src/config/detect-git-host.ts
|
|
402
699
|
async function detectGitHost(cwd) {
|
|
403
|
-
const remoteUrl = await new
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
});
|
|
700
|
+
const remoteUrl = await new Git({
|
|
701
|
+
path: cwd,
|
|
702
|
+
dryRun: false
|
|
703
|
+
}).getRemoteUrl();
|
|
408
704
|
if (remoteUrl.startsWith("https://") && remoteUrl.includes("@dev.azure.com/")) {
|
|
409
705
|
const match = /^https:\/\/(?<atorganisation>.*?)@dev.azure.com\/(?<organisation>.*?)\/(?<project>.*?)\/_git\/(?<repository>.*?)(?:\.git)?$/.exec(
|
|
410
706
|
remoteUrl
|
|
@@ -873,131 +1169,481 @@ var FileManager = class {
|
|
|
873
1169
|
this.logger.error(`[File Manager] Unsupported file: ${fileState.path}`);
|
|
874
1170
|
}
|
|
875
1171
|
};
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
1172
|
+
|
|
1173
|
+
// src/utils/trim-string-array.ts
|
|
1174
|
+
function trimStringArray(array) {
|
|
1175
|
+
const items = [];
|
|
1176
|
+
if (Array.isArray(array)) {
|
|
1177
|
+
for (const item of array) {
|
|
1178
|
+
const _item = item.trim();
|
|
1179
|
+
if (_item) {
|
|
1180
|
+
items.push(_item);
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
886
1183
|
}
|
|
887
|
-
|
|
888
|
-
return
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
1184
|
+
if (items.length === 0) {
|
|
1185
|
+
return void 0;
|
|
1186
|
+
}
|
|
1187
|
+
return items;
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
// src/commit-parser/options.ts
|
|
1191
|
+
function createParserOptions(userOptions) {
|
|
1192
|
+
const referenceActions = trimStringArray(userOptions?.referenceActions) ?? [
|
|
1193
|
+
"close",
|
|
1194
|
+
"closes",
|
|
1195
|
+
"closed",
|
|
1196
|
+
"fix",
|
|
1197
|
+
"fixes",
|
|
1198
|
+
"fixed",
|
|
1199
|
+
"resolve",
|
|
1200
|
+
"resolves",
|
|
1201
|
+
"resolved"
|
|
1202
|
+
];
|
|
1203
|
+
const joinedReferenceActions = referenceActions.join("|");
|
|
1204
|
+
const issuePrefixes = trimStringArray(userOptions?.issuePrefixes) ?? ["#"];
|
|
1205
|
+
const joinedIssuePrefixes = issuePrefixes.join("|");
|
|
1206
|
+
const noteKeywords = trimStringArray(userOptions?.noteKeywords) ?? [
|
|
1207
|
+
"BREAKING CHANGE",
|
|
1208
|
+
"BREAKING-CHANGE"
|
|
1209
|
+
];
|
|
1210
|
+
const joinedNoteKeywords = noteKeywords.join("|");
|
|
1211
|
+
return {
|
|
1212
|
+
subjectPattern: /^(?<type>\w+)(?:\((?<scope>.*)\))?(?<breakingChange>!)?:\s+(?<title>.*)/,
|
|
1213
|
+
mergePattern: /^Merge pull request #(?<id>\d*) from (?<source>.*)/,
|
|
1214
|
+
revertPattern: /^[Rr]evert "(?<subject>.*)"(\s*This reverts commit (?<hash>[a-zA-Z0-9]*)\.)?/,
|
|
1215
|
+
commentPattern: /^#(?!\d+\s)/,
|
|
1216
|
+
mentionPattern: /(?<!\w)@(?<username>[\w-]+)/,
|
|
1217
|
+
referenceActions,
|
|
1218
|
+
referenceActionPattern: joinedReferenceActions ? new RegExp(
|
|
1219
|
+
`(?<action>${joinedReferenceActions})(?:\\s+(?<reference>.*?))(?=(?:${joinedReferenceActions})|$)`
|
|
1220
|
+
) : void 0,
|
|
1221
|
+
issuePrefixes,
|
|
1222
|
+
issuePattern: joinedIssuePrefixes ? new RegExp(
|
|
1223
|
+
`(?:.*?)??\\s*(?<repository>[\\w-\\.\\/]*?)??(?<prefix>${joinedIssuePrefixes})(?<issue>[\\w-]*\\d+)`
|
|
1224
|
+
) : void 0,
|
|
1225
|
+
noteKeywords,
|
|
1226
|
+
notePattern: joinedNoteKeywords ? new RegExp(`^(?<title>${joinedNoteKeywords}):(\\s*(?<text>.*))`) : void 0,
|
|
1227
|
+
// Override defaults with user options
|
|
1228
|
+
...userOptions
|
|
1229
|
+
};
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
// src/commit-parser/parser-error.ts
|
|
1233
|
+
var ParserError = class extends Error {
|
|
1234
|
+
detail;
|
|
1235
|
+
constructor(message, detail) {
|
|
1236
|
+
super(message);
|
|
1237
|
+
this.name = "ParserError";
|
|
1238
|
+
this.detail = detail;
|
|
1239
|
+
}
|
|
1240
|
+
};
|
|
1241
|
+
|
|
1242
|
+
// src/commit-parser/commit-parser.ts
|
|
1243
|
+
var CommitParser = class {
|
|
1244
|
+
#options;
|
|
1245
|
+
#logger;
|
|
1246
|
+
constructor(userOptions) {
|
|
1247
|
+
this.#options = createParserOptions(userOptions);
|
|
1248
|
+
this.setLogger = this.setLogger.bind(this);
|
|
1249
|
+
this.createCommit = this.createCommit.bind(this);
|
|
1250
|
+
this.parseRawCommit = this.parseRawCommit.bind(this);
|
|
1251
|
+
this.parseSubject = this.parseSubject.bind(this);
|
|
1252
|
+
this.parseMerge = this.parseMerge.bind(this);
|
|
1253
|
+
this.parseRevert = this.parseRevert.bind(this);
|
|
1254
|
+
this.parseMentions = this.parseMentions.bind(this);
|
|
1255
|
+
this.parseReferenceParts = this.parseReferenceParts.bind(this);
|
|
1256
|
+
this.parseReferences = this.parseReferences.bind(this);
|
|
1257
|
+
this.parseNotes = this.parseNotes.bind(this);
|
|
1258
|
+
this.parseRawLines = this.parseRawLines.bind(this);
|
|
1259
|
+
this.parse = this.parse.bind(this);
|
|
1260
|
+
}
|
|
1261
|
+
setLogger(logger) {
|
|
1262
|
+
this.#logger = logger;
|
|
1263
|
+
return this;
|
|
1264
|
+
}
|
|
1265
|
+
createCommit() {
|
|
1266
|
+
return {
|
|
1267
|
+
raw: "",
|
|
1268
|
+
subject: "",
|
|
1269
|
+
body: "",
|
|
1270
|
+
hash: "",
|
|
1271
|
+
date: "",
|
|
1272
|
+
name: "",
|
|
1273
|
+
email: "",
|
|
1274
|
+
type: "",
|
|
1275
|
+
scope: "",
|
|
1276
|
+
breakingChange: "",
|
|
1277
|
+
title: "",
|
|
1278
|
+
merge: null,
|
|
1279
|
+
revert: null,
|
|
1280
|
+
notes: [],
|
|
1281
|
+
mentions: [],
|
|
1282
|
+
references: []
|
|
1283
|
+
};
|
|
905
1284
|
}
|
|
906
1285
|
/**
|
|
907
|
-
*
|
|
1286
|
+
* Parse the raw commit message into its expected parts
|
|
1287
|
+
* - subject
|
|
1288
|
+
* - body
|
|
1289
|
+
* - hash
|
|
1290
|
+
* - date
|
|
1291
|
+
* - name
|
|
1292
|
+
* - email
|
|
1293
|
+
*
|
|
1294
|
+
* @throws {ParserError}
|
|
908
1295
|
*/
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
1296
|
+
parseRawCommit(rawCommit) {
|
|
1297
|
+
const parsedCommit = this.createCommit();
|
|
1298
|
+
const parts = rawCommit.split(/\r?\n/);
|
|
1299
|
+
if (parts.length < 6) {
|
|
1300
|
+
throw new ParserError("Commit doesn't contain enough parts", rawCommit);
|
|
1301
|
+
}
|
|
1302
|
+
const email = parts.pop();
|
|
1303
|
+
const name = parts.pop();
|
|
1304
|
+
const date = parts.pop();
|
|
1305
|
+
const hash = parts.pop();
|
|
1306
|
+
if (email) parsedCommit.email = email.trim();
|
|
1307
|
+
if (name) parsedCommit.name = name.trim();
|
|
1308
|
+
if (date) {
|
|
1309
|
+
parsedCommit.date = date.trim();
|
|
1310
|
+
if (Number.isNaN(Date.parse(parsedCommit.date))) {
|
|
1311
|
+
throw new ParserError("Unable to parse commit date", rawCommit);
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
if (hash) parsedCommit.hash = hash.trim();
|
|
1315
|
+
const subject = parts.shift()?.trimStart();
|
|
1316
|
+
if (subject) {
|
|
1317
|
+
parsedCommit.subject = subject;
|
|
1318
|
+
parsedCommit.raw = subject;
|
|
912
1319
|
}
|
|
913
|
-
|
|
1320
|
+
parsedCommit.body = parts.filter((line) => {
|
|
1321
|
+
if (this.#options.commentPattern) {
|
|
1322
|
+
return !this.#options.commentPattern.test(line.trim());
|
|
1323
|
+
}
|
|
1324
|
+
return true;
|
|
1325
|
+
}).join("\n").trim();
|
|
1326
|
+
const raw = parts.join("\n").trim();
|
|
1327
|
+
if (raw) parsedCommit.raw += "\n" + raw;
|
|
1328
|
+
return parsedCommit;
|
|
914
1329
|
}
|
|
915
1330
|
/**
|
|
916
|
-
*
|
|
1331
|
+
* Parse the commit subject into its expected parts
|
|
1332
|
+
* - type
|
|
1333
|
+
* - scope (optional)
|
|
1334
|
+
* - breaking change (optional)
|
|
1335
|
+
* - title
|
|
1336
|
+
*
|
|
1337
|
+
* @throws {ParserError}
|
|
917
1338
|
*/
|
|
918
|
-
|
|
919
|
-
if (this.
|
|
920
|
-
|
|
1339
|
+
parseSubject(commit) {
|
|
1340
|
+
if (!this.#options.subjectPattern) return false;
|
|
1341
|
+
const subjectMatch = new RegExp(this.#options.subjectPattern, "i").exec(commit.subject);
|
|
1342
|
+
if (subjectMatch?.groups) {
|
|
1343
|
+
const { type = "", scope = "", breakingChange = "", title = "" } = subjectMatch.groups;
|
|
1344
|
+
if (!type || !title) {
|
|
1345
|
+
throw new ParserError("Unable to parse commit subject", commit);
|
|
1346
|
+
}
|
|
1347
|
+
commit.type = type;
|
|
1348
|
+
commit.scope = scope;
|
|
1349
|
+
if (breakingChange) commit.breakingChange = breakingChange;
|
|
1350
|
+
commit.title = title;
|
|
1351
|
+
return true;
|
|
921
1352
|
}
|
|
922
|
-
return
|
|
1353
|
+
return false;
|
|
923
1354
|
}
|
|
924
1355
|
/**
|
|
925
|
-
*
|
|
1356
|
+
* Parse merge information from the commit subject
|
|
1357
|
+
* @example
|
|
1358
|
+
* ```txt
|
|
1359
|
+
* "Merge pull request #123 from fork-version/feature"
|
|
1360
|
+
* ```
|
|
926
1361
|
*/
|
|
927
|
-
|
|
928
|
-
if (this.
|
|
929
|
-
|
|
1362
|
+
parseMerge(commit) {
|
|
1363
|
+
if (!this.#options.mergePattern) return false;
|
|
1364
|
+
const mergeMatch = new RegExp(this.#options.mergePattern).exec(commit.subject);
|
|
1365
|
+
if (mergeMatch?.groups) {
|
|
1366
|
+
const { id = "", source = "" } = mergeMatch.groups;
|
|
1367
|
+
commit.merge = {
|
|
1368
|
+
id,
|
|
1369
|
+
source
|
|
1370
|
+
};
|
|
1371
|
+
return true;
|
|
930
1372
|
}
|
|
931
|
-
return
|
|
1373
|
+
return false;
|
|
932
1374
|
}
|
|
933
1375
|
/**
|
|
934
|
-
*
|
|
1376
|
+
* Parse revert information from the commit body
|
|
1377
|
+
* @example
|
|
1378
|
+
* ```txt
|
|
1379
|
+
* "Revert "feat: initial commit"
|
|
1380
|
+
*
|
|
1381
|
+
* This reverts commit 4a79e9e546b4020d2882b7810dc549fa71960f4f."
|
|
1382
|
+
* ```
|
|
935
1383
|
*/
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
1384
|
+
parseRevert(commit) {
|
|
1385
|
+
if (!this.#options.revertPattern) return false;
|
|
1386
|
+
const revertMatch = new RegExp(this.#options.revertPattern).exec(commit.raw);
|
|
1387
|
+
if (revertMatch?.groups) {
|
|
1388
|
+
const { hash = "", subject = "" } = revertMatch.groups;
|
|
1389
|
+
commit.revert = {
|
|
1390
|
+
hash,
|
|
1391
|
+
subject
|
|
1392
|
+
};
|
|
939
1393
|
return true;
|
|
940
|
-
} catch (_error) {
|
|
941
|
-
return false;
|
|
942
1394
|
}
|
|
1395
|
+
return false;
|
|
943
1396
|
}
|
|
944
|
-
|
|
945
|
-
|
|
1397
|
+
/**
|
|
1398
|
+
* Search for mentions from the commit line
|
|
1399
|
+
* @example
|
|
1400
|
+
* ```txt
|
|
1401
|
+
* "@fork-version"
|
|
1402
|
+
* ```
|
|
1403
|
+
*/
|
|
1404
|
+
parseMentions(line, outMentions) {
|
|
1405
|
+
if (!this.#options.mentionPattern) return false;
|
|
1406
|
+
const mentionRegex = new RegExp(this.#options.mentionPattern, "g");
|
|
1407
|
+
let foundMention = false;
|
|
1408
|
+
let mentionMatch;
|
|
1409
|
+
while (mentionMatch = mentionRegex.exec(line)) {
|
|
1410
|
+
if (!mentionMatch) {
|
|
1411
|
+
break;
|
|
1412
|
+
}
|
|
1413
|
+
const { username = "" } = mentionMatch.groups ?? {};
|
|
1414
|
+
outMentions.add(username);
|
|
1415
|
+
foundMention = true;
|
|
1416
|
+
}
|
|
1417
|
+
return foundMention;
|
|
946
1418
|
}
|
|
947
1419
|
/**
|
|
948
|
-
*
|
|
949
|
-
*
|
|
950
|
-
* Using `git log` to get the commit history, we then parse the tags from the
|
|
951
|
-
* commit details which is expected to be in the following format:
|
|
1420
|
+
* Search for references from the commit line
|
|
952
1421
|
* @example
|
|
953
1422
|
* ```txt
|
|
954
|
-
*
|
|
955
|
-
*
|
|
956
|
-
* Date: Sat Nov 9 15:00:00 2024 +0000
|
|
957
|
-
*
|
|
958
|
-
* chore(release): 1.2.3
|
|
1423
|
+
* "#1234"
|
|
1424
|
+
* "owner/repo#1234"
|
|
959
1425
|
* ```
|
|
960
|
-
*
|
|
961
|
-
* - [Functionality extracted from the conventional-changelog - git-semver-tags project](https://github.com/conventional-changelog/conventional-changelog/blob/fac8045242099c016f5f3905e54e02b7d466bd7b/packages/git-semver-tags/index.js)
|
|
962
|
-
* - [conventional-changelog git-semver-tags MIT Licence](https://github.com/conventional-changelog/conventional-changelog/blob/fac8045242099c016f5f3905e54e02b7d466bd7b/packages/git-semver-tags/LICENSE.md)
|
|
963
1426
|
*/
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
const
|
|
967
|
-
const
|
|
968
|
-
let
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
1427
|
+
parseReferenceParts(referenceText, action) {
|
|
1428
|
+
if (!this.#options.issuePattern) return void 0;
|
|
1429
|
+
const references = [];
|
|
1430
|
+
const issueRegex = new RegExp(this.#options.issuePattern, "gi");
|
|
1431
|
+
let issueMatch;
|
|
1432
|
+
while (issueMatch = issueRegex.exec(referenceText)) {
|
|
1433
|
+
if (!issueMatch) {
|
|
1434
|
+
break;
|
|
1435
|
+
}
|
|
1436
|
+
const { repository = "", prefix = "", issue = "" } = issueMatch.groups ?? {};
|
|
1437
|
+
const reference = {
|
|
1438
|
+
prefix,
|
|
1439
|
+
issue,
|
|
1440
|
+
action,
|
|
1441
|
+
owner: null,
|
|
1442
|
+
repository: null
|
|
1443
|
+
};
|
|
1444
|
+
if (repository) {
|
|
1445
|
+
const slashIndex = repository.indexOf("/");
|
|
1446
|
+
if (slashIndex !== -1) {
|
|
1447
|
+
reference.owner = repository.slice(0, slashIndex);
|
|
1448
|
+
reference.repository = repository.slice(slashIndex + 1);
|
|
1449
|
+
} else {
|
|
1450
|
+
reference.repository = repository;
|
|
983
1451
|
}
|
|
984
1452
|
}
|
|
1453
|
+
references.push(reference);
|
|
985
1454
|
}
|
|
986
|
-
|
|
1455
|
+
if (references.length > 0) {
|
|
1456
|
+
return references;
|
|
1457
|
+
}
|
|
1458
|
+
return void 0;
|
|
987
1459
|
}
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
1460
|
+
/**
|
|
1461
|
+
* Search for actions and references from the commit line
|
|
1462
|
+
* @example
|
|
1463
|
+
* ```txt
|
|
1464
|
+
* "Closes #1234"
|
|
1465
|
+
* "fixes owner/repo#1234"
|
|
1466
|
+
* ```
|
|
1467
|
+
*/
|
|
1468
|
+
parseReferences(line, outReferences) {
|
|
1469
|
+
if (!this.#options.referenceActionPattern || !this.#options.issuePattern) return false;
|
|
1470
|
+
const referenceActionRegex = new RegExp(this.#options.referenceActionPattern, "gi").test(line) ? new RegExp(this.#options.referenceActionPattern, "gi") : /(?<reference>.*)/g;
|
|
1471
|
+
let foundReference = false;
|
|
1472
|
+
let referenceActionMatch;
|
|
1473
|
+
while (referenceActionMatch = referenceActionRegex.exec(line)) {
|
|
1474
|
+
if (!referenceActionMatch) {
|
|
1475
|
+
break;
|
|
1476
|
+
}
|
|
1477
|
+
const { action = "", reference = "" } = referenceActionMatch.groups ?? {};
|
|
1478
|
+
const parsedReferences = this.parseReferenceParts(reference, action || null);
|
|
1479
|
+
if (!parsedReferences) {
|
|
1480
|
+
break;
|
|
1481
|
+
}
|
|
1482
|
+
for (const ref of parsedReferences) {
|
|
1483
|
+
if (!outReferences.some((r) => r.prefix === ref.prefix && r.issue === ref.issue)) {
|
|
1484
|
+
outReferences.push(ref);
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
foundReference = true;
|
|
1488
|
+
}
|
|
1489
|
+
return foundReference;
|
|
1490
|
+
}
|
|
1491
|
+
/**
|
|
1492
|
+
* Search for notes from the commit line
|
|
1493
|
+
* @example
|
|
1494
|
+
* ```txt
|
|
1495
|
+
* "BREAKING CHANGE: this is a breaking change"
|
|
1496
|
+
* ```
|
|
1497
|
+
*/
|
|
1498
|
+
parseNotes(line, outNotes) {
|
|
1499
|
+
if (!this.#options.notePattern) return false;
|
|
1500
|
+
const noteMatch = new RegExp(this.#options.notePattern, "ig").exec(line);
|
|
1501
|
+
if (noteMatch?.groups) {
|
|
1502
|
+
const { title = "", text = "" } = noteMatch.groups;
|
|
1503
|
+
outNotes.push({
|
|
1504
|
+
title,
|
|
1505
|
+
text
|
|
1506
|
+
});
|
|
1507
|
+
return true;
|
|
1508
|
+
}
|
|
1509
|
+
return false;
|
|
1510
|
+
}
|
|
1511
|
+
/**
|
|
1512
|
+
* Parse the raw commit for mentions, references and notes
|
|
1513
|
+
*/
|
|
1514
|
+
parseRawLines(commit) {
|
|
1515
|
+
const mentions = /* @__PURE__ */ new Set();
|
|
1516
|
+
const references = [];
|
|
1517
|
+
const notes = [];
|
|
1518
|
+
let lastNoteLine = -1;
|
|
1519
|
+
const splitMessage = commit.raw.split("\n");
|
|
1520
|
+
for (let index = 0; index < splitMessage.length; index++) {
|
|
1521
|
+
const line = splitMessage[index];
|
|
1522
|
+
const trimmedLine = line.trim();
|
|
1523
|
+
if (this.#options.commentPattern?.test(trimmedLine)) {
|
|
1524
|
+
continue;
|
|
1525
|
+
}
|
|
1526
|
+
this.parseMentions(trimmedLine, mentions);
|
|
1527
|
+
const foundReference = this.parseReferences(trimmedLine, references);
|
|
1528
|
+
if (foundReference) {
|
|
1529
|
+
lastNoteLine = -1;
|
|
1530
|
+
continue;
|
|
1531
|
+
}
|
|
1532
|
+
if (this.parseNotes(trimmedLine, notes)) {
|
|
1533
|
+
lastNoteLine = index;
|
|
1534
|
+
} else if (lastNoteLine !== -1) {
|
|
1535
|
+
notes[notes.length - 1].text += `
|
|
1536
|
+
${line}`;
|
|
1537
|
+
lastNoteLine = index;
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
if (mentions.size > 0) {
|
|
1541
|
+
commit.mentions = Array.from(mentions);
|
|
1542
|
+
}
|
|
1543
|
+
if (references.length > 0) {
|
|
1544
|
+
commit.references = references;
|
|
1545
|
+
}
|
|
1546
|
+
if (notes.length > 0) {
|
|
1547
|
+
commit.notes = notes.map((note) => ({
|
|
1548
|
+
...note,
|
|
1549
|
+
text: note.text.trim()
|
|
1550
|
+
}));
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
/**
|
|
1554
|
+
* Parse a commit log with the following format separated by new line characters:
|
|
1555
|
+
* ```txt
|
|
1556
|
+
* refactor: add test file
|
|
1557
|
+
* Add a test file to the project
|
|
1558
|
+
* 4ef2c86d393a9660aa9f753144256b1f200c16bd
|
|
1559
|
+
* 2024-12-22T17:36:50Z
|
|
1560
|
+
* Fork Version
|
|
1561
|
+
* fork-version@example.com
|
|
1562
|
+
* ```
|
|
1563
|
+
*
|
|
1564
|
+
* @example
|
|
1565
|
+
* ```ts
|
|
1566
|
+
* parse("refactor: add test file\nAdd a test file to the project\n4ef2c86d393a9660aa9f753144256b1f200c16bd\n2024-12-22T17:36:50Z\nFork Version\nfork-version@example.com");
|
|
1567
|
+
* ```
|
|
1568
|
+
*
|
|
1569
|
+
* The expected input value can be generated by running the following command:
|
|
1570
|
+
* ```sh
|
|
1571
|
+
* git log --format="%s%n%b%n%H%n%cI%n%cN%n%cE%n"
|
|
1572
|
+
* ```
|
|
1573
|
+
* @see {@link https://git-scm.com/docs/pretty-formats|Git Pretty Format Documentation}
|
|
1574
|
+
*/
|
|
1575
|
+
parse(rawCommit) {
|
|
1576
|
+
try {
|
|
1577
|
+
const commit = this.parseRawCommit(rawCommit);
|
|
1578
|
+
this.parseSubject(commit);
|
|
1579
|
+
this.parseMerge(commit);
|
|
1580
|
+
this.parseRevert(commit);
|
|
1581
|
+
this.parseRawLines(commit);
|
|
1582
|
+
return commit;
|
|
1583
|
+
} catch (error) {
|
|
1584
|
+
if (this.#logger) {
|
|
1585
|
+
this.#logger.debug("[Commit Parser] Failed to parse commit", { error });
|
|
996
1586
|
}
|
|
1587
|
+
return void 0;
|
|
997
1588
|
}
|
|
998
|
-
return cleanedTags.sort(semver__default.default.rcompare)[0];
|
|
999
1589
|
}
|
|
1000
1590
|
};
|
|
1591
|
+
|
|
1592
|
+
// src/commit-parser/filter-reverted-commits.ts
|
|
1593
|
+
function filterRevertedCommits(parsedCommits) {
|
|
1594
|
+
const revertedCommits = [];
|
|
1595
|
+
for (const commit of parsedCommits) {
|
|
1596
|
+
if (!commit.revert) continue;
|
|
1597
|
+
if (revertedCommits.some(
|
|
1598
|
+
(r) => r.revert?.hash === commit.hash || r.revert?.subject === commit.subject
|
|
1599
|
+
)) {
|
|
1600
|
+
continue;
|
|
1601
|
+
}
|
|
1602
|
+
revertedCommits.push(commit);
|
|
1603
|
+
}
|
|
1604
|
+
if (revertedCommits.length === 0) {
|
|
1605
|
+
return parsedCommits;
|
|
1606
|
+
}
|
|
1607
|
+
const commitsWithoutReverts = [];
|
|
1608
|
+
for (const commit of parsedCommits) {
|
|
1609
|
+
if (commit.revert) continue;
|
|
1610
|
+
const revertedIndex = revertedCommits.findIndex(
|
|
1611
|
+
(r) => r.revert?.hash === commit.hash || r.revert?.subject === commit.subject
|
|
1612
|
+
);
|
|
1613
|
+
if (revertedIndex !== -1) {
|
|
1614
|
+
revertedCommits.splice(revertedIndex, 1);
|
|
1615
|
+
continue;
|
|
1616
|
+
}
|
|
1617
|
+
commitsWithoutReverts.push(commit);
|
|
1618
|
+
}
|
|
1619
|
+
return commitsWithoutReverts;
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
// src/process/get-commits.ts
|
|
1623
|
+
async function getCommitsSinceTag(config, logger, git) {
|
|
1624
|
+
const commitParser = new CommitParser();
|
|
1625
|
+
if (config.debug) commitParser.setLogger(logger);
|
|
1626
|
+
const latestTag = await git.getMostRecentTag(config.tagPrefix);
|
|
1627
|
+
if (!latestTag) {
|
|
1628
|
+
logger.warn("No previous tag found, using all commits");
|
|
1629
|
+
}
|
|
1630
|
+
const foundCommits = await git.getCommits(latestTag, "HEAD");
|
|
1631
|
+
logger.debug(`Found ${foundCommits.length} commits since last tag (${latestTag ?? "none"})`);
|
|
1632
|
+
const commits = foundCommits.reduce((acc, commit) => {
|
|
1633
|
+
const parsed = commitParser.parse(commit);
|
|
1634
|
+
if (parsed) {
|
|
1635
|
+
acc.push(parsed);
|
|
1636
|
+
}
|
|
1637
|
+
return acc;
|
|
1638
|
+
}, []);
|
|
1639
|
+
logger.debug(`Parsed ${commits.length} commits after applying commit parser`);
|
|
1640
|
+
const filteredCommits = filterRevertedCommits(commits);
|
|
1641
|
+
logger.debug(`Filtered to ${filteredCommits.length} commits after removing reverts`);
|
|
1642
|
+
return {
|
|
1643
|
+
latestTag,
|
|
1644
|
+
commits: filteredCommits
|
|
1645
|
+
};
|
|
1646
|
+
}
|
|
1001
1647
|
function getPriority(type) {
|
|
1002
1648
|
return ["patch", "minor", "major"].indexOf(type ?? "");
|
|
1003
1649
|
}
|
|
@@ -1047,7 +1693,7 @@ async function getCurrentVersion(config, logger, git, fileManager, filesToUpdate
|
|
|
1047
1693
|
versions.add(config.currentVersion);
|
|
1048
1694
|
}
|
|
1049
1695
|
if (versions.size === 0 && config.gitTagFallback) {
|
|
1050
|
-
const version = await git.
|
|
1696
|
+
const version = await git.getHighestSemverVersionFromTags(config.tagPrefix);
|
|
1051
1697
|
if (version) {
|
|
1052
1698
|
logger.warn(`Using latest git tag as fallback`);
|
|
1053
1699
|
versions.add(version);
|
|
@@ -1074,65 +1720,77 @@ async function getCurrentVersion(config, logger, git, fileManager, filesToUpdate
|
|
|
1074
1720
|
version: currentVersion
|
|
1075
1721
|
};
|
|
1076
1722
|
}
|
|
1077
|
-
async function getNextVersion(config, logger, currentVersion) {
|
|
1723
|
+
async function getNextVersion(config, logger, commits, currentVersion) {
|
|
1078
1724
|
if (config.skipBump) {
|
|
1079
1725
|
logger.warn(`Skip bump, using ${currentVersion} as the next version`);
|
|
1080
1726
|
return {
|
|
1081
1727
|
version: currentVersion
|
|
1082
1728
|
};
|
|
1083
1729
|
}
|
|
1084
|
-
if (config.nextVersion
|
|
1730
|
+
if (config.nextVersion) {
|
|
1731
|
+
if (!semver__default.default.valid(config.nextVersion)) {
|
|
1732
|
+
throw new Error(`Invalid Version: ${config.nextVersion}`);
|
|
1733
|
+
}
|
|
1085
1734
|
logger.log(`Next version: ${config.nextVersion}`);
|
|
1086
1735
|
return {
|
|
1087
1736
|
version: config.nextVersion
|
|
1088
1737
|
};
|
|
1089
1738
|
}
|
|
1090
1739
|
const isPreMajor = semver__default.default.lt(currentVersion, "1.0.0");
|
|
1091
|
-
let
|
|
1740
|
+
let releaseType = "patch";
|
|
1741
|
+
const changes = { major: 0, minor: 0, patch: 0 };
|
|
1092
1742
|
if (config.releaseAs) {
|
|
1093
|
-
|
|
1094
|
-
releaseType: config.releaseAs,
|
|
1095
|
-
level: -1,
|
|
1096
|
-
reason: "User defined"
|
|
1097
|
-
};
|
|
1743
|
+
releaseType = config.releaseAs;
|
|
1098
1744
|
} else {
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1745
|
+
let level = 2;
|
|
1746
|
+
const MINOR_TYPES = ["feat", "feature"];
|
|
1747
|
+
for (const commit of commits) {
|
|
1748
|
+
if (commit.notes.length > 0 || commit.breakingChange) {
|
|
1749
|
+
changes.major += commit.notes.length + (commit.breakingChange ? 1 : 0);
|
|
1750
|
+
level = 0;
|
|
1751
|
+
} else if (MINOR_TYPES.includes(commit.type.toLowerCase())) {
|
|
1752
|
+
changes.minor += 1;
|
|
1753
|
+
if (level === 2) {
|
|
1754
|
+
level = 1;
|
|
1755
|
+
}
|
|
1756
|
+
} else {
|
|
1757
|
+
changes.patch += 1;
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
if (isPreMajor && level < 2) {
|
|
1761
|
+
level++;
|
|
1762
|
+
changes.patch += changes.minor;
|
|
1763
|
+
changes.minor = changes.major;
|
|
1764
|
+
changes.major = 0;
|
|
1765
|
+
}
|
|
1766
|
+
if (level === 0) {
|
|
1767
|
+
releaseType = "major";
|
|
1768
|
+
} else if (level === 1) {
|
|
1769
|
+
releaseType = "minor";
|
|
1770
|
+
} else {
|
|
1771
|
+
releaseType = "patch";
|
|
1114
1772
|
}
|
|
1115
1773
|
}
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1774
|
+
const releaseTypeOrPreRelease = getReleaseType(releaseType, currentVersion, config.preRelease);
|
|
1775
|
+
const nextVersion = semver__default.default.inc(
|
|
1776
|
+
currentVersion,
|
|
1777
|
+
releaseTypeOrPreRelease,
|
|
1778
|
+
typeof config.preRelease === "string" ? config.preRelease : ""
|
|
1779
|
+
) ?? "";
|
|
1780
|
+
logger.log(`Next version: ${nextVersion} (${releaseTypeOrPreRelease})`);
|
|
1781
|
+
if (commits.length > 0) {
|
|
1782
|
+
logger.log(
|
|
1783
|
+
` - Commits: ${commits.length}` + (changes.major > 0 ? `, Breaking Changes: ${changes.major}` : "") + (changes.minor > 0 ? `, New Features: ${changes.minor}` : "") + (changes.patch > 0 ? `, Bug Fixes: ${changes.patch}` : "")
|
|
1121
1784
|
);
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
releaseType,
|
|
1125
|
-
typeof config.preRelease === "string" ? config.preRelease : void 0
|
|
1126
|
-
) ?? "";
|
|
1127
|
-
logger.log(`Next version: ${nextVersion} (${releaseType})`);
|
|
1128
|
-
return {
|
|
1129
|
-
...recommendedBump,
|
|
1130
|
-
preMajor: isPreMajor,
|
|
1131
|
-
releaseType,
|
|
1132
|
-
version: nextVersion
|
|
1133
|
-
};
|
|
1785
|
+
} else {
|
|
1786
|
+
logger.log(" - No commits found.");
|
|
1134
1787
|
}
|
|
1135
|
-
|
|
1788
|
+
return {
|
|
1789
|
+
version: nextVersion,
|
|
1790
|
+
releaseType: releaseTypeOrPreRelease,
|
|
1791
|
+
preMajor: isPreMajor,
|
|
1792
|
+
changes
|
|
1793
|
+
};
|
|
1136
1794
|
}
|
|
1137
1795
|
var RELEASE_PATTERN = /(^#+ \[?[0-9]+\.[0-9]+\.[0-9]+|<a name=)/m;
|
|
1138
1796
|
function getOldReleaseContent(filePath, exists) {
|
|
@@ -1261,15 +1919,19 @@ async function tagChanges(config, logger, git, nextVersion) {
|
|
|
1261
1919
|
);
|
|
1262
1920
|
}
|
|
1263
1921
|
|
|
1922
|
+
exports.CommitParser = CommitParser;
|
|
1264
1923
|
exports.FileManager = FileManager;
|
|
1265
1924
|
exports.ForkConfigSchema = ForkConfigSchema;
|
|
1266
1925
|
exports.Git = Git;
|
|
1267
1926
|
exports.Logger = Logger;
|
|
1268
1927
|
exports.commitChanges = commitChanges;
|
|
1928
|
+
exports.createParserOptions = createParserOptions;
|
|
1929
|
+
exports.filterRevertedCommits = filterRevertedCommits;
|
|
1930
|
+
exports.getCommitsSinceTag = getCommitsSinceTag;
|
|
1269
1931
|
exports.getCurrentVersion = getCurrentVersion;
|
|
1270
1932
|
exports.getNextVersion = getNextVersion;
|
|
1271
1933
|
exports.getUserConfig = getUserConfig;
|
|
1272
1934
|
exports.tagChanges = tagChanges;
|
|
1273
1935
|
exports.updateChangelog = updateChangelog;
|
|
1274
|
-
//# sourceMappingURL=chunk-
|
|
1275
|
-
//# sourceMappingURL=chunk-
|
|
1936
|
+
//# sourceMappingURL=chunk-RJRVHSEG.cjs.map
|
|
1937
|
+
//# sourceMappingURL=chunk-RJRVHSEG.cjs.map
|