| |
| import { graphql } from '@octokit/graphql' |
|
|
| import { |
| addItemsToProject, |
| isDocsTeamMember, |
| findFieldID, |
| findSingleSelectID, |
| generateUpdateProjectV2ItemFieldMutation, |
| } from './projects' |
|
|
| async function getAllOpenPRs() { |
| let prsRemaining = true |
| let cursor |
| let prData: any[] = [] |
| while (prsRemaining) { |
| const data: Record<string, any> = await graphql( |
| ` |
| query ($organization: String!, $repo: String!) { |
| repository(name: $repo, owner: $organization) { |
| pullRequests(last: 100, states: OPEN${cursor ? ` before:"${cursor}"` : ''}) { |
| pageInfo{startCursor, hasPreviousPage}, |
| nodes { |
| id |
| isDraft |
| reviewRequests(first: 10) { |
| nodes { |
| requestedReviewer { |
| ... on Team { |
| name |
| } |
| } |
| } |
| } |
| labels(first: 5) { |
| nodes { |
| name |
| } |
| } |
| reviews(first: 10) { |
| nodes { |
| onBehalfOf(first: 1) { |
| nodes { |
| name |
| } |
| } |
| } |
| } |
| author { |
| login |
| } |
| } |
| } |
| } |
| } |
| `, |
| { |
| organization: process.env.ORGANIZATION, |
| repo: process.env.REPO, |
| headers: { |
| authorization: `token ${process.env.TOKEN}`, |
| }, |
| }, |
| ) |
|
|
| prsRemaining = data.repository.pullRequests.pageInfo.hasPreviousPage |
| cursor = data.repository.pullRequests.pageInfo.startCursor |
| prData = [...prData, ...data.repository.pullRequests.nodes] |
| } |
|
|
| return prData |
| } |
|
|
| async function run() { |
| |
| const prData = await getAllOpenPRs() |
|
|
| |
| |
| |
| |
| |
| const prs = prData.filter( |
| (pr) => |
| !pr.isDraft && |
| !pr.labels.nodes.find((label: Record<string, any>) => label.name === 'Deploy train 🚂') && |
| pr.reviewRequests.nodes.find( |
| (requestedReviewers: Record<string, any>) => |
| requestedReviewers.requestedReviewer?.name === process.env.REVIEWER, |
| ) && |
| !pr.reviews.nodes |
| .flatMap((review: Record<string, any>) => review.onBehalfOf.nodes) |
| .find((behalf: Record<string, any>) => behalf.name === process.env.REVIEWER), |
| ) |
| if (prs.length === 0) { |
| console.log('No PRs found. Exiting.') |
| return |
| } |
|
|
| const prIDs = prs.map((pr) => pr.id) |
| const prAuthors = prs.map((pr) => pr.author.login) |
| console.log(`PRs found: ${prIDs}`) |
|
|
| |
| const projectData: Record<string, any> = await graphql( |
| ` |
| query ($organization: String!, $projectNumber: Int!) { |
| organization(login: $organization) { |
| projectV2(number: $projectNumber) { |
| id |
| items(last: 100) { |
| nodes { |
| id |
| } |
| } |
| fields(first: 100) { |
| nodes { |
| ... on ProjectV2Field { |
| id |
| name |
| } |
| ... on ProjectV2SingleSelectField { |
| id |
| name |
| options { |
| id |
| name |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| `, |
| { |
| organization: process.env.ORGANIZATION, |
| projectNumber: parseInt(process.env.PROJECT_NUMBER || ''), |
| headers: { |
| authorization: `token ${process.env.TOKEN}`, |
| }, |
| }, |
| ) |
|
|
| |
| const projectID = projectData.organization.projectV2.id |
|
|
| |
| |
| |
| |
| const existingItemIDs = projectData.organization.projectV2.items.nodes.map( |
| (node: Record<string, any>) => node.id, |
| ) |
|
|
| |
| const datePostedID = findFieldID('Date posted', projectData) |
| const reviewDueDateID = findFieldID('Review due date', projectData) |
| const statusID = findFieldID('Status', projectData) |
| const featureID = findFieldID('Feature', projectData) |
| const contributorTypeID = findFieldID('Contributor type', projectData) |
| const sizeTypeID = findFieldID('Size', projectData) |
| const authorID = findFieldID('Contributor', projectData) |
|
|
| |
| const readyForReviewID = findSingleSelectID('Ready for review', 'Status', projectData) |
| const hubberTypeID = findSingleSelectID('Hubber or partner', 'Contributor type', projectData) |
| const docsMemberTypeID = findSingleSelectID('Docs team', 'Contributor type', projectData) |
| const sizeMediumID = findSingleSelectID('M', 'Size', projectData) |
|
|
| |
| const itemIDs = await addItemsToProject(prIDs, projectID) |
|
|
| |
| |
| |
| |
| const newItemIDs: any[] = [] |
| const newItemAuthors: any[] = [] |
| for (let index = 0; index < itemIDs.length; index++) { |
| const id = itemIDs[index] |
| if (!existingItemIDs.includes(id)) { |
| newItemIDs.push(id) |
| newItemAuthors.push(prAuthors[index]) |
| } |
| } |
|
|
| if (newItemIDs.length === 0) { |
| console.log('All found PRs are already on the project. Exiting.') |
| return |
| } |
|
|
| |
| |
| for (const [index, itemID] of newItemIDs.entries()) { |
| const updateProjectV2ItemMutation = generateUpdateProjectV2ItemFieldMutation({ |
| item: itemID, |
| author: newItemAuthors[index], |
| turnaround: 2, |
| feature: process.env.FEATURE, |
| }) |
| const contributorType = (await isDocsTeamMember(newItemAuthors[index])) |
| ? docsMemberTypeID |
| : hubberTypeID |
| console.log(`Populating fields for item: ${itemID} with author ${newItemAuthors[index]}`) |
|
|
| await graphql(updateProjectV2ItemMutation, { |
| project: projectID, |
| statusID, |
| statusValueID: readyForReviewID, |
| datePostedID, |
| reviewDueDateID, |
| contributorTypeID, |
| contributorType, |
| sizeTypeID, |
| sizeType: sizeMediumID, |
| featureID, |
| authorID, |
| headers: { |
| authorization: `token ${process.env.TOKEN}`, |
| }, |
| }) |
| console.log('Done populating fields for item') |
| } |
|
|
| return newItemIDs |
| } |
|
|
| try { |
| await run() |
| } catch (error) { |
| console.log(`#ERROR# ${error}`) |
| process.exit(1) |
| } |
|
|