diff --git a/src/workflows/ready-for-docs-review.ts b/src/workflows/ready-for-docs-review.ts index 5d3d51a426..e1b7f12165 100644 --- a/src/workflows/ready-for-docs-review.ts +++ b/src/workflows/ready-for-docs-review.ts @@ -12,6 +12,58 @@ import { getSize, } from './projects.js' +/** + * Determines if a PR is authored by Copilot and extracts the human assignee + * @param data GraphQL response data containing PR information + * @returns Object with isCopilotAuthor boolean and copilotAssignee string + */ +function getCopilotAuthorInfo(data: Record): { + isCopilotAuthor: boolean + copilotAssignee: string +} { + // Check if this is a Copilot-authored PR + const isCopilotAuthor = + data.item.__typename === 'PullRequest' && + data.item.author && + data.item.author.login === 'copilot-swe-agent' + + // For Copilot PRs, find the appropriate assignee (excluding Copilot itself) + let copilotAssignee = '' + if (isCopilotAuthor && data.item.assignees && data.item.assignees.nodes) { + const assignees = data.item.assignees.nodes + .map((assignee: Record) => assignee.login) + .filter((login: string) => login !== 'copilot-swe-agent') + + // Use the first non-Copilot assignee + copilotAssignee = assignees.length > 0 ? assignees[0] : '' + } + + return { isCopilotAuthor, copilotAssignee } +} + +/** + * Determines the appropriate author field value based on contributor type + * @param isCopilotAuthor Whether the PR is authored by Copilot + * @param copilotAssignee The human assignee for Copilot PRs (empty string if none) + * @param firstTimeContributor Whether this is a first-time contributor + * @returns The formatted author field value + */ +function getAuthorFieldValue( + isCopilotAuthor: boolean, + copilotAssignee: string, + firstTimeContributor: boolean | undefined, +): string { + if (isCopilotAuthor) { + return copilotAssignee ? `Copilot + ${copilotAssignee}` : 'Copilot' + } + + if (firstTimeContributor) { + return ':star: first time contributor' + } + + return process.env.AUTHOR_LOGIN || '' +} + async function run() { // Get info about the docs-content review board project const data: Record = await graphql( @@ -48,6 +100,14 @@ async function run() { path } } + author { + login + } + assignees(first: 10) { + nodes { + login + } + } } } } @@ -141,17 +201,31 @@ async function run() { } } const turnaround = process.env.REPO === 'github/docs' ? 3 : 2 + + // Check if this is a Copilot-authored PR and get the human assignee + const { isCopilotAuthor, copilotAssignee } = getCopilotAuthorInfo(data) + + // Determine the author field value + const authorFieldValue = getAuthorFieldValue( + isCopilotAuthor, + copilotAssignee, + firstTimeContributor, + ) + // Generate a mutation to populate fields for the new project item const updateProjectV2ItemMutation = generateUpdateProjectV2ItemFieldMutation({ item: newItemID, - author: firstTimeContributor ? ':star: first time contributor' : process.env.AUTHOR_LOGIN || '', + author: authorFieldValue, turnaround, feature, }) // Determine which variable to use for the contributor type let contributorType - if (await isDocsTeamMember(process.env.AUTHOR_LOGIN || '')) { + if (isCopilotAuthor) { + // Treat Copilot PRs as Docs team + contributorType = docsMemberTypeID + } else if (await isDocsTeamMember(process.env.AUTHOR_LOGIN || '')) { contributorType = docsMemberTypeID } else if (await isGitHubOrgMember(process.env.AUTHOR_LOGIN || '')) { contributorType = hubberTypeID @@ -185,6 +259,8 @@ async function run() { return newItemID } +export { run } + run().catch((error) => { console.log(`#ERROR# ${error}`) process.exit(1)