wuffle 0.57.0 → 0.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/run.js CHANGED
@@ -205,7 +205,7 @@ async function validate() {
205
205
 
206
206
  async function performSetup() {
207
207
 
208
- log.info('Running first time setup');
208
+ log.warn('Running first time setup');
209
209
 
210
210
  const configPath = path.resolve('wuffle.config.js');
211
211
 
@@ -232,7 +232,7 @@ async function performSetup() {
232
232
  log.error(error.message);
233
233
  }
234
234
 
235
- log.error('Please correct above errors and restart');
235
+ log.warn('Please correct above errors and restart');
236
236
 
237
237
  process.exit(1);
238
238
  }
@@ -256,7 +256,8 @@ async function open() {
256
256
  const url = process.env.BASE_URL || 'http://localhost:3000';
257
257
 
258
258
  if (IS_SETUP) {
259
- log.warn(`Visit ${url} to create a GitHub App that connects us to GitHub`);
259
+ log.warn('GitHub App is not configured yet');
260
+ log.warn(`Visit ${url} to continue the setup`);
260
261
  } else {
261
262
  log.info(`Wuffle started on ${url}`);
262
263
  }
@@ -98,9 +98,20 @@ function GitHubClient(app, webhookEvents, logger, githubApp, events) {
98
98
 
99
99
  const access_token = typeof user === 'string' ? user : user.access_token;
100
100
 
101
+ const log = logger.child({ name: 'github:user-auth' });
102
+
101
103
  return cache.get(`user_scoped=${access_token}`, () => {
102
104
  return new ProbotOctokit({
103
- log: logger.child({ name: 'github:user-auth' }),
105
+
106
+ // fallout from Probot@13 migration
107
+ //
108
+ // see https://github.com/probot/probot/pull/1874#issuecomment-1837779069
109
+ log: {
110
+ debug: log.debug.bind(log),
111
+ info: log.info.bind(log),
112
+ warn: log.warn.bind(log),
113
+ error: log.error.bind(log)
114
+ },
104
115
  auth: {
105
116
  token: access_token
106
117
  }
@@ -3,39 +3,60 @@ const { Server, Probot } = require('probot');
3
3
  const { getLog } = require('probot/lib/helpers/get-log');
4
4
  const { setupAppFactory } = require('./apps/setup');
5
5
 
6
+ const { isProduction } = require('probot/lib/helpers/is-production');
7
+
6
8
  const { ManifestCreation } = require('probot/lib/manifest-creation');
7
9
 
10
+ const { readEnvOptions } = require('probot/lib/bin/read-env-options');
11
+
8
12
  const { getErrorHandler } = require('probot/lib/helpers/get-error-handler');
9
- const { getPrivateKey } = require('@probot/get-private-key');
10
13
 
11
14
 
12
- async function run(appFn) {
15
+ async function run(appFn, additionalOptions) {
16
+
17
+ const {
13
18
 
14
- const appId = parseInt(process.env.APP_ID, 10);
15
- const host = process.env.HOST;
16
- const port = parseInt(process.env.PORT || '3000', 10);
17
- const privateKey = getPrivateKey() || undefined;
19
+ // log options
20
+ logLevel: level, logFormat, logLevelInString, logMessageKey, sentryDsn,
18
21
 
19
- const log = getLog();
22
+ // server options
23
+ host, port, webhookPath, webhookProxy,
24
+
25
+ // probot options
26
+ appId, privateKey, redisConfig, secret, baseUrl
27
+
28
+ } = readEnvOptions(additionalOptions?.env);
29
+
30
+ const logOptions = {
31
+ level,
32
+ logFormat,
33
+ logLevelInString,
34
+ logMessageKey,
35
+ sentryDsn
36
+ };
37
+
38
+ const log = getLog(logOptions);
20
39
 
21
40
  const serverOptions = {
22
41
  host,
23
- log: log.child({ name: 'server' }),
24
42
  port,
25
- webhookPath: process.env.WEBHOOK_PATH,
26
- webhookProxy: process.env.WEBHOOK_PROXY_URL
43
+ webhookPath,
44
+ webhookProxy,
45
+ log: log.child({ name: 'server' })
27
46
  };
28
47
 
29
48
  let probotOptions = {
30
49
  appId,
31
- log: log.child({ name: 'probot' }),
32
50
  privateKey,
33
- secret: process.env.WEBHOOK_SECRET
51
+ redisConfig,
52
+ secret,
53
+ baseUrl,
54
+ log: log.child({ name: 'probot' })
34
55
  };
35
56
 
36
57
  // use probots own setup app if the probot app
37
58
  // is not configured yet
38
- if (!isProduction() && !isSetup()) {
59
+ if (!isProduction() && !isSetup(probotOptions)) {
39
60
 
40
61
  // Workaround for setup (probot/probot#1512)
41
62
  // When probot is started for the first time, it gets into a setup mode
@@ -72,22 +93,20 @@ async function run(appFn) {
72
93
  return server;
73
94
  }
74
95
 
75
- function isSetup() {
76
- const appId = parseInt(process.env.APP_ID, 10);
77
- const privateKey = getPrivateKey() || undefined;
96
+ function isSetup(options) {
97
+ const {
98
+ appId,
99
+ privateKey
100
+ } = options || readEnvOptions(process.env);
78
101
 
79
102
  return !!(appId && privateKey);
80
103
  }
81
104
 
82
- function isProduction() {
83
- return process.env.NODE_ENV === 'production';
84
- }
85
-
86
105
  function validateSetup() {
87
106
 
88
107
  const setup = new ManifestCreation();
89
108
 
90
- const manifest = JSON.parse(setup.getManifest(setup.pkg));
109
+ const manifest = JSON.parse(setup.getManifest(setup.pkg, process.env.BASE_URL));
91
110
 
92
111
  return [
93
112
  !manifest.url && new Error('No <url> configured in app.yml'),
@@ -9,6 +9,8 @@ const { getLog } = require('probot/lib/helpers/get-log');
9
9
 
10
10
  const { randomString } = require('../../util');
11
11
 
12
+ const { importView } = require('probot/lib/views/import');
13
+ const { setupView } = require('probot/lib/views/setup');
12
14
 
13
15
  function setupAppFactory(host, port) {
14
16
 
@@ -17,7 +19,11 @@ function setupAppFactory(host, port) {
17
19
 
18
20
  const log = getLog().child({ name: 'wuffle:setup' });
19
21
 
20
- if (process.env.NODE_ENV !== 'production' && !process.env.WEBHOOK_PROXY_URL) {
22
+ if (!(
23
+ process.env.NODE_ENV === 'production' ||
24
+ process.env.WEBHOOK_PROXY_URL ||
25
+ process.env.NO_SMEE_SETUP === 'true'
26
+ )) {
21
27
  await setup.createWebhookChannel();
22
28
  }
23
29
 
@@ -32,48 +38,110 @@ function setupAppFactory(host, port) {
32
38
  route.use(getLoggingMiddleware(app.log));
33
39
 
34
40
  route.get('/probot', async (req, res) => {
35
- const baseUrl = getBaseUrl(req);
41
+ const baseUrl = process.env.BASE_URL || getBaseUrl(req);
36
42
  const pkg = setup.pkg;
37
43
  const manifest = setup.getManifest(pkg, baseUrl);
38
44
  const createAppUrl = setup.createAppUrl;
39
45
 
46
+ await setup.updateEnv({
47
+ BASE_URL: baseUrl
48
+ });
49
+
40
50
  // Pass the manifest to be POST'd
41
- res.render('setup.hbs', { pkg, createAppUrl, manifest });
51
+ res.writeHead(200, { 'content-type': 'text/html' }).end(setupView({
52
+ name: pkg.name || 'Wuffle',
53
+ version: pkg.version,
54
+ description: pkg.description,
55
+ createAppUrl,
56
+ manifest
57
+ }));
42
58
  });
43
59
 
44
60
  route.get('/probot/setup', async (req, res) => {
45
61
  const { code } = req.query;
46
- const app_url = await setup.createAppFromCode(code);
47
62
 
48
- log.info('Setup completed, please start the app');
63
+ if (!code || typeof code !== 'string' || code.length === 0) {
64
+ return res
65
+ .writeHead(400, { 'content-type': 'text/plain' })
66
+ .end('code missing or invalid');
67
+ }
68
+
69
+ const response = await setup.createAppFromCode(code, {
70
+ request: app.state.request
71
+ });
49
72
 
50
- res.send(renderSuccess(app_url + '/installations/new'));
73
+ const appUrl = app.state.appUrl = `${response}/installations/new`;
74
+
75
+ log.warn('Setup completed, please restart the app');
76
+
77
+ log.info(`Visit ${appUrl} to connect GitHub repositories`);
78
+
79
+ const location = '/probot/success';
80
+
81
+ return res
82
+ .writeHead(302, {
83
+ 'content-type': 'text/plain',
84
+ location
85
+ })
86
+ .end(`Redirecting to ${ location }`);
51
87
  });
52
88
 
53
89
  route.get('/probot/import', async (_req, res) => {
90
+
91
+ const pkg = setup.pkg;
54
92
  const { WEBHOOK_PROXY_URL, GHE_HOST } = process.env;
55
93
  const GH_HOST = `https://${GHE_HOST ?? 'github.com'}`;
56
- res.render('import.hbs', { WEBHOOK_PROXY_URL, GH_HOST });
94
+
95
+ return res
96
+ .writeHead(200, {
97
+ 'content-type': 'text/html'
98
+ })
99
+ .end(importView({
100
+ name: pkg.name || 'Wuffle',
101
+ WEBHOOK_PROXY_URL,
102
+ GH_HOST
103
+ }));
57
104
  });
58
105
 
59
106
  route.post('/probot/import', bodyParser.json(), async (req, res) => {
60
107
  const { appId, pem, webhook_secret } = req.body;
61
108
  if (!appId || !pem || !webhook_secret) {
62
- res.status(400).send('appId and/or pem and/or webhook_secret missing');
63
- return;
109
+ return res
110
+ .writeHead(400, {
111
+ 'content-type': 'text/plain'
112
+ })
113
+ .end('appId and/or pem and/or webhook_secret missing');
64
114
  }
115
+
65
116
  await updateDotenv({
66
117
  APP_ID: appId,
67
118
  PRIVATE_KEY: `"${pem}"`,
68
119
  WEBHOOK_SECRET: webhook_secret
69
120
  });
70
121
 
71
- log.info('Setup completed, please start the app');
122
+ log.warn('Setup completed, please restart the app.');
72
123
 
73
- res.send(renderSuccess());
124
+ return res.redirect('/probot/success');
74
125
  });
75
126
 
76
- route.get('/', (req, res, next) => res.redirect('/probot'));
127
+ route.get('/probot/success', (_req, res) => {
128
+ const pkg = setup.pkg;
129
+
130
+ const appUrl = app.state.appUrl;
131
+
132
+ return res
133
+ .writeHead(200, { 'content-type': 'text/html' })
134
+ .end(successView({
135
+ name: pkg.name || 'Wuffle',
136
+ appUrl
137
+ }));
138
+ });
139
+
140
+ route.get('/', (_req, res) => {
141
+ return res
142
+ .writeHead(302, { 'content-type': 'text/plain', location: '/probot' })
143
+ .end();
144
+ });
77
145
  };
78
146
  }
79
147
 
@@ -90,40 +158,40 @@ function getBaseUrl(req) {
90
158
  return baseUrl;
91
159
  }
92
160
 
93
-
94
- function renderSuccess(appUrl = null) {
161
+ function successView({ name, appUrl }) {
95
162
 
96
163
  return `
97
- <!DOCTYPE html>
98
- <html lang="en" class="height-full">
99
- <head>
100
- <meta charset="UTF-8">
101
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
102
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
103
- <title>Setup Wuffle App | built with Probot</title>
104
- <link rel="icon" href="/probot/static/probot-head.png">
105
- <link rel="stylesheet" href="/probot/static/primer.css">
106
- </head>
107
- <body class="height-full bg-gray-light">
108
- <div class="d-flex flex-column flex-justify-center flex-items-center text-center height-full">
109
- <img src="/probot/static/robot.svg" alt="Probot Logo" width="100" class="mb-6">
110
- <div class="box-shadow rounded-2 border p-6 bg-white">
111
- <div class="text-center">
112
- <h1 class="alt-h2 mb-4">Congrats! You have successfully installed your app!</h1>
113
-
114
- <p class="alt-h3 mb-2">
115
- You can now ${ appUrl ? `<a href="${appUrl}" target="_blank" rel="no-opener">` : ''}
116
- connect GitHub repositories
117
- ${appUrl ? '</a>' : ''} to your board.
118
- </p>
119
-
120
- <p class="alt-h3">
121
- Please restart the server to complete the setup.
122
- </p>
164
+ <!DOCTYPE html>
165
+ <html lang="en" class="height-full" data-color-mode="auto" data-light-theme="light" data-dark-theme="dark">
166
+ <head>
167
+ <meta charset="UTF-8">
168
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
169
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
170
+ <title>${ name } Setup complete</title>
171
+ <link rel="icon" href="/probot/static/probot-head.png">
172
+ <link rel="stylesheet" href="/probot/static/primer.css">
173
+ </head>
174
+ <body class="height-full bg-gray-light">
175
+ <div class="d-flex flex-column flex-justify-center flex-items-center text-center height-full">
176
+ <img src="/probot/static/robot.svg" alt="Probot Logo" width="100" class="mb-6">
177
+ <div class="box-shadow rounded-2 border p-6 bg-white">
178
+ <div class="text-center">
179
+ <h1 class="alt-h3 mb-2">You completed your ${name} setup!</h1>
180
+
181
+ <p class="mb-2">
182
+ Go ahead and ${ appUrl ? `<a href="${appUrl}" target="_blank" rel="no-opener">` : ''}
183
+ connect GitHub repositories
184
+ ${appUrl ? '</a>' : ''} to your board.
185
+ </p>
186
+
187
+ <p>
188
+ Please restart the server to complete the setup.
189
+ </p>
190
+
191
+ </div>
123
192
  </div>
124
193
  </div>
125
- </div>
126
- </body>
127
- </html>`;
128
-
194
+ </body>
195
+ </html>
196
+ `;
129
197
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wuffle",
3
- "version": "0.57.0",
3
+ "version": "0.58.0",
4
4
  "description": "A multi-repository task board for GitHub issues",
5
5
  "author": {
6
6
  "name": "Nico Rehwaldt",
@@ -36,30 +36,30 @@
36
36
  "auto-test": "npm test -- --watch"
37
37
  },
38
38
  "dependencies": {
39
- "@aws-sdk/client-s3": "^3.110.0",
39
+ "@aws-sdk/client-s3": "^3.503.1",
40
40
  "async-didi": "^0.3.1",
41
41
  "body-parser": "^1.20.0",
42
42
  "compression": "^1.7.4",
43
- "express-session": "^1.17.3",
43
+ "express-session": "^1.18.0",
44
44
  "fake-tag": "^3.0.0",
45
45
  "memorystore": "^1.6.7",
46
46
  "min-dash": "^4.1.1",
47
47
  "mkdirp": "^3.0.1",
48
48
  "p-defer": "^3.0.0",
49
- "prexit": "0.0.5",
50
- "probot": "^12.2.4",
51
- "smee-client": "^1.2.5"
49
+ "prexit": "^1.0.0",
50
+ "probot": "^13.0.1",
51
+ "smee-client": "^2.0.0"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@graphql-eslint/eslint-plugin": "^3.20.1",
55
- "@octokit/graphql-schema": "^12.10.0",
55
+ "@octokit/graphql-schema": "^14.53.0",
56
56
  "@types/compression": "^1.7.2",
57
- "@types/express-session": "^1.17.4",
58
- "chai": "^4.4.0",
57
+ "@types/express-session": "^1.17.10",
58
+ "chai": "^4.4.1",
59
59
  "graphql": "^16.6.0",
60
60
  "mocha": "^10.2.0",
61
- "nock": "^13.4.0",
62
- "nodemon": "^3.0.2",
61
+ "nock": "^13.5.1",
62
+ "nodemon": "^3.0.3",
63
63
  "npm-run-all": "^4.1.5",
64
64
  "sinon": "^17.0.1",
65
65
  "sinon-chai": "^3.7.0",
@@ -91,5 +91,5 @@
91
91
  "index.js",
92
92
  "wuffle.config.example.js"
93
93
  ],
94
- "gitHead": "a0da3b97298f95e04c09f87a99dfb4bcf45cba76"
94
+ "gitHead": "07336a53705a1ba55405e6817cafa574aeefbe10"
95
95
  }