diff --git a/src/github.js b/src/github.js index 0240981..98a3e56 100755 --- a/src/github.js +++ b/src/github.js @@ -65,5 +65,32 @@ module.exports = { number, labels: Array.isArray(labels) ? labels : [labels] }); + }, + + createRelease(payload, {tag_name, target_commitish, name, body, draft, prerelease}) { + const owner = payload.repository.owner.login; + const repo = payload.repository.name; + + github.repos.createRelease({ + owner, + repo, + tag_name, + target_commitish, + name, + body, + draft, + prerelease + }); + }, + + getReleaseByTag(payload, {tag_name}) { + const owner = payload.repository.owner.login; + const repo = payload.repository.name; + + return github.repos.getReleaseByTag({ + owner, + repo, + tag: tag_name + }); } }; diff --git a/src/modules/issues/autoReleaseNote.js b/src/modules/issues/autoReleaseNote.js index 7909dbb..265f42a 100644 --- a/src/modules/issues/autoReleaseNote.js +++ b/src/modules/issues/autoReleaseNote.js @@ -3,15 +3,79 @@ * @author xuexb */ -const {getReleaseByTag} = require('../../github'); -const {cloneRepo, getTags} = require('../../utils'); +const {getReleaseByTag, createRelease} = require('../../github'); +const {cloneRepo, getTags, getFirstCommitHash, getCommitLog} = require('../../utils'); + +const RELEASE_CHANGE_MAP = { + document: 'docs', + feature: 'feat', + bugfix: 'fix', + close: 'close' +}; function autoReleaseNote(on) { on('create_tag', ({payload, repo}) => { - const repoDir = cloneRepo(payload.repository.clone_url, repo); - const tags = getTags(repoDir); + getReleaseByTag(payload, { + tag_name: payload.ref + }).then(() => {}, () => { + const repoDir = cloneRepo({ + url: payload.repository.clone_url, + repo + }); + const tags = getTags({ + dir: repoDir + }); + const after = tags[0]; + const before = tags.length > 1 ? tags[1] : getFirstCommitHash({ + dir: repoDir + }); + const log = getCommitLog({ + dir: repoDir, + before, + after + }); - console.log(repoDir, tags); + const hash = getCommitLog({ + dir: repoDir, + before, + after, + html_url: payload.repository.html_url, + hash: true + }); + + const changes = Object.keys(RELEASE_CHANGE_MAP).map(title => { + return { + title, + data: log.filter(log => log.indexOf(`- ${RELEASE_CHANGE_MAP[title]}:`) === 0) + } + }).filter(v => v.data.length); + + let body = []; + + if (changes.length) { + body.push('## Notable changes\n'); + changes.forEach(v => { + body.push([ + `- ${v.title}` + ]); + + v.data.forEach(line => body.push(' ' + line)); + }); + } + + if (hash.length) { + body.push('\n## Commits\n'); + body = body.concat(hash); + } + + if (body.length) { + createRelease(payload, { + tag_name: payload.ref, + name: `${payload.ref} @${payload.repository.owner.login}`, + body: body.join('\n') + }); + } + }); }); } diff --git a/src/utils.js b/src/utils.js index 50a38f0..04475dc 100755 --- a/src/utils.js +++ b/src/utils.js @@ -1,3 +1,4 @@ +const format = require('string-template'); const path = require('path'); const fs = require('fs'); const crypto = require('crypto'); @@ -34,13 +35,23 @@ const utils = { } }, - getActionLog({dir, before, after, action}) { - return execSync(`cd ${dir} && FORMAT="- %s, by @%cn" -git log ${before}..${after} --no-merges --pretty=format:"$FORMAT" | grep ${action}`).toString(); - + getFirstCommitHash({dir}) { + return execSync(`cd ${dir} && git log --oneline --pretty=format:"%h"`).toString() + .split(/\n+/).slice(-1)[0]; }, - cloneRepo(url, repo) { + getCommitLog(options) { + const shell = [ + 'cd {dir}', + options.hash + ? 'git log {before}..{after} --no-merges --pretty=format:"- [%h]({html_url}/commit/%H) - %s, by @%cn"' + : 'git log {before}..{after} --no-merges --pretty=format:"- %s, by @%cn"' + ].join(' && '); + + return execSync(format(shell, options)).toString().split(/\n+/); + }, + + cloneRepo({url, repo}) { const repoDir = path.resolve(__dirname, '../github/', repo); if (!utils.isDirectory(repoDir)) { @@ -52,7 +63,7 @@ git log ${before}..${after} --no-merges --pretty=format:"$FORMAT" | grep ${actio return repoDir; }, - getTags(dir) { + getTags({dir}) { return execSync(`cd ${dir} && git tag -l`).toString().split(/\n+/).filter(tag => !!tag).reverse(); } };