Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
071dccea4b | ||
|
|
eb22f9998d | ||
|
|
5847514fcc | ||
|
|
a39ccb8f6c | ||
|
|
0862480cf0 |
@@ -21,6 +21,8 @@
|
||||
- [Travis CI](docs/recipes/travis.md)
|
||||
- [Travis CI with build stages](docs/recipes/travis-build-stages.md)
|
||||
- [GitLab CI](docs/recipes/gitlab-ci.md)
|
||||
- [Git hosted services](docs/recipes/README.md)
|
||||
- [Git authentication with SSH keys](docs/recipes/git-auth-ssh-keys.md)
|
||||
- [Package managers and languages](docs/recipes/README.md)
|
||||
|
||||
## Developer guide
|
||||
|
||||
@@ -124,6 +124,20 @@ Yes, the publishing to the npm registry can be disabled with the [`npmPublish`](
|
||||
|
||||
See the [`@semantic-release/npm`](https://github.com/semantic-release/npm#semantic-releasenpm) plugin documentation for more details.
|
||||
|
||||
## How can I revert a release?
|
||||
|
||||
If you have introduced a breaking bug in a release you have 2 options:
|
||||
- If you have a fix immediately ready, commit and push it (or merge it via a pull request) to the release branch
|
||||
- Otherwise [revert the commit](https://git-scm.com/docs/git-revert) that introduced the bug and push the revert commit (or merge it via a pull request) to the release branch
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
**Note**: If you are using the default [Angular Commit Message Conventions](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines) be aware that it uses a different revert commit format than the standard one created by [git revert](https://git-scm.com/docs/git-revert), contrary to what is [claimed in the convention](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#revert). Therefore, if you revert a commit with [`git revert`](https://git-scm.com/docs/git-revert), use the [`--edit` option](https://git-scm.com/docs/git-revert#git-revert---edit) to format the message according to the [Angular revert commit message format](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#revert). See [conventional-changelog/conventional-changelog#348](https://github.com/conventional-changelog/conventional-changelog/issues/348) for more details.
|
||||
|
||||
## Can I use `.npmrc` options?
|
||||
|
||||
Yes, all the [npm configuration options](https://docs.npmjs.com/misc/config) are supported via the [`.npmrc`](https://docs.npmjs.com/files/npmrc) file at the root of your repository.
|
||||
|
||||
@@ -59,7 +59,7 @@ async function run(options, plugins) {
|
||||
try {
|
||||
await verifyAuth(options.repositoryUrl, options.branch);
|
||||
} catch (err) {
|
||||
if (!(await isBranchUpToDate(options.repositoryUrl, options.branch))) {
|
||||
if (!(await isBranchUpToDate(options.branch))) {
|
||||
logger.log(
|
||||
"The local branch %s is behind the remote one, therefore a new version won't be published.",
|
||||
options.branch
|
||||
@@ -103,7 +103,9 @@ async function run(options, plugins) {
|
||||
logger.log('Call plugin %s', 'generate-notes');
|
||||
const notes = await plugins.generateNotes(generateNotesParam);
|
||||
logger.log('Release note for version %s:\n', nextRelease.version);
|
||||
process.stdout.write(`${marked(notes)}\n`);
|
||||
if (notes) {
|
||||
process.stdout.write(`${marked(notes)}\n`);
|
||||
}
|
||||
} else {
|
||||
logger.log('Call plugin %s', 'generateNotes');
|
||||
nextRelease.notes = await plugins.generateNotes(generateNotesParam);
|
||||
|
||||
+2
-3
@@ -145,15 +145,14 @@ async function verifyTagName(tagName) {
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return {Boolean} `true` is the HEAD of the current local branch is the same as the HEAD of the remote branch, falsy otherwise.
|
||||
*/
|
||||
async function isBranchUpToDate(repositoryUrl, branch) {
|
||||
async function isBranchUpToDate(branch) {
|
||||
try {
|
||||
return await isRefInHistory(
|
||||
(await execa.stdout('git', ['ls-remote', '--heads', repositoryUrl, branch])).match(/^(\w+)?/)[1]
|
||||
(await execa.stdout('git', ['ls-remote', '--heads', 'origin', branch])).match(/^(\w+)?/)[1]
|
||||
);
|
||||
} catch (err) {
|
||||
debug(err);
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@
|
||||
"git-log-parser": "^1.2.0",
|
||||
"git-url-parse": "^9.0.0",
|
||||
"hook-std": "^1.0.1",
|
||||
"hosted-git-info": "^2.6.0",
|
||||
"hosted-git-info": "^2.7.1",
|
||||
"lodash": "^4.17.4",
|
||||
"marked": "^0.4.0",
|
||||
"marked-terminal": "^3.0.0",
|
||||
|
||||
+6
-6
@@ -206,11 +206,11 @@ test.serial('Throws error if obtaining the tags fails', async t => {
|
||||
});
|
||||
|
||||
test.serial('Return "true" if repository is up to date', async t => {
|
||||
const repositoryUrl = await gitRepo(true);
|
||||
await gitRepo(true);
|
||||
await gitCommits(['First']);
|
||||
await gitPush();
|
||||
|
||||
t.true(await isBranchUpToDate(repositoryUrl, 'master'));
|
||||
t.true(await isBranchUpToDate('master'));
|
||||
});
|
||||
|
||||
test.serial('Return falsy if repository is not up to date', async t => {
|
||||
@@ -220,21 +220,21 @@ test.serial('Return falsy if repository is not up to date', async t => {
|
||||
await gitCommits(['Second']);
|
||||
await gitPush();
|
||||
|
||||
t.true(await isBranchUpToDate(repositoryUrl, 'master'));
|
||||
t.true(await isBranchUpToDate('master'));
|
||||
|
||||
await gitShallowClone(repositoryUrl);
|
||||
await gitCommits(['Third']);
|
||||
await gitPush();
|
||||
process.chdir(repoDir);
|
||||
|
||||
t.falsy(await isBranchUpToDate(repositoryUrl, 'master'));
|
||||
t.falsy(await isBranchUpToDate('master'));
|
||||
});
|
||||
|
||||
test.serial('Return "true" if local repository is ahead', async t => {
|
||||
const repositoryUrl = await gitRepo(true);
|
||||
await gitRepo(true);
|
||||
await gitCommits(['First']);
|
||||
await gitPush();
|
||||
await gitCommits(['Second']);
|
||||
|
||||
t.true(await isBranchUpToDate(repositoryUrl, 'master'));
|
||||
t.true(await isBranchUpToDate('master'));
|
||||
});
|
||||
|
||||
@@ -520,6 +520,43 @@ test.serial('Force a dry-run if not on a CI and "noCi" is not explicitly set', a
|
||||
t.is(success.callCount, 0);
|
||||
});
|
||||
|
||||
test.serial('Dry-run does not print changelog if "generateNotes" return "undefined"', 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
|
||||
await gitCommits(['First']);
|
||||
// Create the tag corresponding to version 1.0.0
|
||||
await gitTagVersion('v1.0.0');
|
||||
// Add new commits to the master branch
|
||||
await gitCommits(['Second']);
|
||||
await gitPush();
|
||||
|
||||
const nextRelease = {type: 'major', version: '2.0.0', gitHead: await getGitHead(), gitTag: 'v2.0.0'};
|
||||
const analyzeCommits = stub().resolves(nextRelease.type);
|
||||
const generateNotes = stub().resolves();
|
||||
|
||||
const options = {
|
||||
dryRun: true,
|
||||
branch: 'master',
|
||||
repositoryUrl,
|
||||
verifyConditions: false,
|
||||
analyzeCommits,
|
||||
verifyRelease: false,
|
||||
generateNotes,
|
||||
prepare: false,
|
||||
publish: false,
|
||||
success: false,
|
||||
};
|
||||
|
||||
const semanticRelease = proxyquire('..', {
|
||||
'./lib/logger': t.context.logger,
|
||||
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
|
||||
});
|
||||
t.truthy(await semanticRelease(options));
|
||||
|
||||
t.deepEqual(t.context.log.args[t.context.log.args.length - 1], ['Release note for version %s:\n', '2.0.0']);
|
||||
});
|
||||
|
||||
test.serial('Allow local releases with "noCi" option', async t => {
|
||||
// Create a git repository, set the current working directory at the root of the repo
|
||||
const repositoryUrl = await gitRepo(true);
|
||||
|
||||
Reference in New Issue
Block a user