@ethima/semantic-release-configuration 4.0.1 → 4.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -68,16 +68,85 @@ for this purpose. This library will search for an `ethima` configuration file
68
68
  as explained in the introduction of its `README`, e.g. a JSON or YAML-formatted
69
69
  `.ethimarc` or `.config/ethimarc` file, JavaScript in a `.ethimarc.js`, etc.
70
70
 
71
- Generic configuration options are:
71
+ The available configuration options are explained in detail in the sections
72
+ describing the functionality they apply to.
72
73
 
73
- - `primary_release_branch` a string indicating the "primary" release branch,
74
- i.e. the branch from which new releases should be created. This may also be
75
- specified as a `PRIMARY_RELEASE_BRANCH` environment variable and will default
76
- to [the `CI_DEFAULT_BRANCH` on GitLab][gitlab-predefined-variables-url] and
77
- to `main` on other platforms.
74
+ ### Branches
75
+
76
+ By default, `semantic-release` accepts [_at most_ 3 "release
77
+ branches"][semantic-release-branches-url]. This configuration provides a
78
+ mechanism to work around this limitation by detecting the type of the active
79
+ branch and only configuring `semantic-release` to act on the primary release
80
+ branch and the active branch, enabling the use of more "release branches". The
81
+ primary release branch is _always_ configured as `semantic-release` requires at
82
+ least one "release branch" to be defined.
83
+
84
+ Additionally, this configuration extends the allowed patterns for "maintenance"
85
+ and "prerelease" branches. Specifically `semantic-release` only supports
86
+ [`N.N.x`, `N.x.x` and `N.x` patterns][semantic-release-branch-patterns-url]
87
+ where `N` is a number. When using this configuration `N`, `N.N`, `N.y`, `N.y.z`
88
+ and `N.N.z` (suffix) patterns are also supported.
89
+
90
+ The configuration distinguishes three types of branches:
91
+
92
+ - The "primary release branch" which is the branch from which the most
93
+ up-to-date release gets cut.
94
+ - "Maintenance branches" which represent a specific subset of releases that can
95
+ be used for maintenance releases after the "primary release branch" has moved
96
+ ahead to a newer version. For instance, a `release-2` branch when the primary
97
+ release branch targets releases for version 3 or up, or a `release-1.2`
98
+ branch for releases within the v1.2.z range after the `release-1` branch has
99
+ started to target v1.3.z.
100
+ - "Prerelease branches" which can be used to "gate" releases, e.g. to
101
+ accumulate a number of changes to release at once instead of releasing on
102
+ every single merge into a "release branch", i.e. the "primary release branch"
103
+ or a "maintenance branch". These branches typically follow the naming
104
+ convention of the other "release branches" but with a different prefix, e.g.
105
+ `next-2` corresponds to prereleases for `release-2`, `next-1.2.z` corresponds
106
+ to releases for `release-1.2.z`, etc. The "prerelease branch" for the
107
+ "primary release branch" is a special case which only consists of the prefix
108
+ used to indicate "prerelease branches", e.g. `next`. The tags associated with
109
+ a "prerelease branch" receive an additional suffix.
110
+
111
+ Note that "breaking" or "feature" "prerelease branches" will accept
112
+ prereleases for the next "breaking" or "feature" version as, according to the
113
+ [semantic versioning
114
+ specification][semantic-versioning-prerelease-precedence-url], these versions
115
+ technically fall within the upper bounded version range represented by the
116
+ "prerelease branch". For instance, a feature commit on the `next-3.1` branch
117
+ will be accepted and results in the publication of `3.2.0-rc.1` from that
118
+ branch. If that same commit would have been made on the `release-3.1` branch
119
+ it would not have been accepted.
120
+
121
+ Various aspects of branch and tag naming can be configured through the
122
+ mechanisms [outlined above](#configuration). The folowing branch-related
123
+ configuration options are available:
124
+
125
+ | Configuration option | Description | Environment Variable |
126
+ | --------------------------- | ----------------------------------------------------------------------------------- | --------------------------- |
127
+ | `branch_prefix_separator` | Specifies the character(s) used to separate the branch prefixes from version ranges | `BRANCH_PREFIX_SEPARATOR` |
128
+ | `maintenance_branch_prefix` | Specifies the prefix used for "maintenance branches" | `MAINTENANCE_BRANCH_PREFIX` |
129
+ | `prerelease_branch_prefix` | Specifies the prefix used for "prerelease branches" | `PRERELEASE_BRANCH_PREFIX` |
130
+ | `prerelease_branch_prefix` | Specifies the suffix used for tags created from "prerelease branches" | `PRERELEASE_TAG_SUFFIX` |
131
+ | `primary_release_branch` | Indicates the name of the "primary release branch" | `PRIMARY_RELEASE_BRANCH` |
132
+
133
+ The default configuration is
134
+
135
+ ```js
136
+ {
137
+ branch_prefix_separator: "-",
138
+ maintenance_branch_prefix: "release"
139
+ prerelease_branch_prefix: "next",
140
+ prerelease_tag_suffix: "rc",
141
+ primary_release_branch: env.CI_DEFAULT_BRANCH || "main",
142
+ }
143
+ ```
78
144
 
79
- Other configuration options are explained in more detail in the sections
80
- describing the functionality they apply to.
145
+ The branch for which a release is intended to be triggered should be provided
146
+ as a `CURRENT_BRANCH` environment variable before instantiating this
147
+ configuration. For common platforms, i.e. GitLab CI and GitHub Actions, this
148
+ value will be automatically derived from known environment variables specific
149
+ to each platform.
81
150
 
82
151
  ### Changelog Maintenance
83
152
 
@@ -232,6 +301,8 @@ release by hand from the tag and changelog that was created by the
232
301
  [npm-token-url]: https://docs.npmjs.com/creating-and-viewing-access-tokens#creating-granular-access-tokens-on-the-website
233
302
  [replace-in-file-url]: https://www.npmjs.com/package/replace-in-file
234
303
  [semantic-release-authentication-url]: https://semantic-release.gitbook.io/semantic-release/usage/ci-configuration#authentication
304
+ [semantic-release-branch-patterns-url]: https://semantic-release.gitbook.io/semantic-release/usage/workflow-configuration#range
305
+ [semantic-release-branches-url]: https://semantic-release.gitbook.io/semantic-release/usage/workflow-configuration#release-branches
235
306
  [semantic-release-changelog-plugin-url]: https://github.com/semantic-release/changelog
236
307
  [semantic-release-commit-analyzer-plugin-url]: https://github.com/semantic-release/commit-analyzer
237
308
  [semantic-release-extends-configuration-url]: https://semantic-release.gitbook.io/semantic-release/usage/configuration#extends
@@ -245,3 +316,4 @@ release by hand from the tag and changelog that was created by the
245
316
  [semantic-release-npm-plugin-url]: https://www.npmjs.com/package/@semantic-release/npm
246
317
  [semantic-release-replace-plugin-url]: https://github.com/google/semantic-release-replace-plugin
247
318
  [semantic-release-url]: https://semantic-release.gitbook.io/
319
+ [semantic-versioning-prerelease-precedence-url]: https://semver.org/#spec-item-9
package/package.json CHANGED
@@ -1,12 +1,15 @@
1
1
  {
2
2
  "name": "@ethima/semantic-release-configuration",
3
- "version": "4.0.1",
3
+ "version": "4.1.1",
4
4
  "description": "A shareable semantic release configuration supporting a range of languages and platforms supported by the Ethima organization.",
5
5
  "main": "./src/index.js",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git+ssh://git@gitlab.com/ethima/semantic-release-configuration.git"
9
9
  },
10
+ "scripts": {
11
+ "test": "ava"
12
+ },
10
13
  "keywords": [
11
14
  "Semantic",
12
15
  "Release"
@@ -18,12 +21,15 @@
18
21
  },
19
22
  "homepage": "https://gitlab.com/ethima/semantic-release-configuration#readme",
20
23
  "dependencies": {
21
- "@google/semantic-release-replace-plugin": "1.2.0",
24
+ "@google/semantic-release-replace-plugin": "1.2.5",
22
25
  "@semantic-release/changelog": "6.0.3",
23
26
  "@semantic-release/git": "10.0.1",
24
27
  "@semantic-release/github": "9.0.3",
25
28
  "@semantic-release/gitlab": "12.0.3",
26
- "conventional-changelog-conventionalcommits": "6.0.0",
29
+ "conventional-changelog-conventionalcommits": "6.1.0",
27
30
  "cosmiconfig": "8.2.0"
31
+ },
32
+ "devDependencies": {
33
+ "ava": "5.3.1"
28
34
  }
29
35
  }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Determines the type of branch for the provided `branch`, i.e. whether it
3
+ * represents a "maintenance" or a "prerelease" branch.
4
+ *
5
+ * @return object The `branch_prefix` and whether it `is_prerelease`.
6
+ */
7
+ function determinePrefixedBranchType(
8
+ branch,
9
+ { maintenance_branch_prefix, prerelease_branch_prefix }
10
+ ) {
11
+ if (branch.startsWith(maintenance_branch_prefix)) {
12
+ return { branch_prefix: maintenance_branch_prefix, is_prerelease: false };
13
+ } else {
14
+ return { branch_prefix: prerelease_branch_prefix, is_prerelease: true };
15
+ }
16
+ }
17
+
18
+ /**
19
+ * Determines the "branches" for a semantic-release configuration given the
20
+ * provided `configuration` for the shareable configuration. This ensures more
21
+ * (patterned) release branches can be supported than would typically be the
22
+ * case.
23
+ *
24
+ * The function is capable of dealing with "primary release branches", the
25
+ * corresponding "prerelease branch", and patterned "maintenance" and
26
+ * "prerelease" branches.
27
+ *
28
+ * @return array An array containing the determined branch configuration as the
29
+ * sole entry.
30
+ */
31
+ function BranchesConfiguration(branch, configuration) {
32
+ if (configuration.primary_release_branch === branch) {
33
+ return [branch];
34
+ }
35
+
36
+ if (configuration.prerelease_branch_prefix === branch) {
37
+ return [
38
+ configuration.primary_release_branch,
39
+ { name: branch, prerelease: configuration.prerelease_tag_suffix },
40
+ ];
41
+ }
42
+
43
+ const { branch_prefix, is_prerelease } = determinePrefixedBranchType(
44
+ branch,
45
+ configuration
46
+ );
47
+
48
+ // The matching pattern is configured to match all allowed permutations of
49
+ // version specifications as closely as possible to ensure other permutations
50
+ // that look valid, e.g. `N.z.q`, do not also accidentally match
51
+ const branch_prefix_separator = configuration.branch_prefix_separator ?? "-";
52
+ const version_branch_matcher = new RegExp(
53
+ `^${branch_prefix}${branch_prefix_separator}(?<major>\\d+)(?<minor>\\.(\\d+|x|y))?(\\.(x|z))?$`
54
+ );
55
+ if (version_branch_matcher.test(branch)) {
56
+ let {
57
+ groups: { major, minor },
58
+ } = branch.match(version_branch_matcher);
59
+
60
+ // Remove minor parts not representing digits, so they are not included in
61
+ // the returned `range`
62
+ const version_part_matcher = new RegExp("\\.\\d+");
63
+ if (!version_part_matcher.test(minor)) {
64
+ minor = "";
65
+ }
66
+
67
+ return [
68
+ configuration.primary_release_branch,
69
+ {
70
+ name: branch,
71
+ ...(is_prerelease
72
+ ? { prerelease: configuration.prerelease_tag_suffix }
73
+ : {}),
74
+ range: `${major}${minor}.x`,
75
+ },
76
+ ];
77
+ }
78
+
79
+ return [];
80
+ }
81
+
82
+ module.exports = BranchesConfiguration;
@@ -2,8 +2,17 @@ const { cosmiconfigSync } = require("cosmiconfig");
2
2
  const { env } = require("node:process");
3
3
 
4
4
  const CONFIGURATION_DEFAULTS = {
5
+ // The character(s) to use to separate the prefix for maintenance and
6
+ // prerelease branches from the version pattern
7
+ branch_prefix_separator: env.BRANCH_PREFIX_SEPARATOR || "-",
5
8
  changelog_filename: "CHANGELOG.md",
6
9
  files_with_versioned_templates: ["README.md"],
10
+ // The branch prefix for patterned maintenance branches
11
+ maintenance_branch_prefix: env.MAINTENANCE_BRANCH_PREFIX || "release",
12
+ // The branch prefix for patterned prerelease branches
13
+ prerelease_branch_prefix: env.PRERELEASE_BRANCH_PREFIX || "next",
14
+ // The tag suffix to use for tags created from prerelease branches
15
+ prerelease_tag_suffix: env.PRERELEASE_TAG_SUFFIX || "rc",
7
16
  // The `PRIMARY_RELEASE_BRANCH` environment variable is used as a platform
8
17
  // independent mechanism for specifying the primary release branch. On GitLab
9
18
  // this defaults to the "default" branch. Given that the "default" branch is
package/src/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const { accessSync } = require("node:fs");
2
2
  const { env } = require("node:process");
3
3
 
4
+ const BranchesConfiguration = require("./branches.js");
4
5
  const CONFIGURATION = require("./configuration.js");
5
6
  const VersionedTemplatesConfiguration = require("./versioned-templates.js");
6
7
 
@@ -69,8 +70,14 @@ try {
69
70
  ]);
70
71
  } catch {}
71
72
 
73
+ // Determine the current branch based off well-known environment variables
74
+ // typically available in CI, i.e. Ethima specific configuration, GitLab CI,
75
+ // and GitHub Actions
76
+ const current_branch =
77
+ env.CURRENT_BRANCH ?? env.CI_COMMIT_REF_NAME ?? env.GITHUB_REF_NAME;
78
+
72
79
  const SEMANTIC_RELEASE_CONFIGURATION = {
73
- branches: [CONFIGURATION.primary_release_branch],
80
+ branches: BranchesConfiguration(current_branch, CONFIGURATION),
74
81
  plugins: [
75
82
  ["@semantic-release/commit-analyzer", { preset: "conventionalcommits" }],
76
83
  "@semantic-release/release-notes-generator",