From 38df8948a9e5907ec1d337aaed2c6569647c2b55 Mon Sep 17 00:00:00 2001 From: rich Date: Mon, 16 Sep 2024 13:15:01 +0100 Subject: [PATCH] Add open bot PR count to table User need to know how many of the open PRs are automated depdency updates. This column shows how many open PRs exist for a repo where the user login is either `renovate[bot]` or `dependabot[bot]`. This may need to be finetuned later. --- e2es/testData/repos.json | 9 +++-- index.njk | 6 ++-- utils/githubApi/fetchOpenPrs.js | 11 +++++- utils/githubApi/fetchOpenPrs.test.js | 54 +++++++++++++++++++++++++--- utils/sorting.js | 9 +++-- 5 files changed, 76 insertions(+), 13 deletions(-) diff --git a/e2es/testData/repos.json b/e2es/testData/repos.json index 40e3595..595a6a7 100644 --- a/e2es/testData/repos.json +++ b/e2es/testData/repos.json @@ -13,7 +13,8 @@ "topics": ["composer", "govpress", "packagist", "php"], "openIssues": 0, "dependencies": [], - "openPrsCount": 0 + "openPrsCount": 0, + "openBotPrCount": 0 }, { "name": "govuk-blogs", @@ -27,7 +28,8 @@ "topics": ["govpress", "wordpress-theme"], "openIssues": 1, "dependencies": [], - "openPrsCount": 0 + "openPrsCount": 0, + "openBotPrCount": 1 }, { "name": "php-missing", @@ -41,7 +43,8 @@ "topics": ["composer", "govpress", "packagist", "php"], "openIssues": 7, "dependencies": [], - "openPrsCount": 2 + "openPrsCount": 2, + "openBotPrCount": 3 } ] } diff --git a/index.njk b/index.njk index db6f739..91fd518 100644 --- a/index.njk +++ b/index.njk @@ -37,7 +37,8 @@ Language Topics {{macros.sortableTableHeader("Open issues count", "openIssues", sortDirection, sortBy)}} - {{macros.sortableTableHeader("Open PRs count", "openPrsCount", sortDirection, sortBy)}} + {{macros.sortableTableHeader("Bot PR count", "openBotPrCount", sortDirection, sortBy)}} + {{macros.sortableTableHeader("Open PR count", "openPrCount", sortDirection, sortBy)}} {{macros.sortableTableHeader("Updated at", "updatedAt", sortDirection, sortBy)}} Dependencies @@ -50,7 +51,8 @@ {{ repo.language }} {{ repo.topics | join(", ")}} {{ repo.openIssues }} - {{ repo.openPrsCount }} + {{ repo.openBotPrCount }} + {{ repo.openPrCount }} {{ repo.updatedAt }} {% if repo.dependencies.length %} diff --git a/utils/githubApi/fetchOpenPrs.js b/utils/githubApi/fetchOpenPrs.js index b724770..cc77fe7 100644 --- a/utils/githubApi/fetchOpenPrs.js +++ b/utils/githubApi/fetchOpenPrs.js @@ -8,11 +8,20 @@ export const getOpenPRsForRepo = async ({ octokit, repository }) => { return octokit.request(repository.pulls_url).then(handlePrsApiResponse); }; +const depdencyUpdateBots = ["renovate[bot]", "dependabot[bot]"]; + /** * Returns the length of the PRs array or 0 if there are no PRs * @param {any} {data} * @returns {number} */ export const handlePrsApiResponse = ({ data }) => { - return { openPrCount: data?.length || 0 }; + const openBotPrCount = data.reduce((acc, pr) => { + if (depdencyUpdateBots.includes(pr?.user?.login)) { + return acc + 1; + } + return acc; + }, 0); + + return { openPrCount: data?.length || 0, openBotPrCount }; }; diff --git a/utils/githubApi/fetchOpenPrs.test.js b/utils/githubApi/fetchOpenPrs.test.js index 3439cbb..4f02ee4 100644 --- a/utils/githubApi/fetchOpenPrs.test.js +++ b/utils/githubApi/fetchOpenPrs.test.js @@ -2,20 +2,66 @@ import { describe, it } from "node:test"; import expect from "node:assert"; import { handlePrsApiResponse } from "./fetchOpenPrs.js"; -describe("handlePrsApiResponse", () => { +describe.only("handlePrsApiResponse", () => { describe("openPRCount", () => { it("returns the length of the array containing PRs", () => { const actual = handlePrsApiResponse({ data: [1, 2, 3] }); - const expected = { openCount: 3 }; + const expected = { openPrCount: 3, openBotPrCount: 0 }; expect.deepEqual(actual, expected); }); it("returns 0 if there are no open PRs", () => { const actual = handlePrsApiResponse({ data: [] }); - const expected = { openCount: 0 }; + const expected = { openPrCount: 0, openBotPrCount: 0 }; - expect.equal(actual, expected); + expect.deepEqual(actual, expected); + }); + }); + + describe("openBotPrCount", () => { + it("returns 1 if there is a PR authored by dependabot", () => { + const dependabotPr = { user: { login: "dependabot[bot]" } }; + const actual = handlePrsApiResponse({ data: [dependabotPr] }); + + expect.equal(actual.openBotPrCount, 1); + }); + + it("returns 1 if there is a PR authored by renovate", () => { + const renovatePr = { user: { login: "renovate[bot]" } }; + const actual = handlePrsApiResponse({ data: [renovatePr] }); + + expect.equal(actual.openBotPrCount, 1); + }); + + it("returns 0 if there is a PR authored by other authors", () => { + const humanPr = { user: { login: "rich" } }; + const actual = handlePrsApiResponse({ data: [humanPr] }); + + expect.equal(actual.openBotPrCount, 0); + }); + + it("handles a variety of PR authors correctly", () => { + const dependabotPr = { + user: { + login: "dependabot[bot]", + }, + }; + const renovatePr = { + user: { + login: "renovate[bot]", + }, + }; + const humanPr = { + user: { + login: "rich", + }, + }; + const actual = handlePrsApiResponse({ + data: [dependabotPr, renovatePr, humanPr], + }); + + expect.equal(actual.openBotPrCount, 2); }); }); }); diff --git a/utils/sorting.js b/utils/sorting.js index 366fa46..3f2f175 100644 --- a/utils/sorting.js +++ b/utils/sorting.js @@ -41,15 +41,18 @@ export const sortByUpdatedAt = (repos, sortDirection) => { /** * Sorts repositories based on the specified type and direction. - * @param {"openPrsCount"|"openIssues"} sortBy - The type of sorting to apply, either by open PRs count or open issues. + * @param {"openPrCount"|"openBotPrCount"|"openIssues"|} sortBy - The type of sorting to apply, either by open PRs count or open issues. * @param {SortDirection} sortDirection - The direction to sort, either "asc" for ascending or "desc" for descending. * @param {UiRepo[]} repos - An array of repository objects to sort. * @returns {UiRepo[]} The sorted array of repository objects. */ export const sortByType = (repos, sortDirection, sortBy) => { switch (sortBy) { - case "openPrsCount": - return sortByNumericValue(repos, sortDirection, "openPrsCount"); + case "openPrCount": + return sortByNumericValue(repos, sortDirection, "openPrCount"); + + case "openBotPrCount": + return sortByNumericValue(repos, sortDirection, "openBotPrCount"); case "openIssues": return sortByNumericValue(repos, sortDirection, "openIssues");