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,16 +1,15 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
2
|
+
import { execFile } from 'child_process';
|
|
3
|
+
import semver from 'semver';
|
|
4
|
+
import { resolve, parse } from 'path';
|
|
3
5
|
import { glob } from 'glob';
|
|
4
6
|
import conventionalChangelogConfigSpec from 'conventional-changelog-config-spec';
|
|
5
|
-
import {
|
|
6
|
-
import { writeFileSync, readFileSync, lstatSync } from 'node:fs';
|
|
7
|
+
import { writeFileSync, readFileSync, lstatSync } from 'fs';
|
|
7
8
|
import JoyCon from 'joycon';
|
|
8
9
|
import { bundleRequire } from 'bundle-require';
|
|
9
10
|
import { modify, applyEdits, parse as parse$1 } from 'jsonc-parser';
|
|
10
11
|
import { parse as parse$2, parseDocument } from 'yaml';
|
|
11
12
|
import * as cheerio from 'cheerio/slim';
|
|
12
|
-
import semver from 'semver';
|
|
13
|
-
import conventionalRecommendedBump from 'conventional-recommended-bump';
|
|
14
13
|
import conventionalChangelog from 'conventional-changelog';
|
|
15
14
|
|
|
16
15
|
// src/config/schema.js
|
|
@@ -267,6 +266,303 @@ var ForkConfigSchema = z.object({
|
|
|
267
266
|
*/
|
|
268
267
|
releaseMessageSuffix: z.string().optional().describe("Add a suffix to the release commit message.")
|
|
269
268
|
});
|
|
269
|
+
var Git = class {
|
|
270
|
+
constructor(config) {
|
|
271
|
+
this.config = config;
|
|
272
|
+
this.add = this.add.bind(this);
|
|
273
|
+
this.commit = this.commit.bind(this);
|
|
274
|
+
this.tag = this.tag.bind(this);
|
|
275
|
+
this.log = this.log.bind(this);
|
|
276
|
+
this.isIgnored = this.isIgnored.bind(this);
|
|
277
|
+
this.getBranchName = this.getBranchName.bind(this);
|
|
278
|
+
this.getRemoteUrl = this.getRemoteUrl.bind(this);
|
|
279
|
+
this.getTags = this.getTags.bind(this);
|
|
280
|
+
this.getMostRecentTag = this.getMostRecentTag.bind(this);
|
|
281
|
+
this.getCleanedTags = this.getCleanedTags.bind(this);
|
|
282
|
+
this.getHighestSemverVersionFromTags = this.getHighestSemverVersionFromTags.bind(this);
|
|
283
|
+
this.getCommits = this.getCommits.bind(this);
|
|
284
|
+
}
|
|
285
|
+
async #execGit(command, args) {
|
|
286
|
+
return new Promise((onResolve, onReject) => {
|
|
287
|
+
execFile(
|
|
288
|
+
"git",
|
|
289
|
+
[command, ...args],
|
|
290
|
+
{
|
|
291
|
+
cwd: this.config.path,
|
|
292
|
+
maxBuffer: Infinity
|
|
293
|
+
},
|
|
294
|
+
(error, stdout, stderr) => {
|
|
295
|
+
if (error) {
|
|
296
|
+
onReject(error);
|
|
297
|
+
} else {
|
|
298
|
+
onResolve(stdout ? stdout : stderr);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
);
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Add file contents to the index
|
|
306
|
+
*
|
|
307
|
+
* [git-add Documentation](https://git-scm.com/docs/git-add)
|
|
308
|
+
*
|
|
309
|
+
* @example
|
|
310
|
+
* ```ts
|
|
311
|
+
* await git.add("CHANGELOG.md");
|
|
312
|
+
* ```
|
|
313
|
+
*/
|
|
314
|
+
async add(...args) {
|
|
315
|
+
if (this.config.dryRun) {
|
|
316
|
+
return "";
|
|
317
|
+
}
|
|
318
|
+
return this.#execGit("add", args.filter(Boolean));
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Record changes to the repository
|
|
322
|
+
*
|
|
323
|
+
* [git-commit Documentation](https://git-scm.com/docs/git-commit)
|
|
324
|
+
*
|
|
325
|
+
* @example
|
|
326
|
+
* ```ts
|
|
327
|
+
* await git.commit("--message", "chore(release): 1.2.3");
|
|
328
|
+
* ```
|
|
329
|
+
*/
|
|
330
|
+
async commit(...args) {
|
|
331
|
+
if (this.config.dryRun) {
|
|
332
|
+
return "";
|
|
333
|
+
}
|
|
334
|
+
return this.#execGit("commit", args.filter(Boolean));
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Create, list, delete or verify a tag object
|
|
338
|
+
*
|
|
339
|
+
* [git-tag Documentation](https://git-scm.com/docs/git-tag)
|
|
340
|
+
*
|
|
341
|
+
* @example
|
|
342
|
+
* ```ts
|
|
343
|
+
* await git.tag("--annotate", "v1.2.3", "--message", "chore(release): 1.2.3");
|
|
344
|
+
* ```
|
|
345
|
+
*/
|
|
346
|
+
async tag(...args) {
|
|
347
|
+
if (this.config.dryRun) {
|
|
348
|
+
return "";
|
|
349
|
+
}
|
|
350
|
+
return this.#execGit("tag", args.filter(Boolean));
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Show commit logs
|
|
354
|
+
*
|
|
355
|
+
* - [git-log Documentation](https://git-scm.com/docs/git-log)
|
|
356
|
+
* - [pretty-formats Documentation](https://git-scm.com/docs/pretty-formats)
|
|
357
|
+
*
|
|
358
|
+
* @example
|
|
359
|
+
* ```ts
|
|
360
|
+
* await git.log("--oneline");
|
|
361
|
+
* ```
|
|
362
|
+
*/
|
|
363
|
+
async log(...args) {
|
|
364
|
+
try {
|
|
365
|
+
return await this.#execGit("log", args.filter(Boolean));
|
|
366
|
+
} catch {
|
|
367
|
+
return "";
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Check if a file is ignored by git
|
|
372
|
+
*
|
|
373
|
+
* [git-check-ignore Documentation](https://git-scm.com/docs/git-check-ignore)
|
|
374
|
+
*
|
|
375
|
+
* @example
|
|
376
|
+
* ```ts
|
|
377
|
+
* await git.isIgnored("src/my-file.txt");
|
|
378
|
+
* ```
|
|
379
|
+
*/
|
|
380
|
+
async isIgnored(file) {
|
|
381
|
+
try {
|
|
382
|
+
await this.#execGit("check-ignore", ["--no-index", file]);
|
|
383
|
+
return true;
|
|
384
|
+
} catch (_error) {
|
|
385
|
+
return false;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Get the name of the current branch
|
|
390
|
+
*
|
|
391
|
+
* [git-rev-parse Documentation](https://git-scm.com/docs/git-rev-parse)
|
|
392
|
+
*
|
|
393
|
+
* @example
|
|
394
|
+
* ```ts
|
|
395
|
+
* await git.getBranchName(); // "main"
|
|
396
|
+
* ```
|
|
397
|
+
*/
|
|
398
|
+
async getBranchName() {
|
|
399
|
+
try {
|
|
400
|
+
const branchName = await this.#execGit("rev-parse", ["--abbrev-ref", "HEAD"]);
|
|
401
|
+
return branchName.trim();
|
|
402
|
+
} catch {
|
|
403
|
+
return "";
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Get the URL of the remote repository
|
|
408
|
+
*
|
|
409
|
+
* [git-config Documentation](https://git-scm.com/docs/git-config)
|
|
410
|
+
*
|
|
411
|
+
* @example
|
|
412
|
+
* ```ts
|
|
413
|
+
* await git.getRemoteUrl(); // "https://github.com/eglavin/fork-version"
|
|
414
|
+
* ```
|
|
415
|
+
*/
|
|
416
|
+
async getRemoteUrl() {
|
|
417
|
+
try {
|
|
418
|
+
const remoteUrl = await this.#execGit("config", ["--get", "remote.origin.url"]);
|
|
419
|
+
return remoteUrl.trim();
|
|
420
|
+
} catch (_error) {
|
|
421
|
+
return "";
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* `getTags` returns valid semver version tags in order of the commit history
|
|
426
|
+
*
|
|
427
|
+
* Using `git log` to get the commit history, we then parse the tags from the
|
|
428
|
+
* commit details which is expected to be in the following format:
|
|
429
|
+
* ```txt
|
|
430
|
+
* commit 3841b1d05750d42197fe958e3d8e06df378a842d (HEAD -> main, tag: v1.0.2, tag: v1.0.1, tag: v1.0.0)
|
|
431
|
+
* Author: Username <username@example.com>
|
|
432
|
+
* Date: Sat Nov 9 15:00:00 2024 +0000
|
|
433
|
+
*
|
|
434
|
+
* chore(release): v1.0.0
|
|
435
|
+
* ```
|
|
436
|
+
*
|
|
437
|
+
* - [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)
|
|
438
|
+
* - [conventional-changelog git-semver-tags MIT Licence](https://github.com/conventional-changelog/conventional-changelog/blob/fac8045242099c016f5f3905e54e02b7d466bd7b/packages/git-semver-tags/LICENSE.md)
|
|
439
|
+
*
|
|
440
|
+
* @example
|
|
441
|
+
* ```ts
|
|
442
|
+
* await git.getTags("v"); // ["v1.0.2", "v1.0.1", "v1.0.0"]
|
|
443
|
+
* ```
|
|
444
|
+
*/
|
|
445
|
+
async getTags(tagPrefix) {
|
|
446
|
+
const logOutput = await this.log("--decorate", "--no-color", "--date-order");
|
|
447
|
+
const TAG_REGEX = /tag:\s*(?<tag>.+?)[,)]/gi;
|
|
448
|
+
const tags = [];
|
|
449
|
+
let tagMatch = null;
|
|
450
|
+
while (tagMatch = TAG_REGEX.exec(logOutput)) {
|
|
451
|
+
const { tag = "" } = tagMatch.groups ?? {};
|
|
452
|
+
if (tagPrefix) {
|
|
453
|
+
if (tag.startsWith(tagPrefix)) {
|
|
454
|
+
const tagWithoutPrefix = tag.replace(new RegExp(`^${tagPrefix}`), "");
|
|
455
|
+
if (semver.valid(tagWithoutPrefix)) {
|
|
456
|
+
tags.push(tag);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
} else if (/^\d/.test(tag) && semver.valid(tag)) {
|
|
460
|
+
tags.push(tag);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
return tags;
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Returns the latest git tag based on commit date
|
|
467
|
+
*
|
|
468
|
+
* @example
|
|
469
|
+
* ```ts
|
|
470
|
+
* await git.getMostRecentTag("v"); // "1.2.3"
|
|
471
|
+
* ```
|
|
472
|
+
*/
|
|
473
|
+
async getMostRecentTag(tagPrefix) {
|
|
474
|
+
const tags = await this.getTags(tagPrefix);
|
|
475
|
+
return tags[0] || void 0;
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Get cleaned semver tags, with any tag prefix's removed
|
|
479
|
+
*
|
|
480
|
+
* @example
|
|
481
|
+
* ```ts
|
|
482
|
+
* await git.getCleanedTags("v"); // ["1.2.3", "1.2.2", "1.2.1"]
|
|
483
|
+
* ```
|
|
484
|
+
*/
|
|
485
|
+
async getCleanedTags(tagPrefix) {
|
|
486
|
+
const tags = await this.getTags(tagPrefix);
|
|
487
|
+
const cleanedTags = [];
|
|
488
|
+
for (const tag of tags) {
|
|
489
|
+
const tagWithoutPrefix = tag.replace(new RegExp(`^${tagPrefix}`), "");
|
|
490
|
+
const cleanedTag = semver.clean(tagWithoutPrefix);
|
|
491
|
+
if (cleanedTag) {
|
|
492
|
+
cleanedTags.push(cleanedTag);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
return cleanedTags;
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Get the highest semver version from git tags. This will return the highest
|
|
499
|
+
* semver version found for the given tag prefix, regardless of the commit date.
|
|
500
|
+
*
|
|
501
|
+
* @example
|
|
502
|
+
* ```ts
|
|
503
|
+
* await git.getHighestSemverVersionFromTags("v"); // "1.2.3"
|
|
504
|
+
* ```
|
|
505
|
+
*/
|
|
506
|
+
async getHighestSemverVersionFromTags(tagPrefix) {
|
|
507
|
+
const cleanedTags = await this.getCleanedTags(tagPrefix);
|
|
508
|
+
return cleanedTags.sort(semver.rcompare)[0] || void 0;
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Get commit history in a parsable format
|
|
512
|
+
*
|
|
513
|
+
* An array of strings with commit details is returned in the following format:
|
|
514
|
+
* ```txt
|
|
515
|
+
* subject
|
|
516
|
+
* body
|
|
517
|
+
* hash
|
|
518
|
+
* committer date
|
|
519
|
+
* committer name
|
|
520
|
+
* committer email
|
|
521
|
+
* ```
|
|
522
|
+
*
|
|
523
|
+
* @example
|
|
524
|
+
* ```ts
|
|
525
|
+
* await git.getCommits("v1.0.0", "HEAD", "src/utils");
|
|
526
|
+
* ```
|
|
527
|
+
*/
|
|
528
|
+
async getCommits(from = "", to = "HEAD", ...paths) {
|
|
529
|
+
const SCISSOR = "^----------- FORK VERSION -----------^";
|
|
530
|
+
const LOG_FORMAT = [
|
|
531
|
+
"%s",
|
|
532
|
+
// subject
|
|
533
|
+
"%b",
|
|
534
|
+
// body
|
|
535
|
+
"%H",
|
|
536
|
+
// hash
|
|
537
|
+
"%cI",
|
|
538
|
+
// committer date
|
|
539
|
+
"%cN",
|
|
540
|
+
// committer name
|
|
541
|
+
"%cE",
|
|
542
|
+
// committer email
|
|
543
|
+
SCISSOR
|
|
544
|
+
].join("%n");
|
|
545
|
+
const commits = await this.log(
|
|
546
|
+
`--format=${LOG_FORMAT}`,
|
|
547
|
+
[from, to].filter(Boolean).join(".."),
|
|
548
|
+
paths.length ? "--" : "",
|
|
549
|
+
...paths
|
|
550
|
+
);
|
|
551
|
+
const splitCommits = commits.split(`
|
|
552
|
+
${SCISSOR}
|
|
553
|
+
`);
|
|
554
|
+
if (splitCommits.length === 0) {
|
|
555
|
+
return splitCommits;
|
|
556
|
+
}
|
|
557
|
+
if (splitCommits[0] === SCISSOR) {
|
|
558
|
+
splitCommits.shift();
|
|
559
|
+
}
|
|
560
|
+
if (splitCommits[splitCommits.length - 1] === "") {
|
|
561
|
+
splitCommits.pop();
|
|
562
|
+
}
|
|
563
|
+
return splitCommits;
|
|
564
|
+
}
|
|
565
|
+
};
|
|
270
566
|
function getChangelogPresetConfig(mergedConfig, cliArguments, detectedGitHost) {
|
|
271
567
|
const preset = {
|
|
272
568
|
name: "conventionalcommits"
|
|
@@ -370,12 +666,13 @@ All notable changes to this project will be documented in this file. See [fork-v
|
|
|
370
666
|
skipTag: false,
|
|
371
667
|
changelogPresetConfig: {}
|
|
372
668
|
};
|
|
669
|
+
|
|
670
|
+
// src/config/detect-git-host.ts
|
|
373
671
|
async function detectGitHost(cwd) {
|
|
374
|
-
const remoteUrl = await new
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
});
|
|
672
|
+
const remoteUrl = await new Git({
|
|
673
|
+
path: cwd,
|
|
674
|
+
dryRun: false
|
|
675
|
+
}).getRemoteUrl();
|
|
379
676
|
if (remoteUrl.startsWith("https://") && remoteUrl.includes("@dev.azure.com/")) {
|
|
380
677
|
const match = /^https:\/\/(?<atorganisation>.*?)@dev.azure.com\/(?<organisation>.*?)\/(?<project>.*?)\/_git\/(?<repository>.*?)(?:\.git)?$/.exec(
|
|
381
678
|
remoteUrl
|
|
@@ -844,131 +1141,481 @@ var FileManager = class {
|
|
|
844
1141
|
this.logger.error(`[File Manager] Unsupported file: ${fileState.path}`);
|
|
845
1142
|
}
|
|
846
1143
|
};
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
1144
|
+
|
|
1145
|
+
// src/utils/trim-string-array.ts
|
|
1146
|
+
function trimStringArray(array) {
|
|
1147
|
+
const items = [];
|
|
1148
|
+
if (Array.isArray(array)) {
|
|
1149
|
+
for (const item of array) {
|
|
1150
|
+
const _item = item.trim();
|
|
1151
|
+
if (_item) {
|
|
1152
|
+
items.push(_item);
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
857
1155
|
}
|
|
858
|
-
|
|
859
|
-
return
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
1156
|
+
if (items.length === 0) {
|
|
1157
|
+
return void 0;
|
|
1158
|
+
}
|
|
1159
|
+
return items;
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
// src/commit-parser/options.ts
|
|
1163
|
+
function createParserOptions(userOptions) {
|
|
1164
|
+
const referenceActions = trimStringArray(userOptions?.referenceActions) ?? [
|
|
1165
|
+
"close",
|
|
1166
|
+
"closes",
|
|
1167
|
+
"closed",
|
|
1168
|
+
"fix",
|
|
1169
|
+
"fixes",
|
|
1170
|
+
"fixed",
|
|
1171
|
+
"resolve",
|
|
1172
|
+
"resolves",
|
|
1173
|
+
"resolved"
|
|
1174
|
+
];
|
|
1175
|
+
const joinedReferenceActions = referenceActions.join("|");
|
|
1176
|
+
const issuePrefixes = trimStringArray(userOptions?.issuePrefixes) ?? ["#"];
|
|
1177
|
+
const joinedIssuePrefixes = issuePrefixes.join("|");
|
|
1178
|
+
const noteKeywords = trimStringArray(userOptions?.noteKeywords) ?? [
|
|
1179
|
+
"BREAKING CHANGE",
|
|
1180
|
+
"BREAKING-CHANGE"
|
|
1181
|
+
];
|
|
1182
|
+
const joinedNoteKeywords = noteKeywords.join("|");
|
|
1183
|
+
return {
|
|
1184
|
+
subjectPattern: /^(?<type>\w+)(?:\((?<scope>.*)\))?(?<breakingChange>!)?:\s+(?<title>.*)/,
|
|
1185
|
+
mergePattern: /^Merge pull request #(?<id>\d*) from (?<source>.*)/,
|
|
1186
|
+
revertPattern: /^[Rr]evert "(?<subject>.*)"(\s*This reverts commit (?<hash>[a-zA-Z0-9]*)\.)?/,
|
|
1187
|
+
commentPattern: /^#(?!\d+\s)/,
|
|
1188
|
+
mentionPattern: /(?<!\w)@(?<username>[\w-]+)/,
|
|
1189
|
+
referenceActions,
|
|
1190
|
+
referenceActionPattern: joinedReferenceActions ? new RegExp(
|
|
1191
|
+
`(?<action>${joinedReferenceActions})(?:\\s+(?<reference>.*?))(?=(?:${joinedReferenceActions})|$)`
|
|
1192
|
+
) : void 0,
|
|
1193
|
+
issuePrefixes,
|
|
1194
|
+
issuePattern: joinedIssuePrefixes ? new RegExp(
|
|
1195
|
+
`(?:.*?)??\\s*(?<repository>[\\w-\\.\\/]*?)??(?<prefix>${joinedIssuePrefixes})(?<issue>[\\w-]*\\d+)`
|
|
1196
|
+
) : void 0,
|
|
1197
|
+
noteKeywords,
|
|
1198
|
+
notePattern: joinedNoteKeywords ? new RegExp(`^(?<title>${joinedNoteKeywords}):(\\s*(?<text>.*))`) : void 0,
|
|
1199
|
+
// Override defaults with user options
|
|
1200
|
+
...userOptions
|
|
1201
|
+
};
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
// src/commit-parser/parser-error.ts
|
|
1205
|
+
var ParserError = class extends Error {
|
|
1206
|
+
detail;
|
|
1207
|
+
constructor(message, detail) {
|
|
1208
|
+
super(message);
|
|
1209
|
+
this.name = "ParserError";
|
|
1210
|
+
this.detail = detail;
|
|
1211
|
+
}
|
|
1212
|
+
};
|
|
1213
|
+
|
|
1214
|
+
// src/commit-parser/commit-parser.ts
|
|
1215
|
+
var CommitParser = class {
|
|
1216
|
+
#options;
|
|
1217
|
+
#logger;
|
|
1218
|
+
constructor(userOptions) {
|
|
1219
|
+
this.#options = createParserOptions(userOptions);
|
|
1220
|
+
this.setLogger = this.setLogger.bind(this);
|
|
1221
|
+
this.createCommit = this.createCommit.bind(this);
|
|
1222
|
+
this.parseRawCommit = this.parseRawCommit.bind(this);
|
|
1223
|
+
this.parseSubject = this.parseSubject.bind(this);
|
|
1224
|
+
this.parseMerge = this.parseMerge.bind(this);
|
|
1225
|
+
this.parseRevert = this.parseRevert.bind(this);
|
|
1226
|
+
this.parseMentions = this.parseMentions.bind(this);
|
|
1227
|
+
this.parseReferenceParts = this.parseReferenceParts.bind(this);
|
|
1228
|
+
this.parseReferences = this.parseReferences.bind(this);
|
|
1229
|
+
this.parseNotes = this.parseNotes.bind(this);
|
|
1230
|
+
this.parseRawLines = this.parseRawLines.bind(this);
|
|
1231
|
+
this.parse = this.parse.bind(this);
|
|
1232
|
+
}
|
|
1233
|
+
setLogger(logger) {
|
|
1234
|
+
this.#logger = logger;
|
|
1235
|
+
return this;
|
|
1236
|
+
}
|
|
1237
|
+
createCommit() {
|
|
1238
|
+
return {
|
|
1239
|
+
raw: "",
|
|
1240
|
+
subject: "",
|
|
1241
|
+
body: "",
|
|
1242
|
+
hash: "",
|
|
1243
|
+
date: "",
|
|
1244
|
+
name: "",
|
|
1245
|
+
email: "",
|
|
1246
|
+
type: "",
|
|
1247
|
+
scope: "",
|
|
1248
|
+
breakingChange: "",
|
|
1249
|
+
title: "",
|
|
1250
|
+
merge: null,
|
|
1251
|
+
revert: null,
|
|
1252
|
+
notes: [],
|
|
1253
|
+
mentions: [],
|
|
1254
|
+
references: []
|
|
1255
|
+
};
|
|
876
1256
|
}
|
|
877
1257
|
/**
|
|
878
|
-
*
|
|
1258
|
+
* Parse the raw commit message into its expected parts
|
|
1259
|
+
* - subject
|
|
1260
|
+
* - body
|
|
1261
|
+
* - hash
|
|
1262
|
+
* - date
|
|
1263
|
+
* - name
|
|
1264
|
+
* - email
|
|
1265
|
+
*
|
|
1266
|
+
* @throws {ParserError}
|
|
879
1267
|
*/
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
1268
|
+
parseRawCommit(rawCommit) {
|
|
1269
|
+
const parsedCommit = this.createCommit();
|
|
1270
|
+
const parts = rawCommit.split(/\r?\n/);
|
|
1271
|
+
if (parts.length < 6) {
|
|
1272
|
+
throw new ParserError("Commit doesn't contain enough parts", rawCommit);
|
|
1273
|
+
}
|
|
1274
|
+
const email = parts.pop();
|
|
1275
|
+
const name = parts.pop();
|
|
1276
|
+
const date = parts.pop();
|
|
1277
|
+
const hash = parts.pop();
|
|
1278
|
+
if (email) parsedCommit.email = email.trim();
|
|
1279
|
+
if (name) parsedCommit.name = name.trim();
|
|
1280
|
+
if (date) {
|
|
1281
|
+
parsedCommit.date = date.trim();
|
|
1282
|
+
if (Number.isNaN(Date.parse(parsedCommit.date))) {
|
|
1283
|
+
throw new ParserError("Unable to parse commit date", rawCommit);
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
if (hash) parsedCommit.hash = hash.trim();
|
|
1287
|
+
const subject = parts.shift()?.trimStart();
|
|
1288
|
+
if (subject) {
|
|
1289
|
+
parsedCommit.subject = subject;
|
|
1290
|
+
parsedCommit.raw = subject;
|
|
883
1291
|
}
|
|
884
|
-
|
|
1292
|
+
parsedCommit.body = parts.filter((line) => {
|
|
1293
|
+
if (this.#options.commentPattern) {
|
|
1294
|
+
return !this.#options.commentPattern.test(line.trim());
|
|
1295
|
+
}
|
|
1296
|
+
return true;
|
|
1297
|
+
}).join("\n").trim();
|
|
1298
|
+
const raw = parts.join("\n").trim();
|
|
1299
|
+
if (raw) parsedCommit.raw += "\n" + raw;
|
|
1300
|
+
return parsedCommit;
|
|
885
1301
|
}
|
|
886
1302
|
/**
|
|
887
|
-
*
|
|
1303
|
+
* Parse the commit subject into its expected parts
|
|
1304
|
+
* - type
|
|
1305
|
+
* - scope (optional)
|
|
1306
|
+
* - breaking change (optional)
|
|
1307
|
+
* - title
|
|
1308
|
+
*
|
|
1309
|
+
* @throws {ParserError}
|
|
888
1310
|
*/
|
|
889
|
-
|
|
890
|
-
if (this.
|
|
891
|
-
|
|
1311
|
+
parseSubject(commit) {
|
|
1312
|
+
if (!this.#options.subjectPattern) return false;
|
|
1313
|
+
const subjectMatch = new RegExp(this.#options.subjectPattern, "i").exec(commit.subject);
|
|
1314
|
+
if (subjectMatch?.groups) {
|
|
1315
|
+
const { type = "", scope = "", breakingChange = "", title = "" } = subjectMatch.groups;
|
|
1316
|
+
if (!type || !title) {
|
|
1317
|
+
throw new ParserError("Unable to parse commit subject", commit);
|
|
1318
|
+
}
|
|
1319
|
+
commit.type = type;
|
|
1320
|
+
commit.scope = scope;
|
|
1321
|
+
if (breakingChange) commit.breakingChange = breakingChange;
|
|
1322
|
+
commit.title = title;
|
|
1323
|
+
return true;
|
|
892
1324
|
}
|
|
893
|
-
return
|
|
1325
|
+
return false;
|
|
894
1326
|
}
|
|
895
1327
|
/**
|
|
896
|
-
*
|
|
1328
|
+
* Parse merge information from the commit subject
|
|
1329
|
+
* @example
|
|
1330
|
+
* ```txt
|
|
1331
|
+
* "Merge pull request #123 from fork-version/feature"
|
|
1332
|
+
* ```
|
|
897
1333
|
*/
|
|
898
|
-
|
|
899
|
-
if (this.
|
|
900
|
-
|
|
1334
|
+
parseMerge(commit) {
|
|
1335
|
+
if (!this.#options.mergePattern) return false;
|
|
1336
|
+
const mergeMatch = new RegExp(this.#options.mergePattern).exec(commit.subject);
|
|
1337
|
+
if (mergeMatch?.groups) {
|
|
1338
|
+
const { id = "", source = "" } = mergeMatch.groups;
|
|
1339
|
+
commit.merge = {
|
|
1340
|
+
id,
|
|
1341
|
+
source
|
|
1342
|
+
};
|
|
1343
|
+
return true;
|
|
901
1344
|
}
|
|
902
|
-
return
|
|
1345
|
+
return false;
|
|
903
1346
|
}
|
|
904
1347
|
/**
|
|
905
|
-
*
|
|
1348
|
+
* Parse revert information from the commit body
|
|
1349
|
+
* @example
|
|
1350
|
+
* ```txt
|
|
1351
|
+
* "Revert "feat: initial commit"
|
|
1352
|
+
*
|
|
1353
|
+
* This reverts commit 4a79e9e546b4020d2882b7810dc549fa71960f4f."
|
|
1354
|
+
* ```
|
|
906
1355
|
*/
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
1356
|
+
parseRevert(commit) {
|
|
1357
|
+
if (!this.#options.revertPattern) return false;
|
|
1358
|
+
const revertMatch = new RegExp(this.#options.revertPattern).exec(commit.raw);
|
|
1359
|
+
if (revertMatch?.groups) {
|
|
1360
|
+
const { hash = "", subject = "" } = revertMatch.groups;
|
|
1361
|
+
commit.revert = {
|
|
1362
|
+
hash,
|
|
1363
|
+
subject
|
|
1364
|
+
};
|
|
910
1365
|
return true;
|
|
911
|
-
} catch (_error) {
|
|
912
|
-
return false;
|
|
913
1366
|
}
|
|
1367
|
+
return false;
|
|
914
1368
|
}
|
|
915
|
-
|
|
916
|
-
|
|
1369
|
+
/**
|
|
1370
|
+
* Search for mentions from the commit line
|
|
1371
|
+
* @example
|
|
1372
|
+
* ```txt
|
|
1373
|
+
* "@fork-version"
|
|
1374
|
+
* ```
|
|
1375
|
+
*/
|
|
1376
|
+
parseMentions(line, outMentions) {
|
|
1377
|
+
if (!this.#options.mentionPattern) return false;
|
|
1378
|
+
const mentionRegex = new RegExp(this.#options.mentionPattern, "g");
|
|
1379
|
+
let foundMention = false;
|
|
1380
|
+
let mentionMatch;
|
|
1381
|
+
while (mentionMatch = mentionRegex.exec(line)) {
|
|
1382
|
+
if (!mentionMatch) {
|
|
1383
|
+
break;
|
|
1384
|
+
}
|
|
1385
|
+
const { username = "" } = mentionMatch.groups ?? {};
|
|
1386
|
+
outMentions.add(username);
|
|
1387
|
+
foundMention = true;
|
|
1388
|
+
}
|
|
1389
|
+
return foundMention;
|
|
917
1390
|
}
|
|
918
1391
|
/**
|
|
919
|
-
*
|
|
920
|
-
*
|
|
921
|
-
* Using `git log` to get the commit history, we then parse the tags from the
|
|
922
|
-
* commit details which is expected to be in the following format:
|
|
1392
|
+
* Search for references from the commit line
|
|
923
1393
|
* @example
|
|
924
1394
|
* ```txt
|
|
925
|
-
*
|
|
926
|
-
*
|
|
927
|
-
* Date: Sat Nov 9 15:00:00 2024 +0000
|
|
928
|
-
*
|
|
929
|
-
* chore(release): 1.2.3
|
|
1395
|
+
* "#1234"
|
|
1396
|
+
* "owner/repo#1234"
|
|
930
1397
|
* ```
|
|
931
|
-
*
|
|
932
|
-
* - [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)
|
|
933
|
-
* - [conventional-changelog git-semver-tags MIT Licence](https://github.com/conventional-changelog/conventional-changelog/blob/fac8045242099c016f5f3905e54e02b7d466bd7b/packages/git-semver-tags/LICENSE.md)
|
|
934
1398
|
*/
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
const
|
|
938
|
-
const
|
|
939
|
-
let
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
1399
|
+
parseReferenceParts(referenceText, action) {
|
|
1400
|
+
if (!this.#options.issuePattern) return void 0;
|
|
1401
|
+
const references = [];
|
|
1402
|
+
const issueRegex = new RegExp(this.#options.issuePattern, "gi");
|
|
1403
|
+
let issueMatch;
|
|
1404
|
+
while (issueMatch = issueRegex.exec(referenceText)) {
|
|
1405
|
+
if (!issueMatch) {
|
|
1406
|
+
break;
|
|
1407
|
+
}
|
|
1408
|
+
const { repository = "", prefix = "", issue = "" } = issueMatch.groups ?? {};
|
|
1409
|
+
const reference = {
|
|
1410
|
+
prefix,
|
|
1411
|
+
issue,
|
|
1412
|
+
action,
|
|
1413
|
+
owner: null,
|
|
1414
|
+
repository: null
|
|
1415
|
+
};
|
|
1416
|
+
if (repository) {
|
|
1417
|
+
const slashIndex = repository.indexOf("/");
|
|
1418
|
+
if (slashIndex !== -1) {
|
|
1419
|
+
reference.owner = repository.slice(0, slashIndex);
|
|
1420
|
+
reference.repository = repository.slice(slashIndex + 1);
|
|
1421
|
+
} else {
|
|
1422
|
+
reference.repository = repository;
|
|
954
1423
|
}
|
|
955
1424
|
}
|
|
1425
|
+
references.push(reference);
|
|
956
1426
|
}
|
|
957
|
-
|
|
1427
|
+
if (references.length > 0) {
|
|
1428
|
+
return references;
|
|
1429
|
+
}
|
|
1430
|
+
return void 0;
|
|
958
1431
|
}
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
1432
|
+
/**
|
|
1433
|
+
* Search for actions and references from the commit line
|
|
1434
|
+
* @example
|
|
1435
|
+
* ```txt
|
|
1436
|
+
* "Closes #1234"
|
|
1437
|
+
* "fixes owner/repo#1234"
|
|
1438
|
+
* ```
|
|
1439
|
+
*/
|
|
1440
|
+
parseReferences(line, outReferences) {
|
|
1441
|
+
if (!this.#options.referenceActionPattern || !this.#options.issuePattern) return false;
|
|
1442
|
+
const referenceActionRegex = new RegExp(this.#options.referenceActionPattern, "gi").test(line) ? new RegExp(this.#options.referenceActionPattern, "gi") : /(?<reference>.*)/g;
|
|
1443
|
+
let foundReference = false;
|
|
1444
|
+
let referenceActionMatch;
|
|
1445
|
+
while (referenceActionMatch = referenceActionRegex.exec(line)) {
|
|
1446
|
+
if (!referenceActionMatch) {
|
|
1447
|
+
break;
|
|
1448
|
+
}
|
|
1449
|
+
const { action = "", reference = "" } = referenceActionMatch.groups ?? {};
|
|
1450
|
+
const parsedReferences = this.parseReferenceParts(reference, action || null);
|
|
1451
|
+
if (!parsedReferences) {
|
|
1452
|
+
break;
|
|
1453
|
+
}
|
|
1454
|
+
for (const ref of parsedReferences) {
|
|
1455
|
+
if (!outReferences.some((r) => r.prefix === ref.prefix && r.issue === ref.issue)) {
|
|
1456
|
+
outReferences.push(ref);
|
|
1457
|
+
}
|
|
967
1458
|
}
|
|
1459
|
+
foundReference = true;
|
|
1460
|
+
}
|
|
1461
|
+
return foundReference;
|
|
1462
|
+
}
|
|
1463
|
+
/**
|
|
1464
|
+
* Search for notes from the commit line
|
|
1465
|
+
* @example
|
|
1466
|
+
* ```txt
|
|
1467
|
+
* "BREAKING CHANGE: this is a breaking change"
|
|
1468
|
+
* ```
|
|
1469
|
+
*/
|
|
1470
|
+
parseNotes(line, outNotes) {
|
|
1471
|
+
if (!this.#options.notePattern) return false;
|
|
1472
|
+
const noteMatch = new RegExp(this.#options.notePattern, "ig").exec(line);
|
|
1473
|
+
if (noteMatch?.groups) {
|
|
1474
|
+
const { title = "", text = "" } = noteMatch.groups;
|
|
1475
|
+
outNotes.push({
|
|
1476
|
+
title,
|
|
1477
|
+
text
|
|
1478
|
+
});
|
|
1479
|
+
return true;
|
|
1480
|
+
}
|
|
1481
|
+
return false;
|
|
1482
|
+
}
|
|
1483
|
+
/**
|
|
1484
|
+
* Parse the raw commit for mentions, references and notes
|
|
1485
|
+
*/
|
|
1486
|
+
parseRawLines(commit) {
|
|
1487
|
+
const mentions = /* @__PURE__ */ new Set();
|
|
1488
|
+
const references = [];
|
|
1489
|
+
const notes = [];
|
|
1490
|
+
let lastNoteLine = -1;
|
|
1491
|
+
const splitMessage = commit.raw.split("\n");
|
|
1492
|
+
for (let index = 0; index < splitMessage.length; index++) {
|
|
1493
|
+
const line = splitMessage[index];
|
|
1494
|
+
const trimmedLine = line.trim();
|
|
1495
|
+
if (this.#options.commentPattern?.test(trimmedLine)) {
|
|
1496
|
+
continue;
|
|
1497
|
+
}
|
|
1498
|
+
this.parseMentions(trimmedLine, mentions);
|
|
1499
|
+
const foundReference = this.parseReferences(trimmedLine, references);
|
|
1500
|
+
if (foundReference) {
|
|
1501
|
+
lastNoteLine = -1;
|
|
1502
|
+
continue;
|
|
1503
|
+
}
|
|
1504
|
+
if (this.parseNotes(trimmedLine, notes)) {
|
|
1505
|
+
lastNoteLine = index;
|
|
1506
|
+
} else if (lastNoteLine !== -1) {
|
|
1507
|
+
notes[notes.length - 1].text += `
|
|
1508
|
+
${line}`;
|
|
1509
|
+
lastNoteLine = index;
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
if (mentions.size > 0) {
|
|
1513
|
+
commit.mentions = Array.from(mentions);
|
|
1514
|
+
}
|
|
1515
|
+
if (references.length > 0) {
|
|
1516
|
+
commit.references = references;
|
|
1517
|
+
}
|
|
1518
|
+
if (notes.length > 0) {
|
|
1519
|
+
commit.notes = notes.map((note) => ({
|
|
1520
|
+
...note,
|
|
1521
|
+
text: note.text.trim()
|
|
1522
|
+
}));
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
/**
|
|
1526
|
+
* Parse a commit log with the following format separated by new line characters:
|
|
1527
|
+
* ```txt
|
|
1528
|
+
* refactor: add test file
|
|
1529
|
+
* Add a test file to the project
|
|
1530
|
+
* 4ef2c86d393a9660aa9f753144256b1f200c16bd
|
|
1531
|
+
* 2024-12-22T17:36:50Z
|
|
1532
|
+
* Fork Version
|
|
1533
|
+
* fork-version@example.com
|
|
1534
|
+
* ```
|
|
1535
|
+
*
|
|
1536
|
+
* @example
|
|
1537
|
+
* ```ts
|
|
1538
|
+
* parse("refactor: add test file\nAdd a test file to the project\n4ef2c86d393a9660aa9f753144256b1f200c16bd\n2024-12-22T17:36:50Z\nFork Version\nfork-version@example.com");
|
|
1539
|
+
* ```
|
|
1540
|
+
*
|
|
1541
|
+
* The expected input value can be generated by running the following command:
|
|
1542
|
+
* ```sh
|
|
1543
|
+
* git log --format="%s%n%b%n%H%n%cI%n%cN%n%cE%n"
|
|
1544
|
+
* ```
|
|
1545
|
+
* @see {@link https://git-scm.com/docs/pretty-formats|Git Pretty Format Documentation}
|
|
1546
|
+
*/
|
|
1547
|
+
parse(rawCommit) {
|
|
1548
|
+
try {
|
|
1549
|
+
const commit = this.parseRawCommit(rawCommit);
|
|
1550
|
+
this.parseSubject(commit);
|
|
1551
|
+
this.parseMerge(commit);
|
|
1552
|
+
this.parseRevert(commit);
|
|
1553
|
+
this.parseRawLines(commit);
|
|
1554
|
+
return commit;
|
|
1555
|
+
} catch (error) {
|
|
1556
|
+
if (this.#logger) {
|
|
1557
|
+
this.#logger.debug("[Commit Parser] Failed to parse commit", { error });
|
|
1558
|
+
}
|
|
1559
|
+
return void 0;
|
|
968
1560
|
}
|
|
969
|
-
return cleanedTags.sort(semver.rcompare)[0];
|
|
970
1561
|
}
|
|
971
1562
|
};
|
|
1563
|
+
|
|
1564
|
+
// src/commit-parser/filter-reverted-commits.ts
|
|
1565
|
+
function filterRevertedCommits(parsedCommits) {
|
|
1566
|
+
const revertedCommits = [];
|
|
1567
|
+
for (const commit of parsedCommits) {
|
|
1568
|
+
if (!commit.revert) continue;
|
|
1569
|
+
if (revertedCommits.some(
|
|
1570
|
+
(r) => r.revert?.hash === commit.hash || r.revert?.subject === commit.subject
|
|
1571
|
+
)) {
|
|
1572
|
+
continue;
|
|
1573
|
+
}
|
|
1574
|
+
revertedCommits.push(commit);
|
|
1575
|
+
}
|
|
1576
|
+
if (revertedCommits.length === 0) {
|
|
1577
|
+
return parsedCommits;
|
|
1578
|
+
}
|
|
1579
|
+
const commitsWithoutReverts = [];
|
|
1580
|
+
for (const commit of parsedCommits) {
|
|
1581
|
+
if (commit.revert) continue;
|
|
1582
|
+
const revertedIndex = revertedCommits.findIndex(
|
|
1583
|
+
(r) => r.revert?.hash === commit.hash || r.revert?.subject === commit.subject
|
|
1584
|
+
);
|
|
1585
|
+
if (revertedIndex !== -1) {
|
|
1586
|
+
revertedCommits.splice(revertedIndex, 1);
|
|
1587
|
+
continue;
|
|
1588
|
+
}
|
|
1589
|
+
commitsWithoutReverts.push(commit);
|
|
1590
|
+
}
|
|
1591
|
+
return commitsWithoutReverts;
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
// src/process/get-commits.ts
|
|
1595
|
+
async function getCommitsSinceTag(config, logger, git) {
|
|
1596
|
+
const commitParser = new CommitParser();
|
|
1597
|
+
if (config.debug) commitParser.setLogger(logger);
|
|
1598
|
+
const latestTag = await git.getMostRecentTag(config.tagPrefix);
|
|
1599
|
+
if (!latestTag) {
|
|
1600
|
+
logger.warn("No previous tag found, using all commits");
|
|
1601
|
+
}
|
|
1602
|
+
const foundCommits = await git.getCommits(latestTag, "HEAD");
|
|
1603
|
+
logger.debug(`Found ${foundCommits.length} commits since last tag (${latestTag ?? "none"})`);
|
|
1604
|
+
const commits = foundCommits.reduce((acc, commit) => {
|
|
1605
|
+
const parsed = commitParser.parse(commit);
|
|
1606
|
+
if (parsed) {
|
|
1607
|
+
acc.push(parsed);
|
|
1608
|
+
}
|
|
1609
|
+
return acc;
|
|
1610
|
+
}, []);
|
|
1611
|
+
logger.debug(`Parsed ${commits.length} commits after applying commit parser`);
|
|
1612
|
+
const filteredCommits = filterRevertedCommits(commits);
|
|
1613
|
+
logger.debug(`Filtered to ${filteredCommits.length} commits after removing reverts`);
|
|
1614
|
+
return {
|
|
1615
|
+
latestTag,
|
|
1616
|
+
commits: filteredCommits
|
|
1617
|
+
};
|
|
1618
|
+
}
|
|
972
1619
|
function getPriority(type) {
|
|
973
1620
|
return ["patch", "minor", "major"].indexOf(type ?? "");
|
|
974
1621
|
}
|
|
@@ -1018,7 +1665,7 @@ async function getCurrentVersion(config, logger, git, fileManager, filesToUpdate
|
|
|
1018
1665
|
versions.add(config.currentVersion);
|
|
1019
1666
|
}
|
|
1020
1667
|
if (versions.size === 0 && config.gitTagFallback) {
|
|
1021
|
-
const version = await git.
|
|
1668
|
+
const version = await git.getHighestSemverVersionFromTags(config.tagPrefix);
|
|
1022
1669
|
if (version) {
|
|
1023
1670
|
logger.warn(`Using latest git tag as fallback`);
|
|
1024
1671
|
versions.add(version);
|
|
@@ -1045,65 +1692,77 @@ async function getCurrentVersion(config, logger, git, fileManager, filesToUpdate
|
|
|
1045
1692
|
version: currentVersion
|
|
1046
1693
|
};
|
|
1047
1694
|
}
|
|
1048
|
-
async function getNextVersion(config, logger, currentVersion) {
|
|
1695
|
+
async function getNextVersion(config, logger, commits, currentVersion) {
|
|
1049
1696
|
if (config.skipBump) {
|
|
1050
1697
|
logger.warn(`Skip bump, using ${currentVersion} as the next version`);
|
|
1051
1698
|
return {
|
|
1052
1699
|
version: currentVersion
|
|
1053
1700
|
};
|
|
1054
1701
|
}
|
|
1055
|
-
if (config.nextVersion
|
|
1702
|
+
if (config.nextVersion) {
|
|
1703
|
+
if (!semver.valid(config.nextVersion)) {
|
|
1704
|
+
throw new Error(`Invalid Version: ${config.nextVersion}`);
|
|
1705
|
+
}
|
|
1056
1706
|
logger.log(`Next version: ${config.nextVersion}`);
|
|
1057
1707
|
return {
|
|
1058
1708
|
version: config.nextVersion
|
|
1059
1709
|
};
|
|
1060
1710
|
}
|
|
1061
1711
|
const isPreMajor = semver.lt(currentVersion, "1.0.0");
|
|
1062
|
-
let
|
|
1712
|
+
let releaseType = "patch";
|
|
1713
|
+
const changes = { major: 0, minor: 0, patch: 0 };
|
|
1063
1714
|
if (config.releaseAs) {
|
|
1064
|
-
|
|
1065
|
-
releaseType: config.releaseAs,
|
|
1066
|
-
level: -1,
|
|
1067
|
-
reason: "User defined"
|
|
1068
|
-
};
|
|
1715
|
+
releaseType = config.releaseAs;
|
|
1069
1716
|
} else {
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1717
|
+
let level = 2;
|
|
1718
|
+
const MINOR_TYPES = ["feat", "feature"];
|
|
1719
|
+
for (const commit of commits) {
|
|
1720
|
+
if (commit.notes.length > 0 || commit.breakingChange) {
|
|
1721
|
+
changes.major += commit.notes.length + (commit.breakingChange ? 1 : 0);
|
|
1722
|
+
level = 0;
|
|
1723
|
+
} else if (MINOR_TYPES.includes(commit.type.toLowerCase())) {
|
|
1724
|
+
changes.minor += 1;
|
|
1725
|
+
if (level === 2) {
|
|
1726
|
+
level = 1;
|
|
1727
|
+
}
|
|
1728
|
+
} else {
|
|
1729
|
+
changes.patch += 1;
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
if (isPreMajor && level < 2) {
|
|
1733
|
+
level++;
|
|
1734
|
+
changes.patch += changes.minor;
|
|
1735
|
+
changes.minor = changes.major;
|
|
1736
|
+
changes.major = 0;
|
|
1737
|
+
}
|
|
1738
|
+
if (level === 0) {
|
|
1739
|
+
releaseType = "major";
|
|
1740
|
+
} else if (level === 1) {
|
|
1741
|
+
releaseType = "minor";
|
|
1742
|
+
} else {
|
|
1743
|
+
releaseType = "patch";
|
|
1085
1744
|
}
|
|
1086
1745
|
}
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1746
|
+
const releaseTypeOrPreRelease = getReleaseType(releaseType, currentVersion, config.preRelease);
|
|
1747
|
+
const nextVersion = semver.inc(
|
|
1748
|
+
currentVersion,
|
|
1749
|
+
releaseTypeOrPreRelease,
|
|
1750
|
+
typeof config.preRelease === "string" ? config.preRelease : ""
|
|
1751
|
+
) ?? "";
|
|
1752
|
+
logger.log(`Next version: ${nextVersion} (${releaseTypeOrPreRelease})`);
|
|
1753
|
+
if (commits.length > 0) {
|
|
1754
|
+
logger.log(
|
|
1755
|
+
` - Commits: ${commits.length}` + (changes.major > 0 ? `, Breaking Changes: ${changes.major}` : "") + (changes.minor > 0 ? `, New Features: ${changes.minor}` : "") + (changes.patch > 0 ? `, Bug Fixes: ${changes.patch}` : "")
|
|
1092
1756
|
);
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
releaseType,
|
|
1096
|
-
typeof config.preRelease === "string" ? config.preRelease : void 0
|
|
1097
|
-
) ?? "";
|
|
1098
|
-
logger.log(`Next version: ${nextVersion} (${releaseType})`);
|
|
1099
|
-
return {
|
|
1100
|
-
...recommendedBump,
|
|
1101
|
-
preMajor: isPreMajor,
|
|
1102
|
-
releaseType,
|
|
1103
|
-
version: nextVersion
|
|
1104
|
-
};
|
|
1757
|
+
} else {
|
|
1758
|
+
logger.log(" - No commits found.");
|
|
1105
1759
|
}
|
|
1106
|
-
|
|
1760
|
+
return {
|
|
1761
|
+
version: nextVersion,
|
|
1762
|
+
releaseType: releaseTypeOrPreRelease,
|
|
1763
|
+
preMajor: isPreMajor,
|
|
1764
|
+
changes
|
|
1765
|
+
};
|
|
1107
1766
|
}
|
|
1108
1767
|
var RELEASE_PATTERN = /(^#+ \[?[0-9]+\.[0-9]+\.[0-9]+|<a name=)/m;
|
|
1109
1768
|
function getOldReleaseContent(filePath, exists) {
|
|
@@ -1232,6 +1891,6 @@ async function tagChanges(config, logger, git, nextVersion) {
|
|
|
1232
1891
|
);
|
|
1233
1892
|
}
|
|
1234
1893
|
|
|
1235
|
-
export { FileManager, ForkConfigSchema, Git, Logger, commitChanges, getCurrentVersion, getNextVersion, getUserConfig, tagChanges, updateChangelog };
|
|
1236
|
-
//# sourceMappingURL=chunk-
|
|
1237
|
-
//# sourceMappingURL=chunk-
|
|
1894
|
+
export { CommitParser, FileManager, ForkConfigSchema, Git, Logger, commitChanges, createParserOptions, filterRevertedCommits, getCommitsSinceTag, getCurrentVersion, getNextVersion, getUserConfig, tagChanges, updateChangelog };
|
|
1895
|
+
//# sourceMappingURL=chunk-D2PQT6ZM.js.map
|
|
1896
|
+
//# sourceMappingURL=chunk-D2PQT6ZM.js.map
|