Skip to content

Commit e236c28

Browse files
committed
ci: add PR co-authors to contributors section of release notes
1 parent f09ee0b commit e236c28

File tree

2 files changed

+80
-11
lines changed

2 files changed

+80
-11
lines changed

scripts/release.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,17 +124,21 @@ async function main() {
124124

125125
// Preview/Update changelog
126126
header(`${logPrefix}📝 Updating changelog...`)
127-
const { changelog: changelogContent, releaseUrl } = await generateReleaseNotes({
127+
const {
128+
changelog: changelogContent,
129+
releaseUrl,
130+
releaseNotes,
131+
} = await generateReleaseNotes({
128132
bump,
129133
dryRun,
130134
toVersion: 'HEAD',
131135
fromVersion,
132136
openReleaseUrl: true,
133137
})
134138

135-
console.log(chalk.green('\nChangelog Preview:\n'))
136-
console.log(chalk.gray(changelogContent) + '\n\n')
137-
console.log(`Release URL: ${chalk.dim(releaseUrl)}`)
139+
console.log(chalk.green('\nFull Release Notes:\n\n'))
140+
console.log(chalk.gray(releaseNotes) + '\n\n')
141+
console.log(`\n\nRelease URL: ${chalk.dim(releaseUrl)}`)
138142

139143
let packageDetails = await getPackageDetails(packagePublishList)
140144

scripts/utils/generateReleaseNotes.ts

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ export const generateReleaseNotes = async (args: Args = {}): Promise<ChangelogRe
161161
// Helper functions
162162

163163
async function createContributorSection(commits: GitCommit[]): Promise<string> {
164+
console.log('Fetching contributors...')
164165
const contributors = await getContributors(commits)
165166
if (!contributors.length) {
166167
return ''
@@ -179,18 +180,21 @@ async function getContributors(commits: GitCommit[]): Promise<Contributor[]> {
179180
const contributors: Contributor[] = []
180181
const emails = new Set<string>()
181182

183+
const headers = {
184+
Accept: 'application/vnd.github.v3+json',
185+
Authorization: `token ${process.env.GITHUB_TOKEN}`,
186+
}
187+
182188
for (const commit of commits) {
183-
if (emails.has(commit.author.email) || commit.author.name === 'dependabot[bot]') {
189+
console.log(`Fetching details for ${commit.message} - ${commit.shortHash}`)
190+
if (emails.has(commit.author.email) || commit.author.name.includes('[bot]')) {
184191
continue
185192
}
186193

187194
const res = await fetch(
188195
`https://api.github.com/repos/payloadcms/payload/commits/${commit.shortHash}`,
189196
{
190-
headers: {
191-
Accept: 'application/vnd.github.v3+json',
192-
Authorization: `token ${process.env.GITHUB_TOKEN}`,
193-
},
197+
headers,
194198
},
195199
)
196200

@@ -202,12 +206,73 @@ async function getContributors(commits: GitCommit[]): Promise<Contributor[]> {
202206

203207
const { author } = (await res.json()) as { author: { login: string; email: string } }
204208

205-
// TODO: Handle co-authors
206-
207209
if (!contributors.some((c) => c.username === author.login)) {
208210
contributors.push({ name: commit.author.name, username: author.login })
209211
}
210212
emails.add(author.email)
213+
214+
// Check git commit for 'Co-authored-by:' lines
215+
const coAuthorPattern = /Co-authored-by: (?<name>[^<]+) <(?<email>[^>]+)>/g
216+
const coAuthors = Array.from(
217+
commit.body.matchAll(coAuthorPattern),
218+
(match) => match.groups,
219+
).filter((e) => !e.email.includes('[bot]'))
220+
221+
if (!coAuthors.length) {
222+
continue
223+
}
224+
225+
console.log(
226+
`Fetching co-author details for hash: ${commit.shortHash}. Co-authors:`,
227+
coAuthors.map((c) => c.email).join(', '),
228+
)
229+
230+
// Attempt to co-authors by email
231+
await Promise.all(
232+
(coAuthors || [])
233+
.map(async ({ name, email }) => {
234+
// Check if this co-author has already been added
235+
if (emails.has(email)) {
236+
return null
237+
}
238+
239+
// Get co-author's GitHub username by email
240+
try {
241+
const response = await fetch(
242+
`https://api.github.com/search/users?q=${encodeURIComponent(email)}+in:email`,
243+
{
244+
headers,
245+
},
246+
)
247+
248+
if (!response.ok) {
249+
console.log('Bad response from GitHub API fetching co-author by email')
250+
console.error(response.status)
251+
return null
252+
}
253+
254+
const data = (await response.json()) as { items?: { login: string }[] }
255+
const user = data.items?.[0]
256+
257+
if (!user) {
258+
return null
259+
}
260+
261+
console.log(`Found co-author by email: ${user.login}`)
262+
263+
if (!contributors.some((c) => c.username === user.login)) {
264+
contributors.push({ name, username: user.login })
265+
}
266+
emails.add(email)
267+
return user.login
268+
} catch (error) {
269+
console.log(`ERROR: Failed to fetch co-author by email`)
270+
console.error(error)
271+
return null
272+
}
273+
})
274+
.filter(Boolean),
275+
)
211276
}
212277
return contributors
213278
}

0 commit comments

Comments
 (0)