UNPKG

@roadiehq/backstage-plugin-github-pull-requests

Version:
150 lines (147 loc) 4.73 kB
import { useAsync } from 'react-use'; import { githubPullRequestsApiRef } from '../api/GithubPullRequestsApi.esm.js'; import '@backstage/integration'; import '@octokit/rest'; import { Duration } from 'luxon'; import { useApi } from '@backstage/core-plugin-api'; import { useEntity } from '@backstage/plugin-catalog-react'; import { getHostname } from '../utils/githubUtils.esm.js'; function calculateStatistics(pullRequestsData) { const result = pullRequestsData.reduce( (acc, curr) => { acc.avgTimeUntilMerge += curr.pullRequest.mergedAt ? new Date(curr.pullRequest.mergedAt).getTime() - new Date(curr.createdAt).getTime() : 0; const avgCodingTime = new Date(curr.createdAt).getTime() - new Date(curr.firstCommitAt).getTime(); acc.avgCodingTime += avgCodingTime > 0 ? avgCodingTime : 0; acc.mergedCount += curr.pullRequest.mergedAt ? 1 : 0; acc.closedCount += curr.closedAt ? 1 : 0; acc.additions += curr.pullRequest.additions; acc.deletions += curr.pullRequest.deletions; acc.changedLinesCount += curr.pullRequest.additions + curr.pullRequest.deletions; acc.changedFilesCount += curr.pullRequest.changedFiles; return acc; }, { avgTimeUntilMerge: 0, avgCodingTime: 0, closedCount: 0, mergedCount: 0, changedLinesCount: 0, changedFilesCount: 0, additions: 0, deletions: 0 } ); return { ...result, avgChangedLinesCount: Math.round( result.changedLinesCount / pullRequestsData.length ), avgChangedFilesCount: Math.round( result.changedFilesCount / pullRequestsData.length ), avgAdditions: Math.round(result.additions / pullRequestsData.length), avgDeletions: Math.round(result.deletions / pullRequestsData.length) }; } function usePullRequestsStatistics({ owner, repo, branch, pageSize, state }) { const api = useApi(githubPullRequestsApiRef); const { entity } = useEntity(); const hostname = getHostname(entity); const { loading, value: statsData, error } = useAsync(async () => { if (!repo) { return { avgTimeUntilMerge: "Never", avgCodingTime: "Never", mergedToClosedRatio: "0%", avgChangedLinesCount: 0, avgChangedFilesCount: 0, avgAdditions: 0, avgDeletions: 0 }; } const { pullRequestsData } = await api.listPullRequests({ search: `state:${state}`, hostname, owner, repo, pageSize, page: 1, branch }); const botUsernames = [ "github-actions[bot]", "dependabot[bot]", "roadie-bot" ]; const transformedData = await Promise.all( pullRequestsData.items.filter((obj) => { const login = obj.user?.login; return login && !botUsernames.includes(login); }).map(async (pr) => { const repoData = await api.getRepositoryData({ url: pr.pull_request.url, hostname }); const commitDate = await api.getCommitDetailsData({ hostname, owner, repo, number: pr.number }); return { createdAt: pr.created_at, closedAt: pr.closed_at, firstCommitAt: commitDate.firstCommitDate.toString(), pullRequest: { mergedAt: pr.pull_request.merged_at, additions: repoData.additions, deletions: repoData.deletions, changedFiles: repoData.changedFiles } }; }) ); const calcResult = calculateStatistics(transformedData); if (calcResult.closedCount === 0 || calcResult.mergedCount === 0) return { ...calcResult, avgTimeUntilMerge: "Never", avgCodingTime: "Never", mergedToClosedRatio: "0%" }; const avgTimeUntilMergeDiff = calcResult.avgTimeUntilMerge / calcResult.mergedCount; const avgTimeUntilMerge = Duration.fromMillis(avgTimeUntilMergeDiff).shiftTo("months", "days", "hour").toHuman({ notation: "compact" }); const avgCodingTimeUntilPRRaised = calcResult.avgCodingTime / transformedData.length; const avgCodingTime = Duration.fromMillis(avgCodingTimeUntilPRRaised).shiftTo("months", "days", "hour").toHuman({ notation: "compact" }); return { ...calcResult, avgTimeUntilMerge, avgCodingTime, mergedToClosedRatio: `${Math.round( calcResult.mergedCount / calcResult.closedCount * 100 )}%` }; }, [pageSize, repo, owner]); return [ { loading, statsData, projectName: `${owner}/${repo}`, error } ]; } export { usePullRequestsStatistics }; //# sourceMappingURL=usePullRequestsStatistics.esm.js.map