Skip to content

Commit a1d690a

Browse files
authored
Merge pull request #8994 from github/repo-sync
repo sync
2 parents f7f840a + b36fcab commit a1d690a

File tree

4 files changed

+404
-225
lines changed

4 files changed

+404
-225
lines changed

.github/actions-scripts/fr-add-docs-reviewers-requests.js

Lines changed: 35 additions & 223 deletions
Original file line numberDiff line numberDiff line change
@@ -1,167 +1,12 @@
11
import { graphql } from '@octokit/graphql'
22

3-
// Given a list of PR/issue node IDs and a project node ID,
4-
// adds the PRs/issues to the project
5-
// and returns the node IDs of the project items
6-
async function addItemsToProject(items, project) {
7-
console.log(`Adding ${items} to project ${project}`)
8-
9-
const mutations = items.map(
10-
(pr, index) => `
11-
pr_${index}: addProjectNextItem(input: {
12-
projectId: $project
13-
contentId: "${pr}"
14-
}) {
15-
projectNextItem {
16-
id
17-
}
18-
}
19-
`
20-
)
21-
22-
const mutation = `
23-
mutation($project:ID!) {
24-
${mutations.join(' ')}
25-
}
26-
`
27-
28-
const newItems = await graphql(mutation, {
29-
project: project,
30-
headers: {
31-
authorization: `token ${process.env.TOKEN}`,
32-
'GraphQL-Features': 'projects_next_graphql',
33-
},
34-
})
35-
36-
// The output of the mutation is
37-
// {"pr_0":{"projectNextItem":{"id":ID!}},...}
38-
// Pull out the ID for each new item
39-
const newItemIDs = Object.entries(newItems).map((item) => item[1].projectNextItem.id)
40-
41-
console.log(`New item IDs: ${newItemIDs}`)
42-
43-
return newItemIDs
44-
}
45-
46-
// Given a list of project item node IDs and a list of corresponding authors
47-
// generates a GraphQL mutation to populate:
48-
// - "Status" (as "Ready for review" option)
49-
// - "Date posted" (as today)
50-
// - "Review due date" (as today + 2 weekdays)
51-
// - "Feature" (as "OpenAPI schema update")
52-
// - "Contributor type" (as "Hubber or partner" option)
53-
// Does not populate "Review needs" or "Size"
54-
function generateUpdateProjectNextItemFieldMutation(items, authors) {
55-
// Formats a date object into the required format for projects
56-
function formatDate(date) {
57-
return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate()
58-
}
59-
60-
// Calculate 2 weekdays from now (excluding weekends; not considering holidays)
61-
const datePosted = new Date()
62-
let daysUntilDue
63-
switch (datePosted.getDay()) {
64-
case 0: // Sunday
65-
daysUntilDue = 3
66-
break
67-
case 6: // Saturday
68-
daysUntilDue = 4
69-
break
70-
default:
71-
daysUntilDue = 2
72-
}
73-
const millisecPerDay = 24 * 60 * 60 * 1000
74-
const dueDate = new Date(datePosted.getTime() + millisecPerDay * daysUntilDue)
75-
76-
// Build the mutation for a single field
77-
function generateMutation({ index, item, fieldID, value, literal = false }) {
78-
let parsedValue
79-
if (literal) {
80-
parsedValue = `value: "${value}"`
81-
} else {
82-
parsedValue = `value: ${value}`
83-
}
84-
85-
return `
86-
set_${fieldID.substr(1)}_item_${index}: updateProjectNextItemField(input: {
87-
projectId: $project
88-
itemId: "${item}"
89-
fieldId: ${fieldID}
90-
${parsedValue}
91-
}) {
92-
projectNextItem {
93-
id
94-
}
95-
}
96-
`
97-
}
98-
99-
// Build the mutation for all fields for all items
100-
const mutations = items.map(
101-
(item, index) => `
102-
${generateMutation({
103-
index: index,
104-
item: item,
105-
fieldID: '$statusID',
106-
value: '$readyForReviewID',
107-
})}
108-
${generateMutation({
109-
index: index,
110-
item: item,
111-
fieldID: '$datePostedID',
112-
value: formatDate(datePosted),
113-
literal: true,
114-
})}
115-
${generateMutation({
116-
index: index,
117-
item: item,
118-
fieldID: '$reviewDueDateID',
119-
value: formatDate(dueDate),
120-
literal: true,
121-
})}
122-
${generateMutation({
123-
index: index,
124-
item: item,
125-
fieldID: '$contributorTypeID',
126-
value: '$hubberTypeID',
127-
})}
128-
${generateMutation({
129-
index: index,
130-
item: item,
131-
fieldID: '$featureID',
132-
value: 'OpenAPI schema update',
133-
literal: true,
134-
})}
135-
${generateMutation({
136-
index: index,
137-
item: item,
138-
fieldID: '$authorID',
139-
value: authors[index],
140-
literal: true,
141-
})}
142-
`
143-
)
144-
145-
// Build the full mutation
146-
const mutation = `
147-
mutation(
148-
$project: ID!
149-
$statusID: ID!
150-
$readyForReviewID: String!
151-
$datePostedID: ID!
152-
$reviewDueDateID: ID!
153-
$contributorTypeID: ID!
154-
$hubberTypeID: String!
155-
$featureID: ID!
156-
$authorID: ID!
157-
158-
) {
159-
${mutations.join(' ')}
160-
}
161-
`
162-
163-
return mutation
164-
}
3+
import {
4+
addItemsToProject,
5+
isDocsTeamMember,
6+
findFieldID,
7+
findSingleSelectID,
8+
generateUpdateProjectNextItemFieldMutation,
9+
} from './projects.js'
16510

