Compare commits
41
Commits
@@ -17,11 +17,6 @@
|
||||
<img alt="semantic-release" src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg">
|
||||
</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://waffle.io/semantic-release/semantic-release">
|
||||
<img alt="Waffle.io" src="https://badge.waffle.io/semantic-release/semantic-release.svg?columns=all">
|
||||
</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://www.npmjs.com/package/semantic-release">
|
||||
<img alt="npm latest version" src="https://img.shields.io/npm/v/semantic-release/latest.svg">
|
||||
@@ -57,7 +52,7 @@ This removes the immediate connection between human emotions and version numbers
|
||||
|
||||
By default **semantic-release** uses [Angular Commit Message Conventions](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines). The commit message format can be changed with the [`preset` or `config` options](docs/usage/configuration.md#options) of the [@semantic-release/commit-analyzer](https://github.com/semantic-release/commit-analyzer#options) and [@semantic-release/release-notes-generator](https://github.com/semantic-release/release-notes-generator#options) plugins.
|
||||
|
||||
Tools such as [commitizen](https://github.com/commitizen/cz-cli), [commitlint](https://github.com/marionebl/commitlint) or [semantic-git-commit-cli](https://github.com/JPeer264/node-semantic-git-commit-cli) can be used to help contributors and enforce valid commit messages.
|
||||
Tools such as [commitizen](https://github.com/commitizen/cz-cli), [commitlint](https://github.com/conventional-changelog/commitlint) or [semantic-git-commit-cli](https://github.com/JPeer264/node-semantic-git-commit-cli) can be used to help contributors and enforce valid commit messages.
|
||||
|
||||
Here is an example of the release type that will be done based on a commit messages:
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// Bad news: We have to write plain ES5 in this file
|
||||
// Good news: It's the only file of the entire project
|
||||
|
||||
/* eslint-disable no-var, promise/prefer-await-to-then, prefer-destructuring */
|
||||
/* eslint-disable no-var */
|
||||
|
||||
var semver = require('semver');
|
||||
var execa = require('execa');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const {argv, env, stderr} = require('process');
|
||||
const {argv, env, stderr} = require('process'); // eslint-disable-line node/prefer-global/process
|
||||
const util = require('util');
|
||||
const hideSensitive = require('./lib/hide-sensitive');
|
||||
|
||||
@@ -51,12 +51,14 @@ Usage:
|
||||
// Debug must be enabled before other requires in order to work
|
||||
require('debug').enable('semantic-release:*');
|
||||
}
|
||||
|
||||
await require('.')(opts);
|
||||
return 0;
|
||||
} catch (error) {
|
||||
if (error.name !== 'YError') {
|
||||
stderr.write(hideSensitive(env)(util.inspect(error, {colors: true})));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -39,7 +39,7 @@ try {
|
||||
}
|
||||
|
||||
for (const release of releases) {
|
||||
console.log(`The release was published with plugin "${pluginName}".`);
|
||||
console.log(`The release was published with plugin "${release.pluginName}".`);
|
||||
}
|
||||
} else {
|
||||
console.log('No release published.');
|
||||
|
||||
@@ -2,15 +2,19 @@
|
||||
|
||||
## Official plugins
|
||||
- [@semantic-release/commit-analyzer](https://github.com/semantic-release/commit-analyzer)
|
||||
- **Note**: this is already part of semantic-release and does not have to be installed separately
|
||||
- `analyzeCommits`: Determine the type of release by analyzing commits with [conventional-changelog](https://github.com/conventional-changelog/conventional-changelog)
|
||||
- [@semantic-release/release-notes-generator](https://github.com/semantic-release/release-notes-generator)
|
||||
- **Note**: this is already part of semantic-release and does not have to be installed separately
|
||||
- `generateNotes`: Generate release notes for the commits added since the last release with [conventional-changelog](https://github.com/conventional-changelog/conventional-changelog)
|
||||
- [@semantic-release/github](https://github.com/semantic-release/github)
|
||||
- **Note**: this is already part of semantic-release and does not have to be installed separately
|
||||
- `verifyConditions`: Verify the presence and the validity of the GitHub authentication and release configuration
|
||||
- `publish`: Publish a [GitHub release](https://help.github.com/articles/about-releases)
|
||||
- `success`: Add a comment to GitHub issues and pull requests resolved in the release
|
||||
- `fail`: Open a GitHub issue when a release fails
|
||||
- [@semantic-release/npm](https://github.com/semantic-release/npm)
|
||||
- **Note**: this is already part of semantic-release and does not have to be installed separately
|
||||
- `verifyConditions`: Verify the presence and the validity of the npm authentication and release configuration
|
||||
- `prepare`: Update the package.json version and create the npm package tarball
|
||||
- `publish`: Publish the package on the npm registry
|
||||
@@ -41,6 +45,10 @@
|
||||
|
||||
[Open a Pull Request](https://github.com/semantic-release/semantic-release/blob/master/CONTRIBUTING.md#submitting-a-pull-request) to add your plugin to the list.
|
||||
|
||||
- [semantic-release-slack-bot](https://github.com/juliuscc/semantic-release-slack-bot)
|
||||
- `verifyConditions`: Verify that the environment variable `SLACK_WEBHOOK` has been defined.
|
||||
- `success`: Publish a message about the success to a slack channel.
|
||||
- `fail`: Optionally publish a message about failure to a slack channel.
|
||||
- [semantic-release-docker](https://github.com/felixfbecker/semantic-release-docker)
|
||||
- `verifyConditions`: Verify that all needed configuration is present and login to the Docker registry.
|
||||
- `publish`: Tag the image specified by `name` with the new version, push it to Docker Hub and update the latest tag
|
||||
@@ -71,3 +79,15 @@
|
||||
- `verifyRelease`: Checks and warns (does not error by default) if the version numbers found on maven central and within the Git project differ by quite a bit
|
||||
- `prepare`: Changes the version number in the `pom.xml` (or all `pom.xml` files in maven projects with multiple `pom.xml` files) and optionally creates a commit with this version number and pushes it to `master`
|
||||
- `publish`: Runs `mvn deploy` to deploy to maven central and optionally will update to next snapshot version and merge changes to development branch
|
||||
- [semantic-release-ado](https://github.com/lluchmk/semantic-release-ado)
|
||||
- `prepare`: Stores the version number as an Azure DevOps pipeline variable availabe to downstream steps on the job
|
||||
- [gradle-semantic-release](https://github.com/KengoTODA/gradle-semantic-release-plugin)
|
||||
- `verifyConditions`: Verify that project has a Gradle wrapper script, and `build.gradle` contains a task to publish artifacts.
|
||||
- `prepare`: Changes the version number in the `gradle.properties`
|
||||
- `publish`: Triggers Gradle to publish artifacts.
|
||||
- [semantic-release-circleci-orb](https://github.com/matt-oakes/semantic-release-circleci-orb)
|
||||
- `verifyConditions`: Verify the presence of the `CIRCLECI_API_TOKEN` environment variable, `orbName` option, and the `circleci` CLI.
|
||||
- `publish`: Publish the CircleCI orb.
|
||||
- [semantic-release-github-pages](https://github.com/qiwi/semantic-release-gh-pages-plugin)
|
||||
- `verifyConditions`: Verify the presence of the auth token set via environment variables.
|
||||
- `publish`: Pushes commit to the documentation branch.
|
||||
|
||||
@@ -137,7 +137,7 @@ jobs:
|
||||
# Make sure only the current user can read the private key
|
||||
- chmod 600 /tmp/git_deploy_key
|
||||
# Create a script to return the passphrase environment variable to ssh-add
|
||||
- echo 'echo ${SSH_PASSPHRASE}' > /tmp/askpass && chmod +x /tmp/askpass
|
||||
- echo 'echo ${SSL_PASSPHRASE}' > /tmp/askpass && chmod +x /tmp/askpass
|
||||
# Start the authentication agent
|
||||
- eval "$(ssh-agent -s)"
|
||||
# Add the key to the authentication agent
|
||||
@@ -158,6 +158,6 @@ Commit the encrypted private key and the `.circleci/config.yml` file to your rep
|
||||
|
||||
```bash
|
||||
$ git add git_deploy_key.enc .circleci/config.yml
|
||||
$ git commit -m "ci(cicle): Add the encrypted private ssh key"
|
||||
$ git commit -m "ci(circle): Add the encrypted private ssh key"
|
||||
$ git push
|
||||
```
|
||||
|
||||
+1
-1
@@ -145,7 +145,7 @@ If you have introduced a breaking bug in a release you have 2 options:
|
||||
|
||||
In both cases **semantic-release** will publish a new release, so your package users' will get the fixed/reverted version.
|
||||
|
||||
Depending on the package manager you are using, you might be able to un-publish or deprecate a release, in order to prevent users to download it by accident. For example npm allows you to [un-publish](https://docs.npmjs.com/cli/unpublish) in [next 72 hours](https://www.npmjs.com/policies/unpublish) after releasing or to [deprecate](https://docs.npmjs.com/cli/deprecate) a release.
|
||||
Depending on the package manager you are using, you might be able to un-publish or deprecate a release, in order to prevent users from downloading it by accident. For example npm allows you to [un-publish](https://docs.npmjs.com/cli/unpublish) [within 72 hours](https://www.npmjs.com/policies/unpublish) after releasing. You may also [deprecate](https://docs.npmjs.com/cli/deprecate) a release if you would rather avoid un-publishing.
|
||||
|
||||
In any case **do not remove the Git tag associated with the buggy version**, otherwise **semantic-release** will later try to republish that version. Publishing a version after un-publishing is not supported by most package managers.
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ npm ERR! You do not have permission to publish "<package-name>". Are you logged
|
||||
|
||||
This is most likely related to a misconfiguration of the [npm registry authentication](https://github.com/semantic-release/npm#npm-registry-authentication) or to your user [missing permission](https://docs.npmjs.com/cli/team) for publishing.
|
||||
|
||||
It might also happen if the package name you are trying to publish already exists (in such case npm consider you are trying to publish a new version of a package that is not yours, hence the permission error).
|
||||
It might also happen if the package name you are trying to publish already exists (in the case of npm, you may be trying to publish a new version of a package that is not yours, hence the permission error).
|
||||
|
||||
To verify if your package name is available you can use [npm-name-cli](https://github.com/sindresorhus/npm-name-cli):
|
||||
```bash
|
||||
|
||||
@@ -26,7 +26,7 @@ Most **semantic-release** [plugins](plugins.md) require setting up authenticatio
|
||||
| `NPM_TOKEN` | npm token created via [npm token create](https://docs.npmjs.com/getting-started/working_with_tokens#how-to-create-new-tokens).<br/>**Note**: Only the `auth-only` [level of npm two-factor authentication](https://docs.npmjs.com/getting-started/using-two-factor-authentication#levels-of-authentication) is supported. |
|
||||
| `GH_TOKEN` | GitHub authentication token.<br/>**Note**: Only the [personal token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line) authentication is supported. |
|
||||
|
||||
See each plugin documentation for the environment variables to set up.
|
||||
See each plugin's documentation for the environment variables required.
|
||||
|
||||
The authentication token/credentials have to be made available in the CI service via environment variables.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Getting started
|
||||
|
||||
In order to use **semantic-release** you must follows this steps:
|
||||
In order to use **semantic-release** you must follow these steps:
|
||||
- [Install](./installation.md#installation) **semantic-release** in your project
|
||||
- Configure your Continuous Integration service to [run **semantic-release**](./ci-configuration.md#run-semantic-release-only-after-all-tests-succeeded)
|
||||
- Configure your Git repository and package manager repository [authentication](ci-configuration.md#authentication) in your Continuous Integration service
|
||||
@@ -19,4 +19,4 @@ semantic-release-cli setup
|
||||
|
||||
See the [semantic-release-cli](https://github.com/semantic-release/cli#what-it-does) documentation for more details.
|
||||
|
||||
**Note**: only a limited number of options, CI services and plugins is currently supported by `semantic-release-cli`.
|
||||
**Note**: only a limited number of options, CI services and plugins are currently supported by `semantic-release-cli`.
|
||||
|
||||
+17
-6
@@ -17,15 +17,26 @@ A plugin is a npm module that can implement one or more of the following steps:
|
||||
|
||||
**Note:** If no plugin with a `analyzeCommits` step is defined `@semantic-release/commit-analyzer` will be used.
|
||||
|
||||
See [available plugins](../extending/plugins-list.md).
|
||||
## Plugins installation
|
||||
|
||||
These five plugins are already part of **semantic-release** and don't have to be installed separately:
|
||||
```
|
||||
"@semantic-release/commit-analyzer"
|
||||
"@semantic-release/error"
|
||||
"@semantic-release/github"
|
||||
"@semantic-release/npm"
|
||||
"@semantic-release/release-notes-generator"
|
||||
```
|
||||
|
||||
[Additional plugins](../extending/plugins-list.md) have to be installed via npm:
|
||||
|
||||
```bash
|
||||
$ npm install @semantic-release/git @semantic-release/changelog -D
|
||||
```
|
||||
|
||||
## Plugins configuration
|
||||
|
||||
Each plugin must be installed and configured with the [`plugins` options](./configuration.md#plugins) by specifying the list of plugins by npm module name.
|
||||
|
||||
```bash
|
||||
$ npm install @semantic-release/commit-analyzer @semantic-release/release-notes-generator @semantic-release/npm -D
|
||||
```
|
||||
Each plugin must be configured with the [`plugins` options](./configuration.md#plugins) by specifying the list of plugins by npm module name.
|
||||
|
||||
```json
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Shareable configurations
|
||||
|
||||
A sharable configuration is an [npm](https://www.npmjs.com/) package that exports a **semantic-release** configuration object. It allows for use of the same configuration across several projects.
|
||||
A shareable configuration is an [npm](https://www.npmjs.com/) package that exports a **semantic-release** configuration object. It allows for use of the same configuration across several projects.
|
||||
|
||||
The shareable configurations to use can be set with the [extends](configuration.md#extends) option.
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ async function run(context, plugins) {
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
logger[options.dryRun ? 'warn' : 'success'](
|
||||
`Run automated release from branch ${ciBranch}${options.dryRun ? ' in dry-run mode' : ''}`
|
||||
);
|
||||
@@ -70,6 +71,7 @@ async function run(context, plugins) {
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -92,6 +94,7 @@ async function run(context, plugins) {
|
||||
logger.log('There are no relevant changes, so no new version is released.');
|
||||
return false;
|
||||
}
|
||||
|
||||
context.nextRelease = nextRelease;
|
||||
nextRelease.version = getNextVersion(context);
|
||||
nextRelease.gitTag = template(options.tagFormat)({version: nextRelease.version});
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
const url = require('url');
|
||||
const {inspect} = require('util');
|
||||
const {toLower, isString} = require('lodash');
|
||||
const pkg = require('../../package.json');
|
||||
const {RELEASE_TYPE} = require('./constants');
|
||||
|
||||
const homepage = url.format({...url.parse(pkg.homepage), hash: null});
|
||||
const [homepage] = pkg.homepage.split('#');
|
||||
const stringify = obj => (isString(obj) ? obj : inspect(obj, {breakLength: Infinity, depth: 2, maxArrayLength: 5}));
|
||||
const linkify = file => `${homepage}/blob/master/${file}`;
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ module.exports = {
|
||||
// Regenerate the release notes
|
||||
context.nextRelease.notes = await generateNotes(context);
|
||||
}
|
||||
|
||||
// Call the next prepare plugin with the updated `nextRelease`
|
||||
return context;
|
||||
},
|
||||
|
||||
+2
-1
@@ -30,6 +30,7 @@ module.exports = async (context, opts) => {
|
||||
if (options.ci === false) {
|
||||
options.noCi = true;
|
||||
}
|
||||
|
||||
const pluginsPath = {};
|
||||
let extendPaths;
|
||||
({extends: extendPaths, ...options} = options);
|
||||
@@ -84,6 +85,6 @@ module.exports = async (context, opts) => {
|
||||
};
|
||||
|
||||
async function pkgRepoUrl(opts) {
|
||||
const {pkg} = await readPkgUp(opts);
|
||||
const {package: pkg} = (await readPkgUp(opts)) || {};
|
||||
return pkg && (isPlainObject(pkg.repository) ? pkg.repository.url : pkg.repository);
|
||||
}
|
||||
|
||||
+21
-12
@@ -1,18 +1,8 @@
|
||||
const {parse, format} = require('url');
|
||||
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 GIT_TOKENS = {
|
||||
GIT_CREDENTIALS: undefined,
|
||||
GH_TOKEN: undefined,
|
||||
GITHUB_TOKEN: undefined,
|
||||
GL_TOKEN: 'gitlab-ci-token:',
|
||||
GITLAB_TOKEN: 'gitlab-ci-token:',
|
||||
BB_TOKEN: 'x-token-auth:',
|
||||
BITBUCKET_TOKEN: 'x-token-auth:',
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine the the git repository URL to use to push, either:
|
||||
* - The `repositoryUrl` as is if allowed to push
|
||||
@@ -25,6 +15,18 @@ const GIT_TOKENS = {
|
||||
* @return {String} The formatted Git repository URL.
|
||||
*/
|
||||
module.exports = async ({cwd, env, options: {repositoryUrl, branch}}) => {
|
||||
const GIT_TOKENS = {
|
||||
GIT_CREDENTIALS: undefined,
|
||||
GH_TOKEN: undefined,
|
||||
// GitHub Actions require the "x-access-token:" prefix for git access
|
||||
// https://developer.github.com/apps/building-github-apps/authenticating-with-github-apps/#http-based-git-access-by-an-installation
|
||||
GITHUB_TOKEN: isNil(env.GITHUB_ACTION) ? undefined : 'x-access-token:',
|
||||
GL_TOKEN: 'gitlab-ci-token:',
|
||||
GITLAB_TOKEN: 'gitlab-ci-token:',
|
||||
BB_TOKEN: 'x-token-auth:',
|
||||
BITBUCKET_TOKEN: 'x-token-auth:',
|
||||
};
|
||||
|
||||
const info = hostedGitInfo.fromUrl(repositoryUrl, {noGitPlus: true});
|
||||
const {protocol, ...parsed} = parse(repositoryUrl);
|
||||
|
||||
@@ -43,8 +45,15 @@ module.exports = async ({cwd, env, options: {repositoryUrl, branch}}) => {
|
||||
const envVar = Object.keys(GIT_TOKENS).find(envVar => !isNil(env[envVar]));
|
||||
const gitCredentials = `${GIT_TOKENS[envVar] || ''}${env[envVar] || ''}`;
|
||||
|
||||
console.log(`-------- envVar -------- `);
|
||||
console.log(envVar);
|
||||
console.log(`-------- GIT_TOKENS[envVar] -------- `);
|
||||
console.log(GIT_TOKENS[envVar]);
|
||||
console.log(`-------- env[envVar].substr(5) -------- `);
|
||||
console.log((env[envVar] || '').substr(5));
|
||||
|
||||
if (gitCredentials) {
|
||||
// If credentials are set via anvironment variables, convert the URL to http/https and add basic auth, otherwise return `repositoryUrl` as is
|
||||
// If credentials are set via environment variables, convert the URL to http/https and add basic auth, otherwise return `repositoryUrl` as is
|
||||
const [match, auth, host, path] = /^(?!.+:\/\/)(?:(.*)@)?(.*?):(.*)$/.exec(repositoryUrl) || [];
|
||||
return format({
|
||||
...parse(match ? `ssh://${auth ? `${auth}@` : ''}${host}/${path}` : repositoryUrl),
|
||||
|
||||
@@ -28,7 +28,7 @@ module.exports = async ({cwd, env, options: {tagFormat}, logger}) => {
|
||||
// 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,
|
||||
// so it's guaranteed to no be present in the `tagFormat`.
|
||||
// so it's guaranteed to not be present in the `tagFormat`.
|
||||
const tagRegexp = `^${escapeRegExp(template(tagFormat)({version: ' '})).replace(' ', '(.+)')}`;
|
||||
const tags = (await getTags({cwd, env}))
|
||||
.map(tag => ({gitTag: tag, version: (tag.match(tagRegexp) || new Array(2))[1]}))
|
||||
|
||||
@@ -57,10 +57,12 @@ module.exports = (context, pluginsPath) => {
|
||||
plugin ? [plugin[0], Object.assign(plugin[1], options[type])] : plugin
|
||||
);
|
||||
}
|
||||
|
||||
if (!validateStep({required}, options[type])) {
|
||||
errors.push(getError('EPLUGINCONF', {type, required, pluginConf: options[type]}));
|
||||
return pluginsConf;
|
||||
}
|
||||
|
||||
pluginOpts = options[type];
|
||||
}
|
||||
|
||||
|
||||
@@ -40,9 +40,11 @@ module.exports = (context, type, pluginOpt, pluginsPath) => {
|
||||
if (outputValidator && !outputValidator(result)) {
|
||||
throw getError(`E${type.toUpperCase()}OUTPUT`, {result, pluginName});
|
||||
}
|
||||
|
||||
logger.success(`Completed step "${type}" of plugin "${pluginName}"`);
|
||||
return result;
|
||||
}
|
||||
|
||||
logger.warn(`Skip step "${type}" of plugin "${pluginName}" in dry-run mode`);
|
||||
} catch (error) {
|
||||
logger.error(`Failed step "${type}" of plugin "${pluginName}"`);
|
||||
|
||||
@@ -4,7 +4,7 @@ const AggregateError = require('aggregate-error');
|
||||
const {extractErrors} = require('../utils');
|
||||
|
||||
/**
|
||||
* A Function that execute a list of function sequencially. If at least one Function ins the pipeline throw an Error or rejects, the pipeline function rejects as well.
|
||||
* 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.
|
||||
*
|
||||
* @typedef {Function} Pipeline
|
||||
* @param {Any} input Argument to pass to the first step in the pipeline.
|
||||
@@ -44,6 +44,7 @@ module.exports = (steps, {settleAll = false, getNextInput = identity, transform
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare input for the next step, passing the input of the last iteration (or initial parameter for the first iteration) and the result of the current one
|
||||
return getNextInput(lastInput, result);
|
||||
},
|
||||
@@ -52,5 +53,6 @@ module.exports = (steps, {settleAll = false, getNextInput = identity, transform
|
||||
if (errors.length > 0) {
|
||||
throw new AggregateError(errors);
|
||||
}
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
@@ -12,6 +12,7 @@ const validateSteps = conf => {
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
conf = castArray(conf);
|
||||
|
||||
if (conf.length !== 1) {
|
||||
@@ -39,6 +40,7 @@ function validateStep({required}, conf) {
|
||||
if (required) {
|
||||
return conf.length >= 1 && validateSteps(conf);
|
||||
}
|
||||
|
||||
return conf.length === 0 || validateSteps(conf);
|
||||
}
|
||||
|
||||
@@ -59,6 +61,7 @@ function parseConfig(plugin) {
|
||||
} else {
|
||||
path = plugin;
|
||||
}
|
||||
|
||||
return [path, config || {}];
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 117 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 65 KiB |
+20
-20
@@ -24,49 +24,49 @@
|
||||
"@semantic-release/github": "^5.1.0",
|
||||
"@semantic-release/npm": "^5.0.5",
|
||||
"@semantic-release/release-notes-generator": "^7.1.2",
|
||||
"aggregate-error": "^1.0.0",
|
||||
"aggregate-error": "^3.0.0",
|
||||
"cosmiconfig": "^5.0.1",
|
||||
"debug": "^4.0.0",
|
||||
"env-ci": "^3.0.0",
|
||||
"execa": "^1.0.0",
|
||||
"figures": "^2.0.0",
|
||||
"figures": "^3.0.0",
|
||||
"find-versions": "^3.0.0",
|
||||
"get-stream": "^4.0.0",
|
||||
"get-stream": "^5.0.0",
|
||||
"git-log-parser": "^1.2.0",
|
||||
"hook-std": "^1.1.0",
|
||||
"hook-std": "^2.0.0",
|
||||
"hosted-git-info": "^2.7.1",
|
||||
"lodash": "^4.17.4",
|
||||
"marked": "^0.5.0",
|
||||
"marked-terminal": "^3.0.0",
|
||||
"p-locate": "^3.0.0",
|
||||
"p-reduce": "^1.0.0",
|
||||
"read-pkg-up": "^4.0.0",
|
||||
"resolve-from": "^4.0.0",
|
||||
"semver": "^5.4.1",
|
||||
"marked": "^0.6.0",
|
||||
"marked-terminal": "^3.2.0",
|
||||
"p-locate": "^4.0.0",
|
||||
"p-reduce": "^2.0.0",
|
||||
"read-pkg-up": "^6.0.0",
|
||||
"resolve-from": "^5.0.0",
|
||||
"semver": "^6.0.0",
|
||||
"signale": "^1.2.1",
|
||||
"yargs": "^12.0.0"
|
||||
"yargs": "^13.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "^0.25.0",
|
||||
"ava": "^1.3.1",
|
||||
"clear-module": "^3.0.0",
|
||||
"codecov": "^3.0.0",
|
||||
"commitizen": "^3.0.0",
|
||||
"cz-conventional-changelog": "^2.0.0",
|
||||
"delay": "^4.0.0",
|
||||
"dockerode": "^2.5.2",
|
||||
"file-url": "^2.0.2",
|
||||
"fs-extra": "^7.0.0",
|
||||
"file-url": "^3.0.0",
|
||||
"fs-extra": "^8.0.0",
|
||||
"got": "^9.0.0",
|
||||
"js-yaml": "^3.10.0",
|
||||
"mockserver-client": "^5.1.1",
|
||||
"nock": "^10.0.0",
|
||||
"nyc": "^13.1.0",
|
||||
"p-retry": "^3.0.0",
|
||||
"nyc": "^14.0.0",
|
||||
"p-retry": "^4.0.0",
|
||||
"proxyquire": "^2.0.0",
|
||||
"sinon": "^7.1.1",
|
||||
"sinon": "^7.2.7",
|
||||
"stream-buffers": "^3.0.2",
|
||||
"tempy": "^0.2.1",
|
||||
"xo": "^0.23.0"
|
||||
"tempy": "^0.3.0",
|
||||
"xo": "^0.24.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.3"
|
||||
|
||||
@@ -480,7 +480,7 @@ test('Throw an Error if one of the shareable config cannot be found', async t =>
|
||||
await outputJson(path.resolve(cwd, 'package.json'), {release: pkhOptions});
|
||||
await outputJson(path.resolve(cwd, 'shareable1.json'), options1);
|
||||
|
||||
const error = await t.throws(t.context.getConfig({cwd}), Error);
|
||||
const error = await t.throwsAsync(t.context.getConfig({cwd}), Error);
|
||||
|
||||
t.is(error.message, "Cannot find module 'non-existing-path'");
|
||||
t.is(error.code, 'MODULE_NOT_FOUND');
|
||||
|
||||
@@ -244,6 +244,19 @@ test('Return the "https" formatted URL if "gitCredentials" is defined with "BITB
|
||||
);
|
||||
});
|
||||
|
||||
test('Return the "https" formatted URL if "GITHUB_ACTION" is set', async t => {
|
||||
const {cwd} = await gitRepo();
|
||||
|
||||
t.is(
|
||||
await getAuthUrl({
|
||||
cwd,
|
||||
env: {...env, GITHUB_ACTION: 'foo', GITHUB_TOKEN: 'token'},
|
||||
options: {branch: 'master', repositoryUrl: 'git@host.null:owner/repo.git'},
|
||||
}),
|
||||
'https://x-access-token:token@host.null/owner/repo.git'
|
||||
);
|
||||
});
|
||||
|
||||
test('Handle "https" URL with group and subgroup, with "GIT_CREDENTIALS"', async t => {
|
||||
const {cwd} = await gitRepo();
|
||||
|
||||
|
||||
+4
-4
@@ -42,7 +42,7 @@ test('Throw error if the last commit sha cannot be found', async t => {
|
||||
// Create a git repository, set the current working directory at the root of the repo
|
||||
const {cwd} = await gitRepo();
|
||||
|
||||
await t.throws(getGitHead({cwd}), Error);
|
||||
await t.throwsAsync(getGitHead({cwd}), Error);
|
||||
});
|
||||
|
||||
test('Unshallow and fetch repository', async t => {
|
||||
@@ -67,7 +67,7 @@ test('Do not throw error when unshallow a complete repository', async t => {
|
||||
const {cwd, repositoryUrl} = await gitRepo();
|
||||
// Add commits to the master branch
|
||||
await gitCommits(['First'], {cwd});
|
||||
await t.notThrows(fetch(repositoryUrl, {cwd}));
|
||||
await t.notThrowsAsync(fetch(repositoryUrl, {cwd}));
|
||||
});
|
||||
|
||||
test('Fetch all tags on a detached head repository', async t => {
|
||||
@@ -100,7 +100,7 @@ test('Verify if the commit `sha` is in the direct history of the current branch'
|
||||
|
||||
t.true(await isRefInHistory(commits[0].hash, {cwd}));
|
||||
t.falsy(await isRefInHistory(otherCommits[0].hash, {cwd}));
|
||||
await t.throws(isRefInHistory('non-existant-sha', {cwd}));
|
||||
await t.throwsAsync(isRefInHistory('non-existant-sha', {cwd}));
|
||||
});
|
||||
|
||||
test('Get the commit sha for a given tag or falsy if the tag does not exists', async t => {
|
||||
@@ -206,7 +206,7 @@ test('Return falsy for invalid tag names', async t => {
|
||||
test('Throws error if obtaining the tags fails', async t => {
|
||||
const cwd = tempy.directory();
|
||||
|
||||
await t.throws(getTags({cwd}));
|
||||
await t.throwsAsync(getTags({cwd}));
|
||||
});
|
||||
|
||||
test('Return "true" if repository is up to date', async t => {
|
||||
|
||||
+23
-14
@@ -169,7 +169,7 @@ test('Plugins are called with expected values', async t => {
|
||||
t.deepEqual(success.args[0][1].commits[0].message, commits[0].message);
|
||||
t.deepEqual(success.args[0][1].nextRelease, {...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`});
|
||||
t.deepEqual(success.args[0][1].releases, [
|
||||
{...release1, ...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`, pluginName: '[Function: proxy]'},
|
||||
{...release1, ...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`, pluginName: '[Function: functionStub]'},
|
||||
{...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`, pluginName: pluginNoop},
|
||||
]);
|
||||
|
||||
@@ -178,7 +178,12 @@ test('Plugins are called with expected values', async t => {
|
||||
commits: [commits[0]],
|
||||
nextRelease: {...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`},
|
||||
releases: [
|
||||
{...release1, ...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`, pluginName: '[Function: proxy]'},
|
||||
{
|
||||
...release1,
|
||||
...nextRelease,
|
||||
notes: `${notes1}\n\n${notes2}\n\n${notes3}`,
|
||||
pluginName: '[Function: functionStub]',
|
||||
},
|
||||
{...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`, pluginName: pluginNoop},
|
||||
],
|
||||
});
|
||||
@@ -337,15 +342,19 @@ test('Call all "success" plugins even if one errors out', async t => {
|
||||
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
||||
});
|
||||
|
||||
await t.throws(
|
||||
await t.throwsAsync(
|
||||
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
||||
);
|
||||
|
||||
t.is(success1.callCount, 1);
|
||||
t.deepEqual(success1.args[0][1].releases, [{...release, ...nextRelease, notes, pluginName: '[Function: proxy]'}]);
|
||||
t.deepEqual(success1.args[0][1].releases, [
|
||||
{...release, ...nextRelease, notes, pluginName: '[Function: functionStub]'},
|
||||
]);
|
||||
|
||||
t.is(success2.callCount, 1);
|
||||
t.deepEqual(success2.args[0][1].releases, [{...release, ...nextRelease, notes, pluginName: '[Function: proxy]'}]);
|
||||
t.deepEqual(success2.args[0][1].releases, [
|
||||
{...release, ...nextRelease, notes, pluginName: '[Function: functionStub]'},
|
||||
]);
|
||||
});
|
||||
|
||||
test('Log all "verifyConditions" errors', async t => {
|
||||
@@ -372,7 +381,7 @@ test('Log all "verifyConditions" errors', async t => {
|
||||
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
||||
});
|
||||
const errors = [
|
||||
...(await t.throws(
|
||||
...(await t.throwsAsync(
|
||||
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
||||
)),
|
||||
];
|
||||
@@ -417,7 +426,7 @@ test('Log all "verifyRelease" errors', async t => {
|
||||
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
||||
});
|
||||
const errors = [
|
||||
...(await t.throws(
|
||||
...(await t.throwsAsync(
|
||||
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
||||
)),
|
||||
];
|
||||
@@ -519,7 +528,7 @@ test('Dry-run skips fail', async t => {
|
||||
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
||||
});
|
||||
const errors = [
|
||||
...(await t.throws(
|
||||
...(await t.throwsAsync(
|
||||
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
||||
)),
|
||||
];
|
||||
@@ -757,7 +766,7 @@ test('Accept "undefined" value returned by "generateNotes" and "false" by "publi
|
||||
t.is(publish.args[0][1].nextRelease.notes, notes2);
|
||||
|
||||
t.is(success.callCount, 1);
|
||||
t.deepEqual(success.args[0][1].releases, [{pluginName: '[Function: proxy]'}]);
|
||||
t.deepEqual(success.args[0][1].releases, [{pluginName: '[Function: functionStub]'}]);
|
||||
});
|
||||
|
||||
test('Returns false if triggered by a PR', async t => {
|
||||
@@ -957,7 +966,7 @@ test('Log both plugins errors and errors thrown by "fail" plugin', async t => {
|
||||
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
||||
});
|
||||
|
||||
await t.throws(
|
||||
await t.throwsAsync(
|
||||
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
||||
);
|
||||
|
||||
@@ -982,7 +991,7 @@ test('Call "fail" only if a plugin returns a SemanticReleaseError', async t => {
|
||||
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
||||
});
|
||||
|
||||
await t.throws(
|
||||
await t.throwsAsync(
|
||||
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
||||
);
|
||||
|
||||
@@ -999,7 +1008,7 @@ test('Throw SemanticReleaseError if repositoryUrl is not set and cannot be found
|
||||
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
||||
});
|
||||
const errors = [
|
||||
...(await t.throws(
|
||||
...(await t.throwsAsync(
|
||||
semanticRelease({}, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()})
|
||||
)),
|
||||
];
|
||||
@@ -1036,7 +1045,7 @@ test('Throw an Error if plugin returns an unexpected value', async t => {
|
||||
'./lib/get-logger': () => t.context.logger,
|
||||
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
||||
});
|
||||
const error = await t.throws(
|
||||
const error = await t.throwsAsync(
|
||||
semanticRelease(options, {cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()}),
|
||||
Error
|
||||
);
|
||||
@@ -1066,7 +1075,7 @@ test('Hide sensitive information passed to "fail" plugin', async t => {
|
||||
'./lib/get-logger': () => t.context.logger,
|
||||
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
||||
});
|
||||
await t.throws(
|
||||
await t.throwsAsync(
|
||||
semanticRelease(options, {cwd, env, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer()}),
|
||||
Error
|
||||
);
|
||||
|
||||
@@ -258,7 +258,7 @@ test('Exit with 1 if a plugin is not found', async t => {
|
||||
release: {analyzeCommits: 'non-existing-path', success: false, fail: false},
|
||||
});
|
||||
|
||||
const {code, stderr} = await t.throws(execa(cli, [], {env, cwd}));
|
||||
const {code, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd}));
|
||||
t.is(code, 1);
|
||||
t.regex(stderr, /Cannot find module/);
|
||||
});
|
||||
@@ -276,7 +276,7 @@ test('Exit with 1 if a shareable config is not found', async t => {
|
||||
release: {extends: 'non-existing-path', success: false, fail: false},
|
||||
});
|
||||
|
||||
const {code, stderr} = await t.throws(execa(cli, [], {env, cwd}));
|
||||
const {code, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd}));
|
||||
t.is(code, 1);
|
||||
t.regex(stderr, /Cannot find module/);
|
||||
});
|
||||
@@ -297,7 +297,7 @@ test('Exit with 1 if a shareable config reference a not found plugin', async t =
|
||||
});
|
||||
await writeJson(path.resolve(cwd, 'shareable.json'), shareable);
|
||||
|
||||
const {code, stderr} = await t.throws(execa(cli, [], {env, cwd}));
|
||||
const {code, stderr} = await t.throwsAsync(execa(cli, [], {env, cwd}));
|
||||
t.is(code, 1);
|
||||
t.regex(stderr, /Cannot find module/);
|
||||
});
|
||||
|
||||
@@ -62,7 +62,7 @@ test('Wrap plugin in a function that add the "pluginName" to the error"', async
|
||||
'./plugin-error': './test/fixtures',
|
||||
});
|
||||
|
||||
const error = await t.throws(plugin({options: {}}));
|
||||
const error = await t.throwsAsync(plugin({options: {}}));
|
||||
|
||||
t.is(error.pluginName, './plugin-error');
|
||||
});
|
||||
@@ -72,7 +72,7 @@ test('Wrap plugin in a function that add the "pluginName" to multiple errors"',
|
||||
'./plugin-errors': './test/fixtures',
|
||||
});
|
||||
|
||||
const errors = [...(await t.throws(plugin({options: {}})))];
|
||||
const errors = [...(await t.throwsAsync(plugin({options: {}})))];
|
||||
for (const error of errors) {
|
||||
t.is(error.pluginName, './plugin-errors');
|
||||
}
|
||||
@@ -107,7 +107,7 @@ test('Wrap "analyzeCommits" plugin in a function that validate the output of the
|
||||
{}
|
||||
);
|
||||
|
||||
const error = await t.throws(plugin({options: {}}));
|
||||
const error = await t.throwsAsync(plugin({options: {}}));
|
||||
|
||||
t.is(error.code, 'EANALYZECOMMITSOUTPUT');
|
||||
t.is(error.name, 'SemanticReleaseError');
|
||||
@@ -125,7 +125,7 @@ test('Wrap "generateNotes" plugin in a function that validate the output of the
|
||||
{}
|
||||
);
|
||||
|
||||
const error = await t.throws(plugin({options: {}}));
|
||||
const error = await t.throwsAsync(plugin({options: {}}));
|
||||
|
||||
t.is(error.code, 'EGENERATENOTESOUTPUT');
|
||||
t.is(error.name, 'SemanticReleaseError');
|
||||
@@ -143,7 +143,7 @@ test('Wrap "publish" plugin in a function that validate the output of the plugin
|
||||
{}
|
||||
);
|
||||
|
||||
const error = await t.throws(plugin({options: {}}));
|
||||
const error = await t.throwsAsync(plugin({options: {}}));
|
||||
|
||||
t.is(error.code, 'EPUBLISHOUTPUT');
|
||||
t.is(error.name, 'SemanticReleaseError');
|
||||
|
||||
@@ -83,7 +83,7 @@ test('Stop execution and throw error if a step rejects', async t => {
|
||||
const step2 = stub().rejects(new Error('test error'));
|
||||
const step3 = stub().resolves(3);
|
||||
|
||||
const error = await t.throws(pipeline([step1, step2, step3])(0), Error);
|
||||
const error = await t.throwsAsync(pipeline([step1, step2, step3])(0), Error);
|
||||
t.is(error.message, 'test error');
|
||||
t.true(step1.calledWith(0));
|
||||
t.true(step2.calledWith(0));
|
||||
@@ -98,7 +98,7 @@ test('Throw all errors from the first step throwing an AggregateError', async t
|
||||
const step2 = stub().rejects(new AggregateError([error1, error2]));
|
||||
const step3 = stub().resolves(3);
|
||||
|
||||
const errors = await t.throws(pipeline([step1, step2, step3])(0));
|
||||
const errors = await t.throwsAsync(pipeline([step1, step2, step3])(0));
|
||||
|
||||
t.deepEqual([...errors], [error1, error2]);
|
||||
t.true(step1.calledWith(0));
|
||||
@@ -113,7 +113,7 @@ test('Execute all even if a Promise rejects', async t => {
|
||||
const step2 = stub().rejects(error1);
|
||||
const step3 = stub().rejects(error2);
|
||||
|
||||
const errors = await t.throws(pipeline([step1, step2, step3], {settleAll: true})(0));
|
||||
const errors = await t.throwsAsync(pipeline([step1, step2, step3], {settleAll: true})(0));
|
||||
|
||||
t.deepEqual([...errors], [error1, error2]);
|
||||
t.true(step1.calledWith(0));
|
||||
@@ -129,7 +129,7 @@ test('Throw all errors from all steps throwing an AggregateError', async t => {
|
||||
const step1 = stub().rejects(new AggregateError([error1, error2]));
|
||||
const step2 = stub().rejects(new AggregateError([error3, error4]));
|
||||
|
||||
const errors = await t.throws(pipeline([step1, step2], {settleAll: true})(0));
|
||||
const errors = await t.throwsAsync(pipeline([step1, step2], {settleAll: true})(0));
|
||||
|
||||
t.deepEqual([...errors], [error1, error2, error3, error4]);
|
||||
t.true(step1.calledWith(0));
|
||||
@@ -145,7 +145,7 @@ test('Execute each function in series passing a transformed input even if a step
|
||||
const step4 = stub().resolves(4);
|
||||
const getNextInput = (prevResult, result) => prevResult + result;
|
||||
|
||||
const errors = await t.throws(pipeline([step1, step2, step3, step4], {settleAll: true, getNextInput})(0));
|
||||
const errors = await t.throwsAsync(pipeline([step1, step2, step3, step4], {settleAll: true, getNextInput})(0));
|
||||
|
||||
t.deepEqual([...errors], [error2, error3]);
|
||||
t.true(step1.calledWith(0));
|
||||
|
||||
+6
-6
@@ -7,7 +7,7 @@ test('Throw a AggregateError', async t => {
|
||||
const {cwd} = await gitRepo();
|
||||
const options = {};
|
||||
|
||||
const errors = [...(await t.throws(verify({cwd, options})))];
|
||||
const errors = [...(await t.throwsAsync(verify({cwd, options})))];
|
||||
|
||||
t.is(errors[0].name, 'SemanticReleaseError');
|
||||
t.is(errors[0].code, 'ENOREPOURL');
|
||||
@@ -27,7 +27,7 @@ test('Throw a SemanticReleaseError if does not run on a git repository', async t
|
||||
const cwd = tempy.directory();
|
||||
const options = {};
|
||||
|
||||
const errors = [...(await t.throws(verify({cwd, options})))];
|
||||
const errors = [...(await t.throwsAsync(verify({cwd, options})))];
|
||||
|
||||
t.is(errors[0].name, 'SemanticReleaseError');
|
||||
t.is(errors[0].code, 'ENOGITREPO');
|
||||
@@ -39,7 +39,7 @@ test('Throw a SemanticReleaseError if the "tagFormat" is not valid', async t =>
|
||||
const {cwd, repositoryUrl} = await gitRepo(true);
|
||||
const options = {repositoryUrl, tagFormat: `?\${version}`};
|
||||
|
||||
const errors = [...(await t.throws(verify({cwd, options})))];
|
||||
const errors = [...(await t.throwsAsync(verify({cwd, options})))];
|
||||
|
||||
t.is(errors[0].name, 'SemanticReleaseError');
|
||||
t.is(errors[0].code, 'EINVALIDTAGFORMAT');
|
||||
@@ -51,7 +51,7 @@ test('Throw a SemanticReleaseError if the "tagFormat" does not contains the "ver
|
||||
const {cwd, repositoryUrl} = await gitRepo(true);
|
||||
const options = {repositoryUrl, tagFormat: 'test'};
|
||||
|
||||
const errors = [...(await t.throws(verify({cwd, options})))];
|
||||
const errors = [...(await t.throwsAsync(verify({cwd, options})))];
|
||||
|
||||
t.is(errors[0].name, 'SemanticReleaseError');
|
||||
t.is(errors[0].code, 'ETAGNOVERSION');
|
||||
@@ -63,7 +63,7 @@ test('Throw a SemanticReleaseError if the "tagFormat" contains multiple "version
|
||||
const {cwd, repositoryUrl} = await gitRepo(true);
|
||||
const options = {repositoryUrl, tagFormat: `\${version}v\${version}`};
|
||||
|
||||
const errors = [...(await t.throws(verify({cwd, options})))];
|
||||
const errors = [...(await t.throwsAsync(verify({cwd, options})))];
|
||||
|
||||
t.is(errors[0].name, 'SemanticReleaseError');
|
||||
t.is(errors[0].code, 'ETAGNOVERSION');
|
||||
@@ -75,5 +75,5 @@ test('Return "true" if all verification pass', async t => {
|
||||
const {cwd, repositoryUrl} = await gitRepo(true);
|
||||
const options = {repositoryUrl, tagFormat: `v\${version}`};
|
||||
|
||||
await t.notThrows(verify({cwd, options}));
|
||||
await t.notThrowsAsync(verify({cwd, options}));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user