feat: add the prepare plugin hook
BREAKING CHANGE: Committing or creating files in the `publish` plugin hook is not supported anymore and now must be done in the `prepare` hook Plugins with a `publish` hook that makes a commit or create a file that can be committed must use the `prepare` hook.
This commit is contained in:
@@ -53,6 +53,9 @@ test.serial('Pass options to semantic-release API', async t => {
|
||||
'verify2',
|
||||
'--generate-notes',
|
||||
'notes',
|
||||
'--prepare',
|
||||
'prepare1',
|
||||
'prepare2',
|
||||
'--publish',
|
||||
'publish1',
|
||||
'publish2',
|
||||
@@ -76,6 +79,7 @@ test.serial('Pass options to semantic-release API', async t => {
|
||||
t.is(run.args[0][0].analyzeCommits, 'analyze');
|
||||
t.deepEqual(run.args[0][0].verifyRelease, ['verify1', 'verify2']);
|
||||
t.is(run.args[0][0].generateNotes, 'notes');
|
||||
t.deepEqual(run.args[0][0].prepare, ['prepare1', 'prepare2']);
|
||||
t.deepEqual(run.args[0][0].publish, ['publish1', 'publish2']);
|
||||
t.deepEqual(run.args[0][0].success, ['success1', 'success2']);
|
||||
t.deepEqual(run.args[0][0].fail, ['fail1', 'fail2']);
|
||||
|
||||
@@ -46,6 +46,17 @@ test('The "generateNotes" plugin, if defined, must be a single plugin definition
|
||||
t.true(plugins.generateNotes.config.validator(() => {}));
|
||||
});
|
||||
|
||||
test('The "prepare" plugin, if defined, must be a single or an array of plugins definition', t => {
|
||||
t.false(plugins.verifyRelease.config.validator({}));
|
||||
t.false(plugins.verifyRelease.config.validator({path: null}));
|
||||
|
||||
t.true(plugins.verifyRelease.config.validator({path: 'plugin-path.js'}));
|
||||
t.true(plugins.verifyRelease.config.validator());
|
||||
t.true(plugins.verifyRelease.config.validator('plugin-path.js'));
|
||||
t.true(plugins.verifyRelease.config.validator(() => {}));
|
||||
t.true(plugins.verifyRelease.config.validator([{path: 'plugin-path.js'}, 'plugin-path.js', () => {}]));
|
||||
});
|
||||
|
||||
test('The "publish" plugin is mandatory, and must be a single or an array of plugins definition', t => {
|
||||
t.false(plugins.publish.config.validator({}));
|
||||
t.false(plugins.publish.config.validator({path: null}));
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
push,
|
||||
gitTags,
|
||||
isGitRepo,
|
||||
deleteTag,
|
||||
verifyTagName,
|
||||
} from '../lib/git';
|
||||
import {
|
||||
@@ -139,18 +138,6 @@ test.serial('Add tag on head commit', async t => {
|
||||
await t.is(await gitCommitTag(commits[0].hash), 'tag_name');
|
||||
});
|
||||
|
||||
test.serial('Delete a tag', async t => {
|
||||
// Create a git repository with a remote, set the current working directory at the root of the repo
|
||||
const repo = await gitRepo(true);
|
||||
await gitCommits(['Test commit']);
|
||||
await tag('tag_name');
|
||||
await push(repo, 'master');
|
||||
|
||||
await deleteTag(repo, 'tag_name');
|
||||
t.falsy(await gitTagHead('tag_name'));
|
||||
t.falsy(await gitRemoteTagHead(repo, 'tag_name'));
|
||||
});
|
||||
|
||||
test.serial('Push tag and commit to remote repository', async t => {
|
||||
// Create a git repository with a remote, set the current working directory at the root of the repo
|
||||
const repo = await gitRepo(true);
|
||||
|
||||
+35
-9
@@ -67,6 +67,7 @@ test.serial('Plugins are called with expected values', async t => {
|
||||
const verifyRelease = stub().resolves();
|
||||
const generateNotes = stub().resolves(notes);
|
||||
const release1 = {name: 'Release 1', url: 'https://release1.com'};
|
||||
const prepare = stub().resolves();
|
||||
const publish1 = stub().resolves(release1);
|
||||
const success = stub().resolves();
|
||||
|
||||
@@ -77,6 +78,7 @@ test.serial('Plugins are called with expected values', async t => {
|
||||
analyzeCommits,
|
||||
verifyRelease,
|
||||
generateNotes,
|
||||
prepare,
|
||||
publish: [publish1, pluginNoop],
|
||||
success,
|
||||
};
|
||||
@@ -119,6 +121,15 @@ test.serial('Plugins are called with expected values', async t => {
|
||||
t.deepEqual(generateNotes.args[0][1].commits[0].message, commits[0].message);
|
||||
t.deepEqual(generateNotes.args[0][1].nextRelease, nextRelease);
|
||||
|
||||
t.is(prepare.callCount, 1);
|
||||
t.deepEqual(prepare.args[0][0], config);
|
||||
t.deepEqual(prepare.args[0][1].options, options);
|
||||
t.deepEqual(prepare.args[0][1].logger, t.context.logger);
|
||||
t.deepEqual(prepare.args[0][1].lastRelease, lastRelease);
|
||||
t.deepEqual(prepare.args[0][1].commits[0].hash, commits[0].hash);
|
||||
t.deepEqual(prepare.args[0][1].commits[0].message, commits[0].message);
|
||||
t.deepEqual(prepare.args[0][1].nextRelease, {...nextRelease, ...{notes}});
|
||||
|
||||
t.is(publish1.callCount, 1);
|
||||
t.deepEqual(publish1.args[0][0], config);
|
||||
t.deepEqual(publish1.args[0][1].options, options);
|
||||
@@ -161,6 +172,7 @@ test.serial('Use custom tag format', async t => {
|
||||
analyzeCommits: stub().resolves(nextRelease.type),
|
||||
verifyRelease: stub().resolves(),
|
||||
generateNotes: stub().resolves(notes),
|
||||
prepare: stub().resolves(),
|
||||
publish: stub().resolves(),
|
||||
success: stub().resolves(),
|
||||
fail: stub().resolves(),
|
||||
@@ -177,7 +189,7 @@ test.serial('Use custom tag format', async t => {
|
||||
t.is(await gitRemoteTagHead(repositoryUrl, nextRelease.gitTag), nextRelease.gitHead);
|
||||
});
|
||||
|
||||
test.serial('Use new gitHead, and recreate release notes if a publish plugin create a commit', async t => {
|
||||
test.serial('Use new gitHead, and recreate release notes if a prepare plugin create a commit', async t => {
|
||||
// Create a git repository, set the current working directory at the root of the repo
|
||||
const repositoryUrl = await gitRepo(true);
|
||||
// Add commits to the master branch
|
||||
@@ -191,10 +203,11 @@ test.serial('Use new gitHead, and recreate release notes if a publish plugin cre
|
||||
const notes = 'Release notes';
|
||||
|
||||
const generateNotes = stub().resolves(notes);
|
||||
const publish1 = stub().callsFake(async () => {
|
||||
const prepare1 = stub().callsFake(async () => {
|
||||
commits = (await gitCommits(['Third'])).concat(commits);
|
||||
});
|
||||
const publish2 = stub().resolves();
|
||||
const prepare2 = stub().resolves();
|
||||
const publish = stub().resolves();
|
||||
|
||||
const options = {
|
||||
branch: 'master',
|
||||
@@ -203,7 +216,8 @@ test.serial('Use new gitHead, and recreate release notes if a publish plugin cre
|
||||
analyzeCommits: stub().resolves(nextRelease.type),
|
||||
verifyRelease: stub().resolves(),
|
||||
generateNotes,
|
||||
publish: [publish1, publish2],
|
||||
prepare: [prepare1, prepare2],
|
||||
publish,
|
||||
success: stub().resolves(),
|
||||
fail: stub().resolves(),
|
||||
};
|
||||
@@ -217,14 +231,17 @@ test.serial('Use new gitHead, and recreate release notes if a publish plugin cre
|
||||
|
||||
t.is(generateNotes.callCount, 2);
|
||||
t.deepEqual(generateNotes.args[0][1].nextRelease, nextRelease);
|
||||
t.is(publish1.callCount, 1);
|
||||
t.deepEqual(publish1.args[0][1].nextRelease, {...nextRelease, ...{notes}});
|
||||
t.is(prepare1.callCount, 1);
|
||||
t.deepEqual(prepare1.args[0][1].nextRelease, {...nextRelease, ...{notes}});
|
||||
|
||||
nextRelease.gitHead = await getGitHead();
|
||||
|
||||
t.deepEqual(generateNotes.secondCall.args[1].nextRelease, {...nextRelease, ...{notes}});
|
||||
t.is(publish2.callCount, 1);
|
||||
t.deepEqual(publish2.args[0][1].nextRelease, {...nextRelease, ...{notes}});
|
||||
t.deepEqual(generateNotes.args[1][1].nextRelease, {...nextRelease, ...{notes}});
|
||||
t.is(prepare2.callCount, 1);
|
||||
t.deepEqual(prepare2.args[0][1].nextRelease, {...nextRelease, ...{notes}});
|
||||
|
||||
t.is(publish.callCount, 1);
|
||||
t.deepEqual(publish.args[0][1].nextRelease, {...nextRelease, ...{notes}});
|
||||
|
||||
// Verify the tag has been created on the local and remote repo and reference the last gitHead
|
||||
t.is(await gitTagHead(nextRelease.gitTag), commits[0].hash);
|
||||
@@ -258,6 +275,7 @@ test.serial('Call all "success" plugins even if one errors out', async t => {
|
||||
verifyConditions: [verifyConditions1, verifyConditions2],
|
||||
analyzeCommits,
|
||||
generateNotes,
|
||||
prepare: stub().resolves(),
|
||||
publish,
|
||||
success: [success1, success2],
|
||||
};
|
||||
@@ -383,6 +401,7 @@ test.serial('Dry-run skips publish and success', async t => {
|
||||
analyzeCommits,
|
||||
verifyRelease,
|
||||
generateNotes,
|
||||
prepare: stub().resolves(),
|
||||
publish,
|
||||
success,
|
||||
};
|
||||
@@ -464,6 +483,7 @@ test.serial('Force a dry-run if not on a CI and "noCi" is not explicitly set', a
|
||||
analyzeCommits,
|
||||
verifyRelease,
|
||||
generateNotes,
|
||||
prepare: stub().resolves(),
|
||||
publish,
|
||||
success,
|
||||
fail: stub().resolves(),
|
||||
@@ -512,6 +532,7 @@ test.serial('Allow local releases with "noCi" option', async t => {
|
||||
analyzeCommits,
|
||||
verifyRelease,
|
||||
generateNotes,
|
||||
prepare: stub().resolves(),
|
||||
publish,
|
||||
success,
|
||||
fail: stub().resolves(),
|
||||
@@ -560,6 +581,7 @@ test.serial('Accept "undefined" value returned by the "generateNotes" plugins',
|
||||
analyzeCommits,
|
||||
verifyRelease,
|
||||
generateNotes,
|
||||
prepare: stub().resolves(),
|
||||
publish,
|
||||
success: stub().resolves(),
|
||||
fail: stub().resolves(),
|
||||
@@ -611,6 +633,7 @@ test.serial('Returns falsy value if not running from the configured branch', asy
|
||||
analyzeCommits: stub().resolves(),
|
||||
verifyRelease: stub().resolves(),
|
||||
generateNotes: stub().resolves(),
|
||||
prepare: stub().resolves(),
|
||||
publish: stub().resolves(),
|
||||
success: stub().resolves(),
|
||||
fail: stub().resolves(),
|
||||
@@ -646,6 +669,7 @@ test.serial('Returns falsy value if there is no relevant changes', async t => {
|
||||
analyzeCommits,
|
||||
verifyRelease,
|
||||
generateNotes,
|
||||
prepare: stub().resolves(),
|
||||
publish,
|
||||
success: stub().resolves(),
|
||||
fail: stub().resolves(),
|
||||
@@ -686,6 +710,7 @@ test.serial('Exclude commits with [skip release] or [release skip] from analysis
|
||||
analyzeCommits,
|
||||
verifyRelease: stub().resolves(),
|
||||
generateNotes: stub().resolves(),
|
||||
prepare: stub().resolves(),
|
||||
publish: stub().resolves(),
|
||||
success: stub().resolves(),
|
||||
fail: stub().resolves(),
|
||||
@@ -844,6 +869,7 @@ test.serial('Get all commits including the ones not in the shallow clone', async
|
||||
analyzeCommits,
|
||||
verifyRelease: stub().resolves(),
|
||||
generateNotes: stub().resolves(notes),
|
||||
prepare: stub().resolves(),
|
||||
publish: stub().resolves(),
|
||||
success: stub().resolves(),
|
||||
fail: stub().resolves(),
|
||||
|
||||
@@ -27,6 +27,7 @@ test('Export default plugins', t => {
|
||||
t.is(typeof plugins.analyzeCommits, 'function');
|
||||
t.is(typeof plugins.verifyRelease, 'function');
|
||||
t.is(typeof plugins.generateNotes, 'function');
|
||||
t.is(typeof plugins.prepare, 'function');
|
||||
t.is(typeof plugins.publish, 'function');
|
||||
t.is(typeof plugins.success, 'function');
|
||||
t.is(typeof plugins.fail, 'function');
|
||||
@@ -49,6 +50,7 @@ test('Export plugins based on config', t => {
|
||||
t.is(typeof plugins.analyzeCommits, 'function');
|
||||
t.is(typeof plugins.verifyRelease, 'function');
|
||||
t.is(typeof plugins.generateNotes, 'function');
|
||||
t.is(typeof plugins.prepare, 'function');
|
||||
t.is(typeof plugins.publish, 'function');
|
||||
t.is(typeof plugins.success, 'function');
|
||||
t.is(typeof plugins.fail, 'function');
|
||||
@@ -79,6 +81,7 @@ test.serial('Export plugins loaded from the dependency of a shareable config mod
|
||||
t.is(typeof plugins.analyzeCommits, 'function');
|
||||
t.is(typeof plugins.verifyRelease, 'function');
|
||||
t.is(typeof plugins.generateNotes, 'function');
|
||||
t.is(typeof plugins.prepare, 'function');
|
||||
t.is(typeof plugins.publish, 'function');
|
||||
t.is(typeof plugins.success, 'function');
|
||||
t.is(typeof plugins.fail, 'function');
|
||||
@@ -106,6 +109,7 @@ test.serial('Export plugins loaded from the dependency of a shareable config fil
|
||||
t.is(typeof plugins.analyzeCommits, 'function');
|
||||
t.is(typeof plugins.verifyRelease, 'function');
|
||||
t.is(typeof plugins.generateNotes, 'function');
|
||||
t.is(typeof plugins.prepare, 'function');
|
||||
t.is(typeof plugins.publish, 'function');
|
||||
t.is(typeof plugins.success, 'function');
|
||||
t.is(typeof plugins.fail, 'function');
|
||||
|
||||
Reference in New Issue
Block a user