@@ -73,22 +73,35 @@ function getChangeLog() {
73
73
}
74
74
75
75
const date = exec ( 'git log -1 --format=%cd --date=short' ) ;
76
- return getCommitsInfo ( commitsList . split ( '\n' ) ) . then ( commitsInfo =>
77
- genChangeLog ( tag , date , commitsInfo ) ,
78
- ) ;
76
+ return getCommitsInfo ( commitsList . split ( '\n' ) )
77
+ . then ( commitsInfo => getPRsInfo ( commitsInfoToPRs ( commitsInfo ) ) )
78
+ . then ( prsInfo => genChangeLog ( tag , date , prsInfo ) ) ;
79
79
}
80
80
81
- function genChangeLog ( tag , date , commitsInfo ) {
82
- const allPRs = commitsInfoToPRs ( commitsInfo ) ;
81
+ function genChangeLog ( tag , date , allPRs ) {
83
82
const byLabel = { } ;
84
83
const commitersByLogin = { } ;
85
84
86
85
for ( const pr of allPRs ) {
87
- if ( ! labelsConfig [ pr . label ] ) {
88
- throw new Error ( 'Unknown label: ' + pr . label + pr . number ) ;
86
+ const labels = pr . labels . nodes
87
+ . map ( label => label . name )
88
+ . filter ( label => label . startsWith ( 'PR: ' ) ) ;
89
+
90
+ if ( labels . length === 0 ) {
91
+ throw new Error ( `PR #${ pr . number } missing label` ) ;
89
92
}
90
- byLabel [ pr . label ] = byLabel [ pr . label ] || [ ] ;
91
- byLabel [ pr . label ] . push ( pr ) ;
93
+ if ( labels . length > 1 ) {
94
+ throw new Error (
95
+ `PR #${ pr . number } has conflicting labels: ` + labels . join ( '\n' ) ,
96
+ ) ;
97
+ }
98
+
99
+ const label = labels [ 0 ] ;
100
+ if ( ! labelsConfig [ label ] ) {
101
+ throw new Error ( 'Unknown label: ' + label + pr . number ) ;
102
+ }
103
+ byLabel [ label ] = byLabel [ label ] || [ ] ;
104
+ byLabel [ label ] . push ( pr ) ;
92
105
commitersByLogin [ pr . author . login ] = pr . author ;
93
106
}
94
107
@@ -188,23 +201,9 @@ async function batchCommitInfo(commits) {
188
201
associatedPullRequests(first: 10) {
189
202
nodes {
190
203
number
191
- title
192
- url
193
- author {
194
- login
195
- url
196
- ... on User {
197
- name
198
- }
199
- }
200
204
repository {
201
205
nameWithOwner
202
206
}
203
- labels(first: 10) {
204
- nodes {
205
- name
206
- }
207
- }
208
207
}
209
208
}
210
209
}
@@ -227,13 +226,57 @@ async function batchCommitInfo(commits) {
227
226
return commitsInfo ;
228
227
}
229
228
229
+ async function batchPRInfo ( prs ) {
230
+ let prsSubQuery = '' ;
231
+ for ( const number of prs ) {
232
+ prsSubQuery += `
233
+ pr_${ number } : pullRequest(number: ${ number } ) {
234
+ number
235
+ title
236
+ url
237
+ author {
238
+ login
239
+ url
240
+ ... on User {
241
+ name
242
+ }
243
+ }
244
+ labels(first: 10) {
245
+ nodes {
246
+ name
247
+ }
248
+ }
249
+ }
250
+ ` ;
251
+ }
252
+
253
+ const response = await graphqlRequest ( `
254
+ {
255
+ repository(owner: "${ githubOrg } ", name: "${ githubRepo } ") {
256
+ ${ prsSubQuery }
257
+ }
258
+ }
259
+ ` ) ;
260
+
261
+ const prsInfo = [ ] ;
262
+ for ( const number of prs ) {
263
+ prsInfo . push ( response . repository [ 'pr_' + number ] ) ;
264
+ }
265
+ return prsInfo ;
266
+ }
267
+
230
268
function commitsInfoToPRs ( commits ) {
231
269
const prs = { } ;
232
270
for ( const commit of commits ) {
233
271
const associatedPRs = commit . associatedPullRequests . nodes . filter (
234
272
pr => pr . repository . nameWithOwner === `${ githubOrg } /${ githubRepo } ` ,
235
273
) ;
236
274
if ( associatedPRs . length === 0 ) {
275
+ const match = / \( # ( [ 0 - 9 ] + ) \) $ / m. exec ( commit . message ) ;
276
+ if ( match ) {
277
+ prs [ parseInt ( match [ 1 ] ) ] = true ;
278
+ continue ;
279
+ }
237
280
throw new Error (
238
281
`Commit ${ commit . oid } has no associated PR: ${ commit . message } ` ,
239
282
) ;
@@ -244,30 +287,21 @@ function commitsInfoToPRs(commits) {
244
287
) ;
245
288
}
246
289
247
- const pr = associatedPRs [ 0 ] ;
248
- const labels = pr . labels . nodes
249
- . map ( label => label . name )
250
- . filter ( label => label . startsWith ( 'PR: ' ) ) ;
290
+ prs [ associatedPRs [ 0 ] . number ] = true ;
291
+ }
251
292
252
- if ( labels . length === 0 ) {
253
- throw new Error ( `PR #${ pr . number } missing label` ) ;
254
- }
255
- if ( labels . length > 1 ) {
256
- throw new Error (
257
- `PR #${ pr . number } has conflicting labels: ` + labels . join ( '\n' ) ,
258
- ) ;
259
- }
293
+ return Object . keys ( prs ) ;
294
+ }
260
295
261
- prs [ pr . number ] = {
262
- number : pr . number ,
263
- title : pr . title ,
264
- url : pr . url ,
265
- author : pr . author ,
266
- label : labels [ 0 ] ,
267
- } ;
296
+ async function getPRsInfo ( commits ) {
297
+ // Split pr into batches of 50 to prevent timeouts
298
+ const prInfoPromises = [ ] ;
299
+ for ( let i = 0 ; i < commits . length ; i += 50 ) {
300
+ const batch = commits . slice ( i , i + 50 ) ;
301
+ prInfoPromises . push ( batchPRInfo ( batch ) ) ;
268
302
}
269
303
270
- return Object . values ( prs ) ;
304
+ return ( await Promise . all ( prInfoPromises ) ) . flat ( ) ;
271
305
}
272
306
273
307
async function getCommitsInfo ( commits ) {
0 commit comments