@@ -12,6 +12,58 @@ import {
1212 getSize ,
1313} from './projects.js'
1414
15+ /**
16+ * Determines if a PR is authored by Copilot and extracts the human assignee
17+ * @param data GraphQL response data containing PR information
18+ * @returns Object with isCopilotAuthor boolean and copilotAssignee string
19+ */
20+ function getCopilotAuthorInfo ( data : Record < string , any > ) : {
21+ isCopilotAuthor : boolean
22+ copilotAssignee : string
23+ } {
24+ // Check if this is a Copilot-authored PR
25+ const isCopilotAuthor =
26+ data . item . __typename === 'PullRequest' &&
27+ data . item . author &&
28+ data . item . author . login === 'copilot-swe-agent[bot]'
29+
30+ // For Copilot PRs, find the appropriate assignee (excluding Copilot itself)
31+ let copilotAssignee = ''
32+ if ( isCopilotAuthor && data . item . assignees && data . item . assignees . nodes ) {
33+ const assignees = data . item . assignees . nodes
34+ . map ( ( assignee : Record < string , any > ) => assignee . login )
35+ . filter ( ( login : string ) => login !== 'copilot-swe-agent[bot]' )
36+
37+ // Use the first non-Copilot assignee
38+ copilotAssignee = assignees . length > 0 ? assignees [ 0 ] : ''
39+ }
40+
41+ return { isCopilotAuthor, copilotAssignee }
42+ }
43+
44+ /**
45+ * Determines the appropriate author field value based on contributor type
46+ * @param isCopilotAuthor Whether the PR is authored by Copilot
47+ * @param copilotAssignee The human assignee for Copilot PRs (empty string if none)
48+ * @param firstTimeContributor Whether this is a first-time contributor
49+ * @returns The formatted author field value
50+ */
51+ function getAuthorFieldValue (
52+ isCopilotAuthor : boolean ,
53+ copilotAssignee : string ,
54+ firstTimeContributor : boolean | undefined ,
55+ ) : string {
56+ if ( isCopilotAuthor ) {
57+ return copilotAssignee ? `Copilot + ${ copilotAssignee } ` : 'Copilot'
58+ }
59+
60+ if ( firstTimeContributor ) {
61+ return ':star: first time contributor'
62+ }
63+
64+ return process . env . AUTHOR_LOGIN || ''
65+ }
66+
1567async function run ( ) {
1668 // Get info about the docs-content review board project
1769 const data : Record < string , any > = await graphql (
@@ -48,6 +100,14 @@ async function run() {
48100 path
49101 }
50102 }
103+ author {
104+ login
105+ }
106+ assignees(first: 10) {
107+ nodes {
108+ login
109+ }
110+ }
51111 }
52112 }
53113 }
@@ -141,17 +201,31 @@ async function run() {
141201 }
142202 }
143203 const turnaround = process . env . REPO === 'github/docs' ? 3 : 2
204+
205+ // Check if this is a Copilot-authored PR and get the human assignee
206+ const { isCopilotAuthor, copilotAssignee } = getCopilotAuthorInfo ( data )
207+
208+ // Determine the author field value
209+ const authorFieldValue = getAuthorFieldValue (
210+ isCopilotAuthor ,
211+ copilotAssignee ,
212+ firstTimeContributor ,
213+ )
214+
144215 // Generate a mutation to populate fields for the new project item
145216 const updateProjectV2ItemMutation = generateUpdateProjectV2ItemFieldMutation ( {
146217 item : newItemID ,
147- author : firstTimeContributor ? ':star: first time contributor' : process . env . AUTHOR_LOGIN || '' ,
218+ author : authorFieldValue ,
148219 turnaround,
149220 feature,
150221 } )
151222
152223 // Determine which variable to use for the contributor type
153224 let contributorType
154- if ( await isDocsTeamMember ( process . env . AUTHOR_LOGIN || '' ) ) {
225+ if ( isCopilotAuthor ) {
226+ // Treat Copilot PRs as Docs team
227+ contributorType = docsMemberTypeID
228+ } else if ( await isDocsTeamMember ( process . env . AUTHOR_LOGIN || '' ) ) {
155229 contributorType = docsMemberTypeID
156230 } else if ( await isGitHubOrgMember ( process . env . AUTHOR_LOGIN || '' ) ) {
157231 contributorType = hubberTypeID
@@ -185,6 +259,8 @@ async function run() {
185259 return newItemID
186260}
187261
262+ export { run }
263+
188264run ( ) . catch ( ( error ) => {
189265 console . log ( `#ERROR# ${ error } ` )
190266 process . exit ( 1 )
0 commit comments