feat(esm): convert to esm (#2569)
for #2543 BREAKING CHANGE: semantic-release is now ESM-only. since it is used through its own executable, the impact on consuming projects should be minimal BREAKING CHANGE: references to plugin files in configs need to include the file extension because of executing in an ESM context
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
const {isString, remove, omit, mapValues, template} = require('lodash');
|
||||
const micromatch = require('micromatch');
|
||||
const {getBranches} = require('../git');
|
||||
import {isString, mapValues, omit, remove, template} from 'lodash-es';
|
||||
import micromatch from 'micromatch';
|
||||
import {getBranches} from '../git.js';
|
||||
|
||||
module.exports = async (repositoryUrl, {cwd}, branches) => {
|
||||
export default async (repositoryUrl, {cwd}, branches) => {
|
||||
const gitBranches = await getBranches(repositoryUrl, {cwd});
|
||||
|
||||
return branches.reduce(
|
||||
@@ -15,4 +15,4 @@ module.exports = async (repositoryUrl, {cwd}, branches) => {
|
||||
],
|
||||
[]
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
const {template, escapeRegExp} = require('lodash');
|
||||
const semver = require('semver');
|
||||
const pReduce = require('p-reduce');
|
||||
const debug = require('debug')('semantic-release:get-tags');
|
||||
const {getTags, getNote} = require('../../lib/git');
|
||||
import {escapeRegExp, template} from 'lodash-es';
|
||||
import semver from 'semver';
|
||||
import pReduce from 'p-reduce';
|
||||
import debugTags from 'debug';
|
||||
import {getNote, getTags} from '../../lib/git.js';
|
||||
|
||||
module.exports = async ({cwd, env, options: {tagFormat}}, branches) => {
|
||||
const debug = debugTags('semantic-release:get-tags');
|
||||
|
||||
|
||||
export default async ({cwd, env, options: {tagFormat}}, branches) => {
|
||||
// Generate a regex to parse tags formatted with `tagFormat`
|
||||
// by replacing the `version` variable in the template by `(.+)`.
|
||||
// The `tagFormat` is compiled with space as the `version` as it's an invalid tag character,
|
||||
@@ -30,4 +33,4 @@ module.exports = async ({cwd, env, options: {tagFormat}}, branches) => {
|
||||
},
|
||||
[]
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
+11
-11
@@ -1,14 +1,14 @@
|
||||
const {isString, isRegExp} = require('lodash');
|
||||
const AggregateError = require('aggregate-error');
|
||||
const pEachSeries = require('p-each-series');
|
||||
const DEFINITIONS = require('../definitions/branches');
|
||||
const getError = require('../get-error');
|
||||
const {fetch, fetchNotes, verifyBranchName} = require('../git');
|
||||
const expand = require('./expand');
|
||||
const getTags = require('./get-tags');
|
||||
const normalize = require('./normalize');
|
||||
import {isRegExp, isString} from 'lodash-es';
|
||||
import AggregateError from 'aggregate-error';
|
||||
import pEachSeries from 'p-each-series';
|
||||
import * as DEFINITIONS from '../definitions/branches.js';
|
||||
import getError from '../get-error.js';
|
||||
import {fetch, fetchNotes, verifyBranchName} from '../git.js';
|
||||
import expand from './expand.js';
|
||||
import getTags from './get-tags.js';
|
||||
import * as normalize from './normalize.js';
|
||||
|
||||
module.exports = async (repositoryUrl, ciBranch, context) => {
|
||||
export default async (repositoryUrl, ciBranch, context) => {
|
||||
const {cwd, env} = context;
|
||||
|
||||
const remoteBranches = await expand(
|
||||
@@ -68,4 +68,4 @@ module.exports = async (repositoryUrl, ciBranch, context) => {
|
||||
}
|
||||
|
||||
return [...result.maintenance, ...result.release, ...result.prerelease];
|
||||
};
|
||||
}
|
||||
|
||||
+15
-18
@@ -1,19 +1,18 @@
|
||||
const {sortBy, isNil} = require('lodash');
|
||||
const semverDiff = require('semver-diff');
|
||||
const {FIRST_RELEASE, RELEASE_TYPE} = require('../definitions/constants');
|
||||
const {
|
||||
tagsToVersions,
|
||||
isMajorRange,
|
||||
getUpperBound,
|
||||
getLowerBound,
|
||||
highest,
|
||||
lowest,
|
||||
getLatestVersion,
|
||||
import {isNil, sortBy} from 'lodash-es';
|
||||
import semverDiff from 'semver-diff';
|
||||
import {FIRST_RELEASE, RELEASE_TYPE} from '../definitions/constants.js';
|
||||
import {
|
||||
getFirstVersion,
|
||||
getRange,
|
||||
} = require('../utils');
|
||||
getLatestVersion,
|
||||
getLowerBound, getRange,
|
||||
getUpperBound,
|
||||
highest,
|
||||
isMajorRange,
|
||||
lowest,
|
||||
tagsToVersions
|
||||
} from '../utils.js';
|
||||
|
||||
function maintenance({maintenance, release}) {
|
||||
export function maintenance({maintenance, release}) {
|
||||
return sortBy(
|
||||
maintenance.map(({name, range, channel, ...rest}) => ({
|
||||
...rest,
|
||||
@@ -55,7 +54,7 @@ function maintenance({maintenance, release}) {
|
||||
});
|
||||
}
|
||||
|
||||
function release({release}) {
|
||||
export function release({release}) {
|
||||
if (release.length === 0) {
|
||||
return release;
|
||||
}
|
||||
@@ -89,7 +88,7 @@ function release({release}) {
|
||||
});
|
||||
}
|
||||
|
||||
function prerelease({prerelease}) {
|
||||
export function prerelease({prerelease}) {
|
||||
return prerelease.map(({name, prerelease, channel, tags, ...rest}) => {
|
||||
const preid = prerelease === true ? name : prerelease;
|
||||
return {
|
||||
@@ -102,5 +101,3 @@ function prerelease({prerelease}) {
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {maintenance, release, prerelease};
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
const {isNil, uniqBy} = require('lodash');
|
||||
const semver = require('semver');
|
||||
const {isMaintenanceRange} = require('../utils');
|
||||
import {isNil, uniqBy} from 'lodash-es';
|
||||
import semver from 'semver';
|
||||
import {isMaintenanceRange} from '../utils.js';
|
||||
|
||||
const maintenance = {
|
||||
export const maintenance = {
|
||||
filter: ({name, range}) => (!isNil(range) && range !== false) || isMaintenanceRange(name),
|
||||
branchValidator: ({range}) => (isNil(range) ? true : isMaintenanceRange(range)),
|
||||
branchesValidator: (branches) => uniqBy(branches, ({range}) => semver.validRange(range)).length === branches.length,
|
||||
};
|
||||
|
||||
const prerelease = {
|
||||
export const prerelease = {
|
||||
filter: ({prerelease}) => !isNil(prerelease) && prerelease !== false,
|
||||
branchValidator: ({name, prerelease}) =>
|
||||
Boolean(prerelease) && Boolean(semver.valid(`1.0.0-${prerelease === true ? name : prerelease}.1`)),
|
||||
branchesValidator: (branches) => uniqBy(branches, 'prerelease').length === branches.length,
|
||||
};
|
||||
|
||||
const release = {
|
||||
export const release = {
|
||||
// eslint-disable-next-line unicorn/no-fn-reference-in-iterator
|
||||
filter: (branch) => !maintenance.filter(branch) && !prerelease.filter(branch),
|
||||
branchesValidator: (branches) => branches.length <= 3 && branches.length > 0,
|
||||
};
|
||||
|
||||
module.exports = {maintenance, prerelease, release};
|
||||
|
||||
@@ -1,29 +1,17 @@
|
||||
const RELEASE_TYPE = ['patch', 'minor', 'major'];
|
||||
export const RELEASE_TYPE = ['patch', 'minor', 'major'];
|
||||
|
||||
const FIRST_RELEASE = '1.0.0';
|
||||
export const FIRST_RELEASE = '1.0.0';
|
||||
|
||||
const FIRSTPRERELEASE = '1';
|
||||
export const FIRSTPRERELEASE = '1';
|
||||
|
||||
const COMMIT_NAME = 'semantic-release-bot';
|
||||
export const COMMIT_NAME = 'semantic-release-bot';
|
||||
|
||||
const COMMIT_EMAIL = 'semantic-release-bot@martynus.net';
|
||||
export const COMMIT_EMAIL = 'semantic-release-bot@martynus.net';
|
||||
|
||||
const RELEASE_NOTES_SEPARATOR = '\n\n';
|
||||
export const RELEASE_NOTES_SEPARATOR = '\n\n';
|
||||
|
||||
const SECRET_REPLACEMENT = '[secure]';
|
||||
export const SECRET_REPLACEMENT = '[secure]';
|
||||
|
||||
const SECRET_MIN_SIZE = 5;
|
||||
export const SECRET_MIN_SIZE = 5;
|
||||
|
||||
const GIT_NOTE_REF = 'semantic-release';
|
||||
|
||||
module.exports = {
|
||||
RELEASE_TYPE,
|
||||
FIRST_RELEASE,
|
||||
FIRSTPRERELEASE,
|
||||
COMMIT_NAME,
|
||||
COMMIT_EMAIL,
|
||||
RELEASE_NOTES_SEPARATOR,
|
||||
SECRET_REPLACEMENT,
|
||||
SECRET_MIN_SIZE,
|
||||
GIT_NOTE_REF,
|
||||
};
|
||||
export const GIT_NOTE_REF = 'semantic-release';
|
||||
|
||||
+119
-53
@@ -1,7 +1,10 @@
|
||||
const {inspect} = require('util');
|
||||
const {toLower, isString, trim} = require('lodash');
|
||||
import {inspect} from 'node:util';
|
||||
import {createRequire} from 'node:module';
|
||||
import {isString, toLower, trim} from 'lodash-es';
|
||||
import {RELEASE_TYPE} from './constants.js';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
const pkg = require('../../package.json');
|
||||
const {RELEASE_TYPE} = require('./constants');
|
||||
|
||||
const [homepage] = pkg.homepage.split('#');
|
||||
const stringify = (object) =>
|
||||
@@ -10,16 +13,19 @@ const linkify = (file) => `${homepage}/blob/master/${file}`;
|
||||
const wordsList = (words) =>
|
||||
`${words.slice(0, -1).join(', ')}${words.length > 1 ? ` or ${words[words.length - 1]}` : trim(words[0])}`;
|
||||
|
||||
module.exports = {
|
||||
ENOGITREPO: ({cwd}) => ({
|
||||
export function ENOGITREPO({cwd}) {
|
||||
return {
|
||||
message: 'Not running from a git repository.',
|
||||
details: `The \`semantic-release\` command must be executed from a Git repository.
|
||||
|
||||
The current working directory is \`${cwd}\`.
|
||||
|
||||
Please verify your CI configuration to make sure the \`semantic-release\` command is executed from the root of the cloned repository.`,
|
||||
}),
|
||||
ENOREPOURL: () => ({
|
||||
};
|
||||
}
|
||||
|
||||
export function ENOREPOURL() {
|
||||
return {
|
||||
message: 'The `repositoryUrl` option is required.',
|
||||
details: `The [repositoryUrl option](${linkify(
|
||||
'docs/usage/configuration.md#repositoryurl'
|
||||
@@ -28,8 +34,11 @@ Please verify your CI configuration to make sure the \`semantic-release\` comman
|
||||
Please make sure to add the \`repositoryUrl\` to the [semantic-release configuration] (${linkify(
|
||||
'docs/usage/configuration.md'
|
||||
)}).`,
|
||||
}),
|
||||
EGITNOPERMISSION: ({options: {repositoryUrl}, branch: {name}}) => ({
|
||||
};
|
||||
}
|
||||
|
||||
export function EGITNOPERMISSION({options: {repositoryUrl}, branch: {name}}) {
|
||||
return {
|
||||
message: 'Cannot push to the Git repository.',
|
||||
details: `**semantic-release** cannot push the version tag to the branch \`${name}\` on the remote Git repository with URL \`${repositoryUrl}\`.
|
||||
|
||||
@@ -37,42 +46,57 @@ This can be caused by:
|
||||
- a misconfiguration of the [repositoryUrl](${linkify('docs/usage/configuration.md#repositoryurl')}) option
|
||||
- the repository being unavailable
|
||||
- or missing push permission for the user configured via the [Git credentials on your CI environment](${linkify(
|
||||
'docs/usage/ci-configuration.md#authentication'
|
||||
)})`,
|
||||
}),
|
||||
EINVALIDTAGFORMAT: ({options: {tagFormat}}) => ({
|
||||
'docs/usage/ci-configuration.md#authentication'
|
||||
)})`,
|
||||
};
|
||||
}
|
||||
|
||||
export function EINVALIDTAGFORMAT({options: {tagFormat}}) {
|
||||
return {
|
||||
message: 'Invalid `tagFormat` option.',
|
||||
details: `The [tagFormat](${linkify(
|
||||
'docs/usage/configuration.md#tagformat'
|
||||
)}) must compile to a [valid Git reference](https://git-scm.com/docs/git-check-ref-format#_description).
|
||||
|
||||
Your configuration for the \`tagFormat\` option is \`${stringify(tagFormat)}\`.`,
|
||||
}),
|
||||
ETAGNOVERSION: ({options: {tagFormat}}) => ({
|
||||
};
|
||||
}
|
||||
|
||||
export function ETAGNOVERSION({options: {tagFormat}}) {
|
||||
return {
|
||||
message: 'Invalid `tagFormat` option.',
|
||||
details: `The [tagFormat](${linkify(
|
||||
'docs/usage/configuration.md#tagformat'
|
||||
)}) option must contain the variable \`version\` exactly once.
|
||||
|
||||
Your configuration for the \`tagFormat\` option is \`${stringify(tagFormat)}\`.`,
|
||||
}),
|
||||
EPLUGINCONF: ({type, required, pluginConf}) => ({
|
||||
};
|
||||
}
|
||||
|
||||
export function EPLUGINCONF({type, required, pluginConf}) {
|
||||
return {
|
||||
message: `The \`${type}\` plugin configuration is invalid.`,
|
||||
details: `The [${type} plugin configuration](${linkify(`docs/usage/plugins.md#${toLower(type)}-plugin`)}) ${
|
||||
required ? 'is required and ' : ''
|
||||
} must be a single or an array of plugins definition. A plugin definition is an npm module name, optionally wrapped in an array with an object.
|
||||
|
||||
Your configuration for the \`${type}\` plugin is \`${stringify(pluginConf)}\`.`,
|
||||
}),
|
||||
EPLUGINSCONF: ({plugin}) => ({
|
||||
};
|
||||
}
|
||||
|
||||
export function EPLUGINSCONF({plugin}) {
|
||||
return {
|
||||
message: 'The `plugins` configuration is invalid.',
|
||||
details: `The [plugins](${linkify(
|
||||
'docs/usage/configuration.md#plugins'
|
||||
)}) option must be an array of plugin definitions. A plugin definition is an npm module name, optionally wrapped in an array with an object.
|
||||
|
||||
The invalid configuration is \`${stringify(plugin)}\`.`,
|
||||
}),
|
||||
EPLUGIN: ({pluginName, type}) => ({
|
||||
};
|
||||
}
|
||||
|
||||
export function EPLUGIN({pluginName, type}) {
|
||||
return {
|
||||
message: `A plugin configured in the step ${type} is not a valid semantic-release plugin.`,
|
||||
details: `A valid \`${type}\` **semantic-release** plugin must be a function or an object with a function in the property \`${type}\`.
|
||||
|
||||
@@ -81,8 +105,11 @@ The plugin \`${pluginName}\` doesn't have the property \`${type}\` and cannot be
|
||||
Please refer to the \`${pluginName}\` and [semantic-release plugins configuration](${linkify(
|
||||
'docs/usage/plugins.md'
|
||||
)}) documentation for more details.`,
|
||||
}),
|
||||
EANALYZECOMMITSOUTPUT: ({result, pluginName}) => ({
|
||||
};
|
||||
}
|
||||
|
||||
export function EANALYZECOMMITSOUTPUT({result, pluginName}) {
|
||||
return {
|
||||
message: 'The `analyzeCommits` plugin returned an invalid value. It must return a valid semver release type.',
|
||||
details: `The \`analyzeCommits\` plugin must return a valid [semver](https://semver.org) release type. The valid values are: ${RELEASE_TYPE.map(
|
||||
(type) => `\`${type}\``
|
||||
@@ -97,8 +124,11 @@ We recommend to report the issue to the \`${pluginName}\` authors, providing the
|
||||
- A link to the **semantic-release** plugin developer guide: [${linkify('docs/developer-guide/plugin.md')}](${linkify(
|
||||
'docs/developer-guide/plugin.md'
|
||||
)})`,
|
||||
}),
|
||||
EGENERATENOTESOUTPUT: ({result, pluginName}) => ({
|
||||
};
|
||||
}
|
||||
|
||||
export function EGENERATENOTESOUTPUT({result, pluginName}) {
|
||||
return {
|
||||
message: 'The `generateNotes` plugin returned an invalid value. It must return a `String`.',
|
||||
details: `The \`generateNotes\` plugin must return a \`String\`.
|
||||
|
||||
@@ -111,8 +141,11 @@ We recommend to report the issue to the \`${pluginName}\` authors, providing the
|
||||
- A link to the **semantic-release** plugin developer guide: [${linkify('docs/developer-guide/plugin.md')}](${linkify(
|
||||
'docs/developer-guide/plugin.md'
|
||||
)})`,
|
||||
}),
|
||||
EPUBLISHOUTPUT: ({result, pluginName}) => ({
|
||||
};
|
||||
}
|
||||
|
||||
export function EPUBLISHOUTPUT({result, pluginName}) {
|
||||
return {
|
||||
message: 'A `publish` plugin returned an invalid value. It must return an `Object`.',
|
||||
details: `The \`publish\` plugins must return an \`Object\`.
|
||||
|
||||
@@ -125,8 +158,11 @@ We recommend to report the issue to the \`${pluginName}\` authors, providing the
|
||||
- A link to the **semantic-release** plugin developer guide: [${linkify('docs/developer-guide/plugin.md')}](${linkify(
|
||||
'docs/developer-guide/plugin.md'
|
||||
)})`,
|
||||
}),
|
||||
EADDCHANNELOUTPUT: ({result, pluginName}) => ({
|
||||
};
|
||||
}
|
||||
|
||||
export function EADDCHANNELOUTPUT({result, pluginName}) {
|
||||
return {
|
||||
message: 'A `addChannel` plugin returned an invalid value. It must return an `Object`.',
|
||||
details: `The \`addChannel\` plugins must return an \`Object\`.
|
||||
|
||||
@@ -139,48 +175,66 @@ We recommend to report the issue to the \`${pluginName}\` authors, providing the
|
||||
- A link to the **semantic-release** plugin developer guide: [${linkify('docs/developer-guide/plugin.md')}](${linkify(
|
||||
'docs/developer-guide/plugin.md'
|
||||
)})`,
|
||||
}),
|
||||
EINVALIDBRANCH: ({branch}) => ({
|
||||
};
|
||||
}
|
||||
|
||||
export function EINVALIDBRANCH({branch}) {
|
||||
return {
|
||||
message: 'A branch is invalid in the `branches` configuration.',
|
||||
details: `Each branch in the [branches configuration](${linkify(
|
||||
'docs/usage/configuration.md#branches'
|
||||
)}) must be either a string, a regexp or an object with a \`name\` property.
|
||||
|
||||
Your configuration for the problematic branch is \`${stringify(branch)}\`.`,
|
||||
}),
|
||||
EINVALIDBRANCHNAME: ({branch}) => ({
|
||||
};
|
||||
}
|
||||
|
||||
export function EINVALIDBRANCHNAME({branch}) {
|
||||
return {
|
||||
message: 'A branch name is invalid in the `branches` configuration.',
|
||||
details: `Each branch in the [branches configuration](${linkify(
|
||||
'docs/usage/configuration.md#branches'
|
||||
)}) must be a [valid Git reference](https://git-scm.com/docs/git-check-ref-format#_description).
|
||||
|
||||
Your configuration for the problematic branch is \`${stringify(branch)}\`.`,
|
||||
}),
|
||||
EDUPLICATEBRANCHES: ({duplicates}) => ({
|
||||
};
|
||||
}
|
||||
|
||||
export function EDUPLICATEBRANCHES({duplicates}) {
|
||||
return {
|
||||
message: 'The `branches` configuration has duplicate branches.',
|
||||
details: `Each branch in the [branches configuration](${linkify(
|
||||
'docs/usage/configuration.md#branches'
|
||||
)}) must havea unique name.
|
||||
|
||||
Your configuration contains duplicates for the following branch names: \`${stringify(duplicates)}\`.`,
|
||||
}),
|
||||
EMAINTENANCEBRANCH: ({branch}) => ({
|
||||
};
|
||||
}
|
||||
|
||||
export function EMAINTENANCEBRANCH({branch}) {
|
||||
return {
|
||||
message: 'A maintenance branch is invalid in the `branches` configuration.',
|
||||
details: `Each maintenance branch in the [branches configuration](${linkify(
|
||||
'docs/usage/configuration.md#branches'
|
||||
)}) must have a \`range\` property formatted like \`N.x\`, \`N.x.x\` or \`N.N.x\` (\`N\` is a number).
|
||||
|
||||
Your configuration for the problematic branch is \`${stringify(branch)}\`.`,
|
||||
}),
|
||||
EMAINTENANCEBRANCHES: ({branches}) => ({
|
||||
};
|
||||
}
|
||||
|
||||
export function EMAINTENANCEBRANCHES({branches}) {
|
||||
return {
|
||||
message: 'The maintenance branches are invalid in the `branches` configuration.',
|
||||
details: `Each maintenance branch in the [branches configuration](${linkify(
|
||||
'docs/usage/configuration.md#branches'
|
||||
)}) must have a unique \`range\` property.
|
||||
|
||||
Your configuration for the problematic branches is \`${stringify(branches)}\`.`,
|
||||
}),
|
||||
ERELEASEBRANCHES: ({branches}) => ({
|
||||
};
|
||||
}
|
||||
|
||||
export function ERELEASEBRANCHES({branches}) {
|
||||
return {
|
||||
message: 'The release branches are invalid in the `branches` configuration.',
|
||||
details: `A minimum of 1 and a maximum of 3 release branches are required in the [branches configuration](${linkify(
|
||||
'docs/usage/configuration.md#branches'
|
||||
@@ -189,24 +243,33 @@ Your configuration for the problematic branches is \`${stringify(branches)}\`.`,
|
||||
This may occur if your repository does not have a release branch, such as \`master\`.
|
||||
|
||||
Your configuration for the problematic branches is \`${stringify(branches)}\`.`,
|
||||
}),
|
||||
EPRERELEASEBRANCH: ({branch}) => ({
|
||||
};
|
||||
}
|
||||
|
||||
export function EPRERELEASEBRANCH({branch}) {
|
||||
return {
|
||||
message: 'A pre-release branch configuration is invalid in the `branches` configuration.',
|
||||
details: `Each pre-release branch in the [branches configuration](${linkify(
|
||||
'docs/usage/configuration.md#branches'
|
||||
)}) must have a \`prerelease\` property valid per the [Semantic Versioning Specification](https://semver.org/#spec-item-9). If the \`prerelease\` property is set to \`true\`, then the \`name\` property is used instead.
|
||||
|
||||
Your configuration for the problematic branch is \`${stringify(branch)}\`.`,
|
||||
}),
|
||||
EPRERELEASEBRANCHES: ({branches}) => ({
|
||||
};
|
||||
}
|
||||
|
||||
export function EPRERELEASEBRANCHES({branches}) {
|
||||
return {
|
||||
message: 'The pre-release branches are invalid in the `branches` configuration.',
|
||||
details: `Each pre-release branch in the [branches configuration](${linkify(
|
||||
'docs/usage/configuration.md#branches'
|
||||
)}) must have a unique \`prerelease\` property. If the \`prerelease\` property is set to \`true\`, then the \`name\` property is used instead.
|
||||
|
||||
Your configuration for the problematic branches is \`${stringify(branches)}\`.`,
|
||||
}),
|
||||
EINVALIDNEXTVERSION: ({nextRelease: {version}, branch: {name, range}, commits, validBranches}) => ({
|
||||
};
|
||||
}
|
||||
|
||||
export function EINVALIDNEXTVERSION({nextRelease: {version}, branch: {name, range}, commits, validBranches}) {
|
||||
return {
|
||||
message: `The release \`${version}\` on branch \`${name}\` cannot be published as it is out of range.`,
|
||||
details: `Based on the releases published on other branches, only versions within the range \`${range}\` can be published from branch \`${name}\`.
|
||||
|
||||
@@ -214,19 +277,22 @@ The following commit${commits.length > 1 ? 's are' : ' is'} responsible for the
|
||||
${commits.map(({commit: {short}, subject}) => `- ${subject} (${short})`).join('\n')}
|
||||
|
||||
${
|
||||
commits.length > 1 ? 'Those commits' : 'This commit'
|
||||
} should be moved to a valid branch with [git merge](https://git-scm.com/docs/git-merge) or [git cherry-pick](https://git-scm.com/docs/git-cherry-pick) and removed from branch \`${name}\` with [git revert](https://git-scm.com/docs/git-revert) or [git reset](https://git-scm.com/docs/git-reset).
|
||||
commits.length > 1 ? 'Those commits' : 'This commit'
|
||||
} should be moved to a valid branch with [git merge](https://git-scm.com/docs/git-merge) or [git cherry-pick](https://git-scm.com/docs/git-cherry-pick) and removed from branch \`${name}\` with [git revert](https://git-scm.com/docs/git-revert) or [git reset](https://git-scm.com/docs/git-reset).
|
||||
|
||||
A valid branch could be ${wordsList(validBranches.map(({name}) => `\`${name}\``))}.
|
||||
|
||||
See the [workflow configuration documentation](${linkify('docs/usage/workflow-configuration.md')}) for more details.`,
|
||||
}),
|
||||
EINVALIDMAINTENANCEMERGE: ({nextRelease: {channel, gitTag, version}, branch: {mergeRange, name}}) => ({
|
||||
};
|
||||
}
|
||||
|
||||
export function EINVALIDMAINTENANCEMERGE({nextRelease: {channel, gitTag, version}, branch: {mergeRange, name}}) {
|
||||
return {
|
||||
message: `The release \`${version}\` on branch \`${name}\` cannot be published as it is out of range.`,
|
||||
details: `Only releases within the range \`${mergeRange}\` can be merged into the maintenance branch \`${name}\` and published to the \`${channel}\` distribution channel.
|
||||
|
||||
The branch \`${name}\` head should be [reset](https://git-scm.com/docs/git-reset) to a previous commit so the commit with tag \`${gitTag}\` is removed from the branch history.
|
||||
|
||||
See the [workflow configuration documentation](${linkify('docs/usage/workflow-configuration.md')}) for more details.`,
|
||||
}),
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/* eslint require-atomic-updates: off */
|
||||
|
||||
const {isString, isPlainObject} = require('lodash');
|
||||
const {getGitHead} = require('../git');
|
||||
const hideSensitive = require('../hide-sensitive');
|
||||
const {hideSensitiveValues} = require('../utils');
|
||||
const {RELEASE_TYPE, RELEASE_NOTES_SEPARATOR} = require('./constants');
|
||||
import {isPlainObject, isString} from 'lodash-es';
|
||||
import {getGitHead} from '../git.js';
|
||||
import hideSensitive from '../hide-sensitive.js';
|
||||
import {hideSensitiveValues} from '../utils.js';
|
||||
import {RELEASE_NOTES_SEPARATOR, RELEASE_TYPE} from './constants.js';
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
verifyConditions: {
|
||||
required: false,
|
||||
dryRun: true,
|
||||
|
||||
+6
-4
@@ -1,5 +1,7 @@
|
||||
const debug = require('debug')('semantic-release:get-commits');
|
||||
const {getCommits} = require('./git');
|
||||
import debugCommits from 'debug';
|
||||
import {getCommits} from './git.js';
|
||||
|
||||
const debug = debugCommits('semantic-release:get-commits');
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -8,7 +10,7 @@ const {getCommits} = require('./git');
|
||||
*
|
||||
* @return {Promise<Array<Object>>} The list of commits on the branch `branch` since the last release.
|
||||
*/
|
||||
module.exports = async ({cwd, env, lastRelease: {gitHead: from}, nextRelease: {gitHead: to = 'HEAD'} = {}, logger}) => {
|
||||
export default async ({cwd, env, lastRelease: {gitHead: from}, nextRelease: {gitHead: to = 'HEAD'} = {}, logger}) => {
|
||||
if (from) {
|
||||
debug('Use from: %s', from);
|
||||
} else {
|
||||
@@ -20,4 +22,4 @@ module.exports = async ({cwd, env, lastRelease: {gitHead: from}, nextRelease: {g
|
||||
logger.log(`Found ${commits.length} commits since last release`);
|
||||
debug('Parsed commits: %o', commits);
|
||||
return commits;
|
||||
};
|
||||
}
|
||||
|
||||
+25
-16
@@ -1,16 +1,24 @@
|
||||
const {castArray, pickBy, isNil, isString, isPlainObject} = require('lodash');
|
||||
const readPkgUp = require('read-pkg-up');
|
||||
const {cosmiconfig} = require('cosmiconfig');
|
||||
const resolveFrom = require('resolve-from');
|
||||
const debug = require('debug')('semantic-release:config');
|
||||
const {repoUrl} = require('./git');
|
||||
const PLUGINS_DEFINITIONS = require('./definitions/plugins');
|
||||
const plugins = require('./plugins');
|
||||
const {validatePlugin, parseConfig} = require('./plugins/utils');
|
||||
import {dirname, resolve} from 'node:path';
|
||||
import {fileURLToPath} from 'node:url';
|
||||
import {createRequire} from 'node:module';
|
||||
|
||||
import {castArray, isNil, isPlainObject, isString, pickBy} from 'lodash-es';
|
||||
import {readPackageUp} from 'read-pkg-up';
|
||||
import {cosmiconfig} from 'cosmiconfig';
|
||||
import resolveFrom from 'resolve-from';
|
||||
import debugConfig from 'debug';
|
||||
import {repoUrl} from './git.js';
|
||||
import PLUGINS_DEFINITIONS from './definitions/plugins.js';
|
||||
import plugins from './plugins/index.js';
|
||||
import {parseConfig, validatePlugin} from './plugins/utils.js';
|
||||
|
||||
const debug = debugConfig('semantic-release:config');
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
const CONFIG_NAME = 'release';
|
||||
|
||||
module.exports = async (context, cliOptions) => {
|
||||
export default async (context, cliOptions) => {
|
||||
const {cwd, env} = context;
|
||||
const {config, filepath} = (await cosmiconfig(CONFIG_NAME).search(cwd)) || {};
|
||||
|
||||
@@ -25,11 +33,12 @@ module.exports = async (context, cliOptions) => {
|
||||
if (extendPaths) {
|
||||
// If `extends` is defined, load and merge each shareable config with `options`
|
||||
options = {
|
||||
...castArray(extendPaths).reduce((result, extendPath) => {
|
||||
...await (castArray(extendPaths).reduce(async(eventualResult, extendPath) => {
|
||||
const result = await eventualResult;
|
||||
const extendsOptions = require(resolveFrom.silent(__dirname, extendPath) || resolveFrom(cwd, extendPath));
|
||||
|
||||
// For each plugin defined in a shareable config, save in `pluginsPath` the extendable config path,
|
||||
// so those plugin will be loaded relatively to the config file
|
||||
// so those plugin will be loaded relative to the config file
|
||||
Object.entries(extendsOptions)
|
||||
.filter(([, value]) => Boolean(value))
|
||||
.reduce((pluginsPath, [option, value]) => {
|
||||
@@ -47,7 +56,7 @@ module.exports = async (context, cliOptions) => {
|
||||
}, pluginsPath);
|
||||
|
||||
return {...result, ...extendsOptions};
|
||||
}, {}),
|
||||
}, {})),
|
||||
...options,
|
||||
};
|
||||
}
|
||||
@@ -70,7 +79,7 @@ module.exports = async (context, cliOptions) => {
|
||||
'@semantic-release/npm',
|
||||
'@semantic-release/github',
|
||||
],
|
||||
// Remove `null` and `undefined` options so they can be replaced with default ones
|
||||
// Remove `null` and `undefined` options, so they can be replaced with default ones
|
||||
...pickBy(options, (option) => !isNil(option)),
|
||||
...(options.branches ? {branches: castArray(options.branches)} : {}),
|
||||
};
|
||||
@@ -82,9 +91,9 @@ module.exports = async (context, cliOptions) => {
|
||||
debug('options values: %O', options);
|
||||
|
||||
return {options, plugins: await plugins({...context, options}, pluginsPath)};
|
||||
};
|
||||
}
|
||||
|
||||
async function pkgRepoUrl(options) {
|
||||
const {packageJson} = (await readPkgUp(options)) || {};
|
||||
const {packageJson} = (await readPackageUp(options)) || {};
|
||||
return packageJson && (isPlainObject(packageJson.repository) ? packageJson.repository.url : packageJson.repository);
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
const SemanticReleaseError = require('@semantic-release/error');
|
||||
const ERROR_DEFINITIONS = require('./definitions/errors');
|
||||
import SemanticReleaseError from '@semantic-release/error';
|
||||
import * as ERROR_DEFINITIONS from './definitions/errors.js';
|
||||
|
||||
module.exports = (code, ctx = {}) => {
|
||||
export default (code, ctx = {}) => {
|
||||
const {message, details} = ERROR_DEFINITIONS[code](ctx);
|
||||
return new SemanticReleaseError(message, code, details);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
const {parse, format} = require('url'); // eslint-disable-line node/no-deprecated-api
|
||||
const {isNil} = require('lodash');
|
||||
const hostedGitInfo = require('hosted-git-info');
|
||||
const {verifyAuth} = require('./git');
|
||||
const debug = require('debug')('semantic-release:get-git-auth-url');
|
||||
import {format, parse} from 'node:url';
|
||||
import {isNil} from 'lodash-es';
|
||||
import hostedGitInfo from 'hosted-git-info';
|
||||
import debugAuthUrl from 'debug';
|
||||
import {verifyAuth} from './git.js';
|
||||
|
||||
const debug = debugAuthUrl('semantic-release:get-git-auth-url');
|
||||
|
||||
/**
|
||||
* Machinery to format a repository URL with the given credentials
|
||||
@@ -57,7 +59,7 @@ async function ensureValidAuthUrl({cwd, env, branch}, authUrl) {
|
||||
*
|
||||
* @return {String} The formatted Git repository URL.
|
||||
*/
|
||||
module.exports = async (context) => {
|
||||
export default async (context) => {
|
||||
const {cwd, env, branch} = context;
|
||||
const GIT_TOKENS = {
|
||||
GIT_CREDENTIALS: undefined,
|
||||
@@ -119,4 +121,4 @@ module.exports = async (context) => {
|
||||
}
|
||||
|
||||
return repositoryUrl;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const {isUndefined} = require('lodash');
|
||||
const semver = require('semver');
|
||||
const {makeTag, isSameChannel} = require('./utils');
|
||||
import {isUndefined} from 'lodash-es';
|
||||
import semver from 'semver';
|
||||
import {isSameChannel, makeTag} from './utils.js';
|
||||
|
||||
/**
|
||||
* Last release.
|
||||
@@ -18,7 +18,7 @@ const {makeTag, isSameChannel} = require('./utils');
|
||||
*
|
||||
* - Filter out the branch tags that are not valid semantic version
|
||||
* - Sort the versions
|
||||
* - Retrive the highest version
|
||||
* - Retrieve the highest version
|
||||
*
|
||||
* @param {Object} context semantic-release context.
|
||||
* @param {Object} params Function parameters.
|
||||
@@ -26,7 +26,7 @@ const {makeTag, isSameChannel} = require('./utils');
|
||||
*
|
||||
* @return {LastRelease} The last tagged release or empty object if none is found.
|
||||
*/
|
||||
module.exports = ({branch, options: {tagFormat}}, {before} = {}) => {
|
||||
export default ({branch, options: {tagFormat}}, {before} = {}) => {
|
||||
const [{version, gitTag, channels} = {}] = branch.tags
|
||||
.filter(
|
||||
(tag) =>
|
||||
@@ -41,4 +41,4 @@ module.exports = ({branch, options: {tagFormat}}, {before} = {}) => {
|
||||
}
|
||||
|
||||
return {};
|
||||
};
|
||||
}
|
||||
|
||||
+6
-4
@@ -1,7 +1,9 @@
|
||||
const {Signale} = require('signale');
|
||||
const figures = require('figures');
|
||||
import signale from 'signale';
|
||||
import figures from 'figures';
|
||||
|
||||
module.exports = ({stdout, stderr}) =>
|
||||
const {Signale} = signale;
|
||||
|
||||
export default ({stdout, stderr}) =>
|
||||
new Signale({
|
||||
config: {displayTimestamp: true, underlineMessage: false, displayLabel: false},
|
||||
disabled: false,
|
||||
@@ -13,4 +15,4 @@ module.exports = ({stdout, stderr}) =>
|
||||
log: {badge: figures.info, color: 'magenta', label: '', stream: [stdout]},
|
||||
success: {badge: figures.tick, color: 'green', label: '', stream: [stdout]},
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
const semver = require('semver');
|
||||
const {FIRST_RELEASE, FIRSTPRERELEASE} = require('./definitions/constants');
|
||||
const {isSameChannel, getLatestVersion, tagsToVersions, highest} = require('./utils');
|
||||
import semver from 'semver';
|
||||
import {FIRST_RELEASE, FIRSTPRERELEASE} from './definitions/constants.js';
|
||||
import {getLatestVersion, highest, isSameChannel, tagsToVersions} from './utils.js';
|
||||
|
||||
module.exports = ({branch, nextRelease: {type, channel}, lastRelease, logger}) => {
|
||||
export default ({branch, nextRelease: {type, channel}, lastRelease, logger}) => {
|
||||
let version;
|
||||
if (lastRelease.version) {
|
||||
const {major, minor, patch} = semver.parse(lastRelease.version);
|
||||
@@ -32,4 +32,4 @@ module.exports = ({branch, nextRelease: {type, channel}, lastRelease, logger}) =
|
||||
}
|
||||
|
||||
return version;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
const {uniqBy, intersection} = require('lodash');
|
||||
const semver = require('semver');
|
||||
const semverDiff = require('semver-diff');
|
||||
const getLastRelease = require('./get-last-release');
|
||||
const {makeTag, getLowerBound} = require('./utils');
|
||||
import {intersection, uniqBy} from 'lodash-es';
|
||||
import semver from 'semver';
|
||||
import semverDiff from 'semver-diff';
|
||||
import getLastRelease from './get-last-release.js';
|
||||
import {getLowerBound, makeTag} from './utils.js';
|
||||
|
||||
/**
|
||||
* Find releases that have been merged from from a higher branch but not added on the channel of the current branch.
|
||||
@@ -11,7 +11,7 @@ const {makeTag, getLowerBound} = require('./utils');
|
||||
*
|
||||
* @return {Array<Object>} Last release and next release to be added on the channel of the current branch.
|
||||
*/
|
||||
module.exports = (context) => {
|
||||
export default (context) => {
|
||||
const {
|
||||
branch,
|
||||
branches,
|
||||
@@ -57,4 +57,4 @@ module.exports = (context) => {
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
+26
-46
@@ -1,8 +1,10 @@
|
||||
const gitLogParser = require('git-log-parser');
|
||||
const getStream = require('get-stream');
|
||||
const execa = require('execa');
|
||||
const debug = require('debug')('semantic-release:git');
|
||||
const {GIT_NOTE_REF} = require('./definitions/constants');
|
||||
import gitLogParser from 'git-log-parser';
|
||||
import getStream from 'get-stream';
|
||||
import {execa} from 'execa';
|
||||
import debugGit from 'debug';
|
||||
import {GIT_NOTE_REF} from './definitions/constants.js';
|
||||
|
||||
const debug = debugGit('semantic-release:git');
|
||||
|
||||
Object.assign(gitLogParser.fields, {hash: 'H', message: 'B', gitTags: 'd', committerDate: {key: 'ci', type: Date}});
|
||||
|
||||
@@ -14,7 +16,7 @@ Object.assign(gitLogParser.fields, {hash: 'H', message: 'B', gitTags: 'd', commi
|
||||
*
|
||||
* @return {String} The commit sha of the tag in parameter or `null`.
|
||||
*/
|
||||
async function getTagHead(tagName, execaOptions) {
|
||||
export async function getTagHead(tagName, execaOptions) {
|
||||
return (await execa('git', ['rev-list', '-1', tagName], execaOptions)).stdout;
|
||||
}
|
||||
|
||||
@@ -27,7 +29,7 @@ async function getTagHead(tagName, execaOptions) {
|
||||
* @return {Array<String>} List of git tags.
|
||||
* @throws {Error} If the `git` command fails.
|
||||
*/
|
||||
async function getTags(branch, execaOptions) {
|
||||
export async function getTags(branch, execaOptions) {
|
||||
return (await execa('git', ['tag', '--merged', branch], execaOptions)).stdout
|
||||
.split('\n')
|
||||
.map((tag) => tag.trim())
|
||||
@@ -42,7 +44,7 @@ async function getTags(branch, execaOptions) {
|
||||
* @param {Object} [execaOpts] Options to pass to `execa`.
|
||||
* @return {Promise<Array<Object>>} The list of commits between `from` and `to`.
|
||||
*/
|
||||
async function getCommits(from, to, execaOptions) {
|
||||
export async function getCommits(from, to, execaOptions) {
|
||||
return (
|
||||
await getStream.array(
|
||||
gitLogParser.parse(
|
||||
@@ -62,7 +64,7 @@ async function getCommits(from, to, execaOptions) {
|
||||
* @return {Array<String>} List of git branches.
|
||||
* @throws {Error} If the `git` command fails.
|
||||
*/
|
||||
async function getBranches(repositoryUrl, execaOptions) {
|
||||
export async function getBranches(repositoryUrl, execaOptions) {
|
||||
return (await execa('git', ['ls-remote', '--heads', repositoryUrl], execaOptions)).stdout
|
||||
.split('\n')
|
||||
.filter(Boolean)
|
||||
@@ -77,7 +79,7 @@ async function getBranches(repositoryUrl, execaOptions) {
|
||||
*
|
||||
* @return {Boolean} `true` if the reference exists, falsy otherwise.
|
||||
*/
|
||||
async function isRefExists(ref, execaOptions) {
|
||||
export async function isRefExists(ref, execaOptions) {
|
||||
try {
|
||||
return (await execa('git', ['rev-parse', '--verify', ref], execaOptions)).exitCode === 0;
|
||||
} catch (error) {
|
||||
@@ -99,7 +101,7 @@ async function isRefExists(ref, execaOptions) {
|
||||
* @param {String} branch The repository branch to fetch.
|
||||
* @param {Object} [execaOpts] Options to pass to `execa`.
|
||||
*/
|
||||
async function fetch(repositoryUrl, branch, ciBranch, execaOptions) {
|
||||
export async function fetch(repositoryUrl, branch, ciBranch, execaOptions) {
|
||||
const isDetachedHead =
|
||||
(await execa('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {...execaOptions, reject: false})).stdout === 'HEAD';
|
||||
|
||||
@@ -137,7 +139,7 @@ async function fetch(repositoryUrl, branch, ciBranch, execaOptions) {
|
||||
* @param {String} repositoryUrl The remote repository URL.
|
||||
* @param {Object} [execaOpts] Options to pass to `execa`.
|
||||
*/
|
||||
async function fetchNotes(repositoryUrl, execaOptions) {
|
||||
export async function fetchNotes(repositoryUrl, execaOptions) {
|
||||
try {
|
||||
await execa(
|
||||
'git',
|
||||
@@ -159,7 +161,7 @@ async function fetchNotes(repositoryUrl, execaOptions) {
|
||||
*
|
||||
* @return {String} the sha of the HEAD commit.
|
||||
*/
|
||||
async function getGitHead(execaOptions) {
|
||||
export async function getGitHead(execaOptions) {
|
||||
return (await execa('git', ['rev-parse', 'HEAD'], execaOptions)).stdout;
|
||||
}
|
||||
|
||||
@@ -170,7 +172,7 @@ async function getGitHead(execaOptions) {
|
||||
*
|
||||
* @return {string} The value of the remote git URL.
|
||||
*/
|
||||
async function repoUrl(execaOptions) {
|
||||
export async function repoUrl(execaOptions) {
|
||||
try {
|
||||
return (await execa('git', ['config', '--get', 'remote.origin.url'], execaOptions)).stdout;
|
||||
} catch (error) {
|
||||
@@ -185,7 +187,7 @@ async function repoUrl(execaOptions) {
|
||||
*
|
||||
* @return {Boolean} `true` if the current working directory is in a git repository, falsy otherwise.
|
||||
*/
|
||||
async function isGitRepo(execaOptions) {
|
||||
export async function isGitRepo(execaOptions) {
|
||||
try {
|
||||
return (await execa('git', ['rev-parse', '--git-dir'], execaOptions)).exitCode === 0;
|
||||
} catch (error) {
|
||||
@@ -202,7 +204,7 @@ async function isGitRepo(execaOptions) {
|
||||
*
|
||||
* @throws {Error} if not authorized to push.
|
||||
*/
|
||||
async function verifyAuth(repositoryUrl, branch, execaOptions) {
|
||||
export async function verifyAuth(repositoryUrl, branch, execaOptions) {
|
||||
try {
|
||||
await execa('git', ['push', '--dry-run', '--no-verify', repositoryUrl, `HEAD:${branch}`], execaOptions);
|
||||
} catch (error) {
|
||||
@@ -220,7 +222,7 @@ async function verifyAuth(repositoryUrl, branch, execaOptions) {
|
||||
*
|
||||
* @throws {Error} if the tag creation failed.
|
||||
*/
|
||||
async function tag(tagName, ref, execaOptions) {
|
||||
export async function tag(tagName, ref, execaOptions) {
|
||||
await execa('git', ['tag', tagName, ref], execaOptions);
|
||||
}
|
||||
|
||||
@@ -232,7 +234,7 @@ async function tag(tagName, ref, execaOptions) {
|
||||
*
|
||||
* @throws {Error} if the push failed.
|
||||
*/
|
||||
async function push(repositoryUrl, execaOptions) {
|
||||
export async function push(repositoryUrl, execaOptions) {
|
||||
await execa('git', ['push', '--tags', repositoryUrl], execaOptions);
|
||||
}
|
||||
|
||||
@@ -244,7 +246,7 @@ async function push(repositoryUrl, execaOptions) {
|
||||
*
|
||||
* @throws {Error} if the push failed.
|
||||
*/
|
||||
async function pushNotes(repositoryUrl, execaOptions) {
|
||||
export async function pushNotes(repositoryUrl, execaOptions) {
|
||||
await execa('git', ['push', repositoryUrl, `refs/notes/${GIT_NOTE_REF}`], execaOptions);
|
||||
}
|
||||
|
||||
@@ -256,7 +258,7 @@ async function pushNotes(repositoryUrl, execaOptions) {
|
||||
*
|
||||
* @return {Boolean} `true` if valid, falsy otherwise.
|
||||
*/
|
||||
async function verifyTagName(tagName, execaOptions) {
|
||||
export async function verifyTagName(tagName, execaOptions) {
|
||||
try {
|
||||
return (await execa('git', ['check-ref-format', `refs/tags/${tagName}`], execaOptions)).exitCode === 0;
|
||||
} catch (error) {
|
||||
@@ -272,7 +274,7 @@ async function verifyTagName(tagName, execaOptions) {
|
||||
*
|
||||
* @return {Boolean} `true` if valid, falsy otherwise.
|
||||
*/
|
||||
async function verifyBranchName(branch, execaOptions) {
|
||||
export async function verifyBranchName(branch, execaOptions) {
|
||||
try {
|
||||
return (await execa('git', ['check-ref-format', `refs/heads/${branch}`], execaOptions)).exitCode === 0;
|
||||
} catch (error) {
|
||||
@@ -289,7 +291,7 @@ async function verifyBranchName(branch, execaOptions) {
|
||||
*
|
||||
* @return {Boolean} `true` is the HEAD of the current local branch is the same as the HEAD of the remote branch, falsy otherwise.
|
||||
*/
|
||||
async function isBranchUpToDate(repositoryUrl, branch, execaOptions) {
|
||||
export async function isBranchUpToDate(repositoryUrl, branch, execaOptions) {
|
||||
return (
|
||||
(await getGitHead(execaOptions)) ===
|
||||
(await execa('git', ['ls-remote', '--heads', repositoryUrl, branch], execaOptions)).stdout.match(/^(?<ref>\w+)?/)[1]
|
||||
@@ -304,7 +306,7 @@ async function isBranchUpToDate(repositoryUrl, branch, execaOptions) {
|
||||
*
|
||||
* @return {Object} the parsed JSON note if there is one, an empty object otherwise.
|
||||
*/
|
||||
async function getNote(ref, execaOptions) {
|
||||
export async function getNote(ref, execaOptions) {
|
||||
try {
|
||||
return JSON.parse((await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'show', ref], execaOptions)).stdout);
|
||||
} catch (error) {
|
||||
@@ -324,28 +326,6 @@ async function getNote(ref, execaOptions) {
|
||||
* @param {String} ref The Git reference to add the note to.
|
||||
* @param {Object} [execaOpts] Options to pass to `execa`.
|
||||
*/
|
||||
async function addNote(note, ref, execaOptions) {
|
||||
export async function addNote(note, ref, execaOptions) {
|
||||
await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'add', '-f', '-m', JSON.stringify(note), ref], execaOptions);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getTagHead,
|
||||
getTags,
|
||||
getCommits,
|
||||
getBranches,
|
||||
isRefExists,
|
||||
fetch,
|
||||
fetchNotes,
|
||||
getGitHead,
|
||||
repoUrl,
|
||||
isGitRepo,
|
||||
verifyAuth,
|
||||
tag,
|
||||
push,
|
||||
pushNotes,
|
||||
verifyTagName,
|
||||
isBranchUpToDate,
|
||||
verifyBranchName,
|
||||
getNote,
|
||||
addNote,
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const {escapeRegExp, size, isString} = require('lodash');
|
||||
const {SECRET_REPLACEMENT, SECRET_MIN_SIZE} = require('./definitions/constants');
|
||||
import {escapeRegExp, isString, size} from 'lodash-es';
|
||||
import {SECRET_MIN_SIZE, SECRET_REPLACEMENT} from './definitions/constants.js';
|
||||
|
||||
module.exports = (env) => {
|
||||
export default (env) => {
|
||||
const toReplace = Object.keys(env).filter((envVar) => {
|
||||
// https://github.com/semantic-release/semantic-release/issues/1558
|
||||
if (envVar === 'GOPRIVATE') {
|
||||
@@ -17,4 +17,4 @@ module.exports = (env) => {
|
||||
);
|
||||
return (output) =>
|
||||
output && isString(output) && toReplace.length > 0 ? output.toString().replace(regexp, SECRET_REPLACEMENT) : output;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
const {identity, isPlainObject, omit, castArray, isNil, isString} = require('lodash');
|
||||
const AggregateError = require('aggregate-error');
|
||||
const getError = require('../get-error');
|
||||
const PLUGINS_DEFINITIONS = require('../definitions/plugins');
|
||||
const {validatePlugin, validateStep, loadPlugin, parseConfig} = require('./utils');
|
||||
const pipeline = require('./pipeline');
|
||||
const normalize = require('./normalize');
|
||||
import {castArray, identity, isNil, isPlainObject, isString, omit} from 'lodash-es';
|
||||
import AggregateError from 'aggregate-error';
|
||||
import getError from '../get-error.js';
|
||||
import PLUGINS_DEFINITIONS from '../definitions/plugins.js';
|
||||
import {loadPlugin, parseConfig, validatePlugin, validateStep} from './utils.js';
|
||||
import pipeline from './pipeline.js';
|
||||
import normalize from './normalize.js';
|
||||
|
||||
module.exports = async (context, pluginsPath) => {
|
||||
export default async (context, pluginsPath) => {
|
||||
let {options, logger} = context;
|
||||
const errors = [];
|
||||
|
||||
@@ -100,4 +100,4 @@ module.exports = async (context, pluginsPath) => {
|
||||
}
|
||||
|
||||
return pluginsConfig;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
const {isPlainObject, isFunction, noop, cloneDeep, omit} = require('lodash');
|
||||
const debug = require('debug')('semantic-release:plugins');
|
||||
const getError = require('../get-error');
|
||||
const {extractErrors} = require('../utils');
|
||||
const PLUGINS_DEFINITIONS = require('../definitions/plugins');
|
||||
const {loadPlugin, parseConfig} = require('./utils');
|
||||
import {cloneDeep, isFunction, isPlainObject, noop, omit} from 'lodash-es';
|
||||
import debugPlugins from 'debug';
|
||||
import getError from '../get-error.js';
|
||||
import {extractErrors} from '../utils.js';
|
||||
import PLUGINS_DEFINITIONS from '../definitions/plugins.js';
|
||||
import {loadPlugin, parseConfig} from './utils.js';
|
||||
|
||||
module.exports = async (context, type, pluginOpt, pluginsPath) => {
|
||||
const debug = debugPlugins('semantic-release:plugins');
|
||||
|
||||
export default async (context, type, pluginOpt, pluginsPath) => {
|
||||
const {stdout, stderr, options, logger} = context;
|
||||
if (!pluginOpt) {
|
||||
return noop;
|
||||
@@ -64,4 +66,4 @@ module.exports = async (context, type, pluginOpt, pluginsPath) => {
|
||||
}
|
||||
|
||||
return validator;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const {identity} = require('lodash');
|
||||
const pReduce = require('p-reduce');
|
||||
const AggregateError = require('aggregate-error');
|
||||
const {extractErrors} = require('../utils');
|
||||
import {identity} from 'lodash-es';
|
||||
import pReduce from 'p-reduce';
|
||||
import AggregateError from 'aggregate-error';
|
||||
import {extractErrors} from '../utils.js';
|
||||
|
||||
/**
|
||||
* A Function that execute a list of function sequencially. If at least one Function ins the pipeline throws an Error or rejects, the pipeline function rejects as well.
|
||||
@@ -25,7 +25,7 @@ const {extractErrors} = require('../utils');
|
||||
*
|
||||
* @return {Pipeline} A Function that execute the `steps` sequencially
|
||||
*/
|
||||
module.exports = (steps, {settleAll = false, getNextInput = identity, transform = identity} = {}) => async (input) => {
|
||||
export default (steps, {settleAll = false, getNextInput = identity, transform = identity} = {}) => async (input) => {
|
||||
const results = [];
|
||||
const errors = [];
|
||||
await pReduce(
|
||||
@@ -55,4 +55,4 @@ module.exports = (steps, {settleAll = false, getNextInput = identity, transform
|
||||
}
|
||||
|
||||
return results;
|
||||
};
|
||||
}
|
||||
|
||||
+10
-9
@@ -1,6 +1,9 @@
|
||||
const {dirname} = require('path');
|
||||
const {isString, isFunction, castArray, isArray, isPlainObject, isNil} = require('lodash');
|
||||
const resolveFrom = require('resolve-from');
|
||||
import {dirname} from 'node:path';
|
||||
import {fileURLToPath} from 'node:url';
|
||||
import {castArray, isArray, isFunction, isNil, isPlainObject, isString} from 'lodash-es';
|
||||
import resolveFrom from 'resolve-from';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
const validateSteps = (conf) => {
|
||||
return conf.every((conf) => {
|
||||
@@ -24,7 +27,7 @@ const validateSteps = (conf) => {
|
||||
});
|
||||
};
|
||||
|
||||
function validatePlugin(conf) {
|
||||
export function validatePlugin(conf) {
|
||||
return (
|
||||
isString(conf) ||
|
||||
(isArray(conf) &&
|
||||
@@ -35,7 +38,7 @@ function validatePlugin(conf) {
|
||||
);
|
||||
}
|
||||
|
||||
function validateStep({required}, conf) {
|
||||
export function validateStep({required}, conf) {
|
||||
conf = castArray(conf).filter(Boolean);
|
||||
if (required) {
|
||||
return conf.length >= 1 && validateSteps(conf);
|
||||
@@ -44,7 +47,7 @@ function validateStep({required}, conf) {
|
||||
return conf.length === 0 || validateSteps(conf);
|
||||
}
|
||||
|
||||
async function loadPlugin({cwd}, name, pluginsPath) {
|
||||
export async function loadPlugin({cwd}, name, pluginsPath) {
|
||||
const basePath = pluginsPath[name]
|
||||
? dirname(resolveFrom.silent(__dirname, pluginsPath[name]) || resolveFrom(cwd, pluginsPath[name]))
|
||||
: __dirname;
|
||||
@@ -54,7 +57,7 @@ async function loadPlugin({cwd}, name, pluginsPath) {
|
||||
return isFunction(name) ? name : (await import(resolveFrom.silent(basePath, name) || resolveFrom(cwd, name))).default;
|
||||
}
|
||||
|
||||
function parseConfig(plugin) {
|
||||
export function parseConfig(plugin) {
|
||||
let path;
|
||||
let config;
|
||||
if (isArray(plugin)) {
|
||||
@@ -67,5 +70,3 @@ function parseConfig(plugin) {
|
||||
|
||||
return [path, config || {}];
|
||||
}
|
||||
|
||||
module.exports = {validatePlugin, validateStep, loadPlugin, parseConfig};
|
||||
|
||||
+19
-37
@@ -1,12 +1,12 @@
|
||||
const {isFunction, union, template} = require('lodash');
|
||||
const semver = require('semver');
|
||||
const hideSensitive = require('./hide-sensitive');
|
||||
import {isFunction, template, union} from 'lodash-es';
|
||||
import semver from 'semver';
|
||||
import hideSensitive from './hide-sensitive.js';
|
||||
|
||||
function extractErrors(err) {
|
||||
return err && isFunction(err[Symbol.iterator]) ? [...err] : [err];
|
||||
export function extractErrors(err) {
|
||||
return err && err.errors ? [...err.errors] : [err];
|
||||
}
|
||||
|
||||
function hideSensitiveValues(env, objs) {
|
||||
export function hideSensitiveValues(env, objs) {
|
||||
const hideFunction = hideSensitive(env);
|
||||
return objs.map((object) => {
|
||||
Object.getOwnPropertyNames(object).forEach((prop) => {
|
||||
@@ -18,19 +18,19 @@ function hideSensitiveValues(env, objs) {
|
||||
});
|
||||
}
|
||||
|
||||
function tagsToVersions(tags) {
|
||||
export function tagsToVersions(tags) {
|
||||
return tags.map(({version}) => version);
|
||||
}
|
||||
|
||||
function isMajorRange(range) {
|
||||
export function isMajorRange(range) {
|
||||
return /^\d+\.x(?:\.x)?$/i.test(range);
|
||||
}
|
||||
|
||||
function isMaintenanceRange(range) {
|
||||
export function isMaintenanceRange(range) {
|
||||
return /^\d+\.(?:\d+|x)(?:\.x)?$/i.test(range);
|
||||
}
|
||||
|
||||
function getUpperBound(range) {
|
||||
export function getUpperBound(range) {
|
||||
const result = semver.valid(range)
|
||||
? range
|
||||
: ((semver.validRange(range) || '').match(/<(?<upperBound>\d+\.\d+\.\d+(-\d+)?)$/) || [])[1];
|
||||
@@ -41,27 +41,27 @@ function getUpperBound(range) {
|
||||
: result;
|
||||
}
|
||||
|
||||
function getLowerBound(range) {
|
||||
export function getLowerBound(range) {
|
||||
return ((semver.validRange(range) || '').match(/(?<lowerBound>\d+\.\d+\.\d+)/) || [])[1];
|
||||
}
|
||||
|
||||
function highest(version1, version2) {
|
||||
export function highest(version1, version2) {
|
||||
return version1 && version2 ? (semver.gt(version1, version2) ? version1 : version2) : version1 || version2;
|
||||
}
|
||||
|
||||
function lowest(version1, version2) {
|
||||
export function lowest(version1, version2) {
|
||||
return version1 && version2 ? (semver.lt(version1, version2) ? version1 : version2) : version1 || version2;
|
||||
}
|
||||
|
||||
function getLatestVersion(versions, {withPrerelease} = {}) {
|
||||
export function getLatestVersion(versions, {withPrerelease} = {}) {
|
||||
return versions.filter((version) => withPrerelease || !semver.prerelease(version)).sort(semver.rcompare)[0];
|
||||
}
|
||||
|
||||
function getEarliestVersion(versions, {withPrerelease} = {}) {
|
||||
export function getEarliestVersion(versions, {withPrerelease} = {}) {
|
||||
return versions.filter((version) => withPrerelease || !semver.prerelease(version)).sort(semver.compare)[0];
|
||||
}
|
||||
|
||||
function getFirstVersion(versions, lowerBranches) {
|
||||
export function getFirstVersion(versions, lowerBranches) {
|
||||
const lowerVersion = union(...lowerBranches.map(({tags}) => tagsToVersions(tags))).sort(semver.rcompare);
|
||||
if (lowerVersion[0]) {
|
||||
return versions.sort(semver.compare).find((version) => semver.gt(version, lowerVersion[0]));
|
||||
@@ -70,32 +70,14 @@ function getFirstVersion(versions, lowerBranches) {
|
||||
return getEarliestVersion(versions);
|
||||
}
|
||||
|
||||
function getRange(min, max) {
|
||||
export function getRange(min, max) {
|
||||
return `>=${min}${max ? ` <${max}` : ''}`;
|
||||
}
|
||||
|
||||
function makeTag(tagFormat, version) {
|
||||
export function makeTag(tagFormat, version) {
|
||||
return template(tagFormat)({version});
|
||||
}
|
||||
|
||||
function isSameChannel(channel, otherChannel) {
|
||||
export function isSameChannel(channel, otherChannel) {
|
||||
return channel === otherChannel || (!channel && !otherChannel);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
extractErrors,
|
||||
hideSensitiveValues,
|
||||
tagsToVersions,
|
||||
isMajorRange,
|
||||
isMaintenanceRange,
|
||||
getUpperBound,
|
||||
getLowerBound,
|
||||
highest,
|
||||
lowest,
|
||||
getLatestVersion,
|
||||
getEarliestVersion,
|
||||
getFirstVersion,
|
||||
getRange,
|
||||
makeTag,
|
||||
isSameChannel,
|
||||
};
|
||||
|
||||
+6
-6
@@ -1,9 +1,9 @@
|
||||
const {template, isString, isPlainObject} = require('lodash');
|
||||
const AggregateError = require('aggregate-error');
|
||||
const {isGitRepo, verifyTagName} = require('./git');
|
||||
const getError = require('./get-error');
|
||||
import {isPlainObject, isString, template} from 'lodash-es';
|
||||
import AggregateError from 'aggregate-error';
|
||||
import {isGitRepo, verifyTagName} from './git.js';
|
||||
import getError from './get-error.js';
|
||||
|
||||
module.exports = async (context) => {
|
||||
export default async (context) => {
|
||||
const {
|
||||
cwd,
|
||||
env,
|
||||
@@ -40,4 +40,4 @@ module.exports = async (context) => {
|
||||
if (errors.length > 0) {
|
||||
throw new AggregateError(errors);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user