semantic-release 20.0.0-beta.2 → 20.0.0-beta.4

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.
Files changed (36) hide show
  1. package/README.md +4 -5
  2. package/bin/semantic-release.js +9 -9
  3. package/cli.js +31 -31
  4. package/docs/developer-guide/js-api.md +46 -37
  5. package/docs/developer-guide/plugin.md +97 -93
  6. package/docs/extending/plugins-list.md +8 -7
  7. package/docs/extending/shareable-configurations-list.md +2 -0
  8. package/docs/recipes/ci-configurations/README.md +1 -0
  9. package/docs/recipes/ci-configurations/github-actions.md +6 -3
  10. package/docs/recipes/ci-configurations/gitlab-ci.md +2 -3
  11. package/docs/recipes/git-hosted-services/README.md +1 -0
  12. package/docs/recipes/git-hosted-services/git-auth-ssh-keys.md +4 -1
  13. package/docs/recipes/release-workflow/README.md +1 -0
  14. package/docs/recipes/release-workflow/distribution-channels.md +1 -0
  15. package/docs/recipes/release-workflow/maintenance-releases.md +1 -0
  16. package/docs/recipes/release-workflow/pre-releases.md +1 -0
  17. package/docs/support/FAQ.md +25 -14
  18. package/docs/support/troubleshooting.md +1 -0
  19. package/docs/usage/ci-configuration.md +4 -3
  20. package/docs/usage/configuration.md +8 -2
  21. package/docs/usage/plugins.md +11 -5
  22. package/docs/usage/workflow-configuration.md +29 -17
  23. package/index.js +75 -72
  24. package/lib/get-commits.js +15 -9
  25. package/lib/get-config.js +38 -38
  26. package/lib/get-error.js +4 -4
  27. package/lib/get-git-auth-url.js +32 -32
  28. package/lib/get-last-release.js +8 -8
  29. package/lib/get-logger.js +10 -10
  30. package/lib/get-next-version.js +11 -11
  31. package/lib/get-release-to-add.js +17 -17
  32. package/lib/git.js +41 -41
  33. package/lib/hide-sensitive.js +6 -6
  34. package/lib/utils.js +12 -12
  35. package/lib/verify.js +14 -14
  36. package/package.json +7 -14
@@ -1,6 +1,7 @@
1
1
  # Workflow configuration
2
2
 
3
3
  **semantic-release** allow to manage and automate complex release workflow, based on multiple Git branches and distribution channels. This allow to:
4
+
4
5
  - Distribute certain releases to a particular group of users via distribution channels
5
6
  - Manage the availability of releases on distribution channels via branches merge
6
7
  - Maintain multiple lines of releases in parallel
