From 29ba724b7bd0e14bc327d865477a63ac1e359c49 Mon Sep 17 00:00:00 2001 From: scottluskcis Date: Fri, 13 Dec 2024 11:30:23 -0500 Subject: [PATCH 1/6] only retrieve audit log for git entries --- src/data/copilot-associations-data.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/copilot-associations-data.ts b/src/data/copilot-associations-data.ts index d8dc590..33b4b82 100644 --- a/src/data/copilot-associations-data.ts +++ b/src/data/copilot-associations-data.ts @@ -61,7 +61,7 @@ async function processActiveAreas(org: string, seat_assignee: string, time_perio const active_areas_iterator = getUserActiveAreas({ org, actor: seat_assignee, - include: "all", + include: "git", time_period: time_period, per_page: per_page, }); From b50917aa5cddd5319fb7f5826695e9099d0c408d Mon Sep 17 00:00:00 2001 From: scottluskcis Date: Fri, 13 Dec 2024 11:37:45 -0500 Subject: [PATCH 2/6] remove collaborators check --- src/data/copilot-associations-data.ts | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/data/copilot-associations-data.ts b/src/data/copilot-associations-data.ts index 33b4b82..76a64d0 100644 --- a/src/data/copilot-associations-data.ts +++ b/src/data/copilot-associations-data.ts @@ -61,16 +61,12 @@ async function processActiveAreas(org: string, seat_assignee: string, time_perio const active_areas_iterator = getUserActiveAreas({ org, actor: seat_assignee, - include: "git", + include: "git", // for now only include git activity time_period: time_period, per_page: per_page, }); - for await (const active_area of active_areas_iterator) { - if (active_area.team) { - const [org_name, team_name] = active_area.team.split("/"); - await processTeams(org, team_name, seat_assignee, per_page, teams); - } + for await (const active_area of active_areas_iterator) { if (active_area.repository) { await processRepositories(active_area.repository, seat_assignee, per_page, repositories); } @@ -112,16 +108,17 @@ async function processRepositories(repository_owner_name: string, seat_assignee: repositories[repository_owner_name] = { repo_owner: owner, repo_name: repo_name, collaborators: [], collaborator_affiliation: collaborator_affiliation, contributors: [], associated_copilot_users: [seat_assignee] }; logger.trace(`Found repo ${owner}/${repo_name} for user ${seat_assignee}`); - // collaborators - let collaborator_count: number = 0; - for await (const collaborator of listRepoCollaborators({ owner, repo: repo_name, per_page, affiliation: collaborator_affiliation })) { - const collaborator_name = collaborator.login; - logger.trace(`Found collaborator ${collaborator_name} for repo ${repo_name}`); - repositories[repository_owner_name].collaborators.push(collaborator_name); + // #18 remove collaborators check for now + // // collaborators + // let collaborator_count: number = 0; + // for await (const collaborator of listRepoCollaborators({ owner, repo: repo_name, per_page, affiliation: collaborator_affiliation })) { + // const collaborator_name = collaborator.login; + // logger.trace(`Found collaborator ${collaborator_name} for repo ${repo_name}`); + // repositories[repository_owner_name].collaborators.push(collaborator_name); - collaborator_count++; - } - logger.info(`Found ${collaborator_count} collaborators for repo ${repo_name}`); + // collaborator_count++; + // } + // logger.info(`Found ${collaborator_count} collaborators for repo ${repo_name}`); // contributors let contributor_count: number = 0; From f4bbbc9c4fca71625a8f5e280e8ccca8040dd1dc Mon Sep 17 00:00:00 2001 From: scottluskcis Date: Fri, 13 Dec 2024 11:40:44 -0500 Subject: [PATCH 3/6] remove all uses of collaborators --- src/data/copilot-associations-data.ts | 16 +--------------- src/report/copilot-associations-report.ts | 17 +---------------- src/shared/shared-types.ts | 4 +--- 3 files changed, 3 insertions(+), 34 deletions(-) diff --git a/src/data/copilot-associations-data.ts b/src/data/copilot-associations-data.ts index 76a64d0..307e139 100644 --- a/src/data/copilot-associations-data.ts +++ b/src/data/copilot-associations-data.ts @@ -1,4 +1,3 @@ -import { listRepoCollaborators } from "../restapi/collaborators"; import { listCopilotSeats } from "../restapi/copilot"; import { getAuditLogForActor } from "../restapi/organizations"; import { listRepoContributors } from "../restapi/repositories"; @@ -97,7 +96,6 @@ async function processTeams(org: string, team_name: string, seat_assignee: strin } async function processRepositories(repository_owner_name: string, seat_assignee: string, per_page: number, repositories: { [repo: string]: Repository }) { - const collaborator_affiliation = 'direct'; if (repositories[repository_owner_name]) { if (!repositories[repository_owner_name].associated_copilot_users.includes(seat_assignee)) { logger.trace(`Found repo ${repository_owner_name} for user ${seat_assignee}`); @@ -105,21 +103,9 @@ async function processRepositories(repository_owner_name: string, seat_assignee: } } else { const [owner, repo_name] = repository_owner_name.split("/"); - repositories[repository_owner_name] = { repo_owner: owner, repo_name: repo_name, collaborators: [], collaborator_affiliation: collaborator_affiliation, contributors: [], associated_copilot_users: [seat_assignee] }; + repositories[repository_owner_name] = { repo_owner: owner, repo_name: repo_name, contributors: [], associated_copilot_users: [seat_assignee] }; logger.trace(`Found repo ${owner}/${repo_name} for user ${seat_assignee}`); - // #18 remove collaborators check for now - // // collaborators - // let collaborator_count: number = 0; - // for await (const collaborator of listRepoCollaborators({ owner, repo: repo_name, per_page, affiliation: collaborator_affiliation })) { - // const collaborator_name = collaborator.login; - // logger.trace(`Found collaborator ${collaborator_name} for repo ${repo_name}`); - // repositories[repository_owner_name].collaborators.push(collaborator_name); - - // collaborator_count++; - // } - // logger.info(`Found ${collaborator_count} collaborators for repo ${repo_name}`); - // contributors let contributor_count: number = 0; for await (const contributor of listRepoContributors({ owner, repo: repo_name, per_page })) { diff --git a/src/report/copilot-associations-report.ts b/src/report/copilot-associations-report.ts index 56aac8b..d3d5306 100644 --- a/src/report/copilot-associations-report.ts +++ b/src/report/copilot-associations-report.ts @@ -17,9 +17,7 @@ export interface CopilotAssociationsData { repositories: { [repo_name: string]: { repo_owner: string; - repo_name: string; - collaborators: string[]; - collaborator_affiliation: string; + repo_name: string; contributors: string[]; associated_copilot_users: string[]; }; @@ -123,19 +121,6 @@ function getRepositoryAssociations(data: CopilotAssociationsData): CopilotAssoci const repo = data.repositories[repo_name]; const copilot_users = repo.associated_copilot_users; - for (const collaborator of repo.collaborators) { - if (!copilot_users.includes(collaborator)) { - for (const copilot_user of copilot_users) { - results.push(createAssociation(collaborator, repo.repo_name, false, copilot_user, "repository")); - } - if (copilot_users.length === 0) { - results.push(createAssociation(collaborator, repo.repo_name, false, "Unknown", "repository")); - } - } else { - results.push(createAssociation(collaborator, repo.repo_name, true, "Self", "repository")); - } - } - for (const contributor of repo.contributors) { if (!copilot_users.includes(contributor)) { for (const copilot_user of copilot_users) { diff --git a/src/shared/shared-types.ts b/src/shared/shared-types.ts index 958ec1b..f6d9291 100644 --- a/src/shared/shared-types.ts +++ b/src/shared/shared-types.ts @@ -27,9 +27,7 @@ export interface UserSummary { export type Repository = { repo_owner: string; - repo_name: string; - collaborators: string[]; - collaborator_affiliation: string; + repo_name: string; contributors: string[]; associated_copilot_users: string[]; }; From 1a80945912bbb458f90b78145858d81aede39a3a Mon Sep 17 00:00:00 2001 From: scottluskcis Date: Fri, 13 Dec 2024 11:49:01 -0500 Subject: [PATCH 4/6] only add user to copilot_users for a team if they are in the copilot_seats that were found for the org --- src/data/copilot-associations-data.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/data/copilot-associations-data.ts b/src/data/copilot-associations-data.ts index 307e139..546752f 100644 --- a/src/data/copilot-associations-data.ts +++ b/src/data/copilot-associations-data.ts @@ -31,7 +31,7 @@ export async function generateCopilotAssociationsData({ const copilot_seats = await fetchCopilotSeats(org, per_page); // because the audit may not reflect that a copilot user is in a team, we need to get all teams and their members - await fetchOrgTeamsMembers(org, per_page, teams); + await fetchOrgTeamsMembers(org, per_page, teams, copilot_seats); // for every copilot user, get their active areas (repos and teams) by looking at the audit log // NOTE: there is rate limiting with audit log and its not intended to be used in this way constantly @@ -72,7 +72,7 @@ async function processActiveAreas(org: string, seat_assignee: string, time_perio } } -async function processTeams(org: string, team_name: string, seat_assignee: string | undefined, per_page: number, teams: { [team: string]: TeamInfo }) { +async function processTeams(org: string, team_name: string, per_page: number, teams: { [team: string]: TeamInfo }, org_copilot_seats: CopilotSeatAssignee[]) { let has_loaded_members = false; if(!teams[team_name]) { teams[team_name] = { team_name: team_name, members: [], copilot_users: [] }; @@ -80,17 +80,17 @@ async function processTeams(org: string, team_name: string, seat_assignee: strin has_loaded_members = teams[team_name].members.length > 0; } - if (seat_assignee && !teams[team_name].copilot_users.includes(seat_assignee)) { - logger.debug(`Found team ${team_name} for user ${seat_assignee}`); - teams[team_name].copilot_users.push(seat_assignee); - } - if (!has_loaded_members) { const team_slug = teams[team_name].team_name; for await (const member of listTeamMembers({ org, team_slug, per_page })) { const member_name = member.login; teams[team_name].members.push(member_name); logger.debug(`Found team member ${member_name} for team ${team_name}`); + + if (org_copilot_seats.some(seat => seat.assignee === member_name) && !teams[team_name].copilot_users.includes(member_name)) { + teams[team_name].copilot_users.push(member_name); + logger.debug(`Added copilot user ${member_name} to team ${team_name}`); + } } } } @@ -120,10 +120,10 @@ async function processRepositories(repository_owner_name: string, seat_assignee: } } -async function fetchOrgTeamsMembers(org: string, per_page: number, teams: { [team: string]: TeamInfo }) { +async function fetchOrgTeamsMembers(org: string, per_page: number, teams: { [team: string]: TeamInfo }, org_copilot_seats: CopilotSeatAssignee[]) { let team_count: number = 0; for await (const team of listTeams({ org, per_page })) { - processTeams(org, team.slug, undefined, per_page, teams); + processTeams(org, team.slug, per_page, teams, org_copilot_seats); team_count++; } logger.info(`Found ${team_count} total teams in org ${org}`); From 959f5ef164c433fe2d976e80b2b32cd3f9a8f24c Mon Sep 17 00:00:00 2001 From: scottluskcis Date: Fri, 13 Dec 2024 12:08:21 -0500 Subject: [PATCH 5/6] remove unused arg --- src/data/copilot-associations-data.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/data/copilot-associations-data.ts b/src/data/copilot-associations-data.ts index 546752f..b49c185 100644 --- a/src/data/copilot-associations-data.ts +++ b/src/data/copilot-associations-data.ts @@ -37,7 +37,7 @@ export async function generateCopilotAssociationsData({ // NOTE: there is rate limiting with audit log and its not intended to be used in this way constantly // may need to reconsider other otpions for future for (const seat of copilot_seats) { - await processActiveAreas(org, seat.assignee, time_period, per_page, teams, repositories); + await processActiveAreas(org, seat.assignee, time_period, per_page, repositories); } return { copilot_seats, teams, repositories }; @@ -56,16 +56,16 @@ async function fetchCopilotSeats(org: string, per_page: number): Promise Date: Fri, 13 Dec 2024 12:12:31 -0500 Subject: [PATCH 6/6] add ignore for copilot users for self reference such as their repo or team record --- src/report/copilot-associations-report.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/report/copilot-associations-report.ts b/src/report/copilot-associations-report.ts index d3d5306..ebbcdb4 100644 --- a/src/report/copilot-associations-report.ts +++ b/src/report/copilot-associations-report.ts @@ -105,8 +105,9 @@ function getTeamAssociations(data: CopilotAssociationsData): CopilotAssociation[ if (copilot_users.length === 0) { results.push(createAssociation(member, team.team_name, false, "Unknown", "team")); } - } else { - results.push(createAssociation(member, team.team_name, true, "Self", "team")); + } else { + logger.warn(`Found copilot user ${member} in team ${team.team_name}, ignoring for report...`); + //results.push(createAssociation(member, team.team_name, true, "Self", "team")); } } } @@ -130,7 +131,8 @@ function getRepositoryAssociations(data: CopilotAssociationsData): CopilotAssoci results.push(createAssociation(contributor, repo.repo_name, false, "Unknown", "repository")); } } else { - results.push(createAssociation(contributor, repo.repo_name, true, "Self", "repository")); + logger.warn(`Found copilot user ${contributor} in repo ${repo.repo_name}, ignoring for report...`); + //results.push(createAssociation(contributor, repo.repo_name, true, "Self", "repository")); } } }