chore(deps): upgrade dependencies and drop ESLint

This commit is contained in:
Paul Hatcherian 2026-01-18 17:30:33 -06:00
parent 45a5cbb476
commit 3337b3eed3
30 changed files with 831 additions and 4024 deletions

View file

@ -1,21 +0,0 @@
{
"parser": "@typescript-eslint/parser",
"plugins": ["jest"],
"env": {
"es6": true,
"node": true,
"jest/globals": true
},
"extends": ["eslint:recommended"],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module"
},
"rules": {
"no-unused-vars": "off"
}
}

View file

@ -37,9 +37,6 @@ jobs:
- name: Format check - name: Format check
run: npm run format-check run: npm run format-check
- name: Lint
run: npm run lint
- name: Test - name: Test
run: npm test run: npm test

4
.prettierignore Normal file
View file

@ -0,0 +1,4 @@
dist/
node_modules/
lib/
*.md

View file

@ -99,7 +99,7 @@ outputs:
description: "The current commit hash" description: "The current commit hash"
debug_output: debug_output:
description: "Diagnostic information, if debug is enabled" description: "Diagnostic information, if debug is enabled"
runs: runs:
using: "node20" using: "node20"
main: "dist/index.js" main: "dist/index.js"

225
dist/index.js vendored
View file

@ -379,17 +379,17 @@ const DefaultTagFormatter_1 = __nccwpck_require__(2865);
class BranchVersioningTagFormatter extends DefaultTagFormatter_1.DefaultTagFormatter { class BranchVersioningTagFormatter extends DefaultTagFormatter_1.DefaultTagFormatter {
getRegex(pattern) { getRegex(pattern) {
if (/^\/.+\/[i]*$/.test(pattern)) { if (/^\/.+\/[i]*$/.test(pattern)) {
const regexEnd = pattern.lastIndexOf('/'); const regexEnd = pattern.lastIndexOf("/");
const parsedFlags = pattern.slice(pattern.lastIndexOf('/') + 1); const parsedFlags = pattern.slice(pattern.lastIndexOf("/") + 1);
return new RegExp(pattern.slice(1, regexEnd), parsedFlags); return new RegExp(pattern.slice(1, regexEnd), parsedFlags);
} }
return new RegExp(pattern); return new RegExp(pattern);
} }
constructor(config, branchName) { constructor(config, branchName) {
super(config); super(config);
const pattern = config.versionFromBranch === true ? const pattern = config.versionFromBranch === true
new RegExp("[0-9]+.[0-9]+$|[0-9]+$") : ? new RegExp("[0-9]+.[0-9]+$|[0-9]+$")
this.getRegex(config.versionFromBranch); : this.getRegex(config.versionFromBranch);
const result = pattern.exec(branchName); const result = pattern.exec(branchName);
if (result === null) { if (result === null) {
this.major = NaN; this.major = NaN;
@ -408,7 +408,7 @@ class BranchVersioningTagFormatter extends DefaultTagFormatter_1.DefaultTagForma
throw new Error(`Unable to parse version from branch named '${branchName}' using pattern '${pattern}'`); throw new Error(`Unable to parse version from branch named '${branchName}' using pattern '${pattern}'`);
} }
this.onVersionBranch = true; this.onVersionBranch = true;
const versionValues = branchVersion.split('.'); const versionValues = branchVersion.split(".");
if (versionValues.length > 2) { if (versionValues.length > 2) {
throw new Error(`The version string '${branchVersion}' parsed from branch '${branchName}' is invalid. It must be in the format 'major.minor' or 'major'`); throw new Error(`The version string '${branchVersion}' parsed from branch '${branchName}' is invalid. It must be in the format 'major.minor' or 'major'`);
} }
@ -429,9 +429,9 @@ class BranchVersioningTagFormatter extends DefaultTagFormatter_1.DefaultTagForma
return pattern; return pattern;
} }
if (this.minor === undefined) { if (this.minor === undefined) {
return pattern.replace('*[0-9].*[0-9].*[0-9]', `${this.major}.*[0-9].*[0-9]`); return pattern.replace("*[0-9].*[0-9].*[0-9]", `${this.major}.*[0-9].*[0-9]`);
} }
return pattern.replace('*[0-9].*[0-9].*[0-9]', `${this.major}.${this.minor}.*[0-9]`); return pattern.replace("*[0-9].*[0-9].*[0-9]", `${this.major}.${this.minor}.*[0-9]`);
} }
IsValid(tag) { IsValid(tag) {
if (!this.onVersionBranch) { if (!this.onVersionBranch) {
@ -474,7 +474,7 @@ class CsvUserFormatter {
// placeholder for consistency with other formatters // placeholder for consistency with other formatters
} }
Format(type, users) { Format(type, users) {
return users.map(user => `${user.name} <${user.email}>`).join(', '); return users.map((user) => `${user.name} <${user.email}>`).join(", ");
} }
} }
exports.CsvUserFormatter = CsvUserFormatter; exports.CsvUserFormatter = CsvUserFormatter;
@ -494,7 +494,7 @@ class DefaultTagFormatter {
constructor(config) { constructor(config) {
this.namespace = config.namespace; this.namespace = config.namespace;
this.tagPrefix = config.tagPrefix; this.tagPrefix = config.tagPrefix;
this.namespaceSeparator = '-'; // maybe make configurable in the future this.namespaceSeparator = "-"; // maybe make configurable in the future
} }
Format(versionInfo) { Format(versionInfo) {
const result = `${this.tagPrefix}${versionInfo.major}.${versionInfo.minor}.${versionInfo.patch}`; const result = `${this.tagPrefix}${versionInfo.major}.${versionInfo.minor}.${versionInfo.patch}`;
@ -510,20 +510,20 @@ class DefaultTagFormatter {
return `${this.tagPrefix}*[0-9].*[0-9].*[0-9]`; return `${this.tagPrefix}*[0-9].*[0-9].*[0-9]`;
} }
Parse(tag) { Parse(tag) {
if (tag === '') { if (tag === "") {
return [0, 0, 0]; return [0, 0, 0];
} }
let tagParts = tag let tagParts = tag
.replace(this.tagPrefix, '<--!PREFIX!-->') .replace(this.tagPrefix, "<--!PREFIX!-->")
.replace(this.namespace, '<--!NAMESPACE!-->') .replace(this.namespace, "<--!NAMESPACE!-->")
.split('/'); .split("/");
const stripedTag = tagParts[tagParts.length - 1] const stripedTag = tagParts[tagParts.length - 1]
.replace('<--!PREFIX!-->', this.tagPrefix) .replace("<--!PREFIX!-->", this.tagPrefix)
.replace('<--!NAMESPACE!-->', this.namespace); .replace("<--!NAMESPACE!-->", this.namespace);
let versionValues = stripedTag let versionValues = stripedTag
.substring(this.tagPrefix.length) .substring(this.tagPrefix.length)
.slice(0, this.namespace === '' ? 999 : -(this.namespace.length + 1)) .slice(0, this.namespace === "" ? 999 : -(this.namespace.length + 1))
.split('.'); .split(".");
let major = parseInt(versionValues[0]); let major = parseInt(versionValues[0]);
let minor = versionValues.length > 1 ? parseInt(versionValues[1]) : 0; let minor = versionValues.length > 1 ? parseInt(versionValues[1]) : 0;
let patch = versionValues.length > 2 ? parseInt(versionValues[2]) : 0; let patch = versionValues.length > 2 ? parseInt(versionValues[2]) : 0;
@ -533,7 +533,7 @@ class DefaultTagFormatter {
return [major, minor, patch]; return [major, minor, patch];
} }
IsValid(tag) { IsValid(tag) {
const regexEscape = (literal) => literal.replace(/\W/g, '\\$&'); const regexEscape = (literal) => literal.replace(/\W/g, "\\$&");
const tagPrefix = regexEscape(this.tagPrefix); const tagPrefix = regexEscape(this.tagPrefix);
const namespaceSeparator = regexEscape(this.namespaceSeparator); const namespaceSeparator = regexEscape(this.namespaceSeparator);
const namespace = regexEscape(this.namespace); const namespace = regexEscape(this.namespace);
@ -561,10 +561,10 @@ class DefaultVersionFormatter {
} }
Format(versionInfo) { Format(versionInfo) {
return this.formatString return this.formatString
.replace('${major}', versionInfo.major.toString()) .replace("${major}", versionInfo.major.toString())
.replace('${minor}', versionInfo.minor.toString()) .replace("${minor}", versionInfo.minor.toString())
.replace('${patch}', versionInfo.patch.toString()) .replace("${patch}", versionInfo.patch.toString())
.replace('${increment}', versionInfo.increment.toString()); .replace("${increment}", versionInfo.increment.toString());
} }
} }
exports.DefaultVersionFormatter = DefaultVersionFormatter; exports.DefaultVersionFormatter = DefaultVersionFormatter;
@ -584,8 +584,8 @@ class JsonUserFormatter {
// placeholder for consistency with other formatters // placeholder for consistency with other formatters
} }
Format(type, users) { Format(type, users) {
let result = users.map(u => ({ name: u.name, email: u.email })); let result = users.map((u) => ({ name: u.name, email: u.email }));
return JSON.stringify(result).replace('\n', ''); return JSON.stringify(result).replace("\n", "");
} }
} }
exports.JsonUserFormatter = JsonUserFormatter; exports.JsonUserFormatter = JsonUserFormatter;
@ -751,9 +751,9 @@ class BumpAlwaysVersionClassifier extends DefaultVersionClassifier_1.DefaultVers
constructor(config) { constructor(config) {
super(config); super(config);
this.enablePrereleaseMode = config.enablePrereleaseMode; this.enablePrereleaseMode = config.enablePrereleaseMode;
this.patchPattern = !config.bumpEachCommitPatchPattern ? this.patchPattern = !config.bumpEachCommitPatchPattern
_ => true : ? (_) => true
this.parsePattern(config.bumpEachCommitPatchPattern, "", config.searchCommitBody); : this.parsePattern(config.bumpEachCommitPatchPattern, "", config.searchCommitBody);
} }
ClassifyAsync(lastRelease, commitSet) { ClassifyAsync(lastRelease, commitSet) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
@ -774,7 +774,10 @@ class BumpAlwaysVersionClassifier extends DefaultVersionClassifier_1.DefaultVers
type = VersionType_1.VersionType.Minor; type = VersionType_1.VersionType.Minor;
} }
else if (this.patchPattern(commit) || else if (this.patchPattern(commit) ||
(major === 0 && minor === 0 && patch === 0 && commitSet.commits.length > 0)) { (major === 0 &&
minor === 0 &&
patch === 0 &&
commitSet.commits.length > 0)) {
type = VersionType_1.VersionType.Patch; type = VersionType_1.VersionType.Patch;
} }
else { else {
@ -914,49 +917,47 @@ class DefaultCommitsProvider {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const logSplitter = `@@@START_RECORD`; const logSplitter = `@@@START_RECORD`;
const formatPlaceholders = Object.entries({ const formatPlaceholders = Object.entries({
hash: '%H', hash: "%H",
subject: '%s', subject: "%s",
body: '%b', body: "%b",
author: '%an', author: "%an",
authorEmail: '%ae', authorEmail: "%ae",
authorDate: '%aI', authorDate: "%aI",
committer: '%cn', committer: "%cn",
committerEmail: '%ce', committerEmail: "%ce",
committerDate: '%cI', committerDate: "%cI",
tags: '%d' tags: "%d",
}); });
const pretty = logSplitter + '%n' + formatPlaceholders const pretty = logSplitter +
.map(x => `@@@${x[0]}%n${x[1]}`) "%n" +
.join('%n'); formatPlaceholders.map((x) => `@@@${x[0]}%n${x[1]}`).join("%n");
var logCommand = `git log --pretty="${pretty}" --author-date-order ${(startHash === '' ? endHash : `${startHash}..${endHash}`)}`; var logCommand = `git log --pretty="${pretty}" --author-date-order ${startHash === "" ? endHash : `${startHash}..${endHash}`}`;
if (this.changePath !== '') { if (this.changePath !== "") {
logCommand += ` -- ${this.changePath}`; logCommand += ` -- ${this.changePath}`;
} }
const log = yield (0, CommandRunner_1.cmd)(logCommand); const log = yield (0, CommandRunner_1.cmd)(logCommand);
const entries = log const entries = log.split(logSplitter).slice(1);
.split(logSplitter) const commits = entries.map((entry) => {
.slice(1);
const commits = entries.map(entry => {
const fields = entry const fields = entry
.split(`@@@`) .split(`@@@`)
.slice(1) .slice(1)
.reduce((acc, value) => { .reduce((acc, value) => {
const firstLine = value.indexOf('\n'); const firstLine = value.indexOf("\n");
const key = value.substring(0, firstLine); const key = value.substring(0, firstLine);
acc[key] = value.substring(firstLine + 1).trim(); acc[key] = value.substring(firstLine + 1).trim();
return acc; return acc;
}, {}); }, {});
const tags = fields.tags const tags = fields.tags
.split(',') .split(",")
.map((v) => v.trim()) .map((v) => v.trim())
.filter((v) => v.startsWith('tags: ')) .filter((v) => v.startsWith("tags: "))
.map((v) => v.substring(5).trim()); .map((v) => v.substring(5).trim());
return new CommitInfo_1.CommitInfo(fields.hash, fields.subject, fields.body, fields.author, fields.authorEmail, new Date(fields.authorDate), fields.committer, fields.committerEmail, new Date(fields.committerDate), tags); return new CommitInfo_1.CommitInfo(fields.hash, fields.subject, fields.body, fields.author, fields.authorEmail, new Date(fields.authorDate), fields.committer, fields.committerEmail, new Date(fields.committerDate), tags);
}); });
// check for changes // check for changes
let changed = true; let changed = true;
if (this.changePath !== '') { if (this.changePath !== "") {
if (startHash === '') { if (startHash === "") {
const changedFiles = yield (0, CommandRunner_1.cmd)(`git log --name-only --oneline ${endHash} -- ${this.changePath}`); const changedFiles = yield (0, CommandRunner_1.cmd)(`git log --name-only --oneline ${endHash} -- ${this.changePath}`);
changed = changedFiles.length > 0; changed = changedFiles.length > 0;
} }
@ -997,21 +998,23 @@ class DefaultCurrentCommitResolver {
} }
ResolveAsync() { ResolveAsync() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
if (this.branch === 'HEAD') { if (this.branch === "HEAD") {
return (yield (0, CommandRunner_1.cmd)('git', 'rev-parse', 'HEAD')).trim(); return (yield (0, CommandRunner_1.cmd)("git", "rev-parse", "HEAD")).trim();
} }
return this.branch; return this.branch;
}); });
} }
IsEmptyRepoAsync() { IsEmptyRepoAsync() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
let lastCommitAll = (yield (0, CommandRunner_1.cmd)('git', 'rev-list', '-n1', '--all')).trim(); let lastCommitAll = (yield (0, CommandRunner_1.cmd)("git", "rev-list", "-n1", "--all")).trim();
return lastCommitAll === ''; return lastCommitAll === "";
}); });
} }
ResolveBranchNameAsync() { ResolveBranchNameAsync() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const branchName = this.branch == 'HEAD' ? yield (0, CommandRunner_1.cmd)('git', 'rev-parse', '--abbrev-ref', 'HEAD') : this.branch; const branchName = this.branch == "HEAD"
? yield (0, CommandRunner_1.cmd)("git", "rev-parse", "--abbrev-ref", "HEAD")
: this.branch;
return branchName.trim(); return branchName.trim();
}); });
} }
@ -1082,36 +1085,37 @@ class DefaultLastReleaseResolver {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const releasePattern = tagFormatter.GetPattern(); const releasePattern = tagFormatter.GetPattern();
let currentTag = (yield (0, CommandRunner_1.cmd)(`git tag --points-at ${current} ${releasePattern}`)).trim(); let currentTag = (yield (0, CommandRunner_1.cmd)(`git tag --points-at ${current} ${releasePattern}`)).trim();
currentTag = tagFormatter.IsValid(currentTag) ? currentTag : ''; currentTag = tagFormatter.IsValid(currentTag) ? currentTag : "";
const isTagged = currentTag !== ''; const isTagged = currentTag !== "";
const [currentMajor, currentMinor, currentPatch] = currentTag ? tagFormatter.Parse(currentTag) : [null, null, null]; const [currentMajor, currentMinor, currentPatch] = currentTag
? tagFormatter.Parse(currentTag)
: [null, null, null];
let tagsCount = 0; let tagsCount = 0;
let tag = ''; let tag = "";
try { try {
const refPrefixPattern = this.useBranches ? 'refs/heads/' : 'refs/tags/'; const refPrefixPattern = this.useBranches ? "refs/heads/" : "refs/tags/";
if (currentTag) { if (currentTag) {
// If we already have the current branch tagged, we are checking for the previous one // If we already have the current branch tagged, we are checking for the previous one
// so that we will have an accurate increment (assuming the new tag is the expected one) // so that we will have an accurate increment (assuming the new tag is the expected one)
const command = `git for-each-ref --sort=-v:*refname --format=%(refname:short) --merged=${current} ${refPrefixPattern}${releasePattern}`; const command = `git for-each-ref --sort=-v:*refname --format=%(refname:short) --merged=${current} ${refPrefixPattern}${releasePattern}`;
const tags = (yield (0, CommandRunner_1.cmd)(command)).split('\n'); const tags = (yield (0, CommandRunner_1.cmd)(command)).split("\n");
tagsCount = tags.length; tagsCount = tags.length;
tag = tags tag =
.find(t => tagFormatter.IsValid(t) && t !== currentTag) || ''; tags.find((t) => tagFormatter.IsValid(t) && t !== currentTag) || "";
} }
else { else {
const command = `git for-each-ref --sort=-v:*refname --format=%(refname:short) --merged=${current} ${refPrefixPattern}${releasePattern}`; const command = `git for-each-ref --sort=-v:*refname --format=%(refname:short) --merged=${current} ${refPrefixPattern}${releasePattern}`;
const tags = (yield (0, CommandRunner_1.cmd)(command)).split('\n'); const tags = (yield (0, CommandRunner_1.cmd)(command)).split("\n");
tagsCount = tags.length; tagsCount = tags.length;
tag = tags tag = tags.find((t) => tagFormatter.IsValid(t)) || "";
.find(t => tagFormatter.IsValid(t)) || '';
} }
tag = tag.trim(); tag = tag.trim();
} }
catch (err) { catch (err) {
tag = ''; tag = "";
} }
if (tag === '') { if (tag === "") {
if ((yield (0, CommandRunner_1.cmd)('git', 'remote')) !== '') { if ((yield (0, CommandRunner_1.cmd)("git", "remote")) !== "") {
// Since there is no remote, we assume that there are no other tags to pull. In // Since there is no remote, we assume that there are no other tags to pull. In
// practice this isn't likely to happen, but it keeps the test output from being // practice this isn't likely to happen, but it keeps the test output from being
// polluted with a bunch of warnings. // polluted with a bunch of warnings.
@ -1119,16 +1123,16 @@ class DefaultLastReleaseResolver {
core.warning(`None of the ${tagsCount} tags(s) found were valid version tags for the present configuration. If this is unexpected, check to ensure that the configuration is correct and matches the tag format you are using. If you have not yet tagged this repo with a version tag, this can be ignored.`); core.warning(`None of the ${tagsCount} tags(s) found were valid version tags for the present configuration. If this is unexpected, check to ensure that the configuration is correct and matches the tag format you are using. If you have not yet tagged this repo with a version tag, this can be ignored.`);
} }
else { else {
core.warning('No tags are present for this repository. If this is unexpected, check to ensure that tags have been pulled from the remote. If you have not yet tagged this repo with a version tag, this can be ignored.'); core.warning("No tags are present for this repository. If this is unexpected, check to ensure that tags have been pulled from the remote. If you have not yet tagged this repo with a version tag, this can be ignored.");
} }
} }
const [major, minor, patch] = tagFormatter.Parse(''); const [major, minor, patch] = tagFormatter.Parse("");
// no release tags yet, use the initial commit as the root // no release tags yet, use the initial commit as the root
return new ReleaseInformation_1.ReleaseInformation(major, minor, patch, '', currentMajor, currentMinor, currentPatch, isTagged); return new ReleaseInformation_1.ReleaseInformation(major, minor, patch, "", currentMajor, currentMinor, currentPatch, isTagged);
} }
// parse the version tag // parse the version tag
const [major, minor, patch] = tagFormatter.Parse(tag); const [major, minor, patch] = tagFormatter.Parse(tag);
const root = yield (0, CommandRunner_1.cmd)('git', `merge-base`, tag, current); const root = yield (0, CommandRunner_1.cmd)("git", `merge-base`, tag, current);
return new ReleaseInformation_1.ReleaseInformation(major, minor, patch, root.trim(), currentMajor, currentMinor, currentPatch, isTagged); return new ReleaseInformation_1.ReleaseInformation(major, minor, patch, root.trim(), currentMajor, currentMinor, currentPatch, isTagged);
}); });
} }
@ -1165,18 +1169,19 @@ class DefaultVersionClassifier {
} }
parsePattern(pattern, flags, searchBody) { parsePattern(pattern, flags, searchBody) {
if (/^\/.+\/[i]*$/.test(pattern)) { if (/^\/.+\/[i]*$/.test(pattern)) {
const regexEnd = pattern.lastIndexOf('/'); const regexEnd = pattern.lastIndexOf("/");
const parsedFlags = pattern.slice(pattern.lastIndexOf('/') + 1); const parsedFlags = pattern.slice(pattern.lastIndexOf("/") + 1);
const regex = new RegExp(pattern.slice(1, regexEnd), parsedFlags || flags); const regex = new RegExp(pattern.slice(1, regexEnd), parsedFlags || flags);
return searchBody ? return searchBody
(commit) => regex.test(commit.subject) || regex.test(commit.body) : ? (commit) => regex.test(commit.subject) || regex.test(commit.body)
(commit) => regex.test(commit.subject); : (commit) => regex.test(commit.subject);
} }
else { else {
const matchString = pattern; const matchString = pattern;
return searchBody ? return searchBody
(commit) => commit.subject.includes(matchString) || commit.body.includes(matchString) : ? (commit) => commit.subject.includes(matchString) ||
(commit) => commit.subject.includes(matchString); commit.body.includes(matchString)
: (commit) => commit.subject.includes(matchString);
} }
} }
getNextVersion(current, type) { getNextVersion(current, type) {
@ -1186,9 +1191,17 @@ class DefaultVersionClassifier {
return { major: current.major, minor: current.minor + 1, patch: 0 }; return { major: current.major, minor: current.minor + 1, patch: 0 };
case VersionType_1.VersionType.Minor: case VersionType_1.VersionType.Minor:
case VersionType_1.VersionType.Patch: case VersionType_1.VersionType.Patch:
return { major: current.major, minor: current.minor, patch: current.patch + 1 }; return {
major: current.major,
minor: current.minor,
patch: current.patch + 1,
};
case VersionType_1.VersionType.None: case VersionType_1.VersionType.None:
return { major: current.major, minor: current.minor, patch: current.patch }; return {
major: current.major,
minor: current.minor,
patch: current.patch,
};
default: default:
throw new Error(`Unknown change type: ${type}`); throw new Error(`Unknown change type: ${type}`);
} }
@ -1199,33 +1212,57 @@ class DefaultVersionClassifier {
case VersionType_1.VersionType.Minor: case VersionType_1.VersionType.Minor:
return { major: current.major, minor: current.minor + 1, patch: 0 }; return { major: current.major, minor: current.minor + 1, patch: 0 };
case VersionType_1.VersionType.Patch: case VersionType_1.VersionType.Patch:
return { major: current.major, minor: current.minor, patch: current.patch + 1 }; return {
major: current.major,
minor: current.minor,
patch: current.patch + 1,
};
case VersionType_1.VersionType.None: case VersionType_1.VersionType.None:
return { major: current.major, minor: current.minor, patch: current.patch }; return {
major: current.major,
minor: current.minor,
patch: current.patch,
};
default: default:
throw new Error(`Unknown change type: ${type}`); throw new Error(`Unknown change type: ${type}`);
} }
} }
resolveCommitType(commitsSet) { resolveCommitType(commitsSet) {
if (commitsSet.commits.length === 0) { if (commitsSet.commits.length === 0) {
return { type: VersionType_1.VersionType.None, increment: 0, changed: commitsSet.changed }; return {
type: VersionType_1.VersionType.None,
increment: 0,
changed: commitsSet.changed,
};
} }
const commits = commitsSet.commits.reverse(); const commits = commitsSet.commits.reverse();
let index = 1; let index = 1;
for (let commit of commits) { for (let commit of commits) {
if (this.majorPattern(commit)) { if (this.majorPattern(commit)) {
return { type: VersionType_1.VersionType.Major, increment: commits.length - index, changed: commitsSet.changed }; return {
type: VersionType_1.VersionType.Major,
increment: commits.length - index,
changed: commitsSet.changed,
};
} }
index++; index++;
} }
index = 1; index = 1;
for (let commit of commits) { for (let commit of commits) {
if (this.minorPattern(commit)) { if (this.minorPattern(commit)) {
return { type: VersionType_1.VersionType.Minor, increment: commits.length - index, changed: commitsSet.changed }; return {
type: VersionType_1.VersionType.Minor,
increment: commits.length - index,
changed: commitsSet.changed,
};
} }
index++; index++;
} }
return { type: VersionType_1.VersionType.Patch, increment: commitsSet.commits.length - 1, changed: true }; return {
type: VersionType_1.VersionType.Patch,
increment: commitsSet.commits.length - 1,
changed: true,
};
} }
ClassifyAsync(lastRelease, commitSet) { ClassifyAsync(lastRelease, commitSet) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
@ -1239,7 +1276,9 @@ class DefaultVersionClassifier {
// - commit 2 - v1.0.0+1 // - commit 2 - v1.0.0+1
// - commit 3 was tagged v2.0.0 - v2.0.0+0 // - commit 3 was tagged v2.0.0 - v2.0.0+0
// - commit 4 - v2.0.1+0 // - commit 4 - v2.0.1+0
const versionsMatch = lastRelease.currentMajor === major && lastRelease.currentMinor === minor && lastRelease.currentPatch === patch; const versionsMatch = lastRelease.currentMajor === major &&
lastRelease.currentMinor === minor &&
lastRelease.currentPatch === patch;
const currentIncrement = versionsMatch ? increment : 0; const currentIncrement = versionsMatch ? increment : 0;
return new VersionClassification_1.VersionClassification(VersionType_1.VersionType.None, currentIncrement, false, lastRelease.currentMajor, lastRelease.currentMinor, lastRelease.currentPatch); return new VersionClassification_1.VersionClassification(VersionType_1.VersionType.None, currentIncrement, false, lastRelease.currentMajor, lastRelease.currentMinor, lastRelease.currentPatch);
} }

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

