Skip to content

Commit

Permalink
feat: adapt setup for probot@13
Browse files Browse the repository at this point in the history
fix: setup works without `hbs`

Closes #175
  • Loading branch information
nikku committed Jan 31, 2024
1 parent ffde4c1 commit 34cfe75
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 64 deletions.
61 changes: 40 additions & 21 deletions packages/app/lib/probot/CustomProbot.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,60 @@ const { Server, Probot } = require('probot');
const { getLog } = require('probot/lib/helpers/get-log');
const { setupAppFactory } = require('./apps/setup');

const { isProduction } = require('probot/lib/helpers/is-production');

const { ManifestCreation } = require('probot/lib/manifest-creation');

const { readEnvOptions } = require('probot/lib/bin/read-env-options');

const { getErrorHandler } = require('probot/lib/helpers/get-error-handler');
const { getPrivateKey } = require('@probot/get-private-key');


async function run(appFn) {
async function run(appFn, additionalOptions) {

const {

const appId = parseInt(process.env.APP_ID, 10);
const host = process.env.HOST;
const port = parseInt(process.env.PORT || '3000', 10);
const privateKey = getPrivateKey() || undefined;
// log options
logLevel: level, logFormat, logLevelInString, logMessageKey, sentryDsn,

const log = getLog();
// server options
host, port, webhookPath, webhookProxy,

// probot options
appId, privateKey, redisConfig, secret, baseUrl

} = readEnvOptions(additionalOptions?.env);

const logOptions = {
level,
logFormat,
logLevelInString,
logMessageKey,
sentryDsn
};

const log = getLog(logOptions);

const serverOptions = {
host,
log: log.child({ name: 'server' }),
port,
webhookPath: process.env.WEBHOOK_PATH,
webhookProxy: process.env.WEBHOOK_PROXY_URL
webhookPath,
webhookProxy,
log: log.child({ name: 'server' })
};

let probotOptions = {
appId,
log: log.child({ name: 'probot' }),
privateKey,
secret: process.env.WEBHOOK_SECRET
redisConfig,
secret,
baseUrl,
log: log.child({ name: 'probot' })
};

// use probots own setup app if the probot app
// is not configured yet
if (!isProduction() && !isSetup()) {
if (!isProduction() && !isSetup(probotOptions)) {

// Workaround for setup (probot/probot#1512)
// When probot is started for the first time, it gets into a setup mode
Expand Down Expand Up @@ -72,22 +93,20 @@ async function run(appFn) {
return server;
}

function isSetup() {
const appId = parseInt(process.env.APP_ID, 10);
const privateKey = getPrivateKey() || undefined;
function isSetup(options) {
const {
appId,
privateKey
} = options || readEnvOptions(process.env);

return !!(appId && privateKey);
}

function isProduction() {
return process.env.NODE_ENV === 'production';
}

function validateSetup() {

const setup = new ManifestCreation();

const manifest = JSON.parse(setup.getManifest(setup.pkg));
const manifest = JSON.parse(setup.getManifest(setup.pkg, process.env.BASE_URL));

return [
!manifest.url && new Error('No <url> configured in app.yml'),
Expand Down
150 changes: 107 additions & 43 deletions packages/app/lib/probot/apps/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ const { getLog } = require('probot/lib/helpers/get-log');

const { randomString } = require('../../util');

const { importView } = require('probot/lib/views/import');
const { setupView } = require('probot/lib/views/setup');

function setupAppFactory(host, port) {

Expand Down Expand Up @@ -36,48 +38,110 @@ function setupAppFactory(host, port) {
route.use(getLoggingMiddleware(app.log));

route.get('/probot', async (req, res) => {
const baseUrl = getBaseUrl(req);
const baseUrl = process.env.BASE_URL || getBaseUrl(req);
const pkg = setup.pkg;
const manifest = setup.getManifest(pkg, baseUrl);
const createAppUrl = setup.createAppUrl;

await setup.updateEnv({
BASE_URL: baseUrl
});

// Pass the manifest to be POST'd
res.render('setup.hbs', { pkg, createAppUrl, manifest });
res.writeHead(200, { 'content-type': 'text/html' }).end(setupView({
name: pkg.name || 'Wuffle',
version: pkg.version,
description: pkg.description,
createAppUrl,
manifest
}));
});

route.get('/probot/setup', async (req, res) => {
const { code } = req.query;
const app_url = await setup.createAppFromCode(code);

log.info('Setup completed, please start the app');
if (!code || typeof code !== 'string' || code.length === 0) {
return res
.writeHead(400, { 'content-type': 'text/plain' })
.end('code missing or invalid');
}

const response = await setup.createAppFromCode(code, {
request: app.state.request
});

res.send(renderSuccess(app_url + '/installations/new'));
const appUrl = app.state.appUrl = `${response}/installations/new`;

log.warn('Setup completed, please restart the app');

log.info(`Visit ${appUrl} to connect GitHub repositories`);

const location = '/probot/success';

return res
.writeHead(302, {
'content-type': 'text/plain',
location
})
.end(`Redirecting to ${ location }`);
});

route.get('/probot/import', async (_req, res) => {

const pkg = setup.pkg;
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 });

return res
.writeHead(200, {
'content-type': 'text/html'
})
.end(importView({
name: pkg.name || 'Wuffle',
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;
return res
.writeHead(400, {
'content-type': 'text/plain'
})
.end('appId and/or pem and/or webhook_secret missing');
}

await updateDotenv({
APP_ID: appId,
PRIVATE_KEY: `"${pem}"`,
WEBHOOK_SECRET: webhook_secret
});

log.info('Setup completed, please start the app');
log.warn('Setup completed, please restart the app.');

res.send(renderSuccess());
return res.redirect('/probot/success');
});

route.get('/', (req, res, next) => res.redirect('/probot'));
route.get('/probot/success', (_req, res) => {
const pkg = setup.pkg;

const appUrl = app.state.appUrl;

return res
.writeHead(200, { 'content-type': 'text/html' })
.end(successView({
name: pkg.name || 'Wuffle',
appUrl
}));
});

route.get('/', (_req, res) => {
return res
.writeHead(302, { 'content-type': 'text/plain', location: '/probot' })
.end();
});
};
}

Expand All @@ -94,40 +158,40 @@ function getBaseUrl(req) {
return baseUrl;
}


function renderSuccess(appUrl = null) {
function successView({ name, appUrl }) {

return `
<!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>Setup Wuffle App | built with Probot</title>
<link rel="icon" href="/probot/static/probot-head.png">
<link rel="stylesheet" href="/probot/static/primer.css">
</head>
<body class="height-full bg-gray-light">
<div class="d-flex flex-column flex-justify-center flex-items-center text-center height-full">
<img src="/probot/static/robot.svg" alt="Probot Logo" width="100" class="mb-6">
<div class="box-shadow rounded-2 border p-6 bg-white">
<div class="text-center">
<h1 class="alt-h2 mb-4">Congrats! You have successfully installed your app!</h1>
<p class="alt-h3 mb-2">
You can now ${ appUrl ? `<a href="${appUrl}" target="_blank" rel="no-opener">` : ''}
connect GitHub repositories
${appUrl ? '</a>' : ''} to your board.
</p>
<p class="alt-h3">
Please restart the server to complete the setup.
</p>
<!DOCTYPE html>
<html lang="en" class="height-full" data-color-mode="auto" data-light-theme="light" data-dark-theme="dark">
<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>${ name } Setup complete</title>
<link rel="icon" href="/probot/static/probot-head.png">
<link rel="stylesheet" href="/probot/static/primer.css">
</head>
<body class="height-full bg-gray-light">
<div class="d-flex flex-column flex-justify-center flex-items-center text-center height-full">
<img src="/probot/static/robot.svg" alt="Probot Logo" width="100" class="mb-6">
<div class="box-shadow rounded-2 border p-6 bg-white">
<div class="text-center">
<h1 class="alt-h3 mb-2">You completed your ${name} setup!</h1>
<p class="mb-2">
Go ahead and ${ appUrl ? `<a href="${appUrl}" target="_blank" rel="no-opener">` : ''}
connect GitHub repositories
${appUrl ? '</a>' : ''} to your board.
</p>
<p>
Please restart the server to complete the setup.
</p>
</div>
</div>
</div>
</div>
</body>
</html>`;

</body>
</html>
`;
}

0 comments on commit 34cfe75

Please sign in to comment.