@@ -12,6 +13,7 @@ The release workflow is configured via the [branches option](./configuration.md#
12
13
  Each branch can be defined either as a string, a [glob](https://github.com/micromatch/micromatch#matching-features) or an object. For string and glob definitions each [property](#branches-properties) will be defaulted.
13
14
 
14
15
  A branch can defined as one of three types:
16
+
15
17
  - [release](#release-branches): to make releases on top of the last version released
16
18
  - [maintenance](#maintenance-branches): to make releases on top of an old release
17
19
  - [pre-release](#pre-release-branches): to make pre-releases
@@ -21,7 +23,7 @@ The type of the branch is automatically determined based on naming convention an
21
23
  ## Branches properties
22
24
 
23
25
  | Property | Branch type | Description | Default |
24
- |--------------|-------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------|
26
+ | ------------ | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
25
27
  | `name` | All | **Required.** The Git branch holding the commits to analyze and the code to release. See [name](#name). | - The value itself if defined as a `String` or the matching branches name if defined as a glob. |
26
28
  | `channel` | All | The distribution channel on which to publish releases from this branch. Set to `false` to force the default distribution channel instead of using the default. See [channel](#channel). | `undefined` for the first release branch, the value of `name` for subsequent ones. |
27
29
  | `range` | [maintenance](#maintenance-branches) only | **Required unless `name` is formatted like `N.N.x` or `N.x` (`N` is a number).** The range of [semantic versions](https://semver.org) to support on this branch. See [range](#range). | The value of `name`. |
@@ -35,14 +37,15 @@ It can be defined as a [glob](https://github.com/micromatch/micromatch#matching-
35
37
  If `name` doesn't match to any branch existing in the repository, the definition will be ignored. For example the default configuration includes the definition `next` and `next-major` which will become active only when the branches `next` and/or `next-major` are created in the repository. This allow to define your workflow once with all potential branches you might use and have the effective configuration evolving as you create new branches.
36
38
 
37
39
  For example the configuration `['+([0-9])?(.{+([0-9]),x}).x', 'master', 'next']` will be expanded as:
40
+
38
41
  ```js
39
42
  {
40
43
  branches: [
41
- {name: '1.x', range: '1.x', channel: '1.x'}, // Only after the `1.x` is created in the repo
42
- {name: '2.x', range: '2.x', channel: '2.x'}, // Only after the `2.x` is created in the repo
43
- {name: 'master'},
44
- {name: 'next', channel: 'next'}, // Only after the `next` is created in the repo
45
- ]
44
+ { name: "1.x", range: "1.x", channel: "1.x" }, // Only after the `1.x` is created in the repo
45
+ { name: "2.x", range: "2.x", channel: "2.x" }, // Only after the `2.x` is created in the repo
46
+ { name: "master" },
47
+ { name: "next", channel: "next" }, // Only after the `next` is created in the repo
48
+ ];
46
49
  }
47
50
  ```
48
51
 
@@ -54,12 +57,13 @@ If the `channel` property is set to `false` the default channel will be used.
54
57
  The value of `channel`, if defined as a string, is generated with [Lodash template](https://lodash.com/docs#template) with the variable `name` available.
55
58
 
56
59
  For example the configuration `['master', {name: 'next', channel: 'channel-${name}'}]` will be expanded as:
60
+
57
61
  ```js
58
62
  {
59
63
  branches: [
60
- {name: 'master'}, // `channel` is undefined so the default distribution channel will be used
61
- {name: 'next', channel: 'channel-next'}, // `channel` is built with the template `channel-${name}`
62
- ]
64
+ { name: "master" }, // `channel` is undefined so the default distribution channel will be used
65
+ { name: "next", channel: "channel-next" }, // `channel` is built with the template `channel-${name}`
66
+ ];
63
67
  }
64
68
  ```
65
69
 
@@ -68,13 +72,14 @@ For example the configuration `['master', {name: 'next', channel: 'channel-${nam
68
72
  A `range` only applies to maintenance branches, is required and must be formatted like `N.N.x` or `N.x` (`N` is a number). In case the `name` is formatted as a range (for example `1.x` or `1.5.x`) the branch will be considered a maintenance branch and the `name` value will be used for the `range`.
69
73
 
70
74
  For example the configuration `['1.1.x', '1.2.x', 'master']` will be expanded as:
75
+
71
76
  ```js
72
77
  {
73
78
  branches: [
74
- {name: '1.1.x', range: '1.1.x', channel: '1.1.x'},
75
- {name: '1.2.x', range: '1.2.x', channel: '1.2.x'},
76
- {name: 'master'},
77
- ]
79
+ { name: "1.1.x", range: "1.1.x", channel: "1.1.x" },
80
+ { name: "1.2.x", range: "1.2.x", channel: "1.2.x" },
81
+ { name: "master" },
82
+ ];
78
83
  }
79
84
  ```
80
85
 
@@ -86,13 +91,14 @@ If the `prerelease` property is set to `true` the `name` value will be used.
86
91
  The value of `prerelease`, if defined as a string, is generated with [Lodash template](https://lodash.com/docs#template) with the variable `name` available.
87
92
 
88
93
  For example the configuration `['master', {name: 'pre/rc', prerelease: '${name.replace(/^pre\\//g, "")}'}, {name: 'beta', prerelease: true}]` will be expanded as:
94
+
89
95
  ```js
90
96
  {
91
97
  branches: [
92
- {name: 'master'},
93
- {name: 'pre/rc', channel: 'pre/rc', prerelease: 'rc'}, // `prerelease` is built with the template `${name.replace(/^pre\\//g, "")}`
94
- {name: 'beta', channel: 'beta', prerelease: true}, // `prerelease` is set to `beta` as it is the value of `name`
95
- ]
98
+ { name: "master" },
99
+ { name: "pre/rc", channel: "pre/rc", prerelease: "rc" }, // `prerelease` is built with the template `${name.replace(/^pre\\//g, "")}`
100
+ { name: "beta", channel: "beta", prerelease: true }, // `prerelease` is set to `beta` as it is the value of `name`
101
+ ];
96
102
  }
97
103
  ```
98
104
 
@@ -113,10 +119,12 @@ See [publishing on distribution channels recipe](../recipes/release-workflow/dis
113
119
  #### Pushing to a release branch
114
120
 
115
121
  With the configuration `"branches": ["master", "next"]`, if the last release published from `master` is `1.0.0` and the last one from `next` is `2.0.0` then:
122
+
116
123
  - Only versions in range `1.x.x` can be published from `master`, so only `fix` and `feat` commits can be pushed to `master`
117
124
  - Once `next` get merged into `master` the release `2.0.0` will be made available on the channel associated with `master` and both `master` and `next` will accept any commit type
118
125
 
119
126
  This verification prevent scenario such as:
127
+
120
128
  1. Create a `feat` commit on `next` which triggers the release of version `1.0.0` on the `next` channel
121
129
  2. Merge `next` into `master` which adds `1.0.0` on the default channel
122
130
  3. Create a `feat` commit on `next` which triggers the release of version `1.1.0` on the `next` channel
@@ -147,6 +155,7 @@ See [publishing maintenance releases recipe](../recipes/release-workflow/mainten
147
155
  #### Pushing to a maintenance branch
148
156
 
149
157
  With the configuration `"branches": ["1.0.x", "1.x", "master"]`, if the last release published from `master` is `1.5.0` then:
158
+
150
159
  - Only versions in range `>=1.0.0 <1.1.0` can be published from `1.0.x`, so only `fix` commits can be pushed to `1.0.x`
151
160
  - Only versions in range `>=1.1.0 <1.5.0` can be published from `1.x`, so only `fix` and `feat` commits can be pushed to `1.x` as long the resulting release is lower than `1.5.0`
152
161
  - Once `2.0.0` is released from `master`, versions in range `>=1.1.0 <2.0.0` can be published from `1.x`, so any number of `fix` and `feat` commits can be pushed to `1.x`
@@ -154,6 +163,7 @@ With the configuration `"branches": ["1.0.x", "1.x", "master"]`, if the last rel
154
163
  #### Merging into a maintenance branch
155
164
 
156
165
  With the configuration `"branches": ["1.0.x", "1.x", "master"]`, if the last release published from `master` is `1.0.0` then:
166
+
157
167
  - Creating the branch `1.0.x` from `master` will make the `1.0.0` release available on the `1.0.x` distribution channel
158
168
  - Pushing a `fix` commit on the `1.0.x` branch will release the version `1.0.1` on the `1.0.x` distribution channel
159
169
  - Creating the branch `1.x` from `master` will make the `1.0.0` release available on the `1.x` distribution channel
@@ -176,11 +186,13 @@ See [publishing pre-releases recipe](../recipes/release-workflow/pre-releases.md
176
186
  #### Pushing to a pre-release branch
177
187
 
178
188
  With the configuration `"branches": ["master", {"name": "beta", "prerelease": true}]`, if the last release published from `master` is `1.0.0` then:
189
+
179
190
  - Pushing a `BREAKING CHANGE` commit on the `beta` branch will release the version `2.0.0-beta.1` on the `beta` distribution channel
180
191
  - Pushing either a `fix`, `feat` or a `BREAKING CHANGE` commit on the `beta` branch will release the version `2.0.0-beta.2` (then `2.0.0-beta.3`, `2.0.0-beta.4`, etc...) on the `beta` distribution channel
181
192
 
182
193
  #### Merging into a pre-release branch
183
194
 
184
195
  With the configuration `"branches": ["master", {"name": "beta", "prerelease": true}]`, if the last release published from `master` is `1.0.0` and the last one published from `beta` is `2.0.0-beta.1` then:
196
+
185
197
  - Pushing a `fix` commit on the `master` branch will release the version `1.0.1` on the default distribution channel
186
198
  - Merging the branch `master` into `beta` will release the version `2.0.0-beta.2` on the `beta` distribution channel
package/index.js CHANGED
@@ -1,33 +1,33 @@
1
- import {createRequire} from 'node:module';
2
- import {pick} from 'lodash-es';
3
- import * as marked from 'marked';
4
- import envCi from 'env-ci';
5
- import {hookStd} from 'hook-std';
6
- import semver from 'semver';
7
- import AggregateError from 'aggregate-error';
8
- import hideSensitive from './lib/hide-sensitive.js';
9
- import getConfig from './lib/get-config.js';
10
- import verify from './lib/verify.js';
11
- import getNextVersion from './lib/get-next-version.js';
12
- import getCommits from './lib/get-commits.js';
13
- import getLastRelease from './lib/get-last-release.js';
14
- import getReleaseToAdd from './lib/get-release-to-add.js';
15
- import {extractErrors, makeTag} from './lib/utils.js';
16
- import getGitAuthUrl from './lib/get-git-auth-url.js';
17
- import getBranches from './lib/branches/index.js';
18
- import getLogger from './lib/get-logger.js';
19
- import {addNote, getGitHead, getTagHead, isBranchUpToDate, push, pushNotes, tag, verifyAuth} from './lib/git.js';
20
- import getError from './lib/get-error.js';
21
- import {COMMIT_EMAIL, COMMIT_NAME} from './lib/definitions/constants.js';
1
+ import { createRequire } from "node:module";
2
+ import { pick } from "lodash-es";
3
+ import * as marked from "marked";
4
+ import envCi from "env-ci";
5
+ import { hookStd } from "hook-std";
6
+ import semver from "semver";
7
+ import AggregateError from "aggregate-error";
8
+ import hideSensitive from "./lib/hide-sensitive.js";
9
+ import getConfig from "./lib/get-config.js";
10
+ import verify from "./lib/verify.js";
11
+ import getNextVersion from "./lib/get-next-version.js";
12
+ import getCommits from "./lib/get-commits.js";
13
+ import getLastRelease from "./lib/get-last-release.js";
14
+ import getReleaseToAdd from "./lib/get-release-to-add.js";
15
+ import { extractErrors, makeTag } from "./lib/utils.js";
16
+ import getGitAuthUrl from "./lib/get-git-auth-url.js";
17
+ import getBranches from "./lib/branches/index.js";
18
+ import getLogger from "./lib/get-logger.js";
19
+ import { addNote, getGitHead, getTagHead, isBranchUpToDate, push, pushNotes, tag, verifyAuth } from "./lib/git.js";
20
+ import getError from "./lib/get-error.js";
21
+ import { COMMIT_EMAIL, COMMIT_NAME } from "./lib/definitions/constants.js";
22
22
 
23
23
  const require = createRequire(import.meta.url);
24
- const pkg = require('./package.json');
24
+ const pkg = require("./package.json");
25
25
 
26
26
  let markedOptionsSet = false;
27
27
  async function terminalOutput(text) {
28
28
  if (!markedOptionsSet) {
29
- const {default: TerminalRenderer} = await import('marked-terminal'); // eslint-disable-line node/no-unsupported-features/es-syntax
30
- marked.setOptions({renderer: new TerminalRenderer()});
29
+ const { default: TerminalRenderer } = await import("marked-terminal"); // eslint-disable-line node/no-unsupported-features/es-syntax
30
+ marked.setOptions({ renderer: new TerminalRenderer() });
31
31
  markedOptionsSet = true;
32
32
  }
33
33
 
@@ -36,12 +36,12 @@ async function terminalOutput(text) {
36
36
 
37
37
  /* eslint complexity: off */
38
38
  async function run(context, plugins) {
39
- const {cwd, env, options, logger, envCi} = context;
40
- const {isCi, branch, prBranch, isPr} = envCi;
39
+ const { cwd, env, options, logger, envCi } = context;
40
+ const { isCi, branch, prBranch, isPr } = envCi;
41
41
  const ciBranch = isPr ? prBranch : branch;
42
42
 
43
43
  if (!isCi && !options.dryRun && !options.noCi) {
44
- logger.warn('This run was not triggered in a known CI environment, running in dry-run mode.');
44
+ logger.warn("This run was not triggered in a known CI environment, running in dry-run mode.");
45
45
  options.dryRun = true;
46
46
  } else {
47
47
  // When running on CI, set the commits author and committer info and prevent the `git` CLI to prompt for username/password. See #703.
@@ -51,7 +51,7 @@ async function run(context, plugins) {
51
51
  GIT_COMMITTER_NAME: COMMIT_NAME,
52
52
  GIT_COMMITTER_EMAIL: COMMIT_EMAIL,
53
53
  ...env,
54
- GIT_ASKPASS: 'echo',
54
+ GIT_ASKPASS: "echo",
55
55
  GIT_TERMINAL_PROMPT: 0,
56
56
  });
57
57
  }
@@ -64,30 +64,30 @@ async function run(context, plugins) {
64
64
  // Verify config
65
65
  await verify(context);
66
66
 
67
- options.repositoryUrl = await getGitAuthUrl({...context, branch: {name: ciBranch}});
67
+ options.repositoryUrl = await getGitAuthUrl({ ...context, branch: { name: ciBranch } });
68
68
  context.branches = await getBranches(options.repositoryUrl, ciBranch, context);
69
- context.branch = context.branches.find(({name}) => name === ciBranch);
69
+ context.branch = context.branches.find(({ name }) => name === ciBranch);
70
70
 
71
71
  if (!context.branch) {
72
72
  logger.log(
73
73
  `This test run was triggered on the branch ${ciBranch}, while semantic-release is configured to only publish from ${context.branches
74
- .map(({name}) => name)
75
- .join(', ')}, therefore a new version won’t be published.`
74
+ .map(({ name }) => name)
75
+ .join(", ")}, therefore a new version won’t be published.`
76
76
  );
77
77
  return false;
78
78
  }
79
79
 
80
- logger[options.dryRun ? 'warn' : 'success'](
80
+ logger[options.dryRun ? "warn" : "success"](
81
81
  `Run automated release from branch ${ciBranch} on repository ${options.originalRepositoryURL}${
82
- options.dryRun ? ' in dry-run mode' : ''
82
+ options.dryRun ? " in dry-run mode" : ""
83
83
  }`
84
84
  );
85
85
 
86
86
  try {
87
87
  try {
88
- await verifyAuth(options.repositoryUrl, context.branch.name, {cwd, env});
88
+ await verifyAuth(options.repositoryUrl, context.branch.name, { cwd, env });
89
89
  } catch (error) {
90
- if (!(await isBranchUpToDate(options.repositoryUrl, context.branch.name, {cwd, env}))) {
90
+ if (!(await isBranchUpToDate(options.repositoryUrl, context.branch.name, { cwd, env }))) {
91
91
  logger.log(
92
92
  `The local branch ${context.branch.name} is behind the remote one, therefore a new version won't be published.`
93
93
  );
@@ -98,7 +98,7 @@ async function run(context, plugins) {
98
98
  }
99
99
  } catch (error) {
100
100
  logger.error(`The command "${error.command}" failed with the error message ${error.stderr}.`);
101
- throw getError('EGITNOPERMISSION', context);
101
+ throw getError("EGITNOPERMISSION", context);
102
102
  }
103
103
 
104
104
  logger.success(`Allowed to push to the Git repository`);
@@ -110,24 +110,27 @@ async function run(context, plugins) {
110
110
  const releaseToAdd = getReleaseToAdd(context);
111
111
 
112
112
  if (releaseToAdd) {
113
- const {lastRelease, currentRelease, nextRelease} = releaseToAdd;
113
+ const { lastRelease, currentRelease, nextRelease } = releaseToAdd;
114
114
 
115
- nextRelease.gitHead = await getTagHead(nextRelease.gitHead, {cwd, env});
116
- currentRelease.gitHead = await getTagHead(currentRelease.gitHead, {cwd, env});
115
+ nextRelease.gitHead = await getTagHead(nextRelease.gitHead, { cwd, env });
116
+ currentRelease.gitHead = await getTagHead(currentRelease.gitHead, { cwd, env });
117
117
  if (context.branch.mergeRange && !semver.satisfies(nextRelease.version, context.branch.mergeRange)) {
118
- errors.push(getError('EINVALIDMAINTENANCEMERGE', {...context, nextRelease}));
118
+ errors.push(getError("EINVALIDMAINTENANCEMERGE", { ...context, nextRelease }));
119
119
  } else {
120
- const commits = await getCommits({...context, lastRelease, nextRelease});
121
- nextRelease.notes = await plugins.generateNotes({...context, commits, lastRelease, nextRelease});
120
+ const commits = await getCommits({ ...context, lastRelease, nextRelease });
121
+ nextRelease.notes = await plugins.generateNotes({ ...context, commits, lastRelease, nextRelease });
122
122
 
123
123
  if (options.dryRun) {
124
124
  logger.warn(`Skip ${nextRelease.gitTag} tag creation in dry-run mode`);
125
125
  } else {
126
- await addNote({channels: [...currentRelease.channels, nextRelease.channel]}, nextRelease.gitHead, {cwd, env});
127
- await push(options.repositoryUrl, {cwd, env});
128
- await pushNotes(options.repositoryUrl, {cwd, env});
126
+ await addNote({ channels: [...currentRelease.channels, nextRelease.channel] }, nextRelease.gitHead, {
127
+ cwd,
128
+ env,
129
+ });
130
+ await push(options.repositoryUrl, { cwd, env });
131
+ await pushNotes(options.repositoryUrl, { cwd, env });
129
132
  logger.success(
130
- `Add ${nextRelease.channel ? `channel ${nextRelease.channel}` : 'default channel'} to tag ${
133
+ `Add ${nextRelease.channel ? `channel ${nextRelease.channel}` : "default channel"} to tag ${
131
134
  nextRelease.gitTag
132
135
  }`
133
136
  );
@@ -140,9 +143,9 @@ async function run(context, plugins) {
140
143
  gitHead: nextRelease.gitHead,
141
144
  });
142
145
 
143
- const releases = await plugins.addChannel({...context, commits, lastRelease, currentRelease, nextRelease});
146
+ const releases = await plugins.addChannel({ ...context, commits, lastRelease, currentRelease, nextRelease });
144
147
  context.releases.push(...releases);
145
- await plugins.success({...context, lastRelease, commits, nextRelease, releases});
148
+ await plugins.success({ ...context, lastRelease, commits, nextRelease, releases });
146
149
  }
147
150
  }
148
151
 
@@ -152,7 +155,7 @@ async function run(context, plugins) {
152
155
 
153
156
  context.lastRelease = getLastRelease(context);
154
157
  if (context.lastRelease.gitHead) {
155
- context.lastRelease.gitHead = await getTagHead(context.lastRelease.gitHead, {cwd, env});
158
+ context.lastRelease.gitHead = await getTagHead(context.lastRelease.gitHead, { cwd, env });
156
159
  }
157
160
 
158
161
  if (context.lastRelease.gitTag) {
@@ -168,11 +171,11 @@ async function run(context, plugins) {
168
171
  const nextRelease = {
169
172
  type: await plugins.analyzeCommits(context),
170
173
  channel: context.branch.channel || null,
171
- gitHead: await getGitHead({cwd, env}),
174
+ gitHead: await getGitHead({ cwd, env }),
172
175
  };
173
176
  if (!nextRelease.type) {
174
- logger.log('There are no relevant changes, so no new version is released.');
175
- return context.releases.length > 0 ? {releases: context.releases} : false;
177
+ logger.log("There are no relevant changes, so no new version is released.");
178
+ return context.releases.length > 0 ? { releases: context.releases } : false;
176
179
  }
177
180
 
178
181
  context.nextRelease = nextRelease;
@@ -180,11 +183,11 @@ async function run(context, plugins) {
180
183
  nextRelease.gitTag = makeTag(options.tagFormat, nextRelease.version);
181
184
  nextRelease.name = nextRelease.gitTag;
182
185
 
183
- if (context.branch.type !== 'prerelease' && !semver.satisfies(nextRelease.version, context.branch.range)) {
184
- throw getError('EINVALIDNEXTVERSION', {
186
+ if (context.branch.type !== "prerelease" && !semver.satisfies(nextRelease.version, context.branch.range)) {
187
+ throw getError("EINVALIDNEXTVERSION", {
185
188
  ...context,
186
189
  validBranches: context.branches.filter(
187
- ({type, accept}) => type !== 'prerelease' && accept.includes(nextRelease.type)
190
+ ({ type, accept }) => type !== "prerelease" && accept.includes(nextRelease.type)
188
191
  ),
189
192
  });
190
193
  }
@@ -199,20 +202,20 @@ async function run(context, plugins) {
199
202
  logger.warn(`Skip ${nextRelease.gitTag} tag creation in dry-run mode`);
200
203
  } else {
201
204
  // Create the tag before calling the publish plugins as some require the tag to exists
202
- await tag(nextRelease.gitTag, nextRelease.gitHead, {cwd, env});
203
- await addNote({channels: [nextRelease.channel]}, nextRelease.gitHead, {cwd, env});
204
- await push(options.repositoryUrl, {cwd, env});
205
- await pushNotes(options.repositoryUrl, {cwd, env});
205
+ await tag(nextRelease.gitTag, nextRelease.gitHead, { cwd, env });
206
+ await addNote({ channels: [nextRelease.channel] }, nextRelease.gitHead, { cwd, env });
207
+ await push(options.repositoryUrl, { cwd, env });
208
+ await pushNotes(options.repositoryUrl, { cwd, env });
206
209
  logger.success(`Created tag ${nextRelease.gitTag}`);
207
210
  }
208
211
 
209
212
  const releases = await plugins.publish(context);
210
213
  context.releases.push(...releases);
211
214
 
212
- await plugins.success({...context, releases});
215
+ await plugins.success({ ...context, releases });
213
216
 
214
217
  logger.success(
215
- `Published release ${nextRelease.version} on ${nextRelease.channel ? nextRelease.channel : 'default'} channel`
218
+ `Published release ${nextRelease.version} on ${nextRelease.channel ? nextRelease.channel : "default"} channel`
216
219
  );
217
220
 
218
221
  if (options.dryRun) {
@@ -222,10 +225,10 @@ async function run(context, plugins) {
222
225
  }
223
226
  }
224
227
 
225
- return pick(context, ['lastRelease', 'commits', 'nextRelease', 'releases']);
228
+ return pick(context, ["lastRelease", "commits", "nextRelease", "releases"]);
226
229
  }
227
230
 
228
- async function logErrors({logger, stderr}, err) {
231
+ async function logErrors({ logger, stderr }, err) {
229
232
  const errors = extractErrors(err).sort((error) => (error.semanticRelease ? -1 : 0));
230
233
  for (const error of errors) {
231
234
  if (error.semanticRelease) {
@@ -234,7 +237,7 @@ async function logErrors({logger, stderr}, err) {
234
237
  stderr.write(await terminalOutput(error.details)); // eslint-disable-line no-await-in-loop
235
238
  }
236
239
  } else {
237
- logger.error('An error occurred while running semantic-release: %O', error);
240
+ logger.error("An error occurred while running semantic-release: %O", error);
238
241
  }
239
242
  }
240
243
  }
@@ -243,16 +246,16 @@ async function callFail(context, plugins, err) {
243
246
  const errors = extractErrors(err).filter((err) => err.semanticRelease);
244
247
  if (errors.length > 0) {
245
248
  try {
246
- await plugins.fail({...context, errors});
249
+ await plugins.fail({ ...context, errors });
247
250
  } catch (error) {
248
251
  await logErrors(context, error);
249
252
  }
250
253
  }
251
254
  }
252
255
 
253
- export default async (cliOptions = {}, {cwd = process.cwd(), env = process.env, stdout, stderr} = {}) => {
254
- const {unhook} = hookStd(
255
- {silent: false, streams: [process.stdout, process.stderr, stdout, stderr].filter(Boolean)},
256
+ export default async (cliOptions = {}, { cwd = process.cwd(), env = process.env, stdout, stderr } = {}) => {
257
+ const { unhook } = hookStd(
258
+ { silent: false, streams: [process.stdout, process.stderr, stdout, stderr].filter(Boolean) },
256
259
  hideSensitive(env)
257
260
  );
258
261
  const context = {
@@ -260,12 +263,12 @@ export default async (cliOptions = {}, {cwd = process.cwd(), env = process.env,
260
263
  env,
261
264
  stdout: stdout || process.stdout,
262
265
  stderr: stderr || process.stderr,
263
- envCi: envCi({env, cwd}),
266
+ envCi: envCi({ env, cwd }),
264
267
  };
265
268
  context.logger = getLogger(context);
266
269
  context.logger.log(`Running ${pkg.name} version ${pkg.version}`);
267
270
  try {
268
- const {plugins, options} = await getConfig(context, cliOptions);
271
+ const { plugins, options } = await getConfig(context, cliOptions);
269
272
  options.originalRepositoryURL = options.repositoryUrl;
270
273
  context.options = options;
271
274
  try {
@@ -281,4 +284,4 @@ export default async (cliOptions = {}, {cwd = process.cwd(), env = process.env,
281
284
  unhook();
282
285
  throw error;
283
286
  }
284
- }
287
+ };
@@ -1,7 +1,7 @@
1
- import debugCommits from 'debug';
2
- import {getCommits} from './git.js';
1
+ import debugCommits from "debug";
2
+ import { getCommits } from "./git.js";
3
3
 
4
- const debug = debugCommits('semantic-release:get-commits');
4
+ const debug = debugCommits("semantic-release:get-commits");
5
5
 
6
6
  /**
7
7
  * Retrieve the list of commits on the current branch since the commit sha associated with the last release, or all the commits of the current branch if there is no last released version.
@@ -10,16 +10,22 @@ const debug = debugCommits('semantic-release:get-commits');
10
10
  *
11
11
  * @return {Promise<Array<Object>>} The list of commits on the branch `branch` since the last release.
12
12
  */
13
- export default async ({cwd, env, lastRelease: {gitHead: from}, nextRelease: {gitHead: to = 'HEAD'} = {}, logger}) => {
13
+ export default async ({
14
+ cwd,
15
+ env,
16
+ lastRelease: { gitHead: from },
17
+ nextRelease: { gitHead: to = "HEAD" } = {},
18
+ logger,
19
+ }) => {
14
20
  if (from) {
15
- debug('Use from: %s', from);
21
+ debug("Use from: %s", from);
16
22
  } else {
17
- logger.log('No previous release found, retrieving all commits');
23
+ logger.log("No previous release found, retrieving all commits");
18
24
  }
19
25
 
20
- const commits = await getCommits(from, to, {cwd, env});
26
+ const commits = await getCommits(from, to, { cwd, env });
21
27
 
22
28
  logger.log(`Found ${commits.length} commits since last release`);
23
- debug('Parsed commits: %o', commits);
29
+ debug("Parsed commits: %o", commits);
24
30
  return commits;
25
- }
31
+ };
package/lib/get-config.js CHANGED
@@ -1,39 +1,39 @@
1
- import {dirname, resolve} from 'node:path';
2
- import {fileURLToPath} from 'node:url';
3
- import {createRequire} from 'node:module';
1
+ import { dirname, resolve } from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { createRequire } from "node:module";
4
4
 
5
- import {castArray, isNil, isPlainObject, isString, pickBy} from 'lodash-es';
6
- import {readPackageUp} from 'read-pkg-up';
7
- import {cosmiconfig} from 'cosmiconfig';
8
- import resolveFrom from 'resolve-from';
9
- import debugConfig from 'debug';
10
- import {repoUrl} from './git.js';
11
- import PLUGINS_DEFINITIONS from './definitions/plugins.js';
12
- import plugins from './plugins/index.js';
13
- import {parseConfig, validatePlugin} from './plugins/utils.js';
5
+ import { castArray, isNil, isPlainObject, isString, pickBy } from "lodash-es";
6
+ import { readPackageUp } from "read-pkg-up";
7
+ import { cosmiconfig } from "cosmiconfig";
8
+ import resolveFrom from "resolve-from";
9
+ import debugConfig from "debug";
10
+ import { repoUrl } from "./git.js";
11
+ import PLUGINS_DEFINITIONS from "./definitions/plugins.js";
12
+ import plugins from "./plugins/index.js";
13
+ import { parseConfig, validatePlugin } from "./plugins/utils.js";
14
14
 
15
- const debug = debugConfig('semantic-release:config');
15
+ const debug = debugConfig("semantic-release:config");
16
16
  const __dirname = dirname(fileURLToPath(import.meta.url));
17
17
  const require = createRequire(import.meta.url);
18
18
 
19
- const CONFIG_NAME = 'release';
19
+ const CONFIG_NAME = "release";
20
20
 
21
21
  export default async (context, cliOptions) => {
22
- const {cwd, env} = context;
23
- const {config, filepath} = (await cosmiconfig(CONFIG_NAME).search(cwd)) || {};
22
+ const { cwd, env } = context;
23
+ const { config, filepath } = (await cosmiconfig(CONFIG_NAME).search(cwd)) || {};
24
24
 
25
- debug('load config from: %s', filepath);
25
+ debug("load config from: %s", filepath);
26
26
 
27
27
  // Merge config file options and CLI/API options
28
- let options = {...config, ...cliOptions};
28
+ let options = { ...config, ...cliOptions };
29
29
 
30
30
  const pluginsPath = {};
31
31
  let extendPaths;
32
- ({extends: extendPaths, ...options} = options);
32
+ ({ extends: extendPaths, ...options } = options);
33
33
  if (extendPaths) {
34
34
  // If `extends` is defined, load and merge each shareable config with `options`
35
35
  options = {
36
- ...await (castArray(extendPaths).reduce(async(eventualResult, extendPath) => {
36
+ ...(await castArray(extendPaths).reduce(async (eventualResult, extendPath) => {
37
37
  const result = await eventualResult;
38
38
  const extendsOptions = require(resolveFrom.silent(__dirname, extendPath) || resolveFrom(cwd, extendPath));
39
39
 
@@ -43,7 +43,7 @@ export default async (context, cliOptions) => {
43
43
  .filter(([, value]) => Boolean(value))
44
44
  .reduce((pluginsPath, [option, value]) => {
45
45
  castArray(value).forEach((plugin) => {
46
- if (option === 'plugins' && validatePlugin(plugin)) {
46
+ if (option === "plugins" && validatePlugin(plugin)) {
47
47
  pluginsPath[parseConfig(plugin)[0]] = extendPath;
48
48
  } else if (
49
49
  PLUGINS_DEFINITIONS[option] &&
@@ -55,7 +55,7 @@ export default async (context, cliOptions) => {
55
55
  return pluginsPath;
56
56
  }, pluginsPath);
57
57
 
58
- return {...result, ...extendsOptions};
58
+ return { ...result, ...extendsOptions };
59
59
  }, {})),
60
60
  ...options,
61
61
  };
@@ -64,36 +64,36 @@ export default async (context, cliOptions) => {
64
64
  // Set default options values if not defined yet
65
65
  options = {
66
66
  branches: [
67
- '+([0-9])?(.{+([0-9]),x}).x',
68
- 'master',
69
- 'next',
70
- 'next-major',
71
- {name: 'beta', prerelease: true},
72
- {name: 'alpha', prerelease: true},
67
+ "+([0-9])?(.{+([0-9]),x}).x",
68
+ "master",
69
+ "next",
70
+ "next-major",
71
+ { name: "beta", prerelease: true },
72
+ { name: "alpha", prerelease: true },
73
73
  ],
74
- repositoryUrl: (await pkgRepoUrl({normalize: false, cwd})) || (await repoUrl({cwd, env})),
74
+ repositoryUrl: (await pkgRepoUrl({ normalize: false, cwd })) || (await repoUrl({ cwd, env })),
75
75
  tagFormat: `v\${version}`,
76
76
  plugins: [
77
- '@semantic-release/commit-analyzer',
78
- '@semantic-release/release-notes-generator',
79
- '@semantic-release/npm',
80
- '@semantic-release/github',
77
+ "@semantic-release/commit-analyzer",
78
+ "@semantic-release/release-notes-generator",
79
+ "@semantic-release/npm",
80
+ "@semantic-release/github",
81
81
  ],
82
82
  // Remove `null` and `undefined` options, so they can be replaced with default ones
83
83
  ...pickBy(options, (option) => !isNil(option)),
84
- ...(options.branches ? {branches: castArray(options.branches)} : {}),
84
+ ...(options.branches ? { branches: castArray(options.branches) } : {}),
85
85
  };
86
86
 
87
87
  if (options.ci === false) {
88
88
  options.noCi = true;
89
89
  }
90
90
 
91
- debug('options values: %O', options);
91
+ debug("options values: %O", options);
92
92
 
93
- return {options, plugins: await plugins({...context, options}, pluginsPath)};
94
- }
93
+ return { options, plugins: await plugins({ ...context, options }, pluginsPath) };
94
+ };
95
95
 
96
96
  async function pkgRepoUrl(options) {
97
- const {packageJson} = (await readPackageUp(options)) || {};
97
+ const { packageJson } = (await readPackageUp(options)) || {};
98
98
  return packageJson && (isPlainObject(packageJson.repository) ? packageJson.repository.url : packageJson.repository);
99
99
  }
package/lib/get-error.js CHANGED
@@ -1,7 +1,7 @@
1
- import SemanticReleaseError from '@semantic-release/error';
2
- import * as ERROR_DEFINITIONS from './definitions/errors.js';
1
+ import SemanticReleaseError from "@semantic-release/error";
2
+ import * as ERROR_DEFINITIONS from "./definitions/errors.js";
3
3
 
4
4
  export default (code, ctx = {}) => {
5
- const {message, details} = ERROR_DEFINITIONS[code](ctx);
5
+ const { message, details } = ERROR_DEFINITIONS[code](ctx);
6
6
  return new SemanticReleaseError(message, code, details);
7
- }
7
+ };