feat(plugins): add getLastRelease hook

The code to determine the last-release is now in its own repository: https://github.com/semantic-release/last-release-npm
One can overwrite that behavior by defining a "getLastRelease" plugin. This way
one can decouple semantic-release from npm, e.g. by implementing a git-tag
based version. This is already worked on: https://github.com/semantic-release/last-release-git-tag

Closes #56
This commit is contained in:
Ari Porad 2015-08-17 16:31:18 -07:00 committed by Stephan Bönnemann
parent 77349fcdf1
commit 7ceac76689
6 changed files with 14 additions and 111 deletions

View File

@ -24,12 +24,12 @@
"@semantic-release/commit-analyzer": "^2.0.0",
"@semantic-release/condition-travis": "^4.0.0",
"@semantic-release/error": "^1.0.0",
"@semantic-release/last-release-npm": "^1.1.1",
"@semantic-release/release-notes-generator": "^2.0.0",
"git-head": "^1.2.1",
"github": "^0.2.4",
"lodash": "^3.9.3",
"nopt": "^3.0.3",
"npm-registry-client": "^6.4.0",
"npmconf": "^2.1.2",
"npmlog": "^1.2.1",
"parse-github-repo-url": "^1.0.0",

View File

@ -1,26 +0,0 @@
const SemanticReleaseError = require('@semantic-release/error')
const npmlog = require('npmlog')
const RegClient = require('npm-registry-client')
module.exports = function ({pkg, npm}, cb) {
npmlog.level = npm.loglevel || 'error'
const client = new RegClient({log: npmlog})
client.get(`${npm.registry}${pkg.name.replace('/', '%2F')}`, {
auth: npm.auth
}, (err, data) => {
if (err && err.statusCode === 404) return cb(null, {})
if (err) return cb(err)
const version = data['dist-tags'][npm.tag]
if (!version) return cb(new SemanticReleaseError(`There is no release with the dist-tag "${npm.tag}" yet. Tag a version first.`, 'ENODISTTAG'))
cb(null, {
version,
gitHead: data.versions[version].gitHead,
tag: npm.tag
})
})
}

View File

@ -5,7 +5,8 @@ let exports = module.exports = function (options) {
analyzeCommits: exports.normalize(options.analyzeCommits, '@semantic-release/commit-analyzer'),
generateNotes: exports.normalize(options.generateNotes, '@semantic-release/release-notes-generator'),
verifyConditions: exports.normalize(options.verifyConditions, '@semantic-release/condition-travis'),
verifyRelease: exports.normalize(options.verifyRelease, './plugin-noop')
verifyRelease: exports.normalize(options.verifyRelease, './plugin-noop'),
getLastRelease: exports.normalize(options.getLastRelease, '@semantic-release/last-release-npm')
}
}

View File

@ -2,14 +2,14 @@ const _ = require('lodash')
const auto = require('run-auto')
const semver = require('semver')
const getLastRelease = require('./lib/last-release')
const getCommits = require('./lib/commits')
const getType = require('./lib/type')
module.exports = function (config, cb) {
const {plugins} = config
const { plugins } = config
auto({
lastRelease: getLastRelease.bind(null, config),
lastRelease: plugins.getLastRelease.bind(null, config),
commits: ['lastRelease', (cb, results) => {
getCommits(_.assign({
lastRelease: results.lastRelease

View File

@ -1,79 +0,0 @@
const { defaults } = require('lodash')
const test = require('tap').test
require('../mocks/registry')
const lastRelease = require('../../dist/lib/last-release')
const npm = {
registry: 'http://registry.npmjs.org/',
tag: 'latest'
}
test('last release from registry', (t) => {
t.plan(5)
t.test('get release from package name', (tt) => {
lastRelease({
pkg: {name: 'available'},
npm
}, (err, release) => {
tt.error(err)
tt.is(release.version, '1.33.7', 'version')
tt.is(release.gitHead, 'HEAD', 'gitHead')
tt.is(release.tag, 'latest', 'dist-tag')
tt.end()
})
})
t.test('get release from a tagged package\'s name', (tt) => {
lastRelease({
pkg: {name: 'tagged'},
npm: defaults({tag: 'foo'}, npm)
}, (err, release) => {
tt.error(err)
tt.is(release.version, '0.8.15', 'version')
tt.is(release.gitHead, 'bar', 'gitHead')
tt.is(release.tag, 'foo', 'dist-tag')
tt.end()
})
})
t.test('get error from an untagged package\'s name', (tt) => {
lastRelease({
pkg: {name: 'untagged'},
npm: defaults({tag: 'bar'}, npm)
}, (err) => {
tt.is(err.code, 'ENODISTTAG', 'error')
tt.end()
})
})
t.test('get release from scoped package name', (tt) => {
lastRelease({
pkg: {name: '@scoped/available'},
npm
}, (err, release) => {
tt.error(err)
tt.is(release.version, '1.33.7', 'version')
tt.is(release.gitHead, 'HEAD', 'gitHead')
tt.is(release.tag, 'latest', 'dist-tag')
tt.end()
})
})
t.test('get nothing from not yet published package name', (tt) => {
lastRelease({
pkg: {name: 'unavailable'},
npm
}, (err, release) => {
tt.error(err)
tt.is(release.version, undefined, 'no version')
tt.end()
})
})
})

View File

@ -6,9 +6,16 @@ const pre = proxyquire('../../dist/pre', {
'child_process': require('../mocks/child-process')
})
const versions = {
available: '1.0.0'
}
const plugins = {
verifyRelease: (release, cb) => cb(null, release),
analyzeCommits: (commits, cb) => cb(null, 'major')
analyzeCommits: (commits, cb) => cb(null, 'major'),
getLastRelease: ({ pkg }, cb) => {
cb(null, { version: versions[pkg.name] || null, gitHead: 'HEAD' })
}
}
const npm = {