Compare commits

..
19 changed files with 90 additions and 74 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ try {
const result = await semanticRelease({
// Core options
branches: [
'+([1-9])?(.{+([1-9]),x}).x',
'+([0-9])?(.{+([0-9]),x}).x',
'master',
'next',
'next-major',
+1 -1
View File
@@ -3,7 +3,7 @@
This recipe will walk you through a simple example that uses distribution channels to make releases available only to a subset of users, in order to collect feedbacks before distributing the release to all users.
This example uses the **semantic-release** default configuration:
- [branches](../usage/configuration.md#branches): `['+([1-9])?(.{+([1-9]),x}).x', 'master', 'next', 'next-major', {name: 'beta', prerelease: true}, {name: 'alpha', prerelease: true}]`
- [branches](../usage/configuration.md#branches): `['+([0-9])?(.{+([0-9]),x}).x', 'master', 'next', 'next-major', {name: 'beta', prerelease: true}, {name: 'alpha', prerelease: true}]`
- [plugins](../usage/configuration.md#plugins): `['@semantic-release/commit-analyzer', '@semantic-release/release-notes-generator', '@semantic-release/npm', '@semantic-release/github']`
## Initial release
+1 -1
View File
@@ -3,7 +3,7 @@
This recipe will walk you through a simple example that uses Git branches and distribution channels to publish fixes and features for old versions of a package.
This example uses the **semantic-release** default configuration:
- [branches](../usage/configuration.md#branches): `['+([1-9])?(.{+([1-9]),x}).x', 'master', 'next', 'next-major', {name: 'beta', prerelease: true}, {name: 'alpha', prerelease: true}]`
- [branches](../usage/configuration.md#branches): `['+([0-9])?(.{+([0-9]),x}).x', 'master', 'next', 'next-major', {name: 'beta', prerelease: true}, {name: 'alpha', prerelease: true}]`
- [plugins](../usage/configuration.md#plugins): `['@semantic-release/commit-analyzer', '@semantic-release/release-notes-generator', '@semantic-release/npm', '@semantic-release/github']`
## Initial release
+1 -1
View File
@@ -3,7 +3,7 @@
This recipe will walk you through a simple example that uses pre-releases to publish beta versions while working on a future major release and then make only one release on the default distribution.
This example uses the **semantic-release** default configuration:
- [branches](../usage/configuration.md#branches): `['+([1-9])?(.{+([1-9]),x}).x', 'master', 'next', 'next-major', {name: 'beta', prerelease: true}, {name: 'alpha', prerelease: true}]`
- [branches](../usage/configuration.md#branches): `['+([0-9])?(.{+([0-9]),x}).x', 'master', 'next', 'next-major', {name: 'beta', prerelease: true}, {name: 'alpha', prerelease: true}]`
- [plugins](../usage/configuration.md#plugins): `['@semantic-release/commit-analyzer', '@semantic-release/release-notes-generator', '@semantic-release/npm', '@semantic-release/github']`
## Initial release
+3 -1
View File
@@ -70,7 +70,7 @@ List of modules or file paths containing a [shareable configuration](shareable-c
### branches
Type: `Array`, `String`, `Object`<br>
Default: `['+([1-9])?(.{+([1-9]),x}).x', 'master', 'next', 'next-major', {name: 'beta', prerelease: true}, {name: 'alpha', prerelease: true}]`<br>
Default: `['+([0-9])?(.{+([0-9]),x}).x', 'master', 'next', 'next-major', {name: 'beta', prerelease: true}, {name: 'alpha', prerelease: true}]`<br>
CLI arguments: `--branches`
The branches on which releases should happen. By default **semantic-release** will release:
@@ -81,6 +81,8 @@ The branches on which releases should happen. By default **semantic-release** wi
- prereleases to the `beta` distribution channel from the branch `beta` if it exists
- prereleases to the `alpha` distribution channel from the branch `alpha` if it exists
**Note**: If your repository does not have a release branch, then **semantic-release** will fail with an `ERELEASEBRANCHES` error message. If you are using the default configuration, you can fix this error by pushing a `master` branch.
**Note**: Once **semantic-release** is configured, any user with the permission to push commits on one of those branches will be able to publish a release. It is recommended to protect those branches, for example with [GitHub protected branches](https://help.github.com/articles/about-protected-branches).
See [Plugins configuration](plugins.md#plugins) for more details.
+1 -1
View File
@@ -34,7 +34,7 @@ It can be defined as a [glob](https://github.com/micromatch/micromatch#matching-
If `name` doesn't match to any branch existing in the repository, the definition will be ignored. For example the default configuration includes the definition `next` and `next-major` which will become active only when the branches `next` and/or `next-major` are created in the repository. This allow to define your workflow once with all potential branches you might use and have the effective configuration evolving as you create new branches.
For example the configuration `['+([1-9])?(.{+([1-9]),x}).x', 'master', 'next']` will be expanded as:
For example the configuration `['+([0-9])?(.{+([0-9]),x}).x', 'master', 'next']` will be expanded as:
```js
{
branches: [
+3 -4
View File
@@ -53,7 +53,8 @@ async function run(context, plugins) {
// Verify config
await verify(context);
context.branches = await getBranches(context);
options.repositoryUrl = await getGitAuthUrl(context);
context.branches = await getBranches(options.repositoryUrl, context);
context.branch = context.branches.find(({name}) => name === ciBranch);
if (!context.branch) {
@@ -69,13 +70,11 @@ async function run(context, plugins) {
`Run automated release from branch ${ciBranch}${options.dryRun ? ' in dry-run mode' : ''}`
);
options.repositoryUrl = await getGitAuthUrl(context);
try {
try {
await verifyAuth(options.repositoryUrl, context.branch.name, {cwd, env});
} catch (error) {
if (!(await isBranchUpToDate(context.branch.name, {cwd, env}))) {
if (!(await isBranchUpToDate(options.repositoryUrl, context.branch.name, {cwd, env}))) {
logger.log(
`The local branch ${
context.branch.name
+2 -2
View File
@@ -2,8 +2,8 @@ const {isString, remove, omit, mapValues, template} = require('lodash');
const micromatch = require('micromatch');
const {getBranches} = require('../git');
module.exports = async ({cwd}, branches) => {
const gitBranches = await getBranches({cwd});
module.exports = async (repositoryUrl, {cwd}, branches) => {
const gitBranches = await getBranches(repositoryUrl, {cwd});
return branches.reduce(
(branches, branch) => [
+3 -2
View File
@@ -8,16 +8,17 @@ const expand = require('./expand');
const getTags = require('./get-tags');
const normalize = require('./normalize');
module.exports = async context => {
module.exports = async (repositoryUrl, context) => {
const {cwd, env} = context;
const remoteBranches = await expand(
repositoryUrl,
context,
context.options.branches.map(branch => (isString(branch) || isRegExp(branch) ? {name: branch} : branch))
);
await pEachSeries(remoteBranches, async ({name}) => {
await fetch(name, {cwd, env});
await fetch(repositoryUrl, name, {cwd, env});
});
const branches = await getTags(context, remoteBranches);
+2
View File
@@ -183,6 +183,8 @@ Your configuration for the problematic branches is \`${stringify(branches)}\`.`,
details: `A minimum of 1 and a maximum of 3 release branches are required in the [branches configuration](${linkify(
'docs/usage/configuration.md#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)}\`.`,
}),
+1 -1
View File
@@ -67,7 +67,7 @@ module.exports = async (context, opts) => {
// Set default options values if not defined yet
options = {
branches: [
'+([1-9])?(.{+([1-9]),x}).x',
'+([0-9])?(.{+([0-9]),x}).x',
'master',
'next',
'next-major',
+14 -7
View File
@@ -57,13 +57,14 @@ async function getCommits(from, to, execaOpts) {
/**
* Get all the repository branches.
*
* @param {String} repositoryUrl The remote repository URL.
* @param {Object} [execaOpts] Options to pass to `execa`.
*
* @return {Array<String>} List of git branches.
* @throws {Error} If the `git` command fails.
*/
async function getBranches(execaOpts) {
return (await execa.stdout('git', ['ls-remote', '--heads', 'origin'], execaOpts))
async function getBranches(repositoryUrl, execaOpts) {
return (await execa.stdout('git', ['ls-remote', '--heads', repositoryUrl], execaOpts))
.split('\n')
.map(branch => branch.match(/^.+refs\/heads\/(.+)$/)[1])
.filter(Boolean);
@@ -127,10 +128,11 @@ async function isRefExists(ref, execaOpts) {
/**
* Unshallow the git repository if necessary and fetch all the tags.
*
* @param {String} repositoryUrl The remote repository URL.
* @param {String} branch The repository branch to fetch.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function fetch(branch, execaOpts) {
async function fetch(repositoryUrl, branch, execaOpts) {
const isLocalExists =
(await execa('git', ['rev-parse', '--verify', branch], {...execaOpts, reject: false})).code === 0;
@@ -141,14 +143,18 @@ async function fetch(branch, execaOpts) {
'fetch',
'--unshallow',
'--tags',
...(isLocalExists ? [] : ['origin', `+refs/heads/${branch}:refs/heads/${branch}`]),
...(isLocalExists ? [repositoryUrl] : [repositoryUrl, `+refs/heads/${branch}:refs/heads/${branch}`]),
],
execaOpts
);
} catch (error) {
await execa(
'git',
['fetch', '--tags', ...(isLocalExists ? [] : ['origin', `+refs/heads/${branch}:refs/heads/${branch}`])],
[
'fetch',
'--tags',
...(isLocalExists ? [repositoryUrl] : [repositoryUrl, `+refs/heads/${branch}:refs/heads/${branch}`]),
],
execaOpts
);
}
@@ -273,13 +279,14 @@ async function verifyBranchName(branch, execaOpts) {
/**
* Verify the local branch is up to date with the remote one.
*
* @param {String} repositoryUrl The remote repository URL.
* @param {String} branch The repository branch for which to verify status.
* @param {Object} [execaOpts] Options to pass to `execa`.
*
* @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(branch, execaOpts) {
const remoteHead = await execa.stdout('git', ['ls-remote', '--heads', 'origin', branch], execaOpts);
async function isBranchUpToDate(repositoryUrl, branch, execaOpts) {
const remoteHead = await execa.stdout('git', ['ls-remote', '--heads', repositoryUrl, branch], execaOpts);
try {
return await isRefInHistory(remoteHead.match(/^(\w+)?/)[1], branch, false, execaOpts);
} catch (error) {
+1 -1
View File
@@ -21,7 +21,7 @@
"dependencies": {
"@semantic-release/commit-analyzer": "^7.0.0-beta.1",
"@semantic-release/error": "^2.2.0",
"@semantic-release/github": "^5.3.0-beta.6",
"@semantic-release/github": "^5.4.0-beta.1",
"@semantic-release/npm": "^5.2.0-beta.5",
"@semantic-release/release-notes-generator": "^7.1.2",
"aggregate-error": "^2.0.0",
+18 -18
View File
@@ -24,7 +24,7 @@ test('Enforce ranges with branching release workflow', async t => {
];
const getBranches = proxyquire('../../lib/branches', {'./get-tags': () => branches, './expand': () => []});
let result = (await getBranches({options: {branches}})).map(({name, range}) => ({name, range}));
let result = (await getBranches('repositoryUrl', {options: {branches}})).map(({name, range}) => ({name, range}));
t.is(getBranch(result, '1.0.x').range, '>=1.0.0 <1.0.0', 'Cannot release on 1.0.x before a releasing on master');
t.is(getBranch(result, '1.x').range, '>=1.1.0 <1.0.0', 'Cannot release on 1.x before a releasing on master');
t.is(getBranch(result, 'master').range, '>=1.0.0 <1.1.0', 'Can release only patch on master');
@@ -32,43 +32,43 @@ test('Enforce ranges with branching release workflow', async t => {
t.is(getBranch(result, 'next-major').range, '>=2.0.0', 'Can release only major on next-major');
release(branches, 'master', '1.0.0');
result = (await getBranches({options: {branches}})).map(({name, range}) => ({name, range}));
result = (await getBranches('repositoryUrl', {options: {branches}})).map(({name, range}) => ({name, range}));
t.is(getBranch(result, '1.0.x').range, '>=1.0.0 <1.0.0', 'Cannot release on 1.0.x before a releasing on master');
t.is(getBranch(result, '1.x').range, '>=1.1.0 <1.0.0', 'Cannot release on 1.x before a releasing on master');
t.is(getBranch(result, 'master').range, '>=1.0.0 <1.1.0', 'Can release only patch on master');
release(branches, 'master', '1.0.1');
result = (await getBranches({options: {branches}})).map(({name, range}) => ({name, range}));
result = (await getBranches('repositoryUrl', {options: {branches}})).map(({name, range}) => ({name, range}));
t.is(getBranch(result, 'master').range, '>=1.0.1 <1.1.0', 'Can release only patch, > than 1.0.1 on master');
merge(branches, 'master', 'next');
merge(branches, 'master', 'next-major');
result = (await getBranches({options: {branches}})).map(({name, range}) => ({name, range}));
result = (await getBranches('repositoryUrl', {options: {branches}})).map(({name, range}) => ({name, range}));
t.is(getBranch(result, 'master').range, '>=1.0.1 <1.1.0', 'Can release only patch, > than 1.0.1 on master');
t.is(getBranch(result, 'next').range, '>=1.1.0 <2.0.0', 'Can release only minor on next');
t.is(getBranch(result, 'next-major').range, '>=2.0.0', 'Can release only major on next-major');
release(branches, 'next', '1.1.0');
release(branches, 'next', '1.1.1');
result = (await getBranches({options: {branches}})).map(({name, range}) => ({name, range}));
result = (await getBranches('repositoryUrl', {options: {branches}})).map(({name, range}) => ({name, range}));
t.is(getBranch(result, 'next').range, '>=1.1.1 <2.0.0', 'Can release only patch or minor, > than 1.1.0 on next');
release(branches, 'next-major', '2.0.0');
release(branches, 'next-major', '2.0.1');
result = (await getBranches({options: {branches}})).map(({name, range}) => ({name, range}));
result = (await getBranches('repositoryUrl', {options: {branches}})).map(({name, range}) => ({name, range}));
t.is(getBranch(result, 'next-major').range, '>=2.0.1', 'Can release any version, > than 2.0.1 on next-major');
merge(branches, 'next-major', 'beta');
release(branches, 'beta', '3.0.0-beta.1');
merge(branches, 'beta', 'alpha');
release(branches, 'alpha', '4.0.0-alpha.1');
result = (await getBranches({options: {branches}})).map(({name, range}) => ({name, range}));
result = (await getBranches('repositoryUrl', {options: {branches}})).map(({name, range}) => ({name, range}));
t.is(getBranch(result, 'next-major').range, '>=2.0.1', 'Can release any version, > than 2.0.1 on next-major');
merge(branches, 'master', '1.0.x');
merge(branches, 'master', '1.x');
release(branches, 'master', '1.0.1');
result = (await getBranches({options: {branches}})).map(({name, range}) => ({name, range}));
result = (await getBranches('repositoryUrl', {options: {branches}})).map(({name, range}) => ({name, range}));
t.is(getBranch(result, 'master').range, '>=1.0.1 <1.1.0', 'Can release only patch, > than 1.0.1 on master');
t.is(
getBranch(result, '1.0.x').range,
@@ -80,7 +80,7 @@ test('Enforce ranges with branching release workflow', async t => {
release(branches, 'master', '1.0.2');
release(branches, 'master', '1.0.3');
release(branches, 'master', '1.0.4');
result = (await getBranches({options: {branches}})).map(({name, range}) => ({name, range}));
result = (await getBranches('repositoryUrl', {options: {branches}})).map(({name, range}) => ({name, range}));
t.is(getBranch(result, 'master').range, '>=1.0.4 <1.1.0', 'Can release only patch, > than 1.0.4 on master');
t.is(
getBranch(result, '1.0.x').range,
@@ -90,7 +90,7 @@ test('Enforce ranges with branching release workflow', async t => {
t.is(getBranch(result, '1.x').range, '>=1.1.0 <1.0.2', 'Cannot release on 1.x before >= 1.2.0 is released on master');
merge(branches, 'next', 'master');
result = (await getBranches({options: {branches}})).map(({name, range}) => ({name, range}));
result = (await getBranches('repositoryUrl', {options: {branches}})).map(({name, range}) => ({name, range}));
t.is(getBranch(result, 'master').range, '>=1.1.1 <1.2.0', 'Can release only patch, > than 1.1.1 on master');
t.is(getBranch(result, 'next').range, '>=1.2.0 <2.0.0', 'Can release only patch or minor, > than 1.2.0 on next');
t.is(getBranch(result, 'next-major').range, '>=2.0.1', 'Can release any version, > than 2.0.1 on next-major');
@@ -102,34 +102,34 @@ test('Enforce ranges with branching release workflow', async t => {
t.is(getBranch(result, '1.x').range, '>=1.1.0 <1.0.2', 'Cannot release on 1.x before >= 2.0.0 is released on master');
merge(branches, 'master', '1.0.x', '1.0.4');
result = (await getBranches({options: {branches}})).map(({name, range}) => ({name, range}));
result = (await getBranches('repositoryUrl', {options: {branches}})).map(({name, range}) => ({name, range}));
t.is(getBranch(result, 'master').range, '>=1.1.1 <1.2.0', 'Can release only patch, > than 1.1.1 on master');
t.is(getBranch(result, '1.0.x').range, '>=1.0.4 <1.1.0', 'Can release on 1.0.x only within range');
t.is(getBranch(result, '1.x').range, '>=1.1.0 <1.1.0', 'Cannot release on 1.x before >= 2.0.0 is released on master');
merge(branches, 'master', '1.x');
result = (await getBranches({options: {branches}})).map(({name, range}) => ({name, range}));
result = (await getBranches('repositoryUrl', {options: {branches}})).map(({name, range}) => ({name, range}));
t.is(getBranch(result, 'master').range, '>=1.1.1 <1.2.0', 'Can release only patch, > than 1.1.1 on master');
t.is(getBranch(result, '1.0.x').range, '>=1.0.4 <1.1.0', 'Can release on 1.0.x only within range');
t.is(getBranch(result, '1.x').range, '>=1.1.1 <1.1.1', 'Cannot release on 1.x before >= 2.0.0 is released on master');
merge(branches, 'next-major', 'next');
merge(branches, 'next', 'master');
result = (await getBranches({options: {branches}})).map(({name, range}) => ({name, range}));
result = (await getBranches('repositoryUrl', {options: {branches}})).map(({name, range}) => ({name, range}));
t.is(getBranch(result, 'master').range, '>=2.0.1 <2.1.0', 'Can release only patch, > than 2.0.1 on master');
t.is(getBranch(result, 'next').range, '>=2.1.0 <3.0.0', 'Can release only minor on next');
t.is(getBranch(result, 'next-major').range, '>=3.0.0', 'Can release only major on next-major');
t.is(getBranch(result, '1.x').range, '>=1.1.1 <2.0.0', 'Can release on 1.x only within range');
merge(branches, 'beta', 'master');
result = (await getBranches({options: {branches}})).map(({name, range}) => ({name, range}));
result = (await getBranches('repositoryUrl', {options: {branches}})).map(({name, range}) => ({name, range}));
t.is(getBranch(result, 'master').range, '>=2.0.1 <2.1.0', 'Can release only patch, > than 2.0.1 on master');
t.is(getBranch(result, 'next').range, '>=2.1.0 <3.0.0', 'Can release only minor on next');
t.is(getBranch(result, 'next-major').range, '>=3.0.0', 'Can release only major on next-major');
branches.push({name: '1.1.x', tags: []});
merge(branches, '1.x', '1.1.x');
result = (await getBranches({options: {branches}})).map(({name, range}) => ({name, range}));
result = (await getBranches('repositoryUrl', {options: {branches}})).map(({name, range}) => ({name, range}));
t.is(getBranch(result, '1.0.x').range, '>=1.0.4 <1.1.0', 'Can release on 1.0.x only within range');
t.is(getBranch(result, '1.1.x').range, '>=1.1.1 <1.2.0', 'Can release on 1.1.x only within range');
t.is(getBranch(result, '1.x').range, '>=1.2.0 <2.0.0', 'Can release on 1.x only within range');
@@ -146,7 +146,7 @@ test('Throw SemanticReleaseError for invalid configurations', async t => {
{name: 'preview', prerelease: 'alpha', tags: []},
];
const getBranches = proxyquire('../../lib/branches', {'./get-tags': () => branches, './expand': () => []});
const errors = [...(await t.throwsAsync(getBranches({options: {branches}})))];
const errors = [...(await t.throwsAsync(getBranches('repositoryUrl', {options: {branches}})))];
t.is(errors[0].name, 'SemanticReleaseError');
t.is(errors[0].code, 'EMAINTENANCEBRANCH');
@@ -174,7 +174,7 @@ test('Throw a SemanticReleaseError if there is duplicate branches', async t => {
const branches = [{name: 'master', tags: []}, {name: 'master', tags: []}];
const getBranches = proxyquire('../../lib/branches', {'./get-tags': () => branches, './expand': () => []});
const errors = [...(await t.throwsAsync(getBranches({options: {branches}})))];
const errors = [...(await t.throwsAsync(getBranches('repositoryUrl', {options: {branches}})))];
t.is(errors[0].name, 'SemanticReleaseError');
t.is(errors[0].code, 'EDUPLICATEBRANCHES');
@@ -186,7 +186,7 @@ test('Throw a SemanticReleaseError for each invalid branch name', async t => {
const branches = [{name: '~master', tags: []}, {name: '^master', tags: []}];
const getBranches = proxyquire('../../lib/branches', {'./get-tags': () => branches, './expand': () => []});
const errors = [...(await t.throwsAsync(getBranches({options: {branches}})))];
const errors = [...(await t.throwsAsync(getBranches('repositoryUrl', {options: {branches}})))];
t.is(errors[0].name, 'SemanticReleaseError');
t.is(errors[0].code, 'EINVALIDBRANCHNAME');
+5 -5
View File
@@ -6,9 +6,9 @@ test('Expand branches defined with globs', async t => {
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['First'], {cwd});
await gitPush(repositoryUrl, 'master', {cwd});
await gitCheckout('1.1.x', true, {cwd});
await gitCheckout('1.0.x', true, {cwd});
await gitCommits(['Second'], {cwd});
await gitPush(repositoryUrl, '1.1.x', {cwd});
await gitPush(repositoryUrl, '1.0.x', {cwd});
await gitCheckout('1.x.x', true, {cwd});
await gitCommits(['Third'], {cwd});
await gitPush(repositoryUrl, '1.x.x', {cwd});
@@ -30,7 +30,7 @@ test('Expand branches defined with globs', async t => {
const branches = [
// Should match all maintenance type branches
{name: '+([1-9])?(.{+([1-9]),x}).x'},
{name: '+([0-9])?(.{+([0-9]),x}).x'},
{name: 'master', channel: 'latest'},
{name: 'next'},
{name: 'pre/{foo,bar}', channel: `\${name.replace(/^pre\\//g, '')}`, prerelease: true},
@@ -41,8 +41,8 @@ test('Expand branches defined with globs', async t => {
{name: 'beta', channel: `channel-\${name}`, prerelease: true},
];
t.deepEqual(await expand({cwd}, branches), [
{name: '1.1.x'},
t.deepEqual(await expand(repositoryUrl, {cwd}, branches), [
{name: '1.0.x'},
{name: '1.x.x'},
{name: '2.x'},
{name: 'master', channel: 'latest'},
+4 -4
View File
@@ -36,7 +36,7 @@ test('Default values, reading repositoryUrl from package.json', async t => {
// Verify the default options are set
t.deepEqual(result.branches, [
'+([1-9])?(.{+([1-9]),x}).x',
'+([0-9])?(.{+([0-9]),x}).x',
'master',
'next',
'next-major',
@@ -57,7 +57,7 @@ test('Default values, reading repositoryUrl from repo if not set in package.json
// Verify the default options are set
t.deepEqual(result.branches, [
'+([1-9])?(.{+([1-9]),x}).x',
'+([0-9])?(.{+([0-9]),x}).x',
'master',
'next',
'next-major',
@@ -79,7 +79,7 @@ test('Default values, reading repositoryUrl (http url) from package.json if not
// Verify the default options are set
t.deepEqual(result.branches, [
'+([1-9])?(.{+([1-9]),x}).x',
'+([0-9])?(.{+([0-9]),x}).x',
'master',
'next',
'next-major',
@@ -513,6 +513,6 @@ test('Throw an Error if one of the shareable config cannot be found', async t =>
const error = await t.throwsAsync(t.context.getConfig({cwd}), Error);
t.is(error.message, "Cannot find module 'non-existing-path'");
t.regex(error.message, /Cannot find module 'non-existing-path'/);
t.is(error.code, 'MODULE_NOT_FOUND');
});
+9 -9
View File
@@ -58,7 +58,7 @@ test('Unshallow and fetch repository', async t => {
// Verify the shallow clone contains only one commit
t.is((await gitGetCommits(undefined, {cwd})).length, 1);
await fetch('master', {cwd});
await fetch(repositoryUrl, 'master', {cwd});
// Verify the shallow clone contains all the commits
t.is((await gitGetCommits(undefined, {cwd})).length, 2);
@@ -73,8 +73,8 @@ test('Do not throw error when unshallow a complete repository', async t => {
await gitCommits(['Second'], {cwd});
await gitPush(repositoryUrl, 'second-branch', {cwd});
await t.notThrowsAsync(fetch('master', {cwd}));
await t.notThrowsAsync(fetch('second-branch', {cwd}));
await t.notThrowsAsync(fetch(repositoryUrl, 'master', {cwd}));
await t.notThrowsAsync(fetch(repositoryUrl, 'second-branch', {cwd}));
});
test('Fetch all tags on a detached head repository', async t => {
@@ -89,7 +89,7 @@ test('Fetch all tags on a detached head repository', async t => {
await gitPush(repositoryUrl, 'master', {cwd});
cwd = await gitDetachedHead(repositoryUrl, commit.hash);
await fetch('master', {cwd});
await fetch(repositoryUrl, 'master', {cwd});
t.deepEqual((await getTags({cwd})).sort(), ['v1.0.0', 'v1.0.1', 'v1.1.0'].sort());
});
@@ -137,7 +137,7 @@ test('Get all branches', async t => {
await gitCommits(['Third'], {cwd});
await gitPush(repositoryUrl, 'third-branch', {cwd});
t.deepEqual((await getBranches({cwd})).sort(), ['master', 'second-branch', 'third-branch'].sort());
t.deepEqual((await getBranches(repositoryUrl, {cwd})).sort(), ['master', 'second-branch', 'third-branch'].sort());
});
test('Get the commit sha for a given tag or falsy if the tag does not exists', async t => {
@@ -251,7 +251,7 @@ test('Return "true" if repository is up to date', async t => {
await gitCommits(['First'], {cwd});
await gitPush(repositoryUrl, 'master', {cwd});
t.true(await isBranchUpToDate('master', {cwd}));
t.true(await isBranchUpToDate(repositoryUrl, 'master', {cwd}));
});
test('Return falsy if repository is not up to date', async t => {
@@ -260,13 +260,13 @@ test('Return falsy if repository is not up to date', async t => {
await gitCommits(['Second'], {cwd});
await gitPush(repositoryUrl, 'master', {cwd});
t.true(await isBranchUpToDate('master', {cwd}));
t.true(await isBranchUpToDate(repositoryUrl, 'master', {cwd}));
const tmpRepo = await gitShallowClone(repositoryUrl);
await gitCommits(['Third'], {cwd: tmpRepo});
await gitPush('origin', 'master', {cwd: tmpRepo});
t.falsy(await isBranchUpToDate('master', {cwd}));
t.falsy(await isBranchUpToDate(repositoryUrl, 'master', {cwd}));
});
test('Return "true" if local repository is ahead', async t => {
@@ -275,5 +275,5 @@ test('Return "true" if local repository is ahead', async t => {
await gitPush(repositoryUrl, 'master', {cwd});
await gitCommits(['Second'], {cwd});
t.true(await isBranchUpToDate('master', {cwd}));
t.true(await isBranchUpToDate(repositoryUrl, 'master', {cwd}));
});
+19 -14
View File
@@ -83,7 +83,7 @@ test('Plugins are called with expected values', async t => {
const prepare = stub().resolves();
const publish = stub().resolves(release2);
const success = stub().resolves();
const env = {...process.env};
const env = {};
const config = {
branches: [{name: 'master'}, {name: 'next'}],
repositoryUrl,
@@ -131,9 +131,9 @@ test('Plugins are called with expected values', async t => {
channel: undefined,
gitTag: 'v1.0.0',
notes: `${notes1}\n\n${notes2}\n\n${notes3}`,
pluginName: '[Function: proxy]',
pluginName: '[Function: functionStub]',
},
{...nextRelease, ...release2, notes: `${notes1}\n\n${notes2}\n\n${notes3}`, pluginName: '[Function: proxy]'},
{...nextRelease, ...release2, notes: `${notes1}\n\n${notes2}\n\n${notes3}`, pluginName: '[Function: functionStub]'},
{...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`, pluginName: pluginNoop},
];
@@ -353,7 +353,7 @@ test('Plugins are called with expected values', async t => {
t.deepEqual(result, {
lastRelease,
commits: [{...commits[0], gitTags: '(HEAD -> master, origin/master, origin/HEAD, next)'}],
commits: [{...commits[0], gitTags: '(HEAD -> master, next)'}],
nextRelease: {...nextRelease, notes: `${notes1}\n\n${notes2}\n\n${notes3}`},
releases,
});
@@ -562,7 +562,7 @@ test('Publish a pre-release version', async t => {
'./lib/get-logger': () => t.context.logger,
'env-ci': () => ({isCi: true, branch: 'beta', isPr: false}),
});
let {releases} = await semanticRelease(options, {cwd, stdout: {write: () => {}}, stderr: {write: () => {}}});
let {releases} = await semanticRelease(options, {cwd, env: {}, stdout: {write: () => {}}, stderr: {write: () => {}}});
t.is(releases.length, 1);
t.is(releases[0].version, '1.1.0-beta.1');
@@ -571,6 +571,7 @@ test('Publish a pre-release version', async t => {
await gitCommits(['fix: a fix'], {cwd});
({releases} = await semanticRelease(options, {
cwd,
env: {},
stdout: {write: () => {}},
stderr: {write: () => {}},
}));
@@ -694,10 +695,10 @@ async function addChannelMacro(t, mergeFunction) {
const result = await semanticRelease(options, {cwd, env: {}, stdout: {write: () => {}}, stderr: {write: () => {}}});
t.deepEqual(result.releases, [
{...nextRelease1, ...release1, notes, pluginName: '[Function: proxy]'},
{...nextRelease1, notes, pluginName: '[Function: proxy]'},
{...nextRelease2, ...release1, notes, pluginName: '[Function: proxy]'},
{...nextRelease2, notes, pluginName: '[Function: proxy]'},
{...nextRelease1, ...release1, notes, pluginName: '[Function: functionStub]'},
{...nextRelease1, notes, pluginName: '[Function: functionStub]'},
{...nextRelease2, ...release1, notes, pluginName: '[Function: functionStub]'},
{...nextRelease2, notes, pluginName: '[Function: functionStub]'},
]);
// Verify the tag has been created on the local and remote repo and reference
@@ -769,10 +770,14 @@ test('Call all "success" plugins even if one errors out', async t => {
t.is(success1.callCount, 1);
t.deepEqual(success1.args[0][0], config);
t.deepEqual(success1.args[0][1].releases, [{...nextRelease, ...release, notes, pluginName: '[Function: proxy]'}]);
t.deepEqual(success1.args[0][1].releases, [
{...nextRelease, ...release, notes, pluginName: '[Function: functionStub]'},
]);
t.is(success2.callCount, 1);
t.deepEqual(success2.args[0][1].releases, [{...nextRelease, ...release, notes, pluginName: '[Function: proxy]'}]);
t.deepEqual(success2.args[0][1].releases, [
{...nextRelease, ...release, notes, pluginName: '[Function: functionStub]'},
]);
});
test('Log all "verifyConditions" errors', async t => {
@@ -1202,8 +1207,8 @@ test('Accept "undefined" value returned by "generateNotes" and "false" by "publi
t.is(publish.callCount, 1);
t.is(success.callCount, 2);
t.deepEqual(publish.args[0][1].nextRelease, {...nextRelease, notes: notes2});
t.deepEqual(success.args[0][1].releases, [{pluginName: '[Function: proxy]'}]);
t.deepEqual(success.args[1][1].releases, [{pluginName: '[Function: proxy]'}]);
t.deepEqual(success.args[0][1].releases, [{pluginName: '[Function: functionStub]'}]);
t.deepEqual(success.args[1][1].releases, [{pluginName: '[Function: functionStub]'}]);
});
test('Returns false if triggered by a PR', async t => {
@@ -1399,7 +1404,7 @@ test('Throws "EINVALIDMAINTENANCEMERGE" if merge an out of range release in a ma
t.is(publish.callCount, 0);
t.is(success.callCount, 1);
t.deepEqual(success.args[0][1].releases, [{...nextRelease, notes, pluginName: '[Function: proxy]'}]);
t.deepEqual(success.args[0][1].releases, [{...nextRelease, notes, pluginName: '[Function: functionStub]'}]);
t.is(fail.callCount, 1);
t.deepEqual(fail.args[0][1].errors, errors);
+1 -1
View File
@@ -273,6 +273,6 @@ test('Throws an error if the plugin is not found', t => {
Error
);
t.is(error.message, "Cannot find module 'non-existing-path'");
t.regex(error.message, /Cannot find module 'non-existing-path'/);
t.is(error.code, 'MODULE_NOT_FOUND');
});