1'use strict' 2/* 3Usage: 4 5node scripts/changelog.js [comittish] 6 7Generates changelog entries in our format as best as its able based on 8commits starting at comittish, or if that's not passed, latest. 9 10Ordinarily this is run via the gen-changelog shell script, which appends 11the result to the changelog. 12 13*/ 14const execSync = require('child_process').execSync 15const branch = process.argv[2] || 'origin/latest' 16const log = execSync(`git log --reverse --pretty='format:%h %H%d %s (%aN)%n%b%n---%n' ${branch}...`).toString().split(/\n/) 17 18main() 19 20function shortname (url) { 21 let matched = url.match(/https:\/\/github\.com\/([^/]+\/[^/]+)\/(?:pull|issues)\/(\d+)/) || 22 url.match(/https:\/\/(npm\.community)\/t\/(?:[^/]+\/)(\d+)/) 23 if (!matched) return false 24 let repo = matched[1] 25 let id = matched[2] 26 if (repo !== 'npm/cli') { 27 return `${repo}#${id}` 28 } else { 29 return `#${id}` 30 } 31} 32 33function printCommit (c) { 34 console.log(`* [\`${c.shortid}\`](https://github.com/npm/cli/commit/${c.fullid})`) 35 if (c.fixes) { 36 let label = shortname(c.fixes) 37 if (label) { 38 console.log(` [${label}](${c.fixes})`) 39 } else { 40 console.log(` [npm.community#${c.fixes}](https://npm.community/t/${c.fixes})`) 41 } 42 } else if (c.prurl) { 43 let label = shortname(c.prurl) 44 if (label) { 45 console.log(` [${label}](${c.prurl})`) 46 } else { 47 console.log(` [#](${c.prurl})`) 48 } 49 } 50 let msg = c.message 51 .replace(/^\s+/mg, '') 52 .replace(/^[-a-z]+: /, '') 53 .replace(/^/mg, ' ') 54 .replace(/\n$/, '') 55 // backtickify package@version 56 .replace(/^(\s*[^@\s]+@\d+[.]\d+[.]\d+)(\s*\S)/g, '$1:$2') 57 .replace(/\b([^@\s]+@\d+[.]\d+[.]\d+)\b/g, '`$1`') 58 // linkify commitids 59 .replace(/\b([a-f0-9]{7,8})\b/g, '[`$1`](https://github.com/npm/cli/commit/$1)') 60 .replace(/\b#(\d+)\b/g, '[#$1](https://npm.community/t/$1)') 61 console.log(msg) 62 if (c.credit) { 63 c.credit.forEach(function (credit) { 64 console.log(` ([@${credit}](https://github.com/${credit}))`) 65 }) 66 } else { 67 console.log(` ([@${c.author}](https://github.com/${c.author}))`) 68 } 69} 70 71function main () { 72 let commit 73 log.forEach(function (line) { 74 line = line.replace(/\r/g, '') 75 let m 76 /* eslint no-cond-assign:0 */ 77 if (/^---$/.test(line)) { 78 printCommit(commit) 79 } else if (m = line.match(/^([a-f0-9]{7,10}) ([a-f0-9]+) (?:[(]([^)]+)[)] )?(.*?) [(](.*?)[)]/)) { 80 commit = { 81 shortid: m[1], 82 fullid: m[2], 83 branch: m[3], 84 message: m[4], 85 author: m[5], 86 prurl: null, 87 fixes: null, 88 credit: null 89 } 90 } else if (m = line.match(/^PR-URL: (.*)/)) { 91 commit.prurl = m[1] 92 } else if (m = line.match(/^Credit: @(.*)/)) { 93 if (!commit.credit) commit.credit = [] 94 commit.credit.push(m[1]) 95 } else if (m = line.match(/^Fixes: #?(.*)/)) { 96 commit.fixes = m[1] 97 } else if (m = line.match(/^Reviewed-By: @(.*)/)) { 98 commit.reviewed = m[1] 99 } else if (/\S/.test(line)) { 100 commit.message += `\n${line}` 101 } 102 }) 103} 104