From ff44365fe5119cdc74fcb16fee51857e77360ca3 Mon Sep 17 00:00:00 2001 From: gitcommitshow <56937085+gitcommitshow@users.noreply.github.com> Date: Wed, 9 Oct 2024 09:47:38 +0530 Subject: [PATCH 01/10] feat: add page to list open external pull requests --- app.js | 6 ++++++ src/helpers.js | 32 ++++++++++++++++++++++++++++++-- src/routes.js | 25 +++++++++++++++++++++++++ views/home.html | 1 + 4 files changed, 62 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index ccc01ef..20176c7 100644 --- a/app.js +++ b/app.js @@ -233,6 +233,12 @@ http case "POST /cla": routes.submitCla(req, res, app); break; + case "GET /contributions/sync": + routes.syncPullRequests(req, res, app); + break; + case "GET /contributions": + routes.listPullRequests(req, res, app); + break; case "POST /api/webhook": middleware(req, res); break; diff --git a/src/helpers.js b/src/helpers.js index e864065..8f52310 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -1,12 +1,14 @@ import { storage } from "./storage.js"; import { resolve } from "path"; import { PROJECT_ROOT_PATH } from "./config.js"; +import url from "node:url"; export function parseUrlQueryParams(urlString) { if(!urlString) return urlString; try{ - const url = new URL(urlString); - const params = new URLSearchParams(url.search); + const parsedUrl = url.parse(urlString) + const query = parsedUrl.query; + const params = new URLSearchParams(query); return Object.fromEntries(params.entries()); } catch(err){ console.error(err); @@ -270,6 +272,7 @@ export async function getOctokitForOrg(app, org) { return octokit } } + console.error("No GitHub App installation found for " + org); } export async function verifyGitHubAppAuthenticationAndAccess(app) { @@ -333,4 +336,29 @@ function parseRepoUrl(repoUrl) { // Handle cases where URL constructor fails (e.g., SSH URLs) return null; } +} + +export async function getOpenPullRequests(app, owner, repo) { + const octokit = await getOctokitForOrg(app, owner); + if (!octokit) { + console.error("Failed to search PR because of undefined octokit intance") + return + } + const query = `is:pr is:open -author:dependabot[bot]` + (repo ? ` repo:${owner / repo}` : ` org:${owner}`); + const response = await octokit.rest.search.issuesAndPullRequests({ + q: query, + sort: 'created', + order: 'desc' + }); + const humanPRs = response.data.items.filter(pr => pr.user && pr.user.type === 'User'); + return humanPRs; +} + +export async function getOpenExternalPullRequests(app, owner, repo) { + const openPRs = await getOpenPullRequests(app, owner, repo); + if (Array.isArray(openPRs)) { + // Send only the external PRs + return openPRs?.filter((pr) => isExternalContribution(pr)) + } + return } \ No newline at end of file diff --git a/src/routes.js b/src/routes.js index 64af41b..ff420e4 100644 --- a/src/routes.js +++ b/src/routes.js @@ -9,6 +9,7 @@ import { queryStringToJson, parseUrlQueryParams, jsonToCSV, + getOpenExternalPullRequests, } from "./helpers.js"; import { isPasswordValid } from "./auth.js"; @@ -166,6 +167,30 @@ export const routes = { }) }, + syncPullRequests(req, res, app) { + if (err) { + res.writeHead(404); + res.write("Not implemented yet"); + return res.end(); + } + res.writeHead(302, { + Location: "/pr", + }); + return res.end(); + }, + + async listPullRequests(req, res, app) { + const { org, repo } = parseUrlQueryParams(req.url) || {}; + if (!org) { + res.writeHead(400); + return res.end("Please add org parameter in the url e.g. ?org=my-github-org-name"); + } + const prList = await getOpenExternalPullRequests(app, org, repo); + res.setHeader('Content-Type', 'application/json'); + const jsonString = prList ? JSON.stringify(prList, null, 2) : ("No Open Pull Requests found (or you don't have access to search PRs for " + org); + return res.end(jsonString); + }, + default(req, res) { res.writeHead(404); res.write("Path not found!"); diff --git a/views/home.html b/views/home.html index 237a6a8..a65d21b 100644 --- a/views/home.html +++ b/views/home.html @@ -30,6 +30,7 @@

🙏 Get started with contribution to RudderStack Open Source


Tools & resources for RudderStack contributors '; From 68688af77440d3c268fa901155126c95d66a095f Mon Sep 17 00:00:00 2001 From: gitcommitshow <56937085+gitcommitshow@users.noreply.github.com> Date: Fri, 18 Oct 2024 06:38:07 +0530 Subject: [PATCH 09/10] refactor: rename contirb detail route to contrib pr --- app.js | 2 +- src/routes.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index f010432..a5b3cdf 100644 --- a/app.js +++ b/app.js @@ -239,7 +239,7 @@ http case "GET /contributions": routes.listPullRequests(req, res, app); break; - case "GET /contributions/detail": + case "GET /contributions/pr": routes.getPullRequestDetail(req, res, app); break; case "POST /api/webhook": diff --git a/src/routes.js b/src/routes.js index d0925f3..a4eb66d 100644 --- a/src/routes.js +++ b/src/routes.js @@ -319,7 +319,7 @@ function groupPullRequestsByUser(prs) { ${pr?.title} ${prLabels} updated ${timeAgo(pr?.updated_at)} - + ${typeof pr.isExternalContribution === "boolean" ? "" : " (Click to confirm author association) "} `; }); @@ -352,7 +352,7 @@ function groupPullRequestsByRepo(prs) { by ${pr?.user?.login} ${isCLASigned(pr?.user?.login) ? "✅" : ""} ${prLabels} updated ${timeAgo(pr?.updated_at)} - + ${typeof pr.isExternalContribution === "boolean" ? "" : " (Click to confirm author association) "} `; }); From f4c33bb9a4b7f0f5450bd2f35098ee99859482e8 Mon Sep 17 00:00:00 2001 From: gitcommitshow <56937085+gitcommitshow@users.noreply.github.com> Date: Fri, 18 Oct 2024 06:40:55 +0530 Subject: [PATCH 10/10] fix: style changes --- src/routes.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes.js b/src/routes.js index a4eb66d..97833ba 100644 --- a/src/routes.js +++ b/src/routes.js @@ -320,7 +320,7 @@ function groupPullRequestsByUser(prs) { ${prLabels} updated ${timeAgo(pr?.updated_at)} - ${typeof pr.isExternalContribution === "boolean" ? "" : " (Click to confirm author association) "} + ${typeof pr.isExternalContribution === "boolean" ? "" : " (Click to confirm author association) "} `; }); html += ''; @@ -353,7 +353,7 @@ function groupPullRequestsByRepo(prs) { ${prLabels} updated ${timeAgo(pr?.updated_at)} - ${typeof pr.isExternalContribution === "boolean" ? "" : " (Click to confirm author association) "} + ${typeof pr.isExternalContribution === "boolean" ? "" : " (Click to confirm author association) "} `; }); html += '';