forked from mirrors/probot
feat(setup): support registration using an existing GitHub app (#1345)
This commit is contained in:
parent
31fdd619ac
commit
d907bbda0c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
},
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" class="height-full">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>Import {{#if pkg.name }}{{ pkg.name }}{{else}}Your App{{/if}} | built with Probot</title>
|
||||
<link rel="icon" href="/probot/static/probot-head.png">
|
||||
<link rel="stylesheet" href="/probot/static/primer.css">
|
||||
</head>
|
||||
|
||||
<body class="bg-gray-light">
|
||||
<div class="d-flex flex-column flex-justify-center flex-items-center text-center height-full py-6">
|
||||
<a href="/probot"><img src="/probot/static/robot.svg" alt="Probot Logo" width="100" class="mb-6"></a>
|
||||
<div class="box-shadow rounded-2 border p-6 bg-white">
|
||||
<h2>Use existing Github App</h2>
|
||||
<br>
|
||||
|
||||
<h3>Step 1:</h3>
|
||||
<p class="d-block mt-2">
|
||||
Replace your app's Webhook URL with <br>
|
||||
<b>{{ WEBHOOK_PROXY_URL }}</b>
|
||||
</p>
|
||||
<a class="d-block mt-2" href="{{ GH_HOST }}/settings/apps" target="__blank" rel="noreferrer">
|
||||
You can do it here
|
||||
</a>
|
||||
|
||||
<br>
|
||||
<h3>Step 2:</h3>
|
||||
<p class="mt-2">Fill out this form</p>
|
||||
<form onsubmit="return onSubmit(event) || false">
|
||||
<label class="d-block mt-2" for="appId">App Id</label>
|
||||
<input class="form-control width-full" type="text" required="true" id="appId" name="appId"><br>
|
||||
|
||||
<label class="d-block mt-3" for="whs">Webhook secret (required!)</label>
|
||||
<input class="form-control width-full" type="password" required="true" id="whs" name="whs"><br>
|
||||
|
||||
<label class="d-block mt-3" for="pem">Private Key</label>
|
||||
<input class="form-control width-full m-2" type="file" accept=".pem" required="true" id="pem"
|
||||
name="pem">
|
||||
<br>
|
||||
|
||||
<button class="btn btn-outline m-2" type="submit">Submit</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<h4 class="alt-h4 text-gray-light">Need help?</h4>
|
||||
<div class="d-flex flex-justify-center mt-2">
|
||||
<a href="https://probot.github.io/docs/" class="btn btn-outline mr-2">Documentation</a>
|
||||
<a href="https://probot-slackin.herokuapp.com/" class="btn btn-outline">Chat on Slack</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function onSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const idEl = document.getElementById('appId');
|
||||
const appId = idEl.value;
|
||||
|
||||
|
||||
const secretEl = document.getElementById('whs');
|
||||
const webhook_secret = secretEl.value;
|
||||
|
||||
const fileEl = document.getElementById('pem');
|
||||
const file = fileEl.files[0];
|
||||
|
||||
file.text().then((text) => fetch('', {
|
||||
method: 'POST',
|
||||
headers: { 'content-type': 'application/json' },
|
||||
body: JSON.stringify({ appId, pem: text, webhook_secret })
|
||||
})).then((r) => {
|
||||
if (r.ok) {
|
||||
location.replace('/probot/success');
|
||||
}
|
||||
}).catch((e) => alert(e));
|
||||
return false;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -31,8 +31,9 @@
|
|||
<p>To start building a GitHub App, you'll need to register a new app on GitHub.</p>
|
||||
<br>
|
||||
|
||||
<form action="{{ createAppUrl }}" method="post" target="_blank">
|
||||
<form action="{{ createAppUrl }}" method="post" target="_blank" class="d-flex flex-items-center">
|
||||
<button class="btn btn-outline" name="manifest" id="manifest" value='{{ manifest }}' >Register GitHub App</button>
|
||||
<a href="/probot/import" class="ml-2">or use an existing Github App</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue