diff --git a/dist/bump/index.js b/dist/bump/index.js index aeb32360..da8d70c1 100644 --- a/dist/bump/index.js +++ b/dist/bump/index.js @@ -34349,12 +34349,19 @@ function getNextSdkVer(currentVersion, sdkVerBumpType, isReleaseBranch, headMatc */ async function bumpSdkVer(config, bumpInfo, releaseMode, sdkVerBumpType, headSha, branchName, isBranchAllowedToPublish, createChangelog) { const isReleaseBranch = branchName.match(config.releaseBranches) !== null; - const hasBreakingChange = bumpInfo.processedCommits.some(c => c.message?.breakingChange); + let hasBreakingChange = bumpInfo.processedCommits.some(c => c.message?.breakingChange); if (!bumpInfo.foundVersion) return false; // should never happen // SdkVer requires a prerelease, so apply the default if not set config.prereleasePrefix = config.prereleasePrefix ?? "dev"; let cv = semver_1.SemVer.copy(bumpInfo.foundVersion); + // Do not bump major version when breaking change is found in case + // the max configured major version is already reached + if (config.sdkverMaxMajor !== undefined && + config.sdkverMaxMajor > 0 && + cv.major >= config.sdkverMaxMajor) { + hasBreakingChange = false; + } // Get the latest draft release matching our current version's prefix. // Don't look at the draft version on a release branch; the current version // should always reflect the version to be bumped (as no dev releases are @@ -35099,6 +35106,7 @@ const CONFIG_ITEMS = [ "release-branches", "prereleases", "sdkver-create-release-branches", + "sdkver-max-major", ]; const VERSION_SCHEMES = ["semver", "sdkver"]; /** @@ -35123,6 +35131,7 @@ class Configuration { tags = DEFAULT_ACCEPTED_TAGS; rules = new Map(); sdkverCreateReleaseBranches = undefined; + sdkverMaxMajor = 0; set initialDevelopment(initialDevelopment) { this._initialDevelopment = initialDevelopment; } @@ -35325,11 +35334,23 @@ class Configuration { throw new Error(`Incorrect type '${typeof data[key]}' for '${key}', must be either "boolean" or "string"!`); } break; + case "sdkver-max-major": + /* Example YAML: + * sdkver-max-major: 1 # defaults to 0 + */ + if (typeof data[key] === "number") { + this.sdkverMaxMajor = data[key]; + } + else { + throw new Error(`Incorrect type '${typeof data[key]}' for '${key}', must be '${typeof this.sdkverMaxMajor}'!`); + } + break; } } - if (this.sdkverCreateReleaseBranches !== undefined && + if ((this.sdkverCreateReleaseBranches !== undefined || + this.sdkverMaxMajor !== 0) && this.versionScheme !== "sdkver") { - core.warning("The configuration option `sdkver-create-release-branches` is only relevant " + + core.warning("The configuration options `sdkver-create-release-branches` and `sdkver-max-major` are only relevant " + 'when the `version-scheme` is set to `"sdkver"`.'); } } @@ -35366,6 +35387,7 @@ class Configuration { config.tags = JSON.parse(JSON.stringify(this.tags)); config.rules = new Map(JSON.parse(JSON.stringify(Array.from(this.rules)))); config.sdkverCreateReleaseBranches = this.sdkverCreateReleaseBranches; + config.sdkverMaxMajor = this.sdkverMaxMajor; return config; } } diff --git a/dist/cli/index.js b/dist/cli/index.js index 09519ab1..ad8b5a59 100755 --- a/dist/cli/index.js +++ b/dist/cli/index.js @@ -32919,6 +32919,7 @@ const CONFIG_ITEMS = [ "release-branches", "prereleases", "sdkver-create-release-branches", + "sdkver-max-major", ]; const VERSION_SCHEMES = ["semver", "sdkver"]; /** @@ -32943,6 +32944,7 @@ class Configuration { tags = DEFAULT_ACCEPTED_TAGS; rules = new Map(); sdkverCreateReleaseBranches = undefined; + sdkverMaxMajor = 0; set initialDevelopment(initialDevelopment) { this._initialDevelopment = initialDevelopment; } @@ -33145,11 +33147,23 @@ class Configuration { throw new Error(`Incorrect type '${typeof data[key]}' for '${key}', must be either "boolean" or "string"!`); } break; + case "sdkver-max-major": + /* Example YAML: + * sdkver-max-major: 1 # defaults to 0 + */ + if (typeof data[key] === "number") { + this.sdkverMaxMajor = data[key]; + } + else { + throw new Error(`Incorrect type '${typeof data[key]}' for '${key}', must be '${typeof this.sdkverMaxMajor}'!`); + } + break; } } - if (this.sdkverCreateReleaseBranches !== undefined && + if ((this.sdkverCreateReleaseBranches !== undefined || + this.sdkverMaxMajor !== 0) && this.versionScheme !== "sdkver") { - core.warning("The configuration option `sdkver-create-release-branches` is only relevant " + + core.warning("The configuration options `sdkver-create-release-branches` and `sdkver-max-major` are only relevant " + 'when the `version-scheme` is set to `"sdkver"`.'); } } @@ -33186,6 +33200,7 @@ class Configuration { config.tags = JSON.parse(JSON.stringify(this.tags)); config.rules = new Map(JSON.parse(JSON.stringify(Array.from(this.rules)))); config.sdkverCreateReleaseBranches = this.sdkverCreateReleaseBranches; + config.sdkverMaxMajor = this.sdkverMaxMajor; return config; } } diff --git a/dist/validate/index.js b/dist/validate/index.js index 35d09de8..e58394c0 100644 --- a/dist/validate/index.js +++ b/dist/validate/index.js @@ -34307,12 +34307,19 @@ function getNextSdkVer(currentVersion, sdkVerBumpType, isReleaseBranch, headMatc */ async function bumpSdkVer(config, bumpInfo, releaseMode, sdkVerBumpType, headSha, branchName, isBranchAllowedToPublish, createChangelog) { const isReleaseBranch = branchName.match(config.releaseBranches) !== null; - const hasBreakingChange = bumpInfo.processedCommits.some(c => c.message?.breakingChange); + let hasBreakingChange = bumpInfo.processedCommits.some(c => c.message?.breakingChange); if (!bumpInfo.foundVersion) return false; // should never happen // SdkVer requires a prerelease, so apply the default if not set config.prereleasePrefix = config.prereleasePrefix ?? "dev"; let cv = semver_1.SemVer.copy(bumpInfo.foundVersion); + // Do not bump major version when breaking change is found in case + // the max configured major version is already reached + if (config.sdkverMaxMajor !== undefined && + config.sdkverMaxMajor > 0 && + cv.major >= config.sdkverMaxMajor) { + hasBreakingChange = false; + } // Get the latest draft release matching our current version's prefix. // Don't look at the draft version on a release branch; the current version // should always reflect the version to be bumped (as no dev releases are @@ -35057,6 +35064,7 @@ const CONFIG_ITEMS = [ "release-branches", "prereleases", "sdkver-create-release-branches", + "sdkver-max-major", ]; const VERSION_SCHEMES = ["semver", "sdkver"]; /** @@ -35081,6 +35089,7 @@ class Configuration { tags = DEFAULT_ACCEPTED_TAGS; rules = new Map(); sdkverCreateReleaseBranches = undefined; + sdkverMaxMajor = 0; set initialDevelopment(initialDevelopment) { this._initialDevelopment = initialDevelopment; } @@ -35283,11 +35292,23 @@ class Configuration { throw new Error(`Incorrect type '${typeof data[key]}' for '${key}', must be either "boolean" or "string"!`); } break; + case "sdkver-max-major": + /* Example YAML: + * sdkver-max-major: 1 # defaults to 0 + */ + if (typeof data[key] === "number") { + this.sdkverMaxMajor = data[key]; + } + else { + throw new Error(`Incorrect type '${typeof data[key]}' for '${key}', must be '${typeof this.sdkverMaxMajor}'!`); + } + break; } } - if (this.sdkverCreateReleaseBranches !== undefined && + if ((this.sdkverCreateReleaseBranches !== undefined || + this.sdkverMaxMajor !== 0) && this.versionScheme !== "sdkver") { - core.warning("The configuration option `sdkver-create-release-branches` is only relevant " + + core.warning("The configuration options `sdkver-create-release-branches` and `sdkver-max-major` are only relevant " + 'when the `version-scheme` is set to `"sdkver"`.'); } } @@ -35324,6 +35345,7 @@ class Configuration { config.tags = JSON.parse(JSON.stringify(this.tags)); config.rules = new Map(JSON.parse(JSON.stringify(Array.from(this.rules)))); config.sdkverCreateReleaseBranches = this.sdkverCreateReleaseBranches; + config.sdkverMaxMajor = this.sdkverMaxMajor; return config; } } diff --git a/docs/configuration.md b/docs/configuration.md index b30ff5bc..9c4d3134 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -34,6 +34,7 @@ initial-development: false # OPTIONAL, defaults to `true` | `release-branches` | `/^release\/.*\d+\.\d+\.*$/` | A regex specifying from which branch(es) only `PATCH` version bump are allowed. | | `prereleases` | `undefined` | A string specifying the prereleases prefix. | | `sdkver-create-release-branches` | `false` | For SdkVer versioning scheme only: push a new branch if an RC or release build is performed on a non-release branch. If this config value is boolean `true`, the branch shall be of the form `release/N.N`. If this value is set to a string, it shall be used as the branch name prefix and appended with the major and minor release numbers, e.g. config value `"rel/"` results in a branch named `rel/N.N`. | +| `sdkver-max-major` | `0` | For SdkVer versioning scheme only: do not bump major version when breaking changes are found in case the maximum configured major version is already reached. | > :bulb: By default `commisery-action` will search for the file `.commisery.yml`. You can specify a different file with the `config` input parameter. diff --git a/src/bump.ts b/src/bump.ts index 3eac337f..752d8a59 100644 --- a/src/bump.ts +++ b/src/bump.ts @@ -753,7 +753,7 @@ export async function bumpSdkVer( createChangelog: boolean ): Promise { const isReleaseBranch = branchName.match(config.releaseBranches) !== null; - const hasBreakingChange = bumpInfo.processedCommits.some( + let hasBreakingChange = bumpInfo.processedCommits.some( c => c.message?.breakingChange ); if (!bumpInfo.foundVersion) return false; // should never happen @@ -763,6 +763,16 @@ export async function bumpSdkVer( let cv = SemVer.copy(bumpInfo.foundVersion); + // Do not bump major version when breaking change is found in case + // the max configured major version is already reached + if ( + config.sdkverMaxMajor !== undefined && + config.sdkverMaxMajor > 0 && + cv.major >= config.sdkverMaxMajor + ) { + hasBreakingChange = false; + } + // Get the latest draft release matching our current version's prefix. // Don't look at the draft version on a release branch; the current version // should always reflect the version to be bumped (as no dev releases are diff --git a/src/config.ts b/src/config.ts index 54b53570..b5740b18 100644 --- a/src/config.ts +++ b/src/config.ts @@ -74,6 +74,7 @@ const CONFIG_ITEMS = [ "release-branches", "prereleases", "sdkver-create-release-branches", + "sdkver-max-major", ]; const VERSION_SCHEMES = ["semver", "sdkver"]; @@ -107,6 +108,7 @@ export class Configuration { tags: IConfigurationRules = DEFAULT_ACCEPTED_TAGS; rules: Map = new Map(); sdkverCreateReleaseBranches?: string = undefined; + sdkverMaxMajor = 0; set initialDevelopment(initialDevelopment: boolean) { this._initialDevelopment = initialDevelopment; @@ -365,14 +367,30 @@ export class Configuration { ); } break; + + case "sdkver-max-major": + /* Example YAML: + * sdkver-max-major: 1 # defaults to 0 + */ + if (typeof data[key] === "number") { + this.sdkverMaxMajor = data[key]; + } else { + throw new Error( + `Incorrect type '${typeof data[ + key + ]}' for '${key}', must be '${typeof this.sdkverMaxMajor}'!` + ); + } + break; } } if ( - this.sdkverCreateReleaseBranches !== undefined && + (this.sdkverCreateReleaseBranches !== undefined || + this.sdkverMaxMajor !== 0) && this.versionScheme !== "sdkver" ) { core.warning( - "The configuration option `sdkver-create-release-branches` is only relevant " + + "The configuration options `sdkver-create-release-branches` and `sdkver-max-major` are only relevant " + 'when the `version-scheme` is set to `"sdkver"`.' ); } @@ -411,6 +429,7 @@ export class Configuration { config.tags = JSON.parse(JSON.stringify(this.tags)); config.rules = new Map(JSON.parse(JSON.stringify(Array.from(this.rules)))); config.sdkverCreateReleaseBranches = this.sdkverCreateReleaseBranches; + config.sdkverMaxMajor = this.sdkverMaxMajor; return config; } } diff --git a/test/bump.sdkver.test.ts b/test/bump.sdkver.test.ts index ba37e7c1..04089322 100644 --- a/test/bump.sdkver.test.ts +++ b/test/bump.sdkver.test.ts @@ -105,6 +105,8 @@ interface SdkBumpTestParameters { branch: string; breaking: boolean; expectedVersion: string; + initialDevelopment: boolean; + maxMajor: number; } const generateTests = (paramListList: any): SdkBumpTestParameters[] => { let testList = new Array() as SdkBumpTestParameters[]; @@ -117,6 +119,8 @@ const generateTests = (paramListList: any): SdkBumpTestParameters[] => { branch: paramList[4], breaking: paramList[5] as any as boolean, expectedVersion: paramList[6], + initialDevelopment: paramList[7], + maxMajor: paramList[8], }); } return testList; @@ -127,6 +131,11 @@ const testFunction = async (p: SdkBumpTestParameters) => { U.DEFAULT_COMMIT_LIST ); const prTitle = U.PRTITLE("chore"); + jest + .spyOn(fs, "readFileSync") + .mockReturnValue( + `version-scheme: "sdkver"\ninitial-development: ${p.initialDevelopment}\nsdkver-max-major: ${p.maxMajor}` + ); setInputSpyWith({ "release-type": p.bumpType }); jest.spyOn(github, "getLatestTags").mockResolvedValue([ { @@ -185,137 +194,171 @@ const testFunction = async (p: SdkBumpTestParameters) => { const testSuiteDefinitions = [ // GENERAL BUMPING o7 { - suite: "Dev bumps on main branch", + suite: "test bumps on main branch", tests: [ // [ test description , version , bump , latest draft , branch , breaking?, expected version ] - ["from dev-draft-nopad" , "1.1.0" , "dev" , "1.2.0-dev1+abc12" , "master" , false , `1.2.0-dev002.${U.HEAD_SHA_ABBREV_8}` ], - ["from long-pad-dev" , "1.1.0" , "dev" , "1.2.0-dev00001+ab", "master" , false , `1.2.0-dev00002.${U.HEAD_SHA_ABBREV_8}` ], - ["from dev-draft" , "1.1.0" , "dev" , "1.2.0-dev001.123" , "master" , false , `1.2.0-dev002.${U.HEAD_SHA_ABBREV_8}` ], - ["from dev" , "1.1.0" , "dev" , undefined , "master" , false , `1.2.0-dev001.${U.HEAD_SHA_ABBREV_8}` ], - ["from rc" , "1.2.0-rc01" , "dev" , undefined , "master" , false , `1.3.0-dev001.${U.HEAD_SHA_ABBREV_8}` ], - ["from release" , "1.2.0" , "dev" , undefined , "master" , false , `1.3.0-dev001.${U.HEAD_SHA_ABBREV_8}` ], + ["from dev-draft-nopad" , "0.1.0" , "dev" , "0.1.0-dev1+abc12" , "master" , true , `1.0.0-dev001.${U.HEAD_SHA_ABBREV_8}` , false, 0], + ["from long-pad-dev" , "0.2.0" , "dev" , "0.2.0-dev00001+ab", "master" , false , `1.0.0-dev001.${U.HEAD_SHA_ABBREV_8}` , false, 0], + ["from dev-draft" , "0.50.0" , "dev" , "0.50.0-dev001.123" , "master" , false , `1.0.0-dev001.${U.HEAD_SHA_ABBREV_8}` , false, 0], + ["from dev" , "0.4.0" , "dev" , undefined , "master" , false , `1.0.0-dev001.${U.HEAD_SHA_ABBREV_8}` , false, 0], + ["from rc" , "0.2.0-rc01" , "dev" , undefined , "master" , false , `1.0.0-dev001.${U.HEAD_SHA_ABBREV_8}` , false, 0], + ["from release" , "0.4.0" , "dev" , undefined , "master" , false , `1.0.0-dev001.${U.HEAD_SHA_ABBREV_8}` , false, 0], + ["from release2" , "1.0.0" , "rc" , undefined , "master" , false , `1.1.0-rc01` , false, 0], + ["from release3" , "1.0.0-dev1+abc12" , "rc" , "1.0.0-dev1+abc12" , "master" , false , `1.0.0-rc01` , false, 0], + ["from release4" , "1.0.0" , "rel" , undefined , "master" , false , `1.1.0` , false, 0], + ["from release5" , "1.0.0" , "dev" , undefined , "master" , true , `1.1.0-dev001.${U.HEAD_SHA_ABBREV_8}` , false, 1], + ], + }, + // GENERAL BUMPING o7 + { + suite: "Dev bumps on main branch", + tests: [ + // [ test description , version , bump , latest draft , branch , breaking?, expected version ,initial development?, max major version ] + ["from dev-draft-nopad", "1.1.0" , "dev" , "1.2.0-dev1+abc12" , "master" , false , `1.2.0-dev002.${U.HEAD_SHA_ABBREV_8}` , false , 0 ], + ["from long-pad-dev" , "1.1.0" , "dev" , "1.2.0-dev00001+ab", "master" , false , `1.2.0-dev00002.${U.HEAD_SHA_ABBREV_8}` , false , 0 ], + ["from dev-draft-init" , "0.1.0" , "dev" , "0.2.0-dev001.123" , "master" , false , `0.2.0-dev002.${U.HEAD_SHA_ABBREV_8}` , true , 0 ], + ["from dev-draft" , "1.1.0" , "dev" , "1.2.0-dev001.123" , "master" , false , `1.2.0-dev002.${U.HEAD_SHA_ABBREV_8}` , false , 0 ], + ["from dev-init" , "0.1.0" , "dev" , undefined , "master" , false , `0.2.0-dev001.${U.HEAD_SHA_ABBREV_8}` , true , 0 ], + ["from dev" , "1.1.0" , "dev" , undefined , "master" , false , `1.2.0-dev001.${U.HEAD_SHA_ABBREV_8}` , false , 0 ], + ["from rc" , "1.2.0-rc01" , "dev" , undefined , "master" , false , `1.3.0-dev001.${U.HEAD_SHA_ABBREV_8}` , false , 0 ], + ["from release" , "1.2.0" , "dev" , undefined , "master" , false , `1.3.0-dev001.${U.HEAD_SHA_ABBREV_8}` , false , 0 ], ], }, { suite: "Dev bumps on release branch", tests: [ - // [ test description , version , bump , latest draft , branch , breaking?, expected version ] - ["from dev" , "1.1.0" , "dev" , "1.2.0-dev001.234" , "release/1.2.0", false , "1.1.1" ], // <-- note that the branch name - ["from rc nopad" , "1.2.0-rc1" , "dev" , "1.2.0-dev001.345" , "release/1.2.0", false , "1.2.0-rc02" ], // is not considered as any - ["from rc" , "1.2.0-rc01" , "dev" , "1.2.0-dev001.345" , "release/1.2.0", false , "1.2.0-rc02" ], // sort of versioning input - ["from release" , "1.2.0" , "dev" , undefined , "release/1.2.0", false , "1.2.1" ], - ["from rel + HEADisTag" , "1.2.0" , "dev" , undefined , "release/1.2.0", false , undefined ], + // [ test description , version , bump , latest draft , branch , breaking?, expected version, initial development?, max major version ] + ["from dev init" , "0.1.0" , "dev" , "0.2.0-dev001.234" , "release/0.2.0", false , "0.1.1" , true , 0 ], // <-- note that the branch name + ["from dev" , "1.1.0" , "dev" , "1.2.0-dev001.234" , "release/1.2.0", false , "1.1.1" , false , 0 ], // is not considered as any + ["from rc nopad" , "1.2.0-rc1" , "dev" , "1.2.0-dev001.345" , "release/1.2.0", false , "1.2.0-rc02" , false , 0 ], // sort of versioning input + ["from rc" , "1.2.0-rc01" , "dev" , "1.2.0-dev001.345" , "release/1.2.0", false , "1.2.0-rc02" , false , 0 ], + ["from release" , "1.2.0" , "dev" , undefined , "release/1.2.0", false , "1.2.1" , false , 0 ], + ["from rel + HEADisTag" , "1.2.0" , "dev" , undefined , "release/1.2.0", false , undefined , false , 0 ], ], }, { suite: "Release candidate bumps on main branch", tests: [ - // [ test description , version , bump , latest draft , branch , breaking?, expected version ] // may be non-intuitive; rc - ["from dev" , "1.1.0" , "rc" , "1.2.0-dev001.1" , "master" , false , "1.2.0-rc01" ], // increments only happen on - ["from rc" , "1.2.0-rc01" , "rc" , "1.2.0-dev001.2" , "master" , false , "1.3.0-rc01" ], // <-- rel. branches, so this is - ["from release" , "1.2.0" , "rc" , "1.2.0-dev001.3" , "master" , false , "1.3.0-rc01" ], // the _next_ release + // [ test description , version , bump , latest draft , branch , breaking?, expected version, initial development?, max major version ] // may be non-intuitive; rc + ["from dev" , "1.1.0" , "rc" , "1.2.0-dev001.1" , "master" , false , "1.2.0-rc01" , false , 0 ], // increments only happen on + ["from rc" , "1.2.0-rc01" , "rc" , "1.2.0-dev001.2" , "master" , false , "1.3.0-rc01" , false , 0 ], // <-- rel. branches, so this is + ["from release" , "1.2.0" , "rc" , "1.2.0-dev001.3" , "master" , false , "1.3.0-rc01" , false , 0 ], // the _next_ release ], }, { suite: "Release candidate bumps on release branch", tests: [ - // [ test description , version , bump , latest draft , branch , breaking?, expected version ] - ["from dev" , "1.1.0" , "rc" , "1.2.0-dev001.1" , "release/1.2.0", false , "1.1.1" ], - ["from rc" , "1.2.0-rc01" , "rc" , "1.2.0-dev001.2" , "release/1.2.0", false , "1.2.0-rc02" ], - ["from rc + HEADisTag" , "1.2.0-rc01" , "rc" , "1.2.0-dev001.3" , "release/1.2.0", false , undefined ], - ["from release" , "1.2.0" , "rc" , "1.2.0-dev001.4" , "release/1.2.0", false , "1.2.1" ], + // [ test description , version , bump , latest draft , branch , breaking?, expected version, initial development?, max major version ] + ["from dev" , "1.1.0" , "rc" , "1.2.0-dev001.1" , "release/1.2.0", false , "1.1.1" , false , 0 ], + ["from rc" , "1.2.0-rc01" , "rc" , "1.2.0-dev001.2" , "release/1.2.0", false , "1.2.0-rc02" , false , 0 ], + ["from rc + HEADisTag" , "1.2.0-rc01" , "rc" , "1.2.0-dev001.3" , "release/1.2.0", false , undefined , false , 0 ], + ["from release" , "1.2.0" , "rc" , "1.2.0-dev001.4" , "release/1.2.0", false , "1.2.1" , false , 0 ], ], }, { suite: "Release bumps on main branch", tests: [ - // [ test description , version , bump , latest draft , branch , breaking?, expected version ] - ["from dev" , "1.1.0" , "rel" , "1.2.0-dev001.1" , "master" , false , "1.2.0" ], - ["from rc + HEADisTag" , "1.2.0-rc01" , "rel" , "1.2.0-dev001.1" , "master" , false , "1.2.0" ], // note that "HEADisTag" triggers specialized behavior - ["from rc + HEADisnoTag", "1.2.0-rc01" , "rel" , "1.2.0-dev001.1" , "master" , false , "1.3.0" ], - ["from release" , "1.2.0" , "rel" , "1.2.0-dev001.1" , "master" , false , "1.3.0" ], + // [ test description , version , bump , latest draft , branch , breaking?, expected version, initial development?, max major version ] + ["from dev" , "1.1.0" , "rel" , "1.2.0-dev001.1" , "master" , false , "1.2.0" , false , 0 ], + ["from rc + HEADisTag" , "1.2.0-rc01" , "rel" , "1.2.0-dev001.1" , "master" , false , "1.2.0" , false , 0 ], // note that "HEADisTag" triggers specialized behavior + ["from rc + HEADisnoTag", "1.2.0-rc01" , "rel" , "1.2.0-dev001.1" , "master" , false , "1.3.0" , false , 0 ], + ["from release" , "1.2.0" , "rel" , "1.2.0-dev001.1" , "master" , false , "1.3.0" , false , 0 ], ], }, { suite: "Release bumps on release branch", tests: [ - // [ test description , version , bump , latest draft , branch , breaking?, expected version ] - ["from dev" , "1.1.0" , "rel" , "1.2.0-dev001.1" , "release/1.2.0", false , "1.1.1" ], - ["from rc" , "1.2.0-rc01" , "rel" , "1.2.0-dev001.1" , "release/1.2.0", false , "1.2.0" ], - ["from release" , "1.2.0" , "rel" , "1.2.0-dev001.1" , "release/1.2.0", false , "1.2.1" ], - ["from rel + HEADisTag" , "1.2.0" , "rel" , undefined , "release/1.2.0", false , undefined ], + // [ test description , version , bump , latest draft , branch , breaking?, expected version, initial development?, max major version ] + ["from dev" , "1.1.0" , "rel" , "1.2.0-dev001.1" , "release/1.2.0", false , "1.1.1" , false , 0 ], + ["from rc" , "1.2.0-rc01" , "rel" , "1.2.0-dev001.1" , "release/1.2.0", false , "1.2.0" , false , 0 ], + ["from release" , "1.2.0" , "rel" , "1.2.0-dev001.1" , "release/1.2.0", false , "1.2.1" , false , 0 ], + ["from rel + HEADisTag" , "1.2.0" , "rel" , undefined , "release/1.2.0", false , undefined , false , 0 ], ], }, // BREAKING CHANGES { suite: "Dev bumps with breaking changes", tests: [ - // [ test description , version , bump , latest draft , branch , breaking?, expected version ] - ["main branch" , "1.2.0" , "dev" , undefined , "master" , true , `2.0.0-dev001.${U.HEAD_SHA_ABBREV_8}` ], - ["main branch, draft" , "1.2.0" , "dev" , "1.3.0-dev001.2" , "master" , true , `1.3.0-dev002.${U.HEAD_SHA_ABBREV_8}` ], - ["release branch" , "1.2.0" , "dev" , undefined , "release/1.2.0", true , undefined ], - ["release branch, draft", "1.2.0" , "dev" , "1.3.0-dev001.3" , "release/1.2.0", true , undefined ], - ["release branch+RC" , "1.2.0-rc01" , "dev" , undefined , "release/1.2.0", true , undefined ], - ["rel branch+RC, draft" , "1.2.0-rc01" , "dev" , "1.3.0-dev001.3" , "release/1.2.0", true , undefined ], + // [ test description , version , bump , latest draft , branch , breaking?, expected version , initial development?, max major version ] + ["main branch, init" , "0.2.0" , "dev" , undefined , "master" , true , `0.3.0-dev001.${U.HEAD_SHA_ABBREV_8}`, true , 0 ], + ["main branch, no init" , "0.2.0" , "dev" , undefined , "master" , true , `1.0.0-dev001.${U.HEAD_SHA_ABBREV_8}`, false , 0 ], + ["main branch, max" , "1.2.0" , "dev" , undefined , "master" , true , `1.3.0-dev001.${U.HEAD_SHA_ABBREV_8}`, false , 1 ], + ["main branch, max2" , "1.2.0" , "dev" , undefined , "master" , true , `2.0.0-dev001.${U.HEAD_SHA_ABBREV_8}`, false , 2 ], + ["main branch" , "1.2.0" , "dev" , undefined , "master" , true , `2.0.0-dev001.${U.HEAD_SHA_ABBREV_8}`, false , 0 ], + ["main branch, draft init", "0.2.0" , "dev" , "0.3.0-dev001.2" , "master" , true , `0.3.0-dev002.${U.HEAD_SHA_ABBREV_8}`, true , 0 ], + ["main branch, draft max" , "1.2.0" , "dev" , "1.3.0-dev001.2" , "master" , true , `1.3.0-dev002.${U.HEAD_SHA_ABBREV_8}`, false , 1 ], + ["main branch, draft" , "1.2.0" , "dev" , "1.3.0-dev001.2" , "master" , true , `1.3.0-dev002.${U.HEAD_SHA_ABBREV_8}`, false , 0 ], + ["release branch" , "1.2.0" , "dev" , undefined , "release/1.2.0", true , undefined , false , 0 ], + ["release branch, draft" , "1.2.0" , "dev" , "1.3.0-dev001.3" , "release/1.2.0", true , undefined , false , 0 ], + ["release branch+RC" , "1.2.0-rc01" , "dev" , undefined , "release/1.2.0", true , undefined , false , 0 ], + ["rel branch+RC, draft" , "1.2.0-rc01" , "dev" , "1.3.0-dev001.3" , "release/1.2.0", true , undefined , false , 0 ], ], }, { suite: "Rc bumps with breaking changes", tests: [ - // [ test description , version , bump , latest draft , branch , breaking?, expected version ] - ["main branch" , "1.2.0" , "rc" , undefined , "master" , true , "2.0.0-rc01" ], - ["main branch+RC" , "1.2.0-rc01" , "rc" , undefined , "master" , true , "2.0.0-rc01" ], - ["release branch" , "1.2.0" , "rc" , undefined , "release/1.2.0", true , undefined ], - ["release branch+RC" , "1.2.0-rc01" , "rc" , undefined , "release/1.2.0", true , undefined ], - ["RB+ RC for next major", "2.0.0-rc01" , "dev" , undefined , "release/2.0.0", true , "2.0.0-rc02" ], + // [ test description , version , bump , latest draft , branch , breaking?, expected version, initial development?, max major version ] + ["main branch, init" , "0.2.0" , "rc" , undefined , "master" , true , "0.3.0-rc01" , true , 0 ], + ["main branch, no init" , "0.2.0" , "rc" , undefined , "master" , true , "1.0.0-rc01" , false , 0 ], + ["main branch, max" , "1.2.0" , "rc" , undefined , "master" , true , "1.3.0-rc01" , false , 1 ], + ["main branch, max2" , "1.2.0" , "rc" , undefined , "master" , true , "2.0.0-rc01" , false , 2 ], + ["main branch" , "1.2.0" , "rc" , undefined , "master" , true , "2.0.0-rc01" , false , 0 ], + ["main branch+RC" , "1.2.0-rc01" , "rc" , undefined , "master" , true , "2.0.0-rc01" , false , 0 ], + ["release branch" , "1.2.0" , "rc" , undefined , "release/1.2.0", true , undefined , false , 0 ], + ["release branch+RC" , "1.2.0-rc01" , "rc" , undefined , "release/1.2.0", true , undefined , false , 0 ], + ["RB+ RC for next major", "2.0.0-rc01" , "dev" , undefined , "release/2.0.0", true , "2.0.0-rc02" , false , 0 ], ], }, { suite: "Release bumps with breaking changes", tests: [ - // [ test description , version , bump , latest draft , branch , breaking?, expected version ] - ["main branch" , "1.2.0" , "rel" , undefined , "master" , true , "2.0.0" ], - ["release branch" , "1.2.0" , "rel" , undefined , "release/1.2.0", true , undefined ], - ["release branch+RC" , "1.2.0-rc01" , "rel" , undefined , "release/1.2.0", true , undefined ], + // [ test description , version , bump , latest draft , branch , breaking?, expected version, initial development?, max major version ] + ["main branch, init" , "0.2.0" , "rel" , undefined , "master" , true , "0.3.0" , true , 0 ], + ["main branch, no init" , "0.2.0" , "rel" , undefined , "master" , true , "1.0.0" , false , 0 ], + ["main branch, max" , "1.2.0" , "rel" , undefined , "master" , true , "1.3.0" , false , 1 ], + ["main branch, max2" , "1.2.0" , "rel" , undefined , "master" , true , "2.0.0" , false , 2 ], + ["main branch" , "1.2.0" , "rel" , undefined , "master" , true , "2.0.0" , false , 0 ], + ["release branch" , "1.2.0" , "rel" , undefined , "release/1.2.0", true , undefined , false , 0 ], + ["release branch+RC" , "1.2.0-rc01" , "rel" , undefined , "release/1.2.0", true , undefined , false , 0 ], ], }, // DRAFT RELEASE HANDLING { suite: "Dev bumps considers draft releases", tests: [ - // [ test description , version , bump , latest draft , branch , breaking?, expected version ] - ["no draft" , "1.2.0" , "dev" , undefined , "master" , false , `1.3.0-dev001.${U.HEAD_SHA_ABBREV_8}` ], - ["previous version" , "1.2.0" , "dev" , "1.1.0-dev034", "master" , false , `1.3.0-dev001.${U.HEAD_SHA_ABBREV_8}` ], - ["current version" , "1.2.0" , "dev" , "1.2.0-dev023", "master" , false , `1.3.0-dev001.${U.HEAD_SHA_ABBREV_8}` ], - ["next version" , "1.2.0" , "dev" , "1.3.0-dev019", "master" , false , `1.3.0-dev020.${U.HEAD_SHA_ABBREV_8}` ], - ["next major" , "1.2.0" , "dev" , "2.0.0-dev011", "master" , false , `2.0.0-dev012.${U.HEAD_SHA_ABBREV_8}` ], + // [ test description , version , bump , latest draft , branch , breaking?, expected version , initial development?, max major version ] + ["no draft" , "1.2.0" , "dev" , undefined , "master" , false , `1.3.0-dev001.${U.HEAD_SHA_ABBREV_8}` , false , 0 ], + ["previous version" , "1.2.0" , "dev" , "1.1.0-dev034", "master" , false , `1.3.0-dev001.${U.HEAD_SHA_ABBREV_8}` , false , 0 ], + ["current version" , "1.2.0" , "dev" , "1.2.0-dev023", "master" , false , `1.3.0-dev001.${U.HEAD_SHA_ABBREV_8}` , false , 0 ], + ["next version" , "1.2.0" , "dev" , "1.3.0-dev019", "master" , false , `1.3.0-dev020.${U.HEAD_SHA_ABBREV_8}` , false , 0 ], + ["next major" , "1.2.0" , "dev" , "2.0.0-dev011", "master" , false , `2.0.0-dev012.${U.HEAD_SHA_ABBREV_8}` , false , 0 ], ], }, { suite: "Release candidate bumps ignore draft releases", tests: [ - // [ test description , version , bump , latest draft , branch , breaking?, expected version ] - ["mb: no draft" , "1.2.0" , "rc" , undefined , "master" , false , "1.3.0-rc01" ], - ["mb: previous version" , "1.2.0" , "rc" , "1.1.0-dev034", "master" , true , "2.0.0-rc01" ], - ["mb: current version" , "1.2.0" , "rc" , "1.2.0-dev023", "master" , false , "1.3.0-rc01" ], - ["mb: next version" , "1.2.0" , "rc" , "1.3.0-dev019", "master" , false , "1.3.0-rc01" ], - ["rb: no draft" , "1.2.0" , "rc" , undefined , "release/1.2.0", false , "1.2.1" ], - ["rb: previous version" , "1.2.0" , "rc" , "1.1.0-dev034", "release/1.2.0", false , "1.2.1" ], - ["rb: current version" , "1.2.0" , "rc" , "1.2.0-dev023", "release/1.2.0", false , "1.2.1" ], - ["rb: next version" , "1.2.0" , "rc" , "1.3.0-dev019", "release/1.2.0", false , "1.2.1" ], + // [ test description , version , bump , latest draft , branch , breaking?, expected version, initial development?, max major version ] + ["mb: no draft" , "1.2.0" , "rc" , undefined , "master" , false , "1.3.0-rc01" , false , 0 ], + ["mb: previous version" , "1.2.0" , "rc" , "1.1.0-dev034", "master" , true , "2.0.0-rc01" , false , 0 ], + ["mb: current version" , "1.2.0" , "rc" , "1.2.0-dev023", "master" , false , "1.3.0-rc01" , false , 0 ], + ["mb: next version" , "1.2.0" , "rc" , "1.3.0-dev019", "master" , false , "1.3.0-rc01" , false , 0 ], + ["rb: no draft" , "1.2.0" , "rc" , undefined , "release/1.2.0", false , "1.2.1" , false , 0 ], + ["rb: previous version" , "1.2.0" , "rc" , "1.1.0-dev034", "release/1.2.0", false , "1.2.1" , false , 0 ], + ["rb: current version" , "1.2.0" , "rc" , "1.2.0-dev023", "release/1.2.0", false , "1.2.1" , false , 0 ], + ["rb: next version" , "1.2.0" , "rc" , "1.3.0-dev019", "release/1.2.0", false , "1.2.1" , false , 0 ], ], }, // MISCELLANEOUS ERRORS { suite: "Erroneous situations", tests: [ - // [ test description , version , bump , latest draft , branch , breaking?, expected version ] - ["rel branch major bump", "1.2.0" , "dev" , undefined , "release/1.2.0", true , undefined ], - ["rel branch cur dev" , `1.1.0-dev008.1`, "dev" , "1.2.0-dev001+1" , "release/1.2.0", false , undefined ], - ["incorrect prerelease" , `1.1.0-devs` , "dev" , undefined , "master" , false , `1.2.0-dev001.${U.HEAD_SHA_ABBREV_8}` ], - ["wrong bump input" , `1.1.0-dev001.3`, "beep" , undefined , "master" , false , undefined ], - ["unauth'd branch dev" , `1.1.0-dev001.4`, "dev" , undefined , "mister" , false , `1.1.0-dev002.${U.HEAD_SHA_ABBREV_8}` ], // <-- TODO: make fail; not - ["unauth'd branch rc" , `1.1.0-dev001.5`, "rc" , undefined , "mister" , false , "1.1.0-rc01" ], // <-- implemented yet + // [ test description , version , bump , latest draft , branch , breaking?, expected version , initial development?, max major version ] + ["rel branch major bump", "1.2.0" , "dev" , undefined , "release/1.2.0", true , undefined , false , 0 ], + ["rel branch cur dev" , `1.1.0-dev008.1`, "dev" , "1.2.0-dev001+1" , "release/1.2.0", false , undefined , false , 0 ], + ["incorrect prerelease" , `1.1.0-devs` , "dev" , undefined , "master" , false , `1.2.0-dev001.${U.HEAD_SHA_ABBREV_8}` , false , 0 ], + ["wrong bump input" , `1.1.0-dev001.3`, "beep" , undefined , "master" , false , undefined , false , 0 ], + ["unauth'd branch dev" , `1.1.0-dev001.4`, "dev" , undefined , "mister" , false , `1.1.0-dev002.${U.HEAD_SHA_ABBREV_8}` , false , 0 ], // <-- TODO: make fail; not + ["unauth'd branch rc" , `1.1.0-dev001.5`, "rc" , undefined , "mister" , false , "1.1.0-rc01" , false , 0 ], // <-- implemented yet ], }, ]; @@ -335,7 +378,7 @@ describe("Create release branch", () => { jest .spyOn(fs, "readFileSync") .mockReturnValue( - `version-scheme: "sdkver"\nsdkver-create-release-branches: true` + `version-scheme: "sdkver"\nsdkver-create-release-branches: true\ninitial-development: false` ); setInputSpyWith({ "release-type": "rc" }); }); diff --git a/test/config.test.ts b/test/config.test.ts index fc8a541f..6c198f02 100644 --- a/test/config.test.ts +++ b/test/config.test.ts @@ -382,6 +382,12 @@ describe("Configurable options", () => { }); }); + test("Default SdkVer max major", () => { + withConfig("", (config: Configuration) => { + expect(config.sdkverMaxMajor).toBe(0); + }); + }); + test("Default version prefix", () => { withConfig("", (config: Configuration) => { expect(config.versionPrefix).toBe("*"); @@ -403,6 +409,15 @@ describe("Configurable options", () => { ); }); + test("Number values", () => { + withConfig( + "version-scheme: sdkver\nsdkver-max-major: 1", + (config: Configuration) => { + expect(config.sdkverMaxMajor).toBe(1); + } + ); + }); + test("String values", () => { withConfig( "version-scheme: sdkver\nsdkver-create-release-branches: some-release-prefix-\nversion-prefix: X", @@ -428,6 +443,40 @@ describe("Configurable options", () => { ); expect(core.warning).toHaveBeenCalledTimes(1); }); + + test("Enable SdkVer max major version on non-SdkVer", () => { + // We expect a warning about this option not being useful when the version + // scheme is not 'sdkver' + jest.spyOn(core, "warning").mockImplementation(arg => { + expect(arg).toContain("sdkver-max-major"); + expect(arg).toContain("version-scheme"); + }); + withConfig( + "version-scheme: semver\nsdkver-max-major: 1", + (config: Configuration) => { + expect(config.sdkverMaxMajor).toBe(1); + } + ); + expect(core.warning).toHaveBeenCalledTimes(1); + }); + + test("Enable SdkVer max major version and create release branches on non-SdkVer", () => { + // We expect a warning about this option not being useful when the version + // scheme is not 'sdkver' + jest.spyOn(core, "warning").mockImplementation(arg => { + expect(arg).toContain("sdkver-create-release-branches"); + expect(arg).toContain("sdkver-max-major"); + expect(arg).toContain("version-scheme"); + }); + withConfig( + "version-scheme: semver\nsdkver-create-release-branches: true\nsdkver-max-major: 1", + (config: Configuration) => { + expect(config.sdkverCreateReleaseBranches).toBe("release/"); + expect(config.sdkverMaxMajor).toBe(1); + } + ); + expect(core.warning).toHaveBeenCalledTimes(1); + }); }); describe("(Deep) Copy of Configuration", () => {