diff --git a/data/reusables/reminders/scheduled-reminders-limitations.md b/data/reusables/reminders/scheduled-reminders-limitations.md index 6a36803460fb..9a756ed7f2b3 100644 --- a/data/reusables/reminders/scheduled-reminders-limitations.md +++ b/data/reusables/reminders/scheduled-reminders-limitations.md @@ -1 +1,4 @@ -{% data variables.product.github %} will only trigger reminders for up to five repositories per owner and 20 pull requests per repository. Reminders are not sent when changes are merged from upstream into a fork. +Reminders will only be triggered for up to five repositories per scheduled reminder. Users can either select up to five specific repositories or allow the system to automatically choose the five repositories with the oldest average pull request age. For each repository, up to 20 of the oldest pull requests will be shown. + +> [!NOTE] +> Reminders are not sent when changes are merged from upstream into a fork. diff --git a/src/workflows/ready-for-docs-review.ts b/src/workflows/ready-for-docs-review.ts index 5d3d51a4267d..e1b7f1216566 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)