mirror of
https://github.com/fleetdm/fleet
synced 2026-05-16 21:48:48 +00:00
469 lines
27 KiB
JavaScript
Vendored
469 lines
27 KiB
JavaScript
Vendored
module.exports = {
|
|
|
|
|
|
friendlyName: 'Get bug and PR report',
|
|
|
|
|
|
description: 'Get information about open bugs and pull requests.',
|
|
|
|
|
|
inputs: {
|
|
|
|
},
|
|
|
|
|
|
fn: async function ({}) {
|
|
|
|
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 daysSinceUnreleasedBugsWereOpened = [];
|
|
let daysSinceReleasedBugsWereOpened = [];
|
|
let allBugsWithUnreleasedLabel = [];
|
|
let allBugsWithReleasedLabel = [];
|
|
let allBugsCreatedInPastWeek = [];
|
|
let allBugsClosedInPastWeek = [];
|
|
let daysSincePullRequestsWereOpened = [];
|
|
let daysSinceContributorPullRequestsWereOpened = [];
|
|
let commitToMergeTimesInDays = [];
|
|
|
|
let allPublicOpenPrs = [];
|
|
let publicPrsMergedInThePastThreeWeeks = [];
|
|
let allNonPublicOpenPrs = [];
|
|
let nonPublicPrsClosedInThePastThreeWeeks = [];
|
|
|
|
// Product group KPIS
|
|
|
|
// Endpoint operations
|
|
let allBugsCreatedInPastWeekEndpointOps = [];
|
|
let allBugsCreatedInPastWeekEndpointOpsUnreleased = [];
|
|
let allBugsCreatedInPastWeekEndpointOpsReleased = [];
|
|
let allBugsCreatedInPastWeekEndpointOpsCustomerImpacting = [];
|
|
|
|
// Mobile Device Management
|
|
let allBugsCreatedInPastWeekMobileDeviceManagement = [];
|
|
|
|
let allBugsCreatedInPastWeekMobileDeviceManagementUnreleased = [];
|
|
let allBugsCreatedInPastWeekMobileDeviceManagementReleased = [];
|
|
let allBugsCreatedInPastWeekMobileDeviceManagementCustomerImpacting = [];
|
|
|
|
|
|
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);
|
|
// If we received less results than we requested, we've reached the last page of the results.
|
|
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;
|
|
if (timeOpenInDays <= 7) {
|
|
allBugsCreatedInPastWeek.push(issue);
|
|
// Get Endpoint Ops KPIs
|
|
if (issue.labels.some(label => label.name === '#g-endpoint-ops')) {
|
|
allBugsCreatedInPastWeekEndpointOps.push(issue);
|
|
if (issue.labels.some(label => label.name === '~unreleased bug')) {
|
|
allBugsCreatedInPastWeekEndpointOpsUnreleased.push(issue);
|
|
}
|
|
else if (issue.labels.some(label => label.name === '~released bug')) {
|
|
allBugsCreatedInPastWeekEndpointOpsReleased.push(issue);
|
|
}
|
|
if (issue.labels.some(label => label.name.indexOf('customer-') >= 0)) {
|
|
allBugsCreatedInPastWeekEndpointOpsCustomerImpacting.push(issue);
|
|
}
|
|
}
|
|
// Get MDM KPIs
|
|
if (issue.labels.some(label => label.name === '#g-mdm')) {
|
|
allBugsCreatedInPastWeekMobileDeviceManagement.push(issue);
|
|
if (issue.labels.some(label => label.name === '~unreleased bug')) {
|
|
allBugsCreatedInPastWeekMobileDeviceManagementUnreleased.push(issue);
|
|
}
|
|
else if (issue.labels.some(label => label.name === '~released bug')) {
|
|
allBugsCreatedInPastWeekMobileDeviceManagementReleased.push(issue);
|
|
}
|
|
if (issue.labels.some(label => label.name.indexOf('customer-') >= 0)) {
|
|
allBugsCreatedInPastWeekMobileDeviceManagementCustomerImpacting.push(issue);
|
|
}
|
|
}
|
|
}
|
|
daysSinceBugsWereOpened.push(timeOpenInDays);
|
|
// Send to released or unreleased bugs array
|
|
if (issue.labels.some(label => label.name === '~unreleased bug')) {
|
|
allBugsWithUnreleasedLabel.push(issue);
|
|
daysSinceUnreleasedBugsWereOpened.push(timeOpenInDays);
|
|
} else if (issue.labels.some(label => label.name === '~released bug')) {
|
|
allBugsWithReleasedLabel.push(issue);
|
|
daysSinceReleasedBugsWereOpened.push(timeOpenInDays);
|
|
} else {
|
|
// If not labeled as a released or unreleased bug, log a warning.
|
|
sails.log.warn('Issue #'+issue.number+' is labeled as a bug but is not labeled as released or unreleased.');
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
// ██████╗██╗ ██████╗ ███████╗███████╗██████╗ ██████╗ ██╗ ██╗ ██████╗ ███████╗
|
|
// ██╔════╝██║ ██╔═══██╗██╔════╝██╔════╝██╔══██╗ ██╔══██╗██║ ██║██╔════╝ ██╔════╝
|
|
// ██║ ██║ ██║ ██║███████╗█████╗ ██║ ██║ ██████╔╝██║ ██║██║ ███╗███████╗
|
|
// ██║ ██║ ██║ ██║╚════██║██╔══╝ ██║ ██║ ██╔══██╗██║ ██║██║ ██║╚════██║
|
|
// ╚██████╗███████╗╚██████╔╝███████║███████╗██████╔╝ ██████╔╝╚██████╔╝╚██████╔╝███████║
|
|
// ╚═════╝╚══════╝ ╚═════╝ ╚══════╝╚══════╝╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
|
|
//
|
|
|
|
async()=>{
|
|
|
|
let pageNumberForPaginatedResults = 0;
|
|
let allIssuesWithBugLabel = [];
|
|
|
|
// Fetch all closed 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.
|
|
pageNumberForPaginatedResults += 1;
|
|
let issuesWithBugLabel = await sails.helpers.http.get(
|
|
`https://api.github.com/repos/fleetdm/fleet/issues`,
|
|
{
|
|
'state': 'closed',
|
|
'labels': 'bug',
|
|
'per_page': NUMBER_OF_RESULTS_REQUESTED,
|
|
'page': pageNumberForPaginatedResults,
|
|
},
|
|
baseHeaders
|
|
).retry();
|
|
// Add the results to the allIssuesWithBugLabel array.
|
|
allIssuesWithBugLabel = allIssuesWithBugLabel.concat(issuesWithBugLabel);
|
|
// Stop when we've received results from the third page.
|
|
return pageNumberForPaginatedResults === 3;
|
|
}, 10000);
|
|
|
|
// iterate through the allIssuesWithBugLabel array, adding the number
|
|
for (let issue of allIssuesWithBugLabel) {
|
|
// Create a date object from the issue's closed_at timestamp.
|
|
let issueClosedOn = new Date(issue.closed_at);
|
|
// Get the amount of time this issue has been closed in milliseconds.
|
|
let timeClosedInMS = Math.abs(todaysDate - issueClosedOn);
|
|
// Convert the miliseconds to days and add the value to the allBugsClosedInPastWeek array
|
|
let timeClosedInDays = timeClosedInMS / ONE_DAY_IN_MILLISECONDS;
|
|
if (timeClosedInDays <= 7) {
|
|
allBugsClosedInPastWeek.push(issue);
|
|
}
|
|
}
|
|
},
|
|
|
|
// ██████╗██╗ ██████╗ ███████╗███████╗██████╗ ██████╗ ██████╗ ███████╗
|
|
// ██╔════╝██║ ██╔═══██╗██╔════╝██╔════╝██╔══██╗ ██╔══██╗██╔══██╗██╔════╝
|
|
// ██║ ██║ ██║ ██║███████╗█████╗ ██║ ██║ ██████╔╝██████╔╝███████╗
|
|
// ██║ ██║ ██║ ██║╚════██║██╔══╝ ██║ ██║ ██╔═══╝ ██╔══██╗╚════██║
|
|
// ╚██████╗███████╗╚██████╔╝███████║███████╗██████╔╝ ██║ ██║ ██║███████║
|
|
// ╚═════╝╚══════╝ ╚═════╝ ╚══════╝╚══════╝╚═════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝
|
|
//
|
|
async()=>{
|
|
|
|
let pageNumberForPaginatedResults = 0;
|
|
|
|
// Fetch the last 300 closed pull requests from the fleetdm/fleet GitHub Repo
|
|
// [?] https://docs.github.com/en/free-pro-team@latest/rest/pulls/pulls#list-pull-requests
|
|
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();
|
|
|
|
// Exclude draft PRs and filter the PRs we received from Github using the pull request's merged_at date.
|
|
let resultsToAdd = closedPullRequests.filter((pullRequest)=>{
|
|
return !pullRequest.draft && 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.
|
|
publicPrsMergedInThePastThreeWeeks = publicPrsMergedInThePastThreeWeeks.concat(resultsToAdd);
|
|
// Stop when we've received results from the third page.
|
|
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(publicPrsMergedInThePastThreeWeeks, async (pullRequest)=>{
|
|
// Create a date object from the PR's merged_at timestamp.
|
|
let pullRequestMergedOn = new Date(pullRequest.merged_at);
|
|
|
|
// Get commits on this PR.
|
|
// [?] 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 contributorPullRequests = [];
|
|
// 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.
|
|
// [?] https://docs.github.com/en/free-pro-team@latest/rest/pulls/pulls#list-pull-requests
|
|
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.
|
|
allPublicOpenPrs = allPublicOpenPrs.concat(pullRequests);
|
|
// If we received less results than we requested, we've reached the last page of the results.
|
|
return pullRequests.length !== NUMBER_OF_RESULTS_REQUESTED;
|
|
}, 10000);
|
|
|
|
for(let pullRequest of allPublicOpenPrs) {
|
|
// 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;
|
|
if (!pullRequest.draft) {// Exclude draft PRs
|
|
daysSincePullRequestsWereOpened.push(timeOpenInDays);
|
|
}
|
|
// If not a draft, not a bot, not a PR labeled with #handbook
|
|
// Track as a contributor PR and include in contributor PR KPI
|
|
if (!pullRequest.draft && pullRequest.user.type !== 'Bot' && !pullRequest.labels.some(label => label.name === '#handbook' || label.name === '~ceo' || label.name === ':improve documentation')) {
|
|
daysSinceContributorPullRequestsWereOpened.push(timeOpenInDays);
|
|
contributorPullRequests.push(pullRequest);
|
|
}
|
|
}//∞
|
|
|
|
},
|
|
|
|
// ███╗ ██╗ ██████╗ ███╗ ██╗ ██████╗ ██╗ ██╗██████╗ ██╗ ██╗ ██████╗
|
|
// ████╗ ██║██╔═══██╗████╗ ██║ ██╔══██╗██║ ██║██╔══██╗██║ ██║██╔════╝
|
|
// ██╔██╗ ██║██║ ██║██╔██╗ ██║█████╗██████╔╝██║ ██║██████╔╝██║ ██║██║
|
|
// ██║╚██╗██║██║ ██║██║╚██╗██║╚════╝██╔═══╝ ██║ ██║██╔══██╗██║ ██║██║
|
|
// ██║ ╚████║╚██████╔╝██║ ╚████║ ██║ ╚██████╔╝██████╔╝███████╗██║╚██████╗
|
|
// ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═════╝
|
|
//
|
|
async()=>{
|
|
|
|
// Fetch confidential and classified PRs (current open, and recent closed)
|
|
for (let repoName of ['classified', 'confidential']) {
|
|
// [?] https://docs.github.com/en/free-pro-team@latest/rest/pulls/pulls#list-pull-requests
|
|
let openPrs = await sails.helpers.http.get(`https://api.github.com/repos/fleetdm/${encodeURIComponent(repoName)}/pulls`, {
|
|
state: 'open',
|
|
'per_page': 100,
|
|
page: 1,
|
|
}, baseHeaders);
|
|
allNonPublicOpenPrs = allNonPublicOpenPrs.concat(openPrs);
|
|
|
|
// [?] https://docs.github.com/en/free-pro-team@latest/rest/pulls/pulls#list-pull-requests
|
|
let last100ClosedPrs = await sails.helpers.http.get(`https://api.github.com/repos/fleetdm/${encodeURIComponent(repoName)}/pulls`, {
|
|
state: 'closed',
|
|
sort: 'updated',
|
|
direction: 'desc',
|
|
'per_page': 100,
|
|
page: 1,
|
|
}, baseHeaders);
|
|
|
|
// Exclude draft PRs and filter the PRs we received from Github using the pull request's closed_at date.
|
|
nonPublicPrsClosedInThePastThreeWeeks = nonPublicPrsClosedInThePastThreeWeeks.concat(
|
|
last100ClosedPrs.filter((pr)=>{
|
|
return !pr.draft && threeWeeksAgo.getTime() <= (new Date(pr.closed_at)).getTime();
|
|
})
|
|
);
|
|
}//∞
|
|
}
|
|
|
|
]);
|
|
|
|
// Get the averages from the arrays of results.
|
|
let averageNumberOfDaysBugsAreOpenFor = Math.round(_.sum(daysSinceBugsWereOpened) / daysSinceBugsWereOpened.length);
|
|
let averageNumberOfDaysUnreleasedBugsAreOpenFor = Math.round(_.sum(daysSinceUnreleasedBugsWereOpened) / daysSinceUnreleasedBugsWereOpened.length);
|
|
let averageNumberOfDaysReleasedBugsAreOpenFor = Math.round(_.sum(daysSinceReleasedBugsWereOpened)/daysSinceReleasedBugsWereOpened.length);
|
|
let averageDaysPullRequestsAreOpenFor = Math.round(_.sum(daysSincePullRequestsWereOpened)/daysSincePullRequestsWereOpened.length);
|
|
let averageDaysContributorPullRequestsAreOpenFor = Math.round(_.sum(daysSinceContributorPullRequestsWereOpened)/daysSinceContributorPullRequestsWereOpened.length);
|
|
|
|
|
|
// Compute CEO-dependent PR KPIs, which are slightly simpler.
|
|
// FUTURE: Refactor this to be less messy.
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
let ceoDependentOpenPrs = [];
|
|
ceoDependentOpenPrs = ceoDependentOpenPrs.concat(allPublicOpenPrs.filter((pr) => !pr.draft && _.pluck(pr.labels, 'name').includes('~ceo')));
|
|
ceoDependentOpenPrs = ceoDependentOpenPrs.concat(allNonPublicOpenPrs.filter((pr) => !pr.draft && _.pluck(pr.labels, 'name').includes('~ceo')));
|
|
|
|
let ceoDependentPrsMergedRecently = [];
|
|
ceoDependentPrsMergedRecently = ceoDependentPrsMergedRecently.concat(publicPrsMergedInThePastThreeWeeks.filter((pr) => !pr.draft && _.pluck(pr.labels, 'name').includes('~ceo')));
|
|
ceoDependentPrsMergedRecently = ceoDependentPrsMergedRecently.concat(nonPublicPrsClosedInThePastThreeWeeks.filter((pr) => !pr.draft && _.pluck(pr.labels, 'name').includes('~ceo')));
|
|
|
|
let ceoDependentPrOpenTime = ceoDependentPrsMergedRecently.reduce((avgDaysOpen, pr)=>{
|
|
let openedAt = new Date(pr.created_at).getTime();
|
|
let closedAt = new Date(pr.closed_at).getTime();
|
|
let daysOpen = Math.abs(closedAt - openedAt) / ONE_DAY_IN_MILLISECONDS;
|
|
avgDaysOpen = avgDaysOpen + (daysOpen / ceoDependentPrsMergedRecently.length);
|
|
sails.log.verbose('Processing',pr.head.repo.name,':: #'+pr.number,'open '+daysOpen+' days', 'rolling avg now '+avgDaysOpen);
|
|
return avgDaysOpen;
|
|
}, 0);
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
const kpiResults = [];
|
|
|
|
// NOTE: If order of the KPI sheets columns changes, the order values are pushed into this array needs to change, as well.
|
|
kpiResults.push(
|
|
averageDaysContributorPullRequestsAreOpenFor,
|
|
daysSinceContributorPullRequestsWereOpened.length,
|
|
averageDaysPullRequestsAreOpenFor,
|
|
daysSincePullRequestsWereOpened.length,
|
|
averageNumberOfDaysReleasedBugsAreOpenFor,
|
|
averageNumberOfDaysUnreleasedBugsAreOpenFor,
|
|
allBugsClosedInPastWeek.length,
|
|
averageNumberOfDaysBugsAreOpenFor,
|
|
allBugsCreatedInPastWeek.length,
|
|
allBugsCreatedInPastWeekEndpointOps.length,
|
|
allBugsCreatedInPastWeekEndpointOpsCustomerImpacting.length,
|
|
allBugsCreatedInPastWeekEndpointOpsReleased.length,
|
|
allBugsCreatedInPastWeekEndpointOpsUnreleased.length,
|
|
allBugsCreatedInPastWeekMobileDeviceManagement.length,
|
|
allBugsCreatedInPastWeekMobileDeviceManagementCustomerImpacting.length,
|
|
allBugsCreatedInPastWeekMobileDeviceManagementReleased.length,
|
|
allBugsCreatedInPastWeekMobileDeviceManagementUnreleased.length,
|
|
daysSinceBugsWereOpened.length,
|
|
allBugsWithReleasedLabel.length,
|
|
allBugsWithUnreleasedLabel.length);
|
|
|
|
// Log the results
|
|
sails.log(`
|
|
|
|
CSV for copy-pasting into KPI spreadsheet:
|
|
---------------------------
|
|
${kpiResults.join(',')}
|
|
|
|
Note: Copy the values above, then in Google sheets paste them into a cell and select "Split text to columns" to paste the values into separate cells.
|
|
|
|
Pull requests:
|
|
---------------------------
|
|
Average open time (no bots, no handbook, no ceo): ${averageDaysContributorPullRequestsAreOpenFor} days.
|
|
Number of open pull requests in the fleetdm/fleet Github repo (no bots, no handbook, no ceo): ${daysSinceContributorPullRequestsWereOpened.length}
|
|
|
|
Average open time (all PRs): ${averageDaysPullRequestsAreOpenFor} days.
|
|
Number of open pull requests in the fleetdm/fleet Github repo: ${daysSincePullRequestsWereOpened.length}
|
|
|
|
Bugs (part 1):
|
|
---------------------------
|
|
Average open time (released bugs): ${averageNumberOfDaysReleasedBugsAreOpenFor} days.
|
|
|
|
Average open time (unreleased bugs): ${averageNumberOfDaysUnreleasedBugsAreOpenFor} days.
|
|
|
|
Number of issues with the "bug" label closed in the past week: ${allBugsClosedInPastWeek.length}
|
|
|
|
Average open time (all bugs): ${averageNumberOfDaysBugsAreOpenFor} days.
|
|
|
|
Number of issues with the "bug" label opened in the past week: ${allBugsCreatedInPastWeek.length}
|
|
|
|
Endpoint Operations:
|
|
---------------------------
|
|
Number of issues with the "#g-endpoint-ops" and "bug" labels opened in the past week: ${allBugsCreatedInPastWeekEndpointOps.length}
|
|
|
|
Number of issues with the "#g-endpoint-ops", "bug", and "customer-" labels opened in the past week: ${allBugsCreatedInPastWeekEndpointOpsCustomerImpacting.length}
|
|
|
|
Number of issues with the "#g-endpoint-ops", "bug", and "~released bug" labels opened in the past week: ${allBugsCreatedInPastWeekEndpointOpsReleased.length}
|
|
|
|
Number of issues with the "#g-endpoint-ops", "bug", and "~unreleased bug" labels opened in the past week: ${allBugsCreatedInPastWeekEndpointOpsUnreleased.length}
|
|
|
|
MDM:
|
|
---------------------------
|
|
Number of issues with the "#g-mdm" and "bug" labels opened in the past week: ${allBugsCreatedInPastWeekMobileDeviceManagement.length}
|
|
|
|
Number of issues with the "#g-mdm", "bug", and "customer-" labels opened in the past week: ${allBugsCreatedInPastWeekMobileDeviceManagementCustomerImpacting.length}
|
|
|
|
Number of issues with the "#g-emdm", "bug", and "~released bug" labels opened in the past week: ${allBugsCreatedInPastWeekMobileDeviceManagementReleased.length}
|
|
|
|
Number of issues with the "#g-mdm", "bug", and "~unreleased bug" labels opened in the past week: ${allBugsCreatedInPastWeekMobileDeviceManagementUnreleased.length}
|
|
|
|
Bugs (part 2):
|
|
---------------------------
|
|
Number of open issues with the "bug" label in fleetdm/fleet: ${daysSinceBugsWereOpened.length}
|
|
|
|
Number of open issues with the "~released bug" label in fleetdm/fleet: ${allBugsWithReleasedLabel.length}
|
|
|
|
Number of open issues with the "~unreleased bug" label in fleetdm/fleet: ${allBugsWithUnreleasedLabel.length}
|
|
|
|
Pull requests requiring CEO review
|
|
---------------------------------------
|
|
Number of open ~ceo pull requests in the fleetdm Github org: ${ceoDependentOpenPrs.length}
|
|
Average open time (~ceo PRs): ${Math.round(ceoDependentPrOpenTime*100)/100} days.
|
|
`);
|
|
|
|
}
|
|
|
|
};
|
|
|