Compare commits

...
5 Commits
Author SHA1 Message Date
Pierre Vanduynslager 071dccea4b fix: use unauthenticated URL to check if branch is up to date
In case the authentication token provided is unauthorized the call to `isBranchUpToDate` will fail due to lack of read permission if that URL is used. As a result the error about outdated local branch will be reported instead of the one about missing permission.
By using the original (unauthenticated) URL `isBranchUpToDate` shouldn't fail due to permission as it requires only read permissions, that are necessarly present as the CI wass able to clone the repo.
2018-07-10 13:07:00 -04:00
Pierre Vanduynslager eb22f9998d docs: FAQ for reverting a release 2018-07-10 11:52:39 -04:00
Pierre Vanduynslager 5847514fcc fix: allow empty release notes in dry-run mode 2018-07-10 11:42:22 -04:00
Pierre Vanduynslager a39ccb8f6c docs: add missing link in GitBook summary 2018-07-08 01:16:21 -04:00
Pierre VanduynslagerandGitHub 0862480cf0 fix(package): update hosted-git-info to version 2.7.1 2018-07-06 21:47:50 -04:00
7 changed files with 66 additions and 12 deletions
+2
View File
@@ -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
+14
View File
@@ -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.
+4 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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'));
});
+37
View File
@@ -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);