16611
async function run() {
16712
// Get info about the docs-content review board project
@@ -268,43 +113,6 @@ async function run() {
268113
// If we are overwriting items, query for more items.
269114
const existingItemIDs = data.organization.projectNext.items.nodes.map((node) => node.id)
270115

271-
function findFieldID(fieldName, data) {
272-
const field = data.organization.projectNext.fields.nodes.find(
273-
(field) => field.name === fieldName
274-
)
275-
276-
if (field && field.id) {
277-
return field.id
278-
} else {
279-
throw new Error(
280-
`A field called "${fieldName}" was not found. Check if the field was renamed.`
281-
)
282-
}
283-
}
284-
285-
function findSingleSelectID(singleSelectName, fieldName, data) {
286-
const field = data.organization.projectNext.fields.nodes.find(
287-
(field) => field.name === fieldName
288-
)
289-
if (!field) {
290-
throw new Error(
291-
`A field called "${fieldName}" was not found. Check if the field was renamed.`
292-
)
293-
}
294-
295-
const singleSelect = JSON.parse(field.settings).options.find(
296-
(field) => field.name === singleSelectName
297-
)
298-
299-
if (singleSelect && singleSelect.id) {
300-
return singleSelect.id
301-
} else {
302-
throw new Error(
303-
`A single select called "${singleSelectName}" for the field "${fieldName}" was not found. Check if the single select was renamed.`
304-
)
305-
}
306-
}
307-
308116
// Get the ID of the fields that we want to populate
309117
const datePostedID = findFieldID('Date posted', data)
310118
const reviewDueDateID = findFieldID('Review due date', data)
@@ -316,6 +124,7 @@ async function run() {
316124
// Get the ID of the single select values that we want to set
317125
const readyForReviewID = findSingleSelectID('Ready for review', 'Status', data)
318126
const hubberTypeID = findSingleSelectID('Hubber or partner', 'Contributor type', data)
127+
const docsMemberTypeID = findSingleSelectID('Docs team', 'Contributor type', data)
319128

320129
// Add the PRs to the project
321130
const itemIDs = await addItemsToProject(prIDs, projectID)
@@ -332,30 +141,33 @@ async function run() {
332141
}
333142

334143
// Populate fields for the new project items
335-
// Note: Since there is not a way to check if a PR is already on the board,
336-
// this will overwrite the values of PRs that are on the board
337-
const updateProjectNextItemMutation = generateUpdateProjectNextItemFieldMutation(
338-
newItemIDs,
339-
prAuthors
340-
)
341-
console.log(`Populating fields for these items: ${newItemIDs}`)
342-
343-
await graphql(updateProjectNextItemMutation, {
344-
project: projectID,
345-
statusID: statusID,
346-
readyForReviewID: readyForReviewID,
347-
datePostedID: datePostedID,
348-
reviewDueDateID: reviewDueDateID,
349-
contributorTypeID: contributorTypeID,
350-
hubberTypeID: hubberTypeID,
351-
featureID: featureID,
352-
authorID: authorID,
353-
headers: {
354-
authorization: `token ${process.env.TOKEN}`,
355-
'GraphQL-Features': 'projects_next_graphql',
356-
},
357-
})
358-
console.log('Done populating fields')
144+
// (Using for...of instead of forEach since the function uses await)
145+
for (const [index, itemID] of newItemIDs.entries()) {
146+
const updateProjectNextItemMutation = generateUpdateProjectNextItemFieldMutation({
147+
item: itemID,
148+
author: prAuthors[index],
149+
turnaround: 2,
150+
})
151+
const contributorType = isDocsTeamMember(prAuthors[index]) ? docsMemberTypeID : hubberTypeID
152+
console.log(`Populating fields for item: ${itemID}`)
153+
154+
await graphql(updateProjectNextItemMutation, {
155+
project: projectID,
156+
statusID: statusID,
157+
statusValueID: readyForReviewID,
158+
datePostedID: datePostedID,
159+
reviewDueDateID: reviewDueDateID,
160+
contributorTypeID: contributorTypeID,
161+
contributorType: contributorType,
162+
featureID: featureID,
163+
authorID: authorID,
164+
headers: {
165+
authorization: `token ${process.env.TOKEN}`,
166+
'GraphQL-Features': 'projects_next_graphql',
167+
},
168+
})
169+
console.log('Done populating fields for item')
170+
}
359171

360172
return newItemIDs
361173
}

0 commit comments

Comments
 (0)