2020-07-28 14:07:45 +02:00
|
|
|
// section -> label
|
|
|
|
const sectionLabelMap = {
|
|
|
|
'Core Changes': 'type: next',
|
2021-11-21 13:11:54 +01:00
|
|
|
'Documentation Changes': 'area: documentation',
|
|
|
|
'Example Changes': 'area: examples',
|
2020-07-28 14:07:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const fallbackSection = 'Misc Changes'
|
|
|
|
|
|
|
|
// --------------------------------------------------
|
|
|
|
|
2021-05-07 19:53:38 +02:00
|
|
|
const prNumberRegex = /\(#([-0-9]+)\)$/
|
2020-07-28 14:07:45 +02:00
|
|
|
|
2020-07-28 15:05:26 +02:00
|
|
|
const getCommitPullRequest = async (commit, github) => {
|
2020-07-28 14:07:45 +02:00
|
|
|
const match = prNumberRegex.exec(commit.title)
|
|
|
|
|
|
|
|
if (!match) {
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
|
|
|
const number = parseInt(match[1], 10)
|
|
|
|
|
2020-07-28 15:05:26 +02:00
|
|
|
if (!number) {
|
2020-07-28 14:07:45 +02:00
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
2020-07-28 15:05:26 +02:00
|
|
|
const { data } = await github.connection.pullRequests.get({
|
|
|
|
owner: github.repoDetails.user,
|
|
|
|
repo: github.repoDetails.repo,
|
|
|
|
number,
|
|
|
|
})
|
|
|
|
|
|
|
|
return data
|
2020-07-28 14:07:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const getSectionForPullRequest = (pullRequest) => {
|
|
|
|
const { labels } = pullRequest
|
|
|
|
|
|
|
|
// sections defined first will take priority
|
|
|
|
for (const [section, label] of Object.entries(sectionLabelMap)) {
|
|
|
|
if (labels.some((prLabel) => prLabel.name === label)) {
|
|
|
|
return section
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
|
|
|
const groupByLabels = async (commits, github) => {
|
|
|
|
// Initialize the sections object with empty arrays
|
|
|
|
const sections = Object.keys(sectionLabelMap).reduce((sections, section) => {
|
|
|
|
sections[section] = []
|
|
|
|
return sections
|
|
|
|
}, {})
|
|
|
|
sections.__fallback = []
|
|
|
|
|
|
|
|
for (const commit of commits) {
|
|
|
|
const pullRequest = await getCommitPullRequest(commit, github)
|
|
|
|
|
|
|
|
if (pullRequest) {
|
|
|
|
const section = getSectionForPullRequest(pullRequest)
|
|
|
|
|
|
|
|
if (section) {
|
|
|
|
// Add the change to the respective section
|
|
|
|
sections[section].push({
|
|
|
|
title: pullRequest.title,
|
|
|
|
number: pullRequest.number,
|
|
|
|
})
|
|
|
|
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// No section found, add it to the fallback section
|
|
|
|
sections.__fallback.push({
|
|
|
|
title: pullRequest.title,
|
|
|
|
number: pullRequest.number,
|
|
|
|
})
|
|
|
|
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// No Pull Request found, add it to the fallback section but without the number
|
|
|
|
sections.__fallback.push({
|
|
|
|
title: commit.title,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return sections
|
|
|
|
}
|
|
|
|
|
2020-08-07 09:34:50 +02:00
|
|
|
function cleanupPRTitle(title) {
|
|
|
|
if (title.startsWith('[Docs] ')) {
|
|
|
|
return title.replace('[Docs] ', '')
|
|
|
|
}
|
|
|
|
|
|
|
|
return title
|
|
|
|
}
|
|
|
|
|
2020-07-28 14:07:45 +02:00
|
|
|
const buildChangelog = (sections, authors) => {
|
|
|
|
let text = ''
|
|
|
|
|
|
|
|
for (const section in sections) {
|
|
|
|
const changes = sections[section]
|
|
|
|
|
|
|
|
// No changes in this section? Don't render it
|
|
|
|
if (changes.length === 0) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
const title = section === '__fallback' ? fallbackSection : section
|
|
|
|
text += `### ${title}\n\n`
|
|
|
|
|
|
|
|
for (const change of changes) {
|
|
|
|
const numberText = change.number != null ? `: #${change.number}` : ''
|
|
|
|
|
2020-08-07 09:34:50 +02:00
|
|
|
text += `- ${cleanupPRTitle(change.title)}${numberText}\n`
|
2020-07-28 14:07:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
text += '\n'
|
|
|
|
}
|
|
|
|
|
|
|
|
if (authors.size > 0) {
|
|
|
|
text += '### Credits \n\n'
|
|
|
|
text += 'Huge thanks to '
|
|
|
|
|
|
|
|
let index = 1
|
|
|
|
authors.forEach((author) => {
|
|
|
|
// GitHub links usernames if prefixed with @
|
|
|
|
text += `@${author}`
|
|
|
|
|
|
|
|
const penultimate = index === authors.size - 1
|
|
|
|
const notLast = index !== authors.size
|
|
|
|
|
|
|
|
if (penultimate) {
|
|
|
|
// Oxford comma is applied when list is bigger than 2 names
|
|
|
|
if (authors.size > 2) {
|
|
|
|
text += ','
|
|
|
|
}
|
|
|
|
|
|
|
|
text += ' and '
|
|
|
|
} else if (notLast) {
|
|
|
|
text += ', '
|
|
|
|
}
|
|
|
|
|
|
|
|
index += 1
|
|
|
|
})
|
|
|
|
|
|
|
|
text += ' for helping!'
|
|
|
|
text += '\n'
|
|
|
|
}
|
|
|
|
|
|
|
|
return text
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = async (markdown, metadata) => {
|
2020-07-28 15:05:26 +02:00
|
|
|
const { commits, authors, githubConnection, repoDetails } = metadata
|
|
|
|
|
|
|
|
const github = { connection: githubConnection, repoDetails }
|
2020-07-28 14:07:45 +02:00
|
|
|
|
2020-07-28 15:05:26 +02:00
|
|
|
const sections = await groupByLabels(commits.all, github)
|
2020-07-28 14:07:45 +02:00
|
|
|
const changelog = buildChangelog(sections, authors)
|
|
|
|
|
|
|
|
return changelog
|
|
|
|
}
|