diff --git a/api/src/core/adapters/GitHub/api/repo.ts b/api/src/core/adapters/GitHub/api/repo.ts new file mode 100644 index 00000000..09fba9ab --- /dev/null +++ b/api/src/core/adapters/GitHub/api/repo.ts @@ -0,0 +1,78 @@ +import { Octokit } from "@octokit/rest"; + +import { env } from "../../../../env"; + +export const repoGitHubEndpointMaker = (repoUrl: string | URL) => { + const octokit = new Octokit({ + auth: env.githubPersonalAccessTokenForApiRateLimit + }); + let repoUrlObj = typeof repoUrl === "string" ? URL.parse(repoUrl) : repoUrl; + if (!repoUrlObj) return undefined; + + // Case .git at the end + if (repoUrlObj.pathname.endsWith("/")) repoUrlObj.pathname = repoUrlObj.pathname.slice(0, -1); + if (repoUrlObj.pathname.endsWith(".git")) repoUrlObj.pathname = repoUrlObj.pathname.slice(0, -4); + + const parsed = repoUrlObj.pathname.split("/").filter(text => text); + + const repo = parsed[1]; + const owner = parsed[0]; + + return { + issues: { + getLastClosedIssue: async () => { + try { + const resIssues = await octokit.request("GET /repos/{owner}/{repo}/issues", { + owner, + repo, + headers: { + "X-GitHub-Api-Version": "2022-11-28" + }, + direction: "desc", + state: "closed" + }); + + return resIssues.data[0]; + } catch (error) { + return undefined; + } + } + }, + commits: { + getLastCommit: async () => { + try { + const resCommit = await octokit.request("GET /repos/{owner}/{repo}/commits", { + owner, + repo, + headers: { + "X-GitHub-Api-Version": "2022-11-28" + }, + direction: "desc" + }); + return resCommit.data[0]; + } catch (error) { + return undefined; + } + } + }, + mergeRequests: { + getLast: async () => { + try { + const resPull = await octokit.request("GET /repos/{owner}/{repo}/pulls", { + owner, + repo, + headers: { + "X-GitHub-Api-Version": "2022-11-28" + }, + direction: "desc", + state: "closed" + }); + + return resPull.data[0]; + } catch (error) { + return undefined; + } + } + } + }; +}; diff --git a/api/src/core/adapters/hal/getHalSoftwareExternalData.ts b/api/src/core/adapters/hal/getHalSoftwareExternalData.ts index c4fde1d7..eaebd34e 100644 --- a/api/src/core/adapters/hal/getHalSoftwareExternalData.ts +++ b/api/src/core/adapters/hal/getHalSoftwareExternalData.ts @@ -7,6 +7,7 @@ import { SILL } from "../../../types/SILL"; import { HAL } from "./types/HAL"; import { repoAnalyser, RepoType } from "../../../tools/repoAnalyser"; import { projectGitLabApiMaker } from "../GitLab/api/project"; +import { repoGitHubEndpointMaker } from "../GitHub/api/repo"; const buildParentOrganizationTree = async ( structureIdArray: number[] | string[] | undefined @@ -239,7 +240,30 @@ export const getHalSoftwareExternalData: GetSoftwareExternalData = memoize( } }; case "GitHub": - return undefined; + const gitHubApi = repoGitHubEndpointMaker(halRawSoftware?.softCodeRepository_s?.[0]); + if (!gitHubApi) { + console.error("Bad URL string"); + return undefined; + } + + const lastGHCommit = await gitHubApi.commits.getLastCommit(); + const lastGHCloseIssue = await gitHubApi.issues.getLastClosedIssue(); + const lastGHClosedPull = await gitHubApi.mergeRequests.getLast(); + + return { + healthCheck: { + lastCommit: lastGHCommit?.commit?.author?.date + ? new Date(lastGHCommit.commit.author.date).valueOf() + : undefined, + lastClosedIssue: lastGHCloseIssue?.closed_at + ? new Date(lastGHCloseIssue.closed_at).valueOf() + : undefined, + lastClosedIssuePullRequest: lastGHClosedPull?.closed_at + ? new Date(lastGHClosedPull.closed_at).valueOf() + : undefined + } + }; + case undefined: return undefined; default: