Skip to content

Commit

Permalink
Add open bot PR count to table
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rich committed Sep 16, 2024
1 parent b4b7c63 commit 38df894
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 13 deletions.
9 changes: 6 additions & 3 deletions e2es/testData/repos.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"topics": ["composer", "govpress", "packagist", "php"],
"openIssues": 0,
"dependencies": [],
"openPrsCount": 0
"openPrsCount": 0,
"openBotPrCount": 0
},
{
"name": "govuk-blogs",
Expand All @@ -27,7 +28,8 @@
"topics": ["govpress", "wordpress-theme"],
"openIssues": 1,
"dependencies": [],
"openPrsCount": 0
"openPrsCount": 0,
"openBotPrCount": 1
},
{
"name": "php-missing",
Expand All @@ -41,7 +43,8 @@
"topics": ["composer", "govpress", "packagist", "php"],
"openIssues": 7,
"dependencies": [],
"openPrsCount": 2
"openPrsCount": 2,
"openBotPrCount": 3
}
]
}
6 changes: 4 additions & 2 deletions index.njk
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
<th class="py-2 pl-2" scope="col">Language</th>
<th class="py-2 pl-2" scope="col">Topics</th>
{{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)}}
<th class="py-2 pl-2 last:pr-2" scope="col">Dependencies</th>
</tr>
Expand All @@ -50,7 +51,8 @@
<td class="py-2 pl-2">{{ repo.language }}</td>
<td class="py-2 pl-2">{{ repo.topics | join(", ")}}</td>
<td class="py-2 pl-2">{{ repo.openIssues }}</td>
<td class="py-2 pl-2">{{ repo.openPrsCount }}</td>
<td class="py-2 pl-2">{{ repo.openBotPrCount }}</td>
<td class="py-2 pl-2">{{ repo.openPrCount }}</td>
<td class="py-2 pl-2 last:pr-2">{{ repo.updatedAt }}</td>

{% if repo.dependencies.length %}
Expand Down
11 changes: 10 additions & 1 deletion utils/githubApi/fetchOpenPrs.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
};
54 changes: 50 additions & 4 deletions utils/githubApi/fetchOpenPrs.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});
});
9 changes: 6 additions & 3 deletions utils/sorting.js
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down

0 comments on commit 38df894

Please sign in to comment.