From d907bbda0c28f7f2f664b111828cd4e78fb26b26 Mon Sep 17 00:00:00 2001 From: Max Baumann Date: Fri, 18 Sep 2020 18:17:51 +0200 Subject: [PATCH] feat(setup): support registration using an existing GitHub app (#1345) --- src/apps/setup.ts | 38 ++++++++-- test/apps/__snapshots__/setup.test.ts.snap | 17 +++++ test/apps/setup.test.ts | 39 ++++++++++ views/import.hbs | 84 ++++++++++++++++++++++ views/setup.hbs | 3 +- 5 files changed, 174 insertions(+), 7 deletions(-) create mode 100644 views/import.hbs diff --git a/src/apps/setup.ts b/src/apps/setup.ts index d15f2546..0dbed0b9 100644 --- a/src/apps/setup.ts +++ b/src/apps/setup.ts @@ -1,5 +1,7 @@ +import bodyParser from "body-parser"; import { exec } from "child_process"; import { Request, Response } from "express"; +import updateDotenv from "update-dotenv"; import { Application } from "../application"; import { ManifestCreation } from "../manifest-creation"; @@ -27,12 +29,7 @@ export const setupAppFactory = ( printWelcomeMessage(app, host, port); route.get("/probot", async (req, res) => { - const protocols = req.headers["x-forwarded-proto"] || req.protocol; - const protocol = - typeof protocols === "string" ? protocols.split(",")[0] : protocols[0]; - const host = req.headers["x-forwarded-host"] || req.get("host"); - const baseUrl = `${protocol}://${host}`; - + const baseUrl = getBaseUrl(req); const pkg = setup.pkg; const manifest = setup.getManifest(pkg, baseUrl); const createAppUrl = setup.createAppUrl; @@ -56,6 +53,26 @@ export const setupAppFactory = ( res.redirect(`${response}/installations/new`); }); + route.get("/probot/import", async (_req, res) => { + const { WEBHOOK_PROXY_URL, GHE_HOST } = process.env; + const GH_HOST = `https://${GHE_HOST ?? "github.com"}`; + res.render("import.hbs", { WEBHOOK_PROXY_URL, GH_HOST }); + }); + + route.post("/probot/import", bodyParser.json(), async (req, res) => { + const { appId, pem, webhook_secret } = req.body; + if (!appId || !pem || !webhook_secret) { + res.status(400).send("appId and/or pem and/or webhook_secret missing"); + return; + } + updateDotenv({ + APP_ID: appId, + PRIVATE_KEY: `"${pem}"`, + WEBHOOK_SECRET: webhook_secret, + }); + res.end(); + }); + route.get("/probot/success", async (req, res) => { res.render("success.hbs"); }); @@ -87,3 +104,12 @@ function printWelcomeMessage( app.log.info(line); }); } + +function getBaseUrl(req: Request): string { + const protocols = req.headers["x-forwarded-proto"] || req.protocol; + const protocol = + typeof protocols === "string" ? protocols.split(",")[0] : protocols[0]; + const host = req.headers["x-forwarded-host"] || req.get("host"); + const baseUrl = `${protocol}://${host}`; + return baseUrl; +} diff --git a/test/apps/__snapshots__/setup.test.ts.snap b/test/apps/__snapshots__/setup.test.ts.snap index f3dc2070..011d5150 100644 --- a/test/apps/__snapshots__/setup.test.ts.snap +++ b/test/apps/__snapshots__/setup.test.ts.snap @@ -16,3 +16,20 @@ Array [ ], ] `; + +exports[`Setup app POST /probot/import updates .env 1`] = ` +Array [ + Array [ + Object { + "WEBHOOK_PROXY_URL": "mocked proxy URL", + }, + ], + Array [ + Object { + "APP_ID": "foo", + "PRIVATE_KEY": "\\"bar\\"", + "WEBHOOK_SECRET": "baz", + }, + ], +] +`; diff --git a/test/apps/setup.test.ts b/test/apps/setup.test.ts index 0d2ca5c0..c9ee1cb9 100644 --- a/test/apps/setup.test.ts +++ b/test/apps/setup.test.ts @@ -100,6 +100,45 @@ describe("Setup app", () => { }); }); + describe("GET /probot/import", () => { + it("renders import.hbs", async () => { + await request(probot.server).get("/probot/import").expect(200); + }); + }); + + describe("POST /probot/import", () => { + it("updates .env", async () => { + const body = JSON.stringify({ + appId: "foo", + pem: "bar", + webhook_secret: "baz", + }); + + await request(probot.server) + .post("/probot/import") + .set("content-type", "application/json") + .send(body) + .expect(200) + .expect(""); + + expect(updateDotenv.mock.calls).toMatchSnapshot(); + }); + + it("400 when keys are missing", async () => { + const body = JSON.stringify({ + appId: "foo", + /* no pem */ + webhook_secret: "baz", + }); + + await request(probot.server) + .post("/probot/import") + .set("content-type", "application/json") + .send(body) + .expect(400); + }); + }); + describe("GET /probot/success", () => { it("returns a 200 response", async () => { await request(probot.server).get("/probot/success").expect(200); diff --git a/views/import.hbs b/views/import.hbs new file mode 100644 index 00000000..959a298d --- /dev/null +++ b/views/import.hbs @@ -0,0 +1,84 @@ + + + + + + + + Import {{#if pkg.name }}{{ pkg.name }}{{else}}Your App{{/if}} | built with Probot + + + + + +
+ Probot Logo +
+

Use existing Github App

+
+ +

Step 1:

+

+ Replace your app's Webhook URL with
+ {{ WEBHOOK_PROXY_URL }} +

+ + You can do it here + + +
+

Step 2:

+

Fill out this form

+
+ +
+ + +
+ + + +
+ + +
+
+ +
+

Need help?

+ +
+
+ + + + \ No newline at end of file diff --git a/views/setup.hbs b/views/setup.hbs index cda1d565..5f9f1658 100644 --- a/views/setup.hbs +++ b/views/setup.hbs @@ -31,8 +31,9 @@

To start building a GitHub App, you'll need to register a new app on GitHub.


-
+ + or use an existing Github App