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 +4 -3
- package/lib/apps/github-client/GithubClient.js +12 -1
- package/lib/probot/CustomProbot.js +40 -21
- package/lib/probot/apps/setup.js +112 -44
- package/package.json +12 -12
- package/public/bundle.js.map +1 -1
- package/public/service-worker.js +1 -1
- package/public/service-worker.js.map +1 -1
package/bin/run.js
CHANGED
|
@@ -205,7 +205,7 @@ async function validate() {
|
|
|
205
205
|
|
|
206
206
|
async function performSetup() {
|
|
207
207
|
|
|
208
|
-
log.
|
|
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.
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
15
|
-
|
|
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
|
-
|
|
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
|
|
26
|
-
webhookProxy
|
|
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
|
-
|
|
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
|
|
77
|
-
|
|
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'),
|
package/lib/probot/apps/setup.js
CHANGED
|
@@ -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 (
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
63
|
-
|
|
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.
|
|
122
|
+
log.warn('Setup completed, please restart the app.');
|
|
72
123
|
|
|
73
|
-
res.
|
|
124
|
+
return res.redirect('/probot/success');
|
|
74
125
|
});
|
|
75
126
|
|
|
76
|
-
route.get('/', (
|
|
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
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
-
</
|
|
126
|
-
</
|
|
127
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
50
|
-
"probot": "^
|
|
51
|
-
"smee-client": "^
|
|
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": "^
|
|
55
|
+
"@octokit/graphql-schema": "^14.53.0",
|
|
56
56
|
"@types/compression": "^1.7.2",
|
|
57
|
-
"@types/express-session": "^1.17.
|
|
58
|
-
"chai": "^4.4.
|
|
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.
|
|
62
|
-
"nodemon": "^3.0.
|
|
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": "
|
|
94
|
+
"gitHead": "07336a53705a1ba55405e6817cafa574aeefbe10"
|
|
95
95
|
}
|