UNPKG

github-post-release

Version:

Forms release changelog and posts a note to each referenced issues after semantic release publishes a new module version

187 lines (157 loc) 4.71 kB
'use strict' const bluebird = require('bluebird') const url = require('url') const GitHubApi = require('github') const parseGithubUrl = require('parse-github-repo-url') const debug = require('debug')('github-post-release') const newPublicCommits = require('new-public-commits').newPublicCommits const R = require('ramda') const pluralize = require('pluralize') const join = require('path').join const utils = require('./utils') const formChangelog = require('simple-changelog') const la = require('lazy-ass') const is = require('check-more-types') // :: -> [issue numbers] function getClosedIssues () { return newPublicCommits().then(utils.commitsToIssues) } function getGitHub (githubUrl, token) { if (!token) { throw new Error('Missing gh token') } const githubConfig = githubUrl ? url.parse(githubUrl) : {} let protocol = (githubConfig.protocol || '').split(':')[0] || null if (protocol === 'git+https') { debug('switching github protocol from %s to https', protocol) protocol = 'https' } let host = githubConfig.hostname if (host === 'github.com') { // https://github.com/mikedeboer/node-github/issues/544 debug('using api.github.com host') host = 'api.github.com' } const config = { version: '3.0.0', port: githubConfig.port, protocol, host } debug('github config') debug(config) const github = new GitHubApi(config) github.authenticate({ type: 'token', token: token }) const createComment = bluebird.promisify(github.issues.createComment) return createComment } function getGitHubToken () { return process.env.GH_TOKEN } function commentOnIssues (repoUrl, message, debugMode, issues) { if (!issues) { return Promise.resolve() } if (R.isEmpty(issues)) { debug('no issues to comment on') return Promise.resolve() } const createComment = debugMode ? () => Promise.resolve() : getGitHub(repoUrl, getGitHubToken()) const parsed = parseGithubUrl(repoUrl) const owner = parsed[0] const repo = parsed[1] debug( 'commenting on %d %s: %j', issues.length, pluralize('issues', issues.length), issues ) const onPosted = number => () => { console.log('posted comment for issue', number) } const onFailed = number => err => { console.error('Could not comment on issue', number) console.error(err) } const commentPromises = issues.map(number => createComment({ owner, repo, number, body: message }) .then(onPosted(number)) .catch(onFailed(number)) ) return bluebird.all(commentPromises) } // should call "callback" function with (err, changelog) function githubPostRelease (pluginConfig, config, callback) { // debug('custom plugin config', pluginConfig) // debug('config parameter', config) // normalize message type let messageType = pluginConfig.type || 'npm' if (messageType === 'publish') { messageType = 'npm' } la( is.unemptyString(messageType), 'missing message type to form', pluginConfig ) debug('message type "%s"', messageType) const pkg = config.pkg const repoUrl = pkg.repository.url const parsedRepo = parseGithubUrl(repoUrl) debug('published version %s', pkg.version) debug('repo url %s', repoUrl) debug('debug mode?', config.debug) const onSuccess = changelog => { debug('✅ all done, with issue message:') debug(message) debug('changelog:') debug(changelog) callback(null, changelog) } const onFailure = err => { console.error('🔥 failed with error') console.error(err) callback(err) } const commentingFailed = err => { console.error('😟 commenting on related issues failed') console.error(err) } const generateChangeLog = () => { debug('generate changelog for release version %s', pkg.version) return formChangelog(pkg.version) } const owner = parsedRepo[0] const repo = parsedRepo[1] const message = utils.formMessage( messageType, owner, repo, pkg.name, pkg.version ) getClosedIssues() .then(R.partial(commentOnIssues, [repoUrl, message, config.debug])) .catch(commentingFailed) .then(generateChangeLog) .then(onSuccess, onFailure) } module.exports = githubPostRelease if (!module.parent) { console.log('demo run') const pkg = require(join(__dirname, '..', 'package.json')) const generateNotes = R.path(['release', 'generateNotes'])(pkg) const config = R.is(Object, generateNotes) ? generateNotes : {} debug('config') debug(config) githubPostRelease(config, { pkg: pkg }, (err, changelog) => { console.log('finished with') console.log('err?', err) console.log('changelog\n' + changelog) }) }