fix(commits): add helpful error when lastRelease not in history
Closes #61, Closes #50
This commit is contained in:
parent
a2d6db2ce5
commit
5cc7da6035
@ -1,9 +1,47 @@
|
|||||||
const { exec } = require('child_process')
|
const { exec } = require('child_process')
|
||||||
|
|
||||||
module.exports = function ({lastRelease}, cb) {
|
const log = require('npmlog')
|
||||||
|
|
||||||
|
const SemanticReleaseError = require('@semantic-release/error')
|
||||||
|
|
||||||
|
module.exports = function ({lastRelease, branch}, cb) {
|
||||||
const from = lastRelease.gitHead
|
const from = lastRelease.gitHead
|
||||||
const range = (from ? from + '..' : '') + 'HEAD'
|
const range = (from ? from + '..' : '') + 'HEAD'
|
||||||
|
|
||||||
|
if (!from) return extract()
|
||||||
|
|
||||||
|
exec(`git branch --contains ${from}`, (err, stdout) => {
|
||||||
|
if (err) return cb(err)
|
||||||
|
let inHistory = false
|
||||||
|
|
||||||
|
const branches = stdout.split('\n')
|
||||||
|
.map((result) => {
|
||||||
|
if (branch === result.replace('*', '').trim()) {
|
||||||
|
inHistory = true
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return result.trim()
|
||||||
|
})
|
||||||
|
.filter(branch => !!branch)
|
||||||
|
|
||||||
|
if (!inHistory) {
|
||||||
|
log.error('commits',
|
||||||
|
`The commit the last release of this package was derived from is no longer
|
||||||
|
in the direct history of the "${branch}" branch.
|
||||||
|
This means semantic-release can not extract the commits between now and then.
|
||||||
|
This is usually caused by force pushing or releasing from an unrelated branch.
|
||||||
|
You can recover from this error by publishing manually or restoring
|
||||||
|
the commit "${from}".` + (branches.length ?
|
||||||
|
`\nHere is a list of branches that still contain the commit in question: \n * ${branches.join('\n * ')}` :
|
||||||
|
''
|
||||||
|
))
|
||||||
|
return cb(new SemanticReleaseError('Commit not in history', 'ENOTINHISTORY'))
|
||||||
|
}
|
||||||
|
|
||||||
|
extract()
|
||||||
|
})
|
||||||
|
|
||||||
|
function extract () {
|
||||||
exec(
|
exec(
|
||||||
`git log -E --format=%H==SPLIT==%B==END== ${range}`,
|
`git log -E --format=%H==SPLIT==%B==END== ${range}`,
|
||||||
(err, stdout) => {
|
(err, stdout) => {
|
||||||
@ -23,3 +61,4 @@ module.exports = function ({lastRelease}, cb) {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -5,6 +5,10 @@ const rawCommits = [
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
exec: (command, cb) => {
|
exec: (command, cb) => {
|
||||||
|
if (/contains/.test(command)) {
|
||||||
|
return cb(null, `whatever\nmaster\n`)
|
||||||
|
}
|
||||||
|
|
||||||
cb(
|
cb(
|
||||||
null,
|
null,
|
||||||
/\.\.HEAD/.test(command) ?
|
/\.\.HEAD/.test(command) ?
|
||||||
|
@ -7,7 +7,7 @@ const commits = proxyquire('../../dist/lib/commits', {
|
|||||||
|
|
||||||
test('commits since last release', (t) => {
|
test('commits since last release', (t) => {
|
||||||
t.test('get all commits', (tt) => {
|
t.test('get all commits', (tt) => {
|
||||||
commits({lastRelease: {}}, (err, commits) => {
|
commits({lastRelease: {}, branch: 'master'}, (err, commits) => {
|
||||||
tt.error(err)
|
tt.error(err)
|
||||||
tt.is(commits.length, 2, 'all commits')
|
tt.is(commits.length, 2, 'all commits')
|
||||||
tt.is(commits[0].hash, 'hash-one', 'parsed hash')
|
tt.is(commits[0].hash, 'hash-one', 'parsed hash')
|
||||||
@ -18,7 +18,7 @@ test('commits since last release', (t) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.test('get commits since hash', (tt) => {
|
t.test('get commits since hash', (tt) => {
|
||||||
commits({lastRelease: {gitHead: 'hash'}}, (err, commits) => {
|
commits({lastRelease: {gitHead: 'hash'}, branch: 'master'}, (err, commits) => {
|
||||||
tt.error(err)
|
tt.error(err)
|
||||||
tt.is(commits.length, 1, 'specified commits')
|
tt.is(commits.length, 1, 'specified commits')
|
||||||
tt.is(commits[0].hash, 'hash-one', 'parsed hash')
|
tt.is(commits[0].hash, 'hash-one', 'parsed hash')
|
||||||
@ -28,5 +28,13 @@ test('commits since last release', (t) => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.test('get commits since hash', (tt) => {
|
||||||
|
commits({lastRelease: {gitHead: 'notinhistory'}, branch: 'notmaster'}, (err, commits) => {
|
||||||
|
tt.ok(err)
|
||||||
|
tt.is(err.code, 'ENOTINHISTORY')
|
||||||
|
tt.end()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
t.end()
|
t.end()
|
||||||
})
|
})
|
||||||
|
@ -3,8 +3,10 @@ const proxyquire = require('proxyquire')
|
|||||||
|
|
||||||
require('../mocks/registry')
|
require('../mocks/registry')
|
||||||
const pre = proxyquire('../../dist/pre', {
|
const pre = proxyquire('../../dist/pre', {
|
||||||
|
'./lib/commits': proxyquire('../../dist/lib/commits', {
|
||||||
'child_process': require('../mocks/child-process')
|
'child_process': require('../mocks/child-process')
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
|
||||||
const versions = {
|
const versions = {
|
||||||
available: '1.0.0'
|
available: '1.0.0'
|
||||||
@ -21,7 +23,6 @@ const plugins = {
|
|||||||
const npm = {
|
const npm = {
|
||||||
registry: 'http://registry.npmjs.org/',
|
registry: 'http://registry.npmjs.org/',
|
||||||
tag: 'latest'
|
tag: 'latest'
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test('full pre run', (t) => {
|
test('full pre run', (t) => {
|
||||||
@ -29,6 +30,7 @@ test('full pre run', (t) => {
|
|||||||
tt.plan(3)
|
tt.plan(3)
|
||||||
|
|
||||||
pre({
|
pre({
|
||||||
|
branch: 'master',
|
||||||
npm,
|
npm,
|
||||||
pkg: {name: 'available'},
|
pkg: {name: 'available'},
|
||||||
plugins
|
plugins
|
||||||
@ -43,6 +45,7 @@ test('full pre run', (t) => {
|
|||||||
tt.plan(3)
|
tt.plan(3)
|
||||||
|
|
||||||
pre({
|
pre({
|
||||||
|
branch: 'master',
|
||||||
npm,
|
npm,
|
||||||
pkg: {name: 'unavailable'},
|
pkg: {name: 'unavailable'},
|
||||||
plugins
|
plugins
|
||||||
|
Loading…
x
Reference in New Issue
Block a user