View file

@ -1,12 +1,10 @@
module.exports = { module.exports = {
clearMocks: true, clearMocks: true,
moduleFileExtensions: ['js', 'ts'], moduleFileExtensions: ["js", "ts"],
testMatch: ['**/*.test.ts'], testMatch: ["**/*.test.ts"],
transform: { transform: {
'^.+\\.ts$': 'ts-jest' "^.+\\.ts$": "ts-jest",
}, },
verbose: true, verbose: true,
modulePaths: [ modulePaths: ["<rootDir>/src/"],
"<rootDir>/src/" };
],
}

3384
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -17,12 +17,11 @@
"scripts": { "scripts": {
"prepublishOnly": "npm run build", "prepublishOnly": "npm run build",
"build": "tsc", "build": "tsc",
"format": "prettier --write **/**.ts", "format": "prettier --write .",
"format-check": "prettier --check **/**.ts", "format-check": "prettier --check .",
"lint": "eslint src/**/*.ts",
"package": "ncc build --source-map --license licenses.txt", "package": "ncc build --source-map --license licenses.txt",
"test": "jest --runInBand --config ./jest.config.js", "test": "jest --runInBand --config ./jest.config.js",
"all": "npm run build && npm run format && npm run lint && npm run package && npm test" "all": "npm run build && npm run format-check && npm run package && npm test"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -49,11 +48,7 @@
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^22.19.7", "@types/node": "^22.19.7",
"@typescript-eslint/parser": "^6.21.0",
"@vercel/ncc": "^0.38.4", "@vercel/ncc": "^0.38.4",
"eslint": "^8.57.1",
"eslint-plugin-github": "^4.10.2",
"eslint-plugin-jest": "^27.9.0",
"jest": "^30.2.0", "jest": "^30.2.0",
"js-yaml": "^4.1.1", "js-yaml": "^4.1.1",
"prettier": "^3.8.0", "prettier": "^3.8.0",

View file

@ -1,104 +1,117 @@
import { ActionConfig } from "../ActionConfig";
import { ActionConfig } from '../ActionConfig'; import { DefaultTagFormatter } from "./DefaultTagFormatter";
import { DefaultTagFormatter } from './DefaultTagFormatter';
/** Default tag formatter which allows a prefix to be specified */ /** Default tag formatter which allows a prefix to be specified */
export class BranchVersioningTagFormatter extends DefaultTagFormatter { export class BranchVersioningTagFormatter extends DefaultTagFormatter {
private onVersionBranch: boolean;
private major: number;
private minor?: number;
private onVersionBranch: boolean; private getRegex(pattern: string) {
private major: number; if (/^\/.+\/[i]*$/.test(pattern)) {
private minor?: number; const regexEnd = pattern.lastIndexOf("/");
const parsedFlags = pattern.slice(pattern.lastIndexOf("/") + 1);
return new RegExp(pattern.slice(1, regexEnd), parsedFlags);
}
return new RegExp(pattern);
}
private getRegex(pattern: string) { constructor(config: ActionConfig, branchName: string) {
if (/^\/.+\/[i]*$/.test(pattern)) { super(config);
const regexEnd = pattern.lastIndexOf('/'); const pattern =
const parsedFlags = pattern.slice(pattern.lastIndexOf('/') + 1); config.versionFromBranch === true
return new RegExp(pattern.slice(1, regexEnd), parsedFlags); ? new RegExp("[0-9]+.[0-9]+$|[0-9]+$")
} : this.getRegex(config.versionFromBranch as string);
return new RegExp(pattern); const result = pattern.exec(branchName);
if (result === null) {
this.major = NaN;
this.onVersionBranch = false;
return;
} }
constructor(config: ActionConfig, branchName: string) { let branchVersion: string;
super(config); switch (result?.length) {
const pattern = config.versionFromBranch === true ? case 1:
new RegExp("[0-9]+.[0-9]+$|[0-9]+$") : branchVersion = result[0];
this.getRegex(config.versionFromBranch as string); break;
const result = pattern.exec(branchName); case 2:
branchVersion = result[1];
if (result === null) { break;
this.major = NaN; default:
this.onVersionBranch = false; throw new Error(
return; `Unable to parse version from branch named '${branchName}' using pattern '${pattern}'`,
} );
let branchVersion: string;
switch (result?.length) {
case 1:
branchVersion = result[0];
break;
case 2:
branchVersion = result[1];
break;
default:
throw new Error(`Unable to parse version from branch named '${branchName}' using pattern '${pattern}'`);
}
this.onVersionBranch = true;
const versionValues = branchVersion.split('.');
if (versionValues.length > 2) {
throw new Error(`The version string '${branchVersion}' parsed from branch '${branchName}' is invalid. It must be in the format 'major.minor' or 'major'`);
}
this.major = parseInt(versionValues[0]);
if (isNaN(this.major)) {
throw new Error(`The major version '${versionValues[0]}' parsed from branch '${branchName}' is invalid. It must be a number.`);
}
if (versionValues.length > 1) {
this.minor = parseInt(versionValues[1]);
if (isNaN(this.minor)) {
throw new Error(`The minor version '${versionValues[1]}' parsed from branch '${branchName}' is invalid. It must be a number.`);
}
}
} }
public override GetPattern(): string { this.onVersionBranch = true;
let pattern = super.GetPattern();
if (!this.onVersionBranch) {
return pattern;
}
if(this.minor === undefined) { const versionValues = branchVersion.split(".");
return pattern.replace('*[0-9].*[0-9].*[0-9]', `${this.major}.*[0-9].*[0-9]`); if (versionValues.length > 2) {
} throw new Error(
`The version string '${branchVersion}' parsed from branch '${branchName}' is invalid. It must be in the format 'major.minor' or 'major'`,
);
}
this.major = parseInt(versionValues[0]);
if (isNaN(this.major)) {
throw new Error(
`The major version '${versionValues[0]}' parsed from branch '${branchName}' is invalid. It must be a number.`,
);
}
if (versionValues.length > 1) {
this.minor = parseInt(versionValues[1]);
if (isNaN(this.minor)) {
throw new Error(
`The minor version '${versionValues[1]}' parsed from branch '${branchName}' is invalid. It must be a number.`,
);
}
}
}
return pattern.replace('*[0-9].*[0-9].*[0-9]', `${this.major}.${this.minor}.*[0-9]`); public override GetPattern(): string {
let pattern = super.GetPattern();
if (!this.onVersionBranch) {
return pattern;
} }
override IsValid(tag: string): boolean { if (this.minor === undefined) {
if (!this.onVersionBranch) { return pattern.replace(
return super.IsValid(tag); "*[0-9].*[0-9].*[0-9]",
} `${this.major}.*[0-9].*[0-9]`,
);
if (!super.IsValid(tag)) {
return false;
}
const parsed = super.Parse(tag);
if (parsed[0] !== this.major) {
return false;
}
if (this.minor !== undefined && parsed[1] !== this.minor) {
return false;
}
return true;
} }
override Parse(tag: string): [major: number, minor: number, patch: number] { return pattern.replace(
if (!this.onVersionBranch) { "*[0-9].*[0-9].*[0-9]",
return super.Parse(tag); `${this.major}.${this.minor}.*[0-9]`,
} );
}
const parsed = super.Parse(tag); override IsValid(tag: string): boolean {
return [this.major, this.minor || parsed[1], parsed[2]]; if (!this.onVersionBranch) {
return super.IsValid(tag);
} }
}
if (!super.IsValid(tag)) {
return false;
}
const parsed = super.Parse(tag);
if (parsed[0] !== this.major) {
return false;
}
if (this.minor !== undefined && parsed[1] !== this.minor) {
return false;
}
return true;
}
override Parse(tag: string): [major: number, minor: number, patch: number] {
if (!this.onVersionBranch) {
return super.Parse(tag);
}
const parsed = super.Parse(tag);
return [this.major, this.minor || parsed[1], parsed[2]];
}
}

View file

@ -1,14 +1,13 @@
import { ActionConfig } from '../ActionConfig'; import { ActionConfig } from "../ActionConfig";
import { UserInfo } from '../providers/UserInfo'; import { UserInfo } from "../providers/UserInfo";
import { UserFormatter } from './UserFormatter'; import { UserFormatter } from "./UserFormatter";
export class CsvUserFormatter implements UserFormatter { export class CsvUserFormatter implements UserFormatter {
constructor(config: ActionConfig) { constructor(config: ActionConfig) {
// placeholder for consistency with other formatters // placeholder for consistency with other formatters
} }
public Format(type: string, users: UserInfo[]): string { public Format(type: string, users: UserInfo[]): string {
return users.map(user => `${user.name} <${user.email}>`).join(', '); return users.map((user) => `${user.name} <${user.email}>`).join(", ");
} }
} }

View file

@ -1,10 +1,9 @@
import { TagFormatter } from './TagFormatter'; import { TagFormatter } from "./TagFormatter";
import { VersionInformation } from "../providers/VersionInformation"; import { VersionInformation } from "../providers/VersionInformation";
import { ActionConfig } from '../ActionConfig'; import { ActionConfig } from "../ActionConfig";
/** Default tag formatter which allows a prefix to be specified */ /** Default tag formatter which allows a prefix to be specified */
export class DefaultTagFormatter implements TagFormatter { export class DefaultTagFormatter implements TagFormatter {
private tagPrefix: string; private tagPrefix: string;
private namespace: string; private namespace: string;
private namespaceSeparator: string; private namespaceSeparator: string;
@ -12,7 +11,7 @@ export class DefaultTagFormatter implements TagFormatter {
constructor(config: ActionConfig) { constructor(config: ActionConfig) {
this.namespace = config.namespace; this.namespace = config.namespace;
this.tagPrefix = config.tagPrefix; this.tagPrefix = config.tagPrefix;
this.namespaceSeparator = '-'; // maybe make configurable in the future this.namespaceSeparator = "-"; // maybe make configurable in the future
} }
public Format(versionInfo: VersionInformation): string { public Format(versionInfo: VersionInformation): string {
@ -26,7 +25,6 @@ export class DefaultTagFormatter implements TagFormatter {
} }
public GetPattern(): string { public GetPattern(): string {
if (this.namespace) { if (this.namespace) {
return `${this.tagPrefix}*[0-9].*[0-9].*[0-9]${this.namespaceSeparator}${this.namespace}`; return `${this.tagPrefix}*[0-9].*[0-9].*[0-9]${this.namespaceSeparator}${this.namespace}`;
} }
@ -35,24 +33,23 @@ export class DefaultTagFormatter implements TagFormatter {
} }
public Parse(tag: string): [major: number, minor: number, patch: number] { public Parse(tag: string): [major: number, minor: number, patch: number] {
if (tag === "") {
if(tag === '') {
return [0, 0, 0]; return [0, 0, 0];
} }
let tagParts = tag let tagParts = tag
.replace(this.tagPrefix, '<--!PREFIX!-->') .replace(this.tagPrefix, "<--!PREFIX!-->")
.replace(this.namespace, '<--!NAMESPACE!-->') .replace(this.namespace, "<--!NAMESPACE!-->")
.split('/'); .split("/");
const stripedTag = tagParts[tagParts.length - 1] const stripedTag = tagParts[tagParts.length - 1]
.replace('<--!PREFIX!-->', this.tagPrefix) .replace("<--!PREFIX!-->", this.tagPrefix)
.replace('<--!NAMESPACE!-->', this.namespace); .replace("<--!NAMESPACE!-->", this.namespace);
let versionValues = stripedTag let versionValues = stripedTag
.substring(this.tagPrefix.length) .substring(this.tagPrefix.length)
.slice(0, this.namespace === '' ? 999 : -(this.namespace.length + 1)) .slice(0, this.namespace === "" ? 999 : -(this.namespace.length + 1))
.split('.'); .split(".");
let major = parseInt(versionValues[0]); let major = parseInt(versionValues[0]);
let minor = versionValues.length > 1 ? parseInt(versionValues[1]) : 0; let minor = versionValues.length > 1 ? parseInt(versionValues[1]) : 0;
@ -66,13 +63,15 @@ export class DefaultTagFormatter implements TagFormatter {
} }
public IsValid(tag: string): boolean { public IsValid(tag: string): boolean {
const regexEscape = (literal: string) => literal.replace(/\W/g, '\\$&'); const regexEscape = (literal: string) => literal.replace(/\W/g, "\\$&");
const tagPrefix = regexEscape(this.tagPrefix); const tagPrefix = regexEscape(this.tagPrefix);
const namespaceSeparator = regexEscape(this.namespaceSeparator); const namespaceSeparator = regexEscape(this.namespaceSeparator);
const namespace = regexEscape(this.namespace); const namespace = regexEscape(this.namespace);
if (this.namespace) { if (this.namespace) {
return new RegExp(`^${tagPrefix}[0-9]+\\.[0-9]+\\.[0-9]+${namespaceSeparator}${namespace}$`).test(tag); return new RegExp(
`^${tagPrefix}[0-9]+\\.[0-9]+\\.[0-9]+${namespaceSeparator}${namespace}$`,
).test(tag);
} }
return new RegExp(`^${tagPrefix}[0-9]+\\.[0-9]+\\.[0-9]+$`).test(tag); return new RegExp(`^${tagPrefix}[0-9]+\\.[0-9]+\\.[0-9]+$`).test(tag);

View file

@ -1,9 +1,8 @@
import { VersionFormatter } from './VersionFormatter'; import { VersionFormatter } from "./VersionFormatter";
import { VersionInformation } from "../providers/VersionInformation"; import { VersionInformation } from "../providers/VersionInformation";
import { ActionConfig } from '../ActionConfig'; import { ActionConfig } from "../ActionConfig";
export class DefaultVersionFormatter implements VersionFormatter { export class DefaultVersionFormatter implements VersionFormatter {
private formatString: string; private formatString: string;
constructor(config: ActionConfig) { constructor(config: ActionConfig) {
@ -12,9 +11,9 @@ export class DefaultVersionFormatter implements VersionFormatter {
public Format(versionInfo: VersionInformation): string { public Format(versionInfo: VersionInformation): string {
return this.formatString return this.formatString
.replace('${major}', versionInfo.major.toString()) .replace("${major}", versionInfo.major.toString())
.replace('${minor}', versionInfo.minor.toString()) .replace("${minor}", versionInfo.minor.toString())
.replace('${patch}', versionInfo.patch.toString()) .replace("${patch}", versionInfo.patch.toString())
.replace('${increment}', versionInfo.increment.toString()); .replace("${increment}", versionInfo.increment.toString());
} }
} }

View file

@ -1,13 +1,13 @@
import { ActionConfig } from '../ActionConfig'; import { ActionConfig } from "../ActionConfig";
import { UserInfo } from '../providers/UserInfo'; import { UserInfo } from "../providers/UserInfo";
import { UserFormatter } from './UserFormatter'; import { UserFormatter } from "./UserFormatter";
export class JsonUserFormatter implements UserFormatter { export class JsonUserFormatter implements UserFormatter {
constructor(config: ActionConfig) { constructor(config: ActionConfig) {
// placeholder for consistency with other formatters // placeholder for consistency with other formatters
} }
public Format(type: string, users: UserInfo[]): string { public Format(type: string, users: UserInfo[]): string {
let result: any = users.map(u => ({ name: u.name, email: u.email })); let result: any = users.map((u) => ({ name: u.name, email: u.email }));
return JSON.stringify(result).replace('\n', ''); return JSON.stringify(result).replace("\n", "");
} }
} }

View file

@ -7,87 +7,108 @@ import { VersionClassification } from "./VersionClassification";
import { VersionType } from "./VersionType"; import { VersionType } from "./VersionType";
export class BumpAlwaysVersionClassifier extends DefaultVersionClassifier { export class BumpAlwaysVersionClassifier extends DefaultVersionClassifier {
protected patchPattern: (commit: CommitInfo) => boolean;
protected enablePrereleaseMode: boolean;
protected patchPattern: (commit: CommitInfo) => boolean; constructor(config: ActionConfig) {
protected enablePrereleaseMode: boolean; super(config);
constructor(config: ActionConfig) { this.enablePrereleaseMode = config.enablePrereleaseMode;
super(config); this.patchPattern = !config.bumpEachCommitPatchPattern
? (_) => true
: this.parsePattern(
config.bumpEachCommitPatchPattern,
"",
config.searchCommitBody,
);
}
this.enablePrereleaseMode = config.enablePrereleaseMode; public override async ClassifyAsync(
this.patchPattern = !config.bumpEachCommitPatchPattern ? lastRelease: ReleaseInformation,
_ => true : commitSet: CommitInfoSet,
this.parsePattern(config.bumpEachCommitPatchPattern, "", config.searchCommitBody); ): Promise<VersionClassification> {
if (lastRelease.currentPatch !== null) {
return new VersionClassification(
VersionType.None,
0,
false,
<number>lastRelease.currentMajor,
<number>lastRelease.currentMinor,
<number>lastRelease.currentPatch,
);
} }
public override async ClassifyAsync(lastRelease: ReleaseInformation, commitSet: CommitInfoSet): Promise<VersionClassification> { let { major, minor, patch } = lastRelease;
let type = VersionType.None;
let increment = 0;
if (lastRelease.currentPatch !== null) { if (commitSet.commits.length === 0) {
return new VersionClassification(VersionType.None, 0, false, <number>lastRelease.currentMajor, <number>lastRelease.currentMinor, <number>lastRelease.currentPatch); return new VersionClassification(type, 0, false, major, minor, patch);
}
let { major, minor, patch } = lastRelease;
let type = VersionType.None;
let increment = 0;
if (commitSet.commits.length === 0) {
return new VersionClassification(type, 0, false, major, minor, patch);
}
for (let commit of commitSet.commits.reverse()) {
if (this.majorPattern(commit)) {
type = VersionType.Major;
} else if (this.minorPattern(commit)) {
type = VersionType.Minor;
} else if (this.patchPattern(commit) ||
(major === 0 && minor === 0 && patch === 0 && commitSet.commits.length > 0)) {
type = VersionType.Patch;
} else {
type = VersionType.None;
}
if (this.enablePrereleaseMode && major === 0) {
switch (type) {
case VersionType.Major:
case VersionType.Minor:
minor += 1;
patch = 0;
increment = 0;
break;
case VersionType.Patch:
patch += 1;
increment = 0;
break;
default:
increment++;
break;
}
} else {
switch (type) {
case VersionType.Major:
major += 1;
minor = 0;
patch = 0;
increment = 0;
break;
case VersionType.Minor:
minor += 1;
patch = 0;
break;
case VersionType.Patch:
patch += 1;
increment = 0;
break;
default:
increment++;
break;
}
}
}
return new VersionClassification(type, increment, true, major, minor, patch);
} }
}
for (let commit of commitSet.commits.reverse()) {
if (this.majorPattern(commit)) {
type = VersionType.Major;
} else if (this.minorPattern(commit)) {
type = VersionType.Minor;
} else if (
this.patchPattern(commit) ||
(major === 0 &&
minor === 0 &&
patch === 0 &&
commitSet.commits.length > 0)
) {
type = VersionType.Patch;
} else {
type = VersionType.None;
}
if (this.enablePrereleaseMode && major === 0) {
switch (type) {
case VersionType.Major:
case VersionType.Minor:
minor += 1;
patch = 0;
increment = 0;
break;
case VersionType.Patch:
patch += 1;
increment = 0;
break;
default:
increment++;
break;
}
} else {
switch (type) {
case VersionType.Major:
major += 1;
minor = 0;
patch = 0;
increment = 0;
break;
case VersionType.Minor:
minor += 1;
patch = 0;
break;
case VersionType.Patch:
patch += 1;
increment = 0;
break;
default:
increment++;
break;
}
}
}
return new VersionClassification(
type,
increment,
true,
major,
minor,
patch,
);
}
}

View file

@ -23,5 +23,6 @@ export class CommitInfo {
public committer: string, public committer: string,
public committerEmail: string, public committerEmail: string,
public committerDate: Date, public committerDate: Date,
public tags: string[]) { } public tags: string[],
) {}
} }

View file

@ -2,8 +2,8 @@ import { CommitInfo } from "./CommitInfo";
/** Represents information about a set of commits */ /** Represents information about a set of commits */
export class CommitInfoSet { export class CommitInfoSet {
constructor( constructor(
public changed: boolean, public changed: boolean,
public commits: CommitInfo[] public commits: CommitInfo[],
){} ) {}
} }

View file

@ -5,90 +5,93 @@ import { CommitInfoSet } from "./CommitInfoSet";
import { CommitsProvider } from "./CommitsProvider"; import { CommitsProvider } from "./CommitsProvider";
export class DefaultCommitsProvider implements CommitsProvider { export class DefaultCommitsProvider implements CommitsProvider {
private changePath: string;
private changePath: string; constructor(config: ActionConfig) {
this.changePath = config.changePath;
}
constructor(config: ActionConfig) { async GetCommitsAsync(
this.changePath = config.changePath; startHash: string,
endHash: string,
): Promise<CommitInfoSet> {
const logSplitter = `@@@START_RECORD`;
const formatPlaceholders = Object.entries({
hash: "%H",
subject: "%s",
body: "%b",
author: "%an",
authorEmail: "%ae",
authorDate: "%aI",
committer: "%cn",
committerEmail: "%ce",
committerDate: "%cI",
tags: "%d",
});
const pretty =
logSplitter +
"%n" +
formatPlaceholders.map((x) => `@@@${x[0]}%n${x[1]}`).join("%n");
var logCommand = `git log --pretty="${pretty}" --author-date-order ${startHash === "" ? endHash : `${startHash}..${endHash}`}`;
if (this.changePath !== "") {
logCommand += ` -- ${this.changePath}`;
} }
async GetCommitsAsync(startHash: string, endHash: string): Promise<CommitInfoSet> { const log = await cmd(logCommand);
const logSplitter = `@@@START_RECORD` const entries = log.split(logSplitter).slice(1);
const formatPlaceholders = Object.entries({
hash: '%H',
subject: '%s',
body: '%b',
author: '%an',
authorEmail: '%ae',
authorDate: '%aI',
committer: '%cn',
committerEmail: '%ce',
committerDate: '%cI',
tags: '%d'
});
const pretty = logSplitter + '%n' + formatPlaceholders const commits = entries.map((entry) => {
.map(x => `@@@${x[0]}%n${x[1]}`) const fields: any = entry
.join('%n'); .split(`@@@`)
.slice(1)
.reduce((acc: any, value: string) => {
const firstLine = value.indexOf("\n");
const key = value.substring(0, firstLine);
acc[key] = value.substring(firstLine + 1).trim();
return acc;
}, {});
var logCommand = `git log --pretty="${pretty}" --author-date-order ${(startHash === '' ? endHash : `${startHash}..${endHash}`)}`; const tags = fields.tags
.split(",")
.map((v: string) => v.trim())
.filter((v: string) => v.startsWith("tags: "))
.map((v: string) => v.substring(5).trim());
if (this.changePath !== '') { return new CommitInfo(
logCommand += ` -- ${this.changePath}`; fields.hash,
} fields.subject,
fields.body,
fields.author,
fields.authorEmail,
new Date(fields.authorDate),
fields.committer,
fields.committerEmail,
new Date(fields.committerDate),
tags,
);
});
const log = await cmd(logCommand); // check for changes
const entries = log
.split(logSplitter)
.slice(1);
const commits = entries.map(entry => {
const fields: any = entry
.split(`@@@`)
.slice(1)
.reduce((acc: any, value: string) => {
const firstLine = value.indexOf('\n');
const key = value.substring(0, firstLine);
acc[key] = value.substring(firstLine + 1).trim();
return acc;
}, {});
const tags = fields.tags
.split(',')
.map((v: string) => v.trim())
.filter((v: string) => v.startsWith('tags: '))
.map((v: string) => v.substring(5).trim());
return new CommitInfo(
fields.hash,
fields.subject,
fields.body,
fields.author,
fields.authorEmail,
new Date(fields.authorDate),
fields.committer,
fields.committerEmail,
new Date(fields.committerDate),
tags
);
});
// check for changes
let changed = true;
if (this.changePath !== '') {
if (startHash === '') {
const changedFiles = await cmd(`git log --name-only --oneline ${endHash} -- ${this.changePath}`);
changed = changedFiles.length > 0;
} else {
const changedFiles = await cmd(`git diff --name-only ${startHash}..${endHash} -- ${this.changePath}`);
changed = changedFiles.length > 0;
}
}
return new CommitInfoSet(changed, commits);
let changed = true;
if (this.changePath !== "") {
if (startHash === "") {
const changedFiles = await cmd(
`git log --name-only --oneline ${endHash} -- ${this.changePath}`,
);
changed = changedFiles.length > 0;
} else {
const changedFiles = await cmd(
`git diff --name-only ${startHash}..${endHash} -- ${this.changePath}`,
);
changed = changedFiles.length > 0;
}
} }
}
return new CommitInfoSet(changed, commits);
}
}

View file

@ -2,32 +2,31 @@ import { ActionConfig } from "../ActionConfig";
import { cmd } from "../CommandRunner"; import { cmd } from "../CommandRunner";
import { CurrentCommitResolver } from "./CurrentCommitResolver"; import { CurrentCommitResolver } from "./CurrentCommitResolver";
export class DefaultCurrentCommitResolver implements CurrentCommitResolver { export class DefaultCurrentCommitResolver implements CurrentCommitResolver {
private branch: string;
private branch: string; constructor(config: ActionConfig) {
this.branch = config.branch;
}
constructor(config: ActionConfig) { public async ResolveAsync(): Promise<string> {
this.branch = config.branch; if (this.branch === "HEAD") {
return (await cmd("git", "rev-parse", "HEAD")).trim();
} }
return this.branch;
}
public async ResolveAsync(): Promise<string> { public async IsEmptyRepoAsync(): Promise<boolean> {
if (this.branch === 'HEAD') { let lastCommitAll = (await cmd("git", "rev-list", "-n1", "--all")).trim();
return (await cmd('git', 'rev-parse', 'HEAD')).trim(); return lastCommitAll === "";
} }
return this.branch;
}
public async IsEmptyRepoAsync(): Promise<boolean> { public async ResolveBranchNameAsync(): Promise<string> {
let lastCommitAll = (await cmd('git', 'rev-list', '-n1', '--all')).trim(); const branchName =
return lastCommitAll === ''; this.branch == "HEAD"
} ? await cmd("git", "rev-parse", "--abbrev-ref", "HEAD")
: this.branch;
public async ResolveBranchNameAsync(): Promise<string> { return branchName.trim();
const branchName = }
this.branch == 'HEAD' ? await cmd('git', 'rev-parse', '--abbrev-ref', 'HEAD') : this.branch; }
return branchName.trim();
}
}

View file

@ -3,80 +3,101 @@ import { TagFormatter } from "../formatting/TagFormatter";
import { LastReleaseResolver } from "./LastReleaseResolver"; import { LastReleaseResolver } from "./LastReleaseResolver";
import { ReleaseInformation } from "./ReleaseInformation"; import { ReleaseInformation } from "./ReleaseInformation";
import { ActionConfig } from "../ActionConfig"; import { ActionConfig } from "../ActionConfig";
import * as core from '@actions/core'; import * as core from "@actions/core";
export class DefaultLastReleaseResolver implements LastReleaseResolver { export class DefaultLastReleaseResolver implements LastReleaseResolver {
private changePath: string;
private useBranches: boolean;
private changePath: string; constructor(config: ActionConfig) {
private useBranches: boolean; this.changePath = config.changePath;
this.useBranches = config.useBranches;
}
constructor(config: ActionConfig) { async ResolveAsync(
this.changePath = config.changePath; current: string,
this.useBranches = config.useBranches; tagFormatter: TagFormatter,
): Promise<ReleaseInformation> {
const releasePattern = tagFormatter.GetPattern();
let currentTag = (
await cmd(`git tag --points-at ${current} ${releasePattern}`)
).trim();
currentTag = tagFormatter.IsValid(currentTag) ? currentTag : "";
const isTagged = currentTag !== "";
const [currentMajor, currentMinor, currentPatch] = currentTag
? tagFormatter.Parse(currentTag)
: [null, null, null];
let tagsCount = 0;
let tag = "";
try {
const refPrefixPattern = this.useBranches ? "refs/heads/" : "refs/tags/";
if (currentTag) {
// If we already have the current branch tagged, we are checking for the previous one
// so that we will have an accurate increment (assuming the new tag is the expected one)
const command = `git for-each-ref --sort=-v:*refname --format=%(refname:short) --merged=${current} ${refPrefixPattern}${releasePattern}`;
const tags = (await cmd(command)).split("\n");
tagsCount = tags.length;
tag =
tags.find((t) => tagFormatter.IsValid(t) && t !== currentTag) || "";
} else {
const command = `git for-each-ref --sort=-v:*refname --format=%(refname:short) --merged=${current} ${refPrefixPattern}${releasePattern}`;
const tags = (await cmd(command)).split("\n");
tagsCount = tags.length;
tag = tags.find((t) => tagFormatter.IsValid(t)) || "";
}
tag = tag.trim();
} catch (err) {
tag = "";
} }
async ResolveAsync(current: string, tagFormatter: TagFormatter): Promise<ReleaseInformation> { if (tag === "") {
const releasePattern = tagFormatter.GetPattern(); if ((await cmd("git", "remote")) !== "") {
// Since there is no remote, we assume that there are no other tags to pull. In
// practice this isn't likely to happen, but it keeps the test output from being
// polluted with a bunch of warnings.
let currentTag = (await cmd( if (tagsCount > 0) {
`git tag --points-at ${current} ${releasePattern}` core.warning(
)).trim(); `None of the ${tagsCount} tags(s) found were valid version tags for the present configuration. If this is unexpected, check to ensure that the configuration is correct and matches the tag format you are using. If you have not yet tagged this repo with a version tag, this can be ignored.`,
);
currentTag = tagFormatter.IsValid(currentTag) ? currentTag : ''; } else {
const isTagged = currentTag !== ''; core.warning(
"No tags are present for this repository. If this is unexpected, check to ensure that tags have been pulled from the remote. If you have not yet tagged this repo with a version tag, this can be ignored.",
const [currentMajor, currentMinor, currentPatch] = currentTag ? tagFormatter.Parse(currentTag) : [null, null, null]; );
let tagsCount = 0;
let tag = '';
try {
const refPrefixPattern = this.useBranches ? 'refs/heads/' : 'refs/tags/';
if (currentTag) {
// If we already have the current branch tagged, we are checking for the previous one
// so that we will have an accurate increment (assuming the new tag is the expected one)
const command = `git for-each-ref --sort=-v:*refname --format=%(refname:short) --merged=${current} ${refPrefixPattern}${releasePattern}`;
const tags = (await cmd(command)).split('\n')
tagsCount = tags.length;
tag = tags
.find(t => tagFormatter.IsValid(t) && t !== currentTag) || '';
} else {
const command = `git for-each-ref --sort=-v:*refname --format=%(refname:short) --merged=${current} ${refPrefixPattern}${releasePattern}`;
const tags = (await cmd(command)).split('\n')
tagsCount = tags.length;
tag = tags
.find(t => tagFormatter.IsValid(t)) || '';
}
tag = tag.trim();
} }
catch (err) { }
tag = ''; const [major, minor, patch] = tagFormatter.Parse("");
} // no release tags yet, use the initial commit as the root
return new ReleaseInformation(
if (tag === '') { major,
if (await cmd('git', 'remote') !== '') { minor,
patch,
// Since there is no remote, we assume that there are no other tags to pull. In "",
// practice this isn't likely to happen, but it keeps the test output from being currentMajor,
// polluted with a bunch of warnings. currentMinor,
currentPatch,
if (tagsCount > 0) { isTagged,
core.warning(`None of the ${tagsCount} tags(s) found were valid version tags for the present configuration. If this is unexpected, check to ensure that the configuration is correct and matches the tag format you are using. If you have not yet tagged this repo with a version tag, this can be ignored.`); );
} else {
core.warning('No tags are present for this repository. If this is unexpected, check to ensure that tags have been pulled from the remote. If you have not yet tagged this repo with a version tag, this can be ignored.');
}
}
const [major, minor, patch] = tagFormatter.Parse('');
// no release tags yet, use the initial commit as the root
return new ReleaseInformation(major, minor, patch, '', currentMajor, currentMinor, currentPatch, isTagged);
}
// parse the version tag
const [major, minor, patch] = tagFormatter.Parse(tag);
const root = await cmd('git', `merge-base`, tag, current);
return new ReleaseInformation(major, minor, patch, root.trim(), currentMajor, currentMinor, currentPatch, isTagged);
} }
} // parse the version tag
const [major, minor, patch] = tagFormatter.Parse(tag);
const root = await cmd("git", `merge-base`, tag, current);
return new ReleaseInformation(
major,
minor,
patch,
root.trim(),
currentMajor,
currentMinor,
currentPatch,
isTagged,
);
}
}

View file

@ -5,20 +5,53 @@ import { CommitInfoSet } from "./CommitInfoSet";
import { DefaultVersionClassifier } from "./DefaultVersionClassifier"; import { DefaultVersionClassifier } from "./DefaultVersionClassifier";
import { ReleaseInformation } from "./ReleaseInformation"; import { ReleaseInformation } from "./ReleaseInformation";
test('Regular expressions can be used as minor tag direct', async () => { test("Regular expressions can be used as minor tag direct", async () => {
const classifier = new DefaultVersionClassifier({
...new ActionConfig(),
...{ tagPrefix: "", minorPattern: "/S[a-z]+Value/" },
});
const classifier = new DefaultVersionClassifier({ ...new ActionConfig(), ...{ tagPrefix: '', minorPattern: '/S[a-z]+Value/' }}); const releaseInfo = new ReleaseInformation(
0,
0,
1,
"",
null,
null,
null,
false,
);
const commitSet = new CommitInfoSet(false, [
new CommitInfo(
"",
"Second Commit SomeValue",
"",
"",
"",
new Date(),
"",
"",
new Date(),
[],
),
new CommitInfo(
"",
"Initial Commit",
"",
"",
"",
new Date(),
"",
"",
new Date(),
[],
),
]);
const releaseInfo =new ReleaseInformation(0,0,1,"",null,null,null,false); const result = await classifier.ClassifyAsync(releaseInfo, commitSet);
const commitSet = new CommitInfoSet(false, [
new CommitInfo("", "Second Commit SomeValue", "", "","", new Date(), "", "", new Date(), []),
new CommitInfo("", "Initial Commit", "", "","", new Date(), "", "", new Date(), []),
]);
const result = await classifier.ClassifyAsync(releaseInfo, commitSet); expect(result.major).toBe(0);
expect(result.minor).toBe(1);
expect(result.major).toBe(0); expect(result.patch).toBe(0);
expect(result.minor).toBe(1); expect(result.increment).toBe(0);
expect(result.patch).toBe(0); });
expect(result.increment).toBe(0);
});

View file

@ -7,111 +7,184 @@ import { VersionClassifier } from "./VersionClassifier";
import { VersionType } from "./VersionType"; import { VersionType } from "./VersionType";
export class DefaultVersionClassifier implements VersionClassifier { export class DefaultVersionClassifier implements VersionClassifier {
protected majorPattern: (commit: CommitInfo) => boolean;
protected minorPattern: (commit: CommitInfo) => boolean;
protected enablePrereleaseMode: boolean;
protected majorPattern: (commit: CommitInfo) => boolean; constructor(config: ActionConfig) {
protected minorPattern: (commit: CommitInfo) => boolean; const searchBody = config.searchCommitBody;
protected enablePrereleaseMode: boolean; this.majorPattern = this.parsePattern(
config.majorPattern,
config.majorFlags,
searchBody,
);
this.minorPattern = this.parsePattern(
config.minorPattern,
config.minorFlags,
searchBody,
);
this.enablePrereleaseMode = config.enablePrereleaseMode;
}
constructor(config: ActionConfig) { protected parsePattern(
const searchBody = config.searchCommitBody; pattern: string,
this.majorPattern = this.parsePattern(config.majorPattern, config.majorFlags, searchBody); flags: string,
this.minorPattern = this.parsePattern(config.minorPattern, config.minorFlags, searchBody); searchBody: boolean,
this.enablePrereleaseMode = config.enablePrereleaseMode; ): (pattern: CommitInfo) => boolean {
if (/^\/.+\/[i]*$/.test(pattern)) {
const regexEnd = pattern.lastIndexOf("/");
const parsedFlags = pattern.slice(pattern.lastIndexOf("/") + 1);
const regex = new RegExp(
pattern.slice(1, regexEnd),
parsedFlags || flags,
);
return searchBody
? (commit: CommitInfo) =>
regex.test(commit.subject) || regex.test(commit.body)
: (commit: CommitInfo) => regex.test(commit.subject);
} else {
const matchString = pattern;
return searchBody
? (commit: CommitInfo) =>
commit.subject.includes(matchString) ||
commit.body.includes(matchString)
: (commit: CommitInfo) => commit.subject.includes(matchString);
}
}
protected getNextVersion(
current: ReleaseInformation,
type: VersionType,
): { major: number; minor: number; patch: number } {
if (this.enablePrereleaseMode && current.major === 0) {
switch (type) {
case VersionType.Major:
return { major: current.major, minor: current.minor + 1, patch: 0 };
case VersionType.Minor:
case VersionType.Patch:
return {
major: current.major,
minor: current.minor,
patch: current.patch + 1,
};
case VersionType.None:
return {
major: current.major,
minor: current.minor,
patch: current.patch,
};
default:
throw new Error(`Unknown change type: ${type}`);
}
} }
protected parsePattern(pattern: string, flags: string, searchBody: boolean): (pattern: CommitInfo) => boolean { switch (type) {
if (/^\/.+\/[i]*$/.test(pattern)) { case VersionType.Major:
const regexEnd = pattern.lastIndexOf('/'); return { major: current.major + 1, minor: 0, patch: 0 };
const parsedFlags = pattern.slice(pattern.lastIndexOf('/') + 1); case VersionType.Minor:
const regex = new RegExp(pattern.slice(1, regexEnd), parsedFlags || flags); return { major: current.major, minor: current.minor + 1, patch: 0 };
return searchBody ? case VersionType.Patch:
(commit: CommitInfo) => regex.test(commit.subject) || regex.test(commit.body) : return {
(commit: CommitInfo) => regex.test(commit.subject); major: current.major,
} else { minor: current.minor,
const matchString = pattern; patch: current.patch + 1,
return searchBody ? };
(commit: CommitInfo) => commit.subject.includes(matchString) || commit.body.includes(matchString) : case VersionType.None:
(commit: CommitInfo) => commit.subject.includes(matchString); return {
} major: current.major,
minor: current.minor,
patch: current.patch,
};
default:
throw new Error(`Unknown change type: ${type}`);
}
}
private resolveCommitType(commitsSet: CommitInfoSet): {
type: VersionType;
increment: number;
changed: boolean;
} {
if (commitsSet.commits.length === 0) {
return {
type: VersionType.None,
increment: 0,
changed: commitsSet.changed,
};
} }
protected getNextVersion(current: ReleaseInformation, type: VersionType): ({ major: number, minor: number, patch: number }) { const commits = commitsSet.commits.reverse();
let index = 1;
if (this.enablePrereleaseMode && current.major === 0) { for (let commit of commits) {
switch (type) { if (this.majorPattern(commit)) {
case VersionType.Major: return {
return { major: current.major, minor: current.minor + 1, patch: 0 }; type: VersionType.Major,
case VersionType.Minor: increment: commits.length - index,
case VersionType.Patch: changed: commitsSet.changed,
return { major: current.major, minor: current.minor, patch: current.patch + 1 }; };
case VersionType.None: }
return { major: current.major, minor: current.minor, patch: current.patch }; index++;
default:
throw new Error(`Unknown change type: ${type}`);
}
}
switch (type) {
case VersionType.Major:
return { major: current.major + 1, minor: 0, patch: 0 };
case VersionType.Minor:
return { major: current.major, minor: current.minor + 1, patch: 0 };
case VersionType.Patch:
return { major: current.major, minor: current.minor, patch: current.patch + 1 };
case VersionType.None:
return { major: current.major, minor: current.minor, patch: current.patch };
default:
throw new Error(`Unknown change type: ${type}`);
}
} }
private resolveCommitType(commitsSet: CommitInfoSet): ({ type: VersionType, increment: number, changed: boolean }) { index = 1;
if (commitsSet.commits.length === 0) { for (let commit of commits) {
return { type: VersionType.None, increment: 0, changed: commitsSet.changed }; if (this.minorPattern(commit)) {
} return {
type: VersionType.Minor,
const commits = commitsSet.commits.reverse(); increment: commits.length - index,
let index = 1; changed: commitsSet.changed,
for (let commit of commits) { };
if (this.majorPattern(commit)) { }
return { type: VersionType.Major, increment: commits.length - index, changed: commitsSet.changed }; index++;
}
index++;
}
index = 1;
for (let commit of commits) {
if (this.minorPattern(commit)) {
return { type: VersionType.Minor, increment: commits.length - index, changed: commitsSet.changed };
}
index++;
}
return { type: VersionType.Patch, increment: commitsSet.commits.length - 1, changed: true };
} }
public async ClassifyAsync(lastRelease: ReleaseInformation, commitSet: CommitInfoSet): Promise<VersionClassification> { return {
type: VersionType.Patch,
increment: commitsSet.commits.length - 1,
changed: true,
};
}
const { type, increment, changed } = this.resolveCommitType(commitSet); public async ClassifyAsync(
lastRelease: ReleaseInformation,
commitSet: CommitInfoSet,
): Promise<VersionClassification> {
const { type, increment, changed } = this.resolveCommitType(commitSet);
const { major, minor, patch } = this.getNextVersion(lastRelease, type); const { major, minor, patch } = this.getNextVersion(lastRelease, type);
if (lastRelease.currentPatch !== null) { if (lastRelease.currentPatch !== null) {
// If the current commit is tagged, we must use that version. Here we check if the version we have resolved from the // If the current commit is tagged, we must use that version. Here we check if the version we have resolved from the
// previous commits is the same as the current version. If it is, we will use the increment value, otherwise we reset // previous commits is the same as the current version. If it is, we will use the increment value, otherwise we reset
// to zero. For example: // to zero. For example:
// - commit 1 - v1.0.0+0 // - commit 1 - v1.0.0+0
// - commit 2 - v1.0.0+1 // - commit 2 - v1.0.0+1
// - commit 3 was tagged v2.0.0 - v2.0.0+0 // - commit 3 was tagged v2.0.0 - v2.0.0+0
// - commit 4 - v2.0.1+0 // - commit 4 - v2.0.1+0
const versionsMatch = lastRelease.currentMajor === major && lastRelease.currentMinor === minor && lastRelease.currentPatch === patch; const versionsMatch =
const currentIncrement = versionsMatch ? increment : 0; lastRelease.currentMajor === major &&
return new VersionClassification(VersionType.None, currentIncrement, false, <number>lastRelease.currentMajor, <number>lastRelease.currentMinor, <number>lastRelease.currentPatch); lastRelease.currentMinor === minor &&
} lastRelease.currentPatch === patch;
const currentIncrement = versionsMatch ? increment : 0;
return new VersionClassification(
return new VersionClassification(type, increment, changed, major, minor, patch); VersionType.None,
currentIncrement,
false,
<number>lastRelease.currentMajor,
<number>lastRelease.currentMinor,
<number>lastRelease.currentPatch,
);
} }
}
return new VersionClassification(
type,
increment,
changed,
major,
minor,
patch,
);
}
}

View file

@ -1,6 +1,9 @@
import { TagFormatter } from '../formatting/TagFormatter'; import { TagFormatter } from "../formatting/TagFormatter";
import { ReleaseInformation } from './ReleaseInformation'; import { ReleaseInformation } from "./ReleaseInformation";
export interface LastReleaseResolver { export interface LastReleaseResolver {
ResolveAsync(current: string, tagFormatter: TagFormatter): Promise<ReleaseInformation>; ResolveAsync(
current: string,
tagFormatter: TagFormatter,
): Promise<ReleaseInformation>;
} }

View file

@ -19,5 +19,6 @@ export class ReleaseInformation {
public currentMajor: number | null, public currentMajor: number | null,
public currentMinor: number | null, public currentMinor: number | null,
public currentPatch: number | null, public currentPatch: number | null,
public isTagged: boolean,) { } public isTagged: boolean,
) {}
} }

View file

@ -1,8 +1,7 @@
/** Represents information about a user (e.g. committer, author, tagger) */ /** Represents information about a user (e.g. committer, author, tagger) */
export class UserInfo { export class UserInfo {
/** /**
* Creates a new instance * Creates a new instance
* @param name - User's name * @param name - User's name
* @param email - User's email * @param email - User's email
* @param commits - Number of commits in the scope evaluated * @param commits - Number of commits in the scope evaluated
@ -10,5 +9,6 @@ export class UserInfo {
constructor( constructor(
public name: string, public name: string,
public email: string, public email: string,
public commits: number) { } public commits: number,
) {}
} }

View file

@ -1,4 +1,4 @@
import { VersionType } from './VersionType'; import { VersionType } from "./VersionType";
/** The result of a version classification */ /** The result of a version classification */
export class VersionClassification { export class VersionClassification {
@ -17,5 +17,6 @@ export class VersionClassification {
public changed: boolean, public changed: boolean,
public major: number, public major: number,
public minor: number, public minor: number,
public patch: number) { } public patch: number,
) {}
} }

View file

@ -13,5 +13,8 @@ export interface VersionClassifier {
* @param commitSet - The commits to classify, ordered from most recent to oldest * @param commitSet - The commits to classify, ordered from most recent to oldest
* @returns - The version classification * @returns - The version classification
*/ */
ClassifyAsync(lastRelease: ReleaseInformation, commitSet: CommitInfoSet): Promise<VersionClassification>; ClassifyAsync(
lastRelease: ReleaseInformation,
commitSet: CommitInfoSet,
): Promise<VersionClassification>;
} }

View file

@ -25,5 +25,6 @@ export class VersionInformation {
public type: VersionType, public type: VersionType,
public commits: CommitInfo[], public commits: CommitInfo[],
public changed: boolean, public changed: boolean,
public isTagged: boolean) { } public isTagged: boolean,
) {}
} }

View file

@ -1,12 +1,11 @@
/** Indicates the type of change a particular version change represents */ /** Indicates the type of change a particular version change represents */
export enum VersionType { export enum VersionType {
/** Indicates a major version change */ /** Indicates a major version change */
Major = 'Major', Major = "Major",
/** Indicates a minor version change */ /** Indicates a minor version change */
Minor = 'Minor', Minor = "Minor",
/** Indicates a patch version change */ /** Indicates a patch version change */
Patch = 'Patch', Patch = "Patch",
/** Indicates no change--generally this means that the current commit is already tagged with a version */ /** Indicates no change--generally this means that the current commit is already tagged with a version */
None = 'None' None = "None",
} }

View file

@ -1,12 +1,12 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
"outDir": "./lib", /* Redirect output structure to the directory. */ "outDir": "./lib" /* Redirect output structure to the directory. */,
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
"strict": true, /* Enable all strict type-checking options. */ "strict": true /* Enable all strict type-checking options. */,
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
}, },
"exclude": ["node_modules", "**/*.test.ts"] "exclude": ["node_modules", "**/*.test.ts"]
} }