-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
Copy pathsemantic-release-plugin.js
134 lines (114 loc) · 3.98 KB
/
semantic-release-plugin.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
const Octokit = require('@octokit/rest')
const commitMetadata = new Map()
const noteGroups = {
breaking: {title: ':boom: Breaking changes'},
enhancement: {title: ':rocket: Enhancements'},
fix: {title: ':bug: Bug fixes'},
docs: {title: ':memo: Documentation'},
internal: {title: ':house: Internal'},
polish: {title: ':nail_care: Polish'}
}
const releaseLabels = {
'Tag: Breaking Change': {releaseType: 'major', group: 'breaking'},
'Tag: Enhancement': {releaseType: 'minor', group: 'enhancement'},
'Tag: Bug Fix': {releaseType: 'patch', group: 'fix'},
'Tag: Documentation': {releaseType: 'patch', group: 'docs'},
'Tag: Internal': {releaseType: 'patch', group: 'internal'},
'Tag: Polish': {releaseType: 'patch', group: 'polish'}
}
const repoContext = {owner: 'primer', repo: 'css'}
const githubOptions = {
userAgent: '@primer/css changelog'
}
const {GITHUB_TOKEN} = process.env
if (GITHUB_TOKEN) {
githubOptions.auth = GITHUB_TOKEN
}
const github = new Octokit(githubOptions)
module.exports = {analyzeCommits, generateNotes}
async function analyzeCommits(options, context) {
const {commits, logger} = context
const releaseTypes = new Map()
for (const commit of commits) {
const match = commit.message.match(/Merge pull request #(\d+)/)
if (match) {
const [, pullNumber] = match
logger.log(`Fetching PR #${pullNumber}...`)
// eslint-disable-next-line camelcase
const {data: pull} = await github.pulls.get(Object.assign({pull_number: pullNumber}, repoContext))
const labels = pull.labels.map(label => label.name)
if (labels.length) {
logger.log(`Got labels: "${labels.join('", "')}"`)
for (const label of labels) {
const {releaseType, group} = releaseLabels[label] || {}
if (releaseType) {
logger.info(`Label "${label}" matches release type: ${releaseType}`)
if (!releaseTypes.has(releaseType)) {
releaseTypes.set(releaseType, [])
}
releaseTypes.get(releaseType).push({pull, label})
commitMetadata.set(commit.hash, {pull, group})
}
}
}
} else {
logger.log(`No PR number found in commit: "${commit.message}"`)
}
}
let returnReleaseType
for (const releaseType of ['major', 'minor', 'patch']) {
if (releaseTypes.has(releaseType)) {
const pulls = releaseTypes.get(releaseType)
logger.info(`Found ${pulls.length} pulls for release type: ${releaseType}`)
for (const {pull, label} of pulls) {
logger.info(`- PR #${pull.number} labeled "${label}"`)
if (!returnReleaseType) {
returnReleaseType = releaseType
}
}
}
}
return returnReleaseType
}
async function generateNotes(options, context) {
const {
commits,
logger,
nextRelease: {version}
} = context
logger.info(`Finding metadata for ${commitMetadata.size} commits...`)
const releaseCommits = commits.map(commit => commitMetadata.get(commit.hash)).filter(Boolean)
if (releaseCommits.length) {
logger.info(`Got ${releaseCommits.length} release commits!`)
const groupItems = new Map()
const committers = new Set()
const {owner, repo} = repoContext
const baseURL = `https://github.com/${owner}/${repo}`
for (const {pull, group} of releaseCommits) {
if (!groupItems.has(group)) {
groupItems.set(group, [])
}
const {
number,
title,
user: {login}
} = pull
groupItems.get(group).push(`- [#${number}](${baseURL}/${number}) ${title}`)
committers.add(login)
}
return [
`## ${version}`,
...Object.entries(noteGroups)
.filter(([group]) => groupItems.has(group))
.map(([group, {title}]) => `\n### ${title}\n${groupItems.get(group).join('\n')}`),
'',
`### Committers`,
...Array.from(committers)
.sort()
.map(login => `- [@${login}](https://github.com/${login})`),
''
].join('\n')
} else {
logger.info(`No release commits. :(`)
}
}