2022-12-05 23:01:03 +00:00
module . exports = {
friendlyName : 'Get bug and PR report' ,
description : 'Get information about open bugs and closed pull requests in the fleetdm/fleet GitHub repo.' ,
inputs : {
} ,
fn : async function ( { } ) {
sails . log ( 'Getting metrics for issues with the "bug" label and pull requests in the fleetdm/fleet Github repo...' ) ;
if ( ! sails . config . custom . githubAccessToken ) {
throw new Error ( 'Missing GitHub access token! To use this script, a GitHub access token is required. To resolve, add a GitHub access token to your local configuration (website/config/local.js) as sails.config.custom.githubAccessToken or provide one when running this script. (ex: "sails_custom__githubAccessToken=YOUR_PERSONAL_ACCESS_TOKEN sails run get-bug-and-pr-report")' ) ;
}
let baseHeaders = {
'User-Agent' : 'Fleet average open time' ,
'Authorization' : ` token ${ sails . config . custom . githubAccessToken } `
} ;
const ONE _DAY _IN _MILLISECONDS = ( 1000 * 60 * 60 * 24 ) ;
const todaysDate = new Date ;
const threeWeeksAgo = new Date ( Date . now ( ) - ( 21 * ONE _DAY _IN _MILLISECONDS ) ) ;
const NUMBER _OF _RESULTS _REQUESTED = 100 ;
let daysSinceBugsWereOpened = [ ] ;
let daysSincePullRequestsWereOpened = [ ] ;
let commitToMergeTimesInDays = [ ] ;
await sails . helpers . flow . simultaneously ( [
// ██████╗ ██████╗ ███████╗███╗ ██╗ ██████╗ ██╗ ██╗ ██████╗ ███████╗
// ██╔═══██╗██╔══██╗██╔════╝████╗ ██║ ██╔══██╗██║ ██║██╔════╝ ██╔════╝
// ██║ ██║██████╔╝█████╗ ██╔██╗ ██║ ██████╔╝██║ ██║██║ ███╗███████╗
// ██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║ ██╔══██╗██║ ██║██║ ██║╚════██║
// ╚██████╔╝██║ ███████╗██║ ╚████║ ██████╔╝╚██████╔╝╚██████╔╝███████║
// ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
//
async ( ) => {
let pageNumberForPossiblePaginatedResults = 0 ;
let allIssuesWithBugLabel = [ ] ;
// Fetch all open issues in the fleetdm/fleet repo with the bug label.
// Note: This will send requests to GitHub until the number of results is less than the number we requested.
await sails . helpers . flow . until ( async ( ) => {
// Increment the page of results we're requesting.
pageNumberForPossiblePaginatedResults += 1 ;
let issuesWithBugLabel = await sails . helpers . http . get (
` https://api.github.com/repos/fleetdm/fleet/issues ` ,
{
'state' : 'open' ,
'labels' : 'bug' ,
'per_page' : NUMBER _OF _RESULTS _REQUESTED ,
'page' : pageNumberForPossiblePaginatedResults ,
} ,
baseHeaders
) . retry ( ) ;
// Add the results to the allIssuesWithBugLabel array.
allIssuesWithBugLabel = allIssuesWithBugLabel . concat ( issuesWithBugLabel ) ;
2022-12-13 23:33:23 +00:00
// If we received less results than we requested, we've reached the last page of the results.
2022-12-05 23:01:03 +00:00
return issuesWithBugLabel . length !== NUMBER _OF _RESULTS _REQUESTED ;
} , 10000 ) ;
// iterate through the allIssuesWithBugLabel array, adding the number
for ( let issue of allIssuesWithBugLabel ) {
// Create a date object from the issue's created_at timestamp.
let issueOpenedOn = new Date ( issue . created _at ) ;
// Get the amount of time this issue has been open in milliseconds.
let timeOpenInMS = Math . abs ( todaysDate - issueOpenedOn ) ;
// Convert the miliseconds to days and add the value to the daysSinceBugsWereOpened array
let timeOpenInDays = timeOpenInMS / ONE _DAY _IN _MILLISECONDS ;
daysSinceBugsWereOpened . push ( timeOpenInDays ) ;
}
} ,
// ██████╗██╗ ██████╗ ███████╗███████╗██████╗ ██████╗ ██████╗ ███████╗
// ██╔════╝██║ ██╔═══██╗██╔════╝██╔════╝██╔══██╗ ██╔══██╗██╔══██╗██╔════╝
// ██║ ██║ ██║ ██║███████╗█████╗ ██║ ██║ ██████╔╝██████╔╝███████╗
// ██║ ██║ ██║ ██║╚════██║██╔══╝ ██║ ██║ ██╔═══╝ ██╔══██╗╚════██║
// ╚██████╗███████╗╚██████╔╝███████║███████╗██████╔╝ ██║ ██║ ██║███████║
// ╚═════╝╚══════╝ ╚═════╝ ╚══════╝╚══════╝╚═════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝
//
async ( ) => {
let pageNumberForPaginatedResults = 0 ;
let pullRequestsMergedInThePastThreeWeeks = [ ] ;
// Fetch the last 300 closed pull requests from the fleetdm/fleet GitHub Repo
await sails . helpers . flow . until ( async ( ) => {
// Increment the page of results we're requesting.
pageNumberForPaginatedResults += 1 ;
let closedPullRequests = await sails . helpers . http . get (
` https://api.github.com/repos/fleetdm/fleet/pulls ` ,
{
'state' : 'closed' ,
'sort' : 'updated' ,
'direction' : 'desc' ,
'per_page' : NUMBER _OF _RESULTS _REQUESTED ,
'page' : pageNumberForPaginatedResults ,
} ,
baseHeaders
) . retry ( ) ;
2022-12-13 23:33:23 +00:00
// Filter the PRs we received from Github using the pull request's merged_at date.
2022-12-05 23:01:03 +00:00
let resultsToAdd = closedPullRequests . filter ( ( pullRequest ) => {
return threeWeeksAgo <= new Date ( pullRequest . merged _at ) ;
} ) ;
// Add the filtered array of PRs to the array of all pull requests merged in the past three weeks.
pullRequestsMergedInThePastThreeWeeks = pullRequestsMergedInThePastThreeWeeks . concat ( resultsToAdd ) ;
2022-12-13 23:33:23 +00:00
// Stop when we've received results from the third page.
2022-12-05 23:01:03 +00:00
return pageNumberForPaginatedResults === 3 ;
} ) ;
// To get the timestamp of the first commit for each pull request, we'll need to send a request to the commits API endpoint.
await sails . helpers . flow . simultaneouslyForEach ( pullRequestsMergedInThePastThreeWeeks , async ( pullRequest ) => {
// Create a date object from the PR's merged_at timestamp.
let pullRequestMergedOn = new Date ( pullRequest . merged _at ) ;
// https://docs.github.com/en/rest/commits/commits#list-commits
let commitsOnThisPullRequest = await sails . helpers . http . get ( pullRequest . commits _url , { } , baseHeaders ) . retry ( ) ;
// Create a new Date from the timestamp of the first commit on this pull request.
let firstCommitAt = new Date ( commitsOnThisPullRequest [ 0 ] . commit . author . date ) ; // https://docs.github.com/en/rest/commits/commits#list-commits--code-samples
// Get the amount of time this issue has been open in milliseconds.
let timeFromCommitToMergeInMS = pullRequestMergedOn - firstCommitAt ;
// Convert the miliseconds to days and add the value to the daysSincePullRequestsWereOpened array.
let timeFromFirstCommitInDays = timeFromCommitToMergeInMS / ONE _DAY _IN _MILLISECONDS ;
commitToMergeTimesInDays . push ( timeFromFirstCommitInDays ) ;
} ) ;
} ,
// ██████╗ ██████╗ ███████╗███╗ ██╗ ██████╗ ██████╗ ███████╗
// ██╔═══██╗██╔══██╗██╔════╝████╗ ██║ ██╔══██╗██╔══██╗██╔════╝
// ██║ ██║██████╔╝█████╗ ██╔██╗ ██║ ██████╔╝██████╔╝███████╗
// ██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║ ██╔═══╝ ██╔══██╗╚════██║
// ╚██████╔╝██║ ███████╗██║ ╚████║ ██║ ██║ ██║███████║
// ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝╚══════╝
//
async ( ) => {
let pullRequestResultsPageNumber = 0 ;
let allOpenPullRequests = [ ] ;
// Fetch all open pull requests in the fleetdm/fleet repo.
// Note: This will send requests to GitHub until the number of results is less than the number we requested.
await sails . helpers . flow . until ( async ( ) => {
// Increment the page of results we're requesting.
pullRequestResultsPageNumber += 1 ;
let pullRequests = await sails . helpers . http . get (
` https://api.github.com/repos/fleetdm/fleet/pulls ` ,
{
'state' : 'open' ,
'per_page' : NUMBER _OF _RESULTS _REQUESTED ,
'page' : pullRequestResultsPageNumber ,
} ,
baseHeaders
) . retry ( ) ;
// Add the results to the array of results.
allOpenPullRequests = allOpenPullRequests . concat ( pullRequests ) ;
2022-12-13 23:33:23 +00:00
// If we received less results than we requested, we've reached the last page of the results.
2022-12-05 23:01:03 +00:00
return pullRequests . length !== NUMBER _OF _RESULTS _REQUESTED ;
} , 10000 ) ;
for ( let pullRequest of allOpenPullRequests ) {
// Create a date object from the PR's created_at timestamp.
let pullRequestOpenedOn = new Date ( pullRequest . created _at ) ;
// Get the amount of time this issue has been open in milliseconds.
let timeOpenInMS = Math . abs ( todaysDate - pullRequestOpenedOn ) ;
// Convert the miliseconds to days and add the value to the daysSincePullRequestsWereOpened array
let timeOpenInDays = timeOpenInMS / ONE _DAY _IN _MILLISECONDS ;
daysSincePullRequestsWereOpened . push ( timeOpenInDays ) ;
}
}
] ) ;
// Get the averages from the arrays of results.
let averageNumberOfDaysBugsAreOpenFor = Math . round ( _ . sum ( daysSinceBugsWereOpened ) / daysSinceBugsWereOpened . length ) ;
let averageNumberOfDaysFromCommitToMerge = Math . round ( _ . sum ( commitToMergeTimesInDays ) / commitToMergeTimesInDays . length ) ;
let averageDaysPullRequestsAreOpenFor = Math . round ( _ . sum ( daysSincePullRequestsWereOpened ) / daysSincePullRequestsWereOpened . length ) ;
// Log the results
sails . log ( `
Bugs :
-- -- -- -- -- -- -- -- -- -- -- -- -- -
Number of open issues with the "bug" label : $ { daysSinceBugsWereOpened . length }
Average open time : $ { averageNumberOfDaysBugsAreOpenFor } days .
Closed pull requests :
-- -- -- -- -- -- -- -- -- -- -- -- -- -
Number of pull requests merged in the past three weeks : $ { commitToMergeTimesInDays . length }
Average time from first commit to merge : $ { averageNumberOfDaysFromCommitToMerge } days .
Open pull requests
-- -- -- -- -- -- -- -- -- -- -- -- -- -
Number of open pull requests in the fleetdm / fleet Github repo : $ { daysSincePullRequestsWereOpened . length }
Average open time : $ { averageDaysPullRequestsAreOpenFor } days . ` );
}
} ;