Add several fixes and improvements in the identification of the last release gitHead: - If there is no last release, unshallow the repo in order to retrieve all existing commits - If git head is not present in last release, try to retrieve it from git tag with format ‘v\<version\>’ or ‘\<version\>’ - If the last release git head cannot be determined and found in commit history, unshallow the repo and try again - Throw a ENOGITHEAD error if the gitHead for the last release cannot be found in the npm metadata nor in the git tags, preventing to make release based on the all the commits in the repo as before - Add integration test for the scenario with a packed repo from which `npm republish` fails to read the git head Fix #447, Fix #393, Fix #280, Fix #276
210 lines
8.1 KiB
JavaScript
210 lines
8.1 KiB
JavaScript
import test from 'ava';
|
|
import {writeJson, readJson} from 'fs-extra';
|
|
import {start, stop, uri} from './helpers/registry';
|
|
import {gitRepo, gitCommits, gitHead, gitTagVersion, gitPackRefs} from './helpers/git-utils';
|
|
import execa from 'execa';
|
|
|
|
test.before(async t => {
|
|
// Start the local NPM registry
|
|
await start();
|
|
});
|
|
|
|
test.beforeEach(async t => {
|
|
// Save the current working diretory
|
|
t.context.cwd = process.cwd();
|
|
});
|
|
|
|
test.afterEach.always(async t => {
|
|
// Restore the current working directory
|
|
process.chdir(t.context.cwd);
|
|
});
|
|
|
|
test.after.always(async t => {
|
|
// Stop the local NPM registry
|
|
await stop();
|
|
});
|
|
|
|
test.serial('Release patch, minor and major versions', async t => {
|
|
// Environment variables used with cli
|
|
const env = {
|
|
CI: true,
|
|
npm_config_registry: uri,
|
|
GH_TOKEN: 'github_token',
|
|
NPM_OLD_TOKEN: 'aW50ZWdyYXRpb246c3VjaHNlY3VyZQ==',
|
|
NPM_EMAIL: 'integration@test.com',
|
|
};
|
|
// Create a git repository, set the current working directory at the root of the repo
|
|
t.log('Create git repository');
|
|
await gitRepo();
|
|
|
|
// Create package.json in repository root
|
|
await writeJson('./package.json', {
|
|
name: 'test-module',
|
|
version: '0.0.0-dev',
|
|
repository: {url: 'git+https://github.com/semantic-release/test-module'},
|
|
release: {verifyConditions: require.resolve('../src/lib/plugin-noop')},
|
|
});
|
|
// Create a npm-shrinkwrap.json file
|
|
await execa('npm', ['shrinkwrap'], {env});
|
|
|
|
/** No release **/
|
|
|
|
t.log('Commit a chore');
|
|
await gitCommits(['chore: Init repository']);
|
|
t.log('$ semantic-release pre');
|
|
let {stdout, stderr, code} = await t.throws(execa(require.resolve('../bin/semantic-release'), ['pre'], {env}));
|
|
t.regex(stderr, /ENOCHANGE There are no relevant changes, so no new version is released/);
|
|
t.is(code, 1);
|
|
|
|
/** Minor release **/
|
|
|
|
t.log('Commit a feature');
|
|
await gitCommits(['feat: Initial commit']);
|
|
t.log('$ semantic-release pre');
|
|
({stdout, stderr, code} = await execa(require.resolve('../bin/semantic-release'), ['pre'], {env}));
|
|
// Verify package.json and npm-shrinkwrap.json have been updated
|
|
t.is((await readJson('./package.json')).version, '1.0.0');
|
|
t.is((await readJson('./npm-shrinkwrap.json')).version, '1.0.0');
|
|
t.log('$ npm publish');
|
|
({stdout, stderr, code} = await execa('npm', ['publish'], {env}));
|
|
// Verify output of npm publish
|
|
t.regex(stdout, /test-module@1.0.0/);
|
|
t.is(code, 0);
|
|
// Retrieve the published package from the registry and check version and gitHead
|
|
let [, version, releaseGitHead] = /^version = '(.+)'\s+gitHead = '(.+)'$/.exec(
|
|
(await execa('npm', ['show', 'test-module', 'version', 'gitHead'], {env})).stdout
|
|
);
|
|
t.is(version, '1.0.0');
|
|
t.is(releaseGitHead, await gitHead());
|
|
t.log(`+ released ${version} with gitHead ${releaseGitHead}`);
|
|
|
|
/** Patch release **/
|
|
|
|
t.log('Commit a fix');
|
|
await gitCommits(['fix: bar']);
|
|
t.log('$ semantic-release pre');
|
|
({stdout, stderr, code} = await execa(require.resolve('../bin/semantic-release'), ['pre'], {env}));
|
|
// Verify package.json and npm-shrinkwrap.json have been updated
|
|
t.is((await readJson('./package.json')).version, '1.0.1');
|
|
t.is((await readJson('./npm-shrinkwrap.json')).version, '1.0.1');
|
|
t.log('$ npm publish');
|
|
({stdout, stderr, code} = await execa('npm', ['publish'], {env}));
|
|
// Verify output of npm publish
|
|
t.regex(stdout, /test-module@1.0.1/);
|
|
t.is(code, 0);
|
|
// Retrieve the published package from the registry and check version and gitHead
|
|
[, version, releaseGitHead] = /^version = '(.+)'\s+gitHead = '(.+)'$/.exec(
|
|
(await execa('npm', ['show', 'test-module', 'version', 'gitHead'], {env})).stdout
|
|
);
|
|
t.is(version, '1.0.1');
|
|
t.is(releaseGitHead, await gitHead());
|
|
t.log(`+ released ${version} with gitHead ${releaseGitHead}`);
|
|
|
|
/** Minor release **/
|
|
|
|
t.log('Commit a feature');
|
|
await gitCommits(['feat: baz']);
|
|
t.log('$ semantic-release pre');
|
|
({stdout, stderr, code} = await execa(require.resolve('../bin/semantic-release'), ['pre'], {env}));
|
|
// Verify package.json and npm-shrinkwrap.json have been updated
|
|
t.is((await readJson('./package.json')).version, '1.1.0');
|
|
t.is((await readJson('./npm-shrinkwrap.json')).version, '1.1.0');
|
|
t.log('$ npm publish');
|
|
({stdout, stderr, code} = await execa('npm', ['publish'], {env}));
|
|
// Verify output of npm publish
|
|
t.regex(stdout, /test-module@1.1.0/);
|
|
t.is(code, 0);
|
|
// Retrieve the published package from the registry and check version and gitHead
|
|
[, version, releaseGitHead] = /^version = '(.+)'\s+gitHead = '(.+)'$/.exec(
|
|
(await execa('npm', ['show', 'test-module', 'version', 'gitHead'], {env})).stdout
|
|
);
|
|
t.is(version, '1.1.0');
|
|
t.is(releaseGitHead, await gitHead());
|
|
t.log(`+ released ${version} with gitHead ${releaseGitHead}`);
|
|
|
|
/** Major release **/
|
|
|
|
t.log('Commit a breaking change');
|
|
await gitCommits(['feat: foo\n\n BREAKING CHANGE: bar']);
|
|
t.log('$ semantic-release pre');
|
|
({stdout, stderr, code} = await execa(require.resolve('../bin/semantic-release'), ['pre'], {env}));
|
|
// Verify package.json and npm-shrinkwrap.json have been updated
|
|
t.is((await readJson('./package.json')).version, '2.0.0');
|
|
t.is((await readJson('./npm-shrinkwrap.json')).version, '2.0.0');
|
|
t.log('$ npm publish');
|
|
({stdout, stderr, code} = await execa('npm', ['publish'], {env}));
|
|
// Verify output of npm publish
|
|
t.regex(stdout, /test-module@2.0.0/);
|
|
t.is(code, 0);
|
|
// Retrieve the published package from the registry and check version and gitHead
|
|
[, version, releaseGitHead] = /^version = '(.+)'\s+gitHead = '(.+)'$/.exec(
|
|
(await execa('npm', ['show', 'test-module', 'version', 'gitHead'], {env})).stdout
|
|
);
|
|
t.is(version, '2.0.0');
|
|
t.is(releaseGitHead, await gitHead());
|
|
t.log(`+ released ${version} with gitHead ${releaseGitHead}`);
|
|
});
|
|
|
|
test.serial('Release versions from a packed git repository, using tags to determine last release gitHead', async t => {
|
|
// Environment variables used with cli
|
|
const env = {
|
|
CI: true,
|
|
npm_config_registry: uri,
|
|
GH_TOKEN: 'github_token',
|
|
NPM_OLD_TOKEN: 'aW50ZWdyYXRpb246c3VjaHNlY3VyZQ==',
|
|
NPM_EMAIL: 'integration@test.com',
|
|
};
|
|
// Create a git repository, set the current working directory at the root of the repo
|
|
t.log('Create git repository');
|
|
await gitRepo();
|
|
|
|
// Create package.json in repository root
|
|
await writeJson('./package.json', {
|
|
name: 'test-module-2',
|
|
version: '0.0.0-dev',
|
|
repository: {url: 'git+https://github.com/semantic-release/test-module-2'},
|
|
release: {verifyConditions: require.resolve('../src/lib/plugin-noop')},
|
|
});
|
|
|
|
/** Minor release **/
|
|
|
|
t.log('Commit a feature');
|
|
await gitCommits(['feat: Initial commit']);
|
|
t.log('$ git pack-refs --all');
|
|
await gitPackRefs();
|
|
t.log('$ semantic-release pre');
|
|
let {stdout, code} = await execa(require.resolve('../bin/semantic-release'), ['pre'], {env});
|
|
// Verify package.json has been updated
|
|
t.is((await readJson('./package.json')).version, '1.0.0');
|
|
t.log('$ npm publish');
|
|
({stdout, code} = await execa('npm', ['publish'], {env}));
|
|
// Verify output of npm publish
|
|
t.regex(stdout, /test-module-2@1.0.0/);
|
|
t.is(code, 0);
|
|
// Retrieve the published package from the registry and check version and gitHead
|
|
let version = (await execa('npm', ['show', 'test-module-2', 'version'], {env})).stdout;
|
|
t.is(version, '1.0.0');
|
|
t.log(`+ released ${version}`);
|
|
// Create a tag version so the tag can be used later to determine the commit associated with the version
|
|
await gitTagVersion('v1.0.0');
|
|
t.log('Create git tag v1.0.0');
|
|
|
|
/** Patch release **/
|
|
|
|
t.log('Commit a fix');
|
|
await gitCommits(['fix: bar']);
|
|
t.log('$ semantic-release pre');
|
|
({stdout, code} = await execa(require.resolve('../bin/semantic-release'), ['pre'], {env}));
|
|
// Verify package.json has been updated
|
|
t.is((await readJson('./package.json')).version, '1.0.1');
|
|
t.log('$ npm publish');
|
|
({stdout, code} = await execa('npm', ['publish'], {env}));
|
|
// Verify output of npm publish
|
|
t.regex(stdout, /test-module-2@1.0.1/);
|
|
t.is(code, 0);
|
|
// Retrieve the published package from the registry and check version and gitHead
|
|
version = (await execa('npm', ['show', 'test-module-2', 'version'], {env})).stdout;
|
|
t.is(version, '1.0.1');
|
|
t.log(`+ released ${version}`);
|
|
});
|