Skip to content

Commit

Permalink
ci: compile estimate totals per milestone (#10442)
Browse files Browse the repository at this point in the history
**Related Issue:** #8359

## Summary

Add an action that creates a spreadsheet and JSON file with the total
estimates per milestone. The action runs when an issue closes and can be
manually dispatched. The files are saved as artifacts in the workflow
run. I'll add a wiki page about running the workflow and retrieving the
data once it's live.

It might be because I'm a GraphQL noob, but Monday's API reference was
not very helpful. I can give the integration another try if this is not
ergonomic enough.
  • Loading branch information
benelan authored Oct 1, 2024
1 parent 064af48 commit 06105ac
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 0 deletions.
78 changes: 78 additions & 0 deletions .github/scripts/trackMilestoneEstimates.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// @ts-check
const { writeFile } = require("fs/promises");

/** @param {import('github-script').AsyncFunctionArguments} AsyncFunctionArguments */
module.exports = async ({ github, context, core }) => {
const { repo, owner } = context.repo;

const outputJson = {};
let outputCsv = "id,title,due_on,open_issues,closed_issues,remaining_estimate,completed_estimate";

try {
const milestones = await github.rest.issues.listMilestones({
owner: owner,
repo: repo,
state: "all",
sort: "due_on",
per_page: 100,
direction: "desc",
});

if (milestones.data.length === 0) {
console.error("No milestones found.");
process.exit(1);
}

for (const milestone of milestones.data) {
outputJson[milestone.number] = {
title: milestone.title,
due_on: milestone.due_on,
open_issues: milestone.open_issues,
closed_issues: milestone.closed_issues,
remaining_estimate: 0,
completed_estimate: 0,
};

const issues = await github.paginate(github.rest.issues.listForRepo, {
// @ts-ignore milestone.number is valid: https://docs.github.com/en/rest/issues/issues#list-repository-issues--parameters
milestone: milestone.number,
owner: owner,
repo: repo,
state: "all",
per_page: 100,
});

for (const issue of issues) {
if (issue.pull_request) {
continue;
}

for (const label of issue.labels) {
const estimateLabelMatch = (typeof label === "string" ? label : label?.name)?.match(/estimate - (\d+)/);

if (estimateLabelMatch?.length > 1) {
outputJson[milestone.number][issue.state === "open" ? "remaining_estimate" : "completed_estimate"] +=
Number.parseInt(estimateLabelMatch[1]);

break; // assumes an issue will only have one estimate label
}
}
}

outputCsv = `${outputCsv}\n${milestone.number},${Object.values(outputJson[milestone.number]).join(",")}`;
}

const stringifiedOutputJson = JSON.stringify(outputJson, null, 2);

core.debug(`JSON Output:\n${stringifiedOutputJson}`);
core.debug(`CSV Output:\n${outputCsv}`);

await writeFile("./milestone-estimates.csv", outputCsv);
await writeFile("./milestone-estimates.json", stringifiedOutputJson);

process.exit(0);
} catch (error) {
console.error(error);
process.exit(1);
}
};
21 changes: 21 additions & 0 deletions .github/workflows/track-milestone-estimates.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Track Milestone Estimates
on:
workflow_dispatch:
issues:
types: [closed]
jobs:
estimates:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create estimates data
uses: actions/github-script@v7
with:
script: |
const action = require('${{ github.workspace }}/.github/scripts/trackMilestoneEstimates.js')
await action({github, context, core})
- name: Upload estimates data
uses: actions/upload-artifact@v4
with:
name: milestone-estimates
path: milestone-estimates.*

0 comments on commit 06105ac

Please sign in to comment.