GitHub Service
The GitHub Service provides centralised functionality for interacting with the GitHub API, specifically for retrieving GitHub Copilot metrics and seat information. It handles authentication through the GitHub App integration and provides automatic pagination for large data sets.
Overview
The service specialises in GitHub Copilot data retrieval: - Organisation-level Copilot metrics - Seat information and assignment data - Automatic pagination handling - Integration with GitHub App authentication
Dependencies
The service relies on:
- GitHub App authentication (via getAppAndInstallation
utility)
- Application logging system
- Environment variables for organisation configuration
Methods
getCopilotMetrics()
Retrieves comprehensive GitHub Copilot metrics for the organisation.
Returns: Promise resolving to Copilot metrics object
GitHub API Response:
More information on the response structure can be found here.
Example:
const githubService = require('./githubService');
try {
const metrics = await githubService.getCopilotMetrics();
console.log(`Total Copilot seats: ${metrics.seat_breakdown.total}`);
} catch (error) {
console.error('Failed to retrieve Copilot metrics:', error);
}
getCopilotSeats()
Retrieves detailed information about all GitHub Copilot seats in the organisation.
Returns: Promise resolving to array of seat objects
GitHub API Response:
More information on the response structure can be found here.
[
{
created_at: string,
updated_at: string,
pending_cancellation_date: string | null,
last_activity_at: string,
last_activity_editor: string,
assignee: {
login: string,
id: number,
avatar_url: string,
// ... other user properties
}
}
// ... more seats
]
Features: - Automatic pagination handling for large organisations - Complete seat information including activity data - User assignee details
Example:
const seats = await githubService.getCopilotSeats();
console.log(`Retrieved ${seats.length} Copilot seats`);
// Find recently active seats
const recentlyActive = seats.filter(seat =>
new Date(seat.last_activity_at) > new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
);
console.log(`${recentlyActive.length} seats active in the last 7 days`);
Authentication
The service uses GitHub App authentication:
- Retrieves GitHub App credentials from AWS Secrets Manager
- Authenticates using the App ID and private key
- Gets installation access for the configured organisation
- Uses installation-scoped Octokit instance for API calls
Pagination Handling
The getCopilotSeats()
method automatically handles pagination:
- Starts with the first page of results
- Continues fetching until all pages are retrieved
- Combines results into a single array
- Logs progress for monitoring
// Automatic pagination example
let allSeats = [];
let page = 1;
while (true) {
const response = await octokit.request(
`GET /orgs/${GITHUB_ORG}/copilot/billing/seats`,
{ per_page: 100, page }
);
if (response.data.seats.length === 0) break;
allSeats = allSeats.concat(response.data.seats);
page++;
}
Error Handling
The service implements robust error handling:
- Logs authentication failures
- Handles GitHub API rate limiting
- Provides descriptive error messages
- Graceful degradation for failed requests
Environment Configuration
Required environment variables:
GITHUB_ORG
- Target GitHub organisation nameGITHUB_APP_ID
- GitHub App ID for authenticationAWS_SECRET_NAME
- AWS Secrets Manager secret containing private keyAWS_REGION
- AWS region for Secrets Manager
Usage Examples
Retrieve Current Metrics
const githubService = require('../services/githubService');
async function getCopilotSummary() {
try {
const metrics = await githubService.getCopilotMetrics();
const seats = await githubService.getCopilotSeats();
return {
totalSeats: metrics.seat_breakdown.total,
activeSeats: metrics.seat_breakdown.active_this_cycle,
seatDetails: seats.length,
lastUpdate: new Date().toISOString()
};
} catch (error) {
console.error('Failed to get Copilot summary:', error);
throw error;
}
}
Monitor Seat Activity
async function getInactiveSeats(daysThreshold = 30) {
const seats = await githubService.getCopilotSeats();
const cutoffDate = new Date(Date.now() - daysThreshold * 24 * 60 * 60 * 1000);
return seats.filter(seat =>
new Date(seat.last_activity_at) < cutoffDate
).map(seat => ({
user: seat.assignee.login,
lastActivity: seat.last_activity_at,
daysSinceActivity: Math.floor(
(Date.now() - new Date(seat.last_activity_at)) / (1000 * 60 * 60 * 24)
)
}));
}
Implementation Notes
- Uses authenticated GitHub App for enhanced rate limits
- Implements automatic pagination for scalability
- Provides comprehensive error logging
- Designed for organisation-level Copilot management
- Supports monitoring and analytics use cases