5959# }
6060
6161
62- def get_copilot_team_date (gh : github_api_toolkit .github_interface , page : int ) -> list :
63- """Gets a list of GitHub Teams with Copilot Data for a given API page.
64-
65- Args:
66- gh (github_api_toolkit.github_interface): An instance of the github_interface class.
67- page (int): The page number of the API request.
68-
69- Returns:
70- list: A list of GitHub Teams with Copilot Data.
71- """
72- copilot_teams = []
73-
74- response = gh .get (f"/orgs/{ org } /teams" , params = {"per_page" : 100 , "page" : page })
75- teams = response .json ()
76- for team in teams :
77- usage_data = gh .get (f"/orgs/{ org } /team/{ team ['name' ]} /copilot/metrics" )
78-
79- if not isinstance (usage_data , Response ):
80-
81- # If the response is not a Response object, no copilot data is available for this team
82- # We can then skip this team
83-
84- # We don't log this as an error, as it is expected and it'd be too noisy within logs
85-
86- continue
87-
88- # If the response has data, append the team to the list
89- # If there is no data, .json() will return an empty list
90- if usage_data .json ():
91-
92- team_name = team .get ("name" , "" )
93- team_slug = team .get ("slug" , "" )
94- team_description = team .get ("description" , "" )
95- team_html_url = team .get ("html_url" , "" )
96-
97- logger .info (
98- "Team %s has Copilot data" ,
99- team_name ,
100- extra = {
101- "team_name" : team_name ,
102- "team_slug" : team_slug ,
103- "team_description" : team_description ,
104- "team_html_url" : team_html_url ,
105- },
106- )
107-
108- copilot_teams .append (
109- {
110- "name" : team_name ,
111- "slug" : team_slug ,
112- "description" : team_description ,
113- "url" : team_html_url ,
114- }
115- )
116-
117- return copilot_teams
118-
119-
12062def get_and_update_historic_usage (
12163 s3 : boto3 .client , gh : github_api_toolkit .github_interface , write_data_locally : bool
12264) -> tuple :
@@ -176,104 +118,6 @@ def get_and_update_historic_usage(
176118 return sorted_historic_usage , dates_added
177119
178120
179- def get_and_update_copilot_teams (
180- s3 : boto3 .client , gh : github_api_toolkit .github_interface , write_data_locally : bool
181- ) -> list :
182- """Get and update GitHub Teams with Copilot Data.
183-
184- Args:
185- s3 (boto3.client): An S3 client.
186- gh (github_api_toolkit.github_interface): An instance of the github_interface class.
187- write_data_locally (bool): Whether to write data locally instead of to an S3 bucket.
188-
189- Returns:
190- list: A list of GitHub Teams with Copilot Data.
191- """
192- logger .info ("Getting GitHub Teams with Copilot Data" )
193-
194- copilot_teams = []
195-
196- response = gh .get (f"/orgs/{ org } /teams" , params = {"per_page" : 100 })
197-
198- # Get the last page of teams
199- try :
200- last_page = int (response .links ["last" ]["url" ].split ("=" )[- 1 ])
201- except KeyError :
202- last_page = 1
203-
204- for page in range (1 , last_page + 1 ):
205- page_teams = get_copilot_team_date (gh , page )
206-
207- copilot_teams = copilot_teams + page_teams
208-
209- logger .info (
210- "Fetched GitHub Teams with Copilot Data" ,
211- extra = {"no_teams" : len (copilot_teams )},
212- )
213-
214- if not write_data_locally :
215- update_s3_object (s3 , BUCKET_NAME , "copilot_teams.json" , copilot_teams )
216- else :
217- local_path = "output/copilot_teams.json"
218- os .makedirs ("output" , exist_ok = True )
219- with open (local_path , "w" , encoding = "utf-8" ) as f :
220- json .dump (copilot_teams , f , indent = 4 )
221- logger .info ("Copilot teams data written locally to %s (S3 skipped)" , local_path )
222-
223- return copilot_teams
224-
225-
226- def create_dictionary (
227- gh : github_api_toolkit .github_interface , copilot_teams : list , existing_team_history : list
228- ) -> list :
229- """Create a dictionary for quick lookup of existing team data using the `name` field.
230-
231- Args:
232- gh (github_api_toolkit.github_interface): An instance of the github_interface class.
233- copilot_teams (list): List of teams with Copilot data.
234- existing_team_history (list): List of existing team history data.
235-
236- Returns:
237- list: A list of dictionaries containing team data and their history.
238- """
239- existing_team_data_map = {
240- single_team ["team" ]["name" ]: single_team for single_team in existing_team_history
241- }
242-
243- # Iterate through identified teams
244- for team in copilot_teams :
245- team_name = team .get ("name" , "" )
246- if not team_name :
247- logger .warning ("Skipping team with no name" )
248- continue
249-
250- # Determine the last known date for the team
251- last_known_date = None
252- if team_name in existing_team_data_map :
253- existing_dates = [entry ["date" ] for entry in existing_team_data_map [team_name ]["data" ]]
254- if existing_dates :
255- last_known_date = max (existing_dates ) # Get the most recent date
256-
257- # Assign the last known date to the `since` query parameter
258- query_params = {}
259- if last_known_date :
260- query_params ["since" ] = last_known_date
261-
262- single_team_history = get_team_history (gh , team_name , query_params )
263- if not single_team_history :
264- logger .info ("No new history found for team %s" , team_name )
265- continue
266-
267- # Append new data to the existing team history
268- new_team_data = single_team_history
269- if team_name in existing_team_data_map :
270- existing_team_data_map [team_name ]["data" ].extend (new_team_data )
271- else :
272- existing_team_data_map [team_name ] = {"team" : team , "data" : new_team_data }
273-
274- return list (existing_team_data_map .values ())
275-
276-
277121def update_s3_object (
278122 s3_client : boto3 .client ,
279123 bucket_name : str ,
@@ -304,31 +148,6 @@ def update_s3_object(
304148 return False
305149
306150
307- def get_team_history (
308- gh : github_api_toolkit .github_interface , team : str , query_params : Optional [dict ] = None
309- ) -> list [dict ]:
310- """Gets the team metrics Copilot data through the API.
311- Note - This endpoint will only return results for a given day if the team had
312- five or more members with active Copilot licenses on that day,
313- as evaluated at the end of that day.
314-
315- Args:
316- gh (github_api_toolkit.github_interface): An instance of the github_interface class.
317- team (str): Team name.
318- query_params (dict): Additional query parameters for the API request.
319-
320- Returns:
321- list[dict]: A team's GitHub Copilot metrics or None if an error occurs.
322- """
323- response = gh .get (f"/orgs/{ org } /team/{ team } /copilot/metrics" , params = query_params )
324-
325- if not isinstance (response , Response ):
326- # If the response is not a Response object, no copilot data is available for this team
327- # We can return None which is then handled by the calling function
328- return None
329- return response .json ()
330-
331-
332151def get_dict_value (dictionary : dict , key : str ) -> Any :
333152 """Gets a value from a dictionary and raises an exception if it is not found.
334153
@@ -451,37 +270,6 @@ def handler(event: dict, context) -> str: # pylint: disable=unused-argument, to
451270 # Copilot Usage Data (Historic)
452271 historic_usage , dates_added = get_and_update_historic_usage (s3 , gh , write_data_locally )
453272
454- # GitHub Teams with Copilot Data
455- copilot_teams = get_and_update_copilot_teams (s3 , gh , write_data_locally )
456-
457- logger .info ("Getting history of each team identified previously" )
458-
459- # Retrieve existing team history from S3
460- try :
461- response = s3 .get_object (Bucket = BUCKET_NAME , Key = "teams_history.json" )
462- existing_team_history = json .loads (response ["Body" ].read ().decode ("utf-8" ))
463- except ClientError as e :
464- logger .warning ("Error retrieving existing team history: %s" , e )
465- existing_team_history = []
466-
467- logger .info ("Existing team history has %d entries" , len (existing_team_history ))
468-
469- if not write_data_locally :
470- # Convert to dictionary for quick lookup
471- updated_team_history = create_dictionary (gh , copilot_teams , existing_team_history )
472-
473- # Write updated team history to S3
474- # This line isn't covered by tests as it's painful to get to.
475- # The function itself is tested though.
476- update_s3_object (s3 , BUCKET_NAME , "teams_history.json" , updated_team_history )
477- else :
478- local_path = "output/teams_history.json"
479- os .makedirs ("output" , exist_ok = True )
480- updated_team_history = create_dictionary (gh , copilot_teams , existing_team_history )
481- with open (local_path , "w" , encoding = "utf-8" ) as f :
482- json .dump (updated_team_history , f , indent = 4 )
483- logger .info ("Team history written locally to %s (S3 skipped)" , local_path )
484-
485273 logger .info (
486274 "Process complete" ,
487275 extra = {
@@ -490,14 +278,13 @@ def handler(event: dict, context) -> str: # pylint: disable=unused-argument, to
490278 "dates_added" : dates_added ,
491279 "no_dates_before" : len (historic_usage ) - len (dates_added ),
492280 "no_dates_after" : len (historic_usage ),
493- "no_copilot_teams" : len (copilot_teams ),
494281 },
495282 )
496283
497284 return "Github Data logging is now complete."
498285
499286
500- # # Dev Only
501- # # Uncomment the following line to run the script locally
502- if __name__ == "__main__" :
503- handler (None , None )
287+ # Dev Only
288+ # Uncomment the following line to run the script locally
289+ # if __name__ == "__main__":
290+ # handler(None, None)
0 commit comments