wuffle 0.73.3 → 0.75.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.
Files changed (29) hide show
  1. package/lib/apps/auth-routes/AuthRoutes.js +16 -14
  2. package/lib/apps/{automatic-dev-flow.js → automatic-dev-flow/AutomaticDevFlow.js} +12 -13
  3. package/lib/apps/automatic-dev-flow/index.js +6 -0
  4. package/lib/apps/background-sync/BackgroundSync.js +41 -83
  5. package/lib/apps/background-sync/BackgroundSyncBackend.js +140 -0
  6. package/lib/apps/background-sync/index.js +3 -1
  7. package/lib/apps/board-api-routes/board-api-routes.js +20 -14
  8. package/lib/apps/dump-store/s3/S3.js +12 -0
  9. package/lib/apps/{events-sync.js → events-sync/EventsSync.js} +7 -5
  10. package/lib/apps/events-sync/index.js +6 -0
  11. package/lib/apps/github-app/GithubApp.js +69 -6
  12. package/lib/apps/github-checks/GithubChecks.js +2 -0
  13. package/lib/apps/github-comments/GithubComments.js +9 -78
  14. package/lib/apps/github-comments/GithubCommentsBackend.js +132 -0
  15. package/lib/apps/github-comments/index.js +3 -1
  16. package/lib/apps/github-issues/GithubIssues.js +161 -9
  17. package/lib/apps/github-reviews/GithubReviews.js +2 -0
  18. package/lib/apps/github-statuses/GithubStatuses.js +2 -0
  19. package/lib/apps/issue-filter/IssueFilter.js +5 -3
  20. package/lib/apps/log-events.js +4 -4
  21. package/lib/apps/{reindex-store.js → reindex-store/ReindexStore.js} +6 -4
  22. package/lib/apps/reindex-store/index.js +6 -0
  23. package/lib/apps/search/Search.js +9 -5
  24. package/lib/apps/webhook-events/WebhookEvents.js +12 -5
  25. package/lib/events.js +2 -2
  26. package/lib/index.js +13 -5
  27. package/lib/probot/CustomProbot.js +2 -1
  28. package/lib/util/search.js +1 -1
  29. package/package.json +6 -5
@@ -1,5 +1,7 @@
1
1
  /**
2
2
  * @typedef { { ignoreFilter?: string } } StoreFilterConfig
3
+ *
4
+ * @typedef { Extract<import('@octokit/webhooks').EmitterWebhookEventName, 'issues' | `issues.${string}` | 'issue_comment' | `issue_comment.${string}` | 'pull_request' | `pull_request.${string}` | 'pull_request_review' | `pull_request_review.${string}` | 'pull_request_review_comment' | `pull_request_review_comment.${string}` | 'pull_request_review_thread' | `pull_request_review_thread.${string}`> } IssueOrPullWebhookEventName
3
5
  */
4
6
 
5
7
  import { filterIssueOrPull } from '../../filters.js';
@@ -41,7 +43,7 @@ export default function IssueFilter(config, store, search, logger) {
41
43
  /**
42
44
  * @param {import('../../types.js').Logger } log
43
45
  *
44
- * @return { (filterFn) => (any) => any }
46
+ * @return {<E extends IssueOrPullWebhookEventName>(fn: (context: import('probot').Context<E>) => any) => (context: import('probot').Context<E>) => any}
45
47
  */
46
48
  function createWebhookFilter(log) {
47
49
 
@@ -49,7 +51,7 @@ export default function IssueFilter(config, store, search, logger) {
49
51
 
50
52
  return (context) => {
51
53
 
52
- const payload = context.payload;
54
+ const payload = /** @type {any} */ (context.payload);
53
55
 
54
56
  const issueOrPull = filterIssueOrPull(
55
57
  payload.issue || payload.pull_request,
@@ -79,7 +81,7 @@ export default function IssueFilter(config, store, search, logger) {
79
81
  /**
80
82
  * @param {import('../../types.js').Logger } log
81
83
  *
82
- * @return { (filterFn) => (any) => any }
84
+ * @return {<E extends IssueOrPullWebhookEventName>(fn: (context: import('probot').Context<E>) => any) => (context: import('probot').Context<E>) => any}
83
85
  */
84
86
  this.createWebhookFilter = createWebhookFilter;
85
87
  }
@@ -27,18 +27,18 @@ export default function LogEvents(logger, webhookEvents) {
27
27
 
28
28
  log.info('dumping webhook events to %s', path.resolve(eventsDir));
29
29
 
30
- function write(event, payload) {
30
+ function write(name, payload) {
31
31
 
32
32
  const {
33
33
  action
34
34
  } = payload;
35
35
 
36
- const name = action ? `${event}.${action}` : event;
36
+ const eventName = action ? `${name}.${action}` : name;
37
37
 
38
- const data = JSON.stringify({ event, payload }, null, ' ');
38
+ const data = JSON.stringify({ name, payload }, null, ' ');
39
39
 
40
40
  return fs.mkdir(eventsDir, { recursive: true }).then(() => {
41
- const fileName = path.join(eventsDir, `${Date.now()}-${counter++}-${name}.json`);
41
+ const fileName = path.join(eventsDir, `${Date.now()}-${counter++}-${eventName}.json`);
42
42
 
43
43
  return fs.writeFile(fileName, data, 'utf8');
44
44
  });
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  getPackageVersion,
3
3
  hash
4
- } from '../util/index.js';
4
+ } from '../../util/index.js';
5
5
 
6
6
 
7
7
  /**
8
8
  * @constructor
9
9
  *
10
10
  * @param {any} config
11
- * @param {import('../types.js').Logger} logger
12
- * @param {import('../events.js').default} events
13
- * @param {import('../store.js').default} store
11
+ * @param {import('../../types.js').Logger} logger
12
+ * @param {import('../../events.js').default} events
13
+ * @param {import('../../store.js').default} store
14
14
  */
15
15
  export default function ReindexStore(config, logger, events, store) {
16
16
 
@@ -48,6 +48,8 @@ export default function ReindexStore(config, logger, events, store) {
48
48
  log.info('config changed');
49
49
 
50
50
  await reindexStore();
51
+ } else {
52
+ log.debug('config unchanged - skipping reindexing');
51
53
  }
52
54
  });
53
55
 
@@ -0,0 +1,6 @@
1
+ import ReindexStore from './ReindexStore.js';
2
+
3
+ export default {
4
+ __init__: [ 'reindexStore' ],
5
+ reindexStore: [ 'type', ReindexStore ]
6
+ };
@@ -37,7 +37,7 @@ export default function Search(config, logger, store) {
37
37
 
38
38
  const {
39
39
  treatBotsAsReviewers = false,
40
- defaultFilter
40
+ defaultFilter = ''
41
41
  } = config;
42
42
 
43
43
  function filterNoop(issue) {
@@ -63,13 +63,17 @@ export default function Search(config, logger, store) {
63
63
  *
64
64
  * @return { boolean }
65
65
  */
66
- function includes(actual, pattern, exact) {
66
+ function includes(actual, pattern, exact = false) {
67
+
68
+ if (!pattern) {
69
+ return false;
70
+ }
67
71
 
68
72
  if (exact) {
69
- return pattern && actual === pattern;
73
+ return actual === pattern;
70
74
  }
71
75
 
72
- return pattern && actual.toLowerCase().includes(pattern.toLowerCase());
76
+ return actual.toLowerCase().includes(pattern.toLowerCase());
73
77
  }
74
78
 
75
79
  function isPull(issue) {
@@ -445,7 +449,7 @@ export default function Search(config, logger, store) {
445
449
  * Retrieve a filter function from the given search string.
446
450
  *
447
451
  * @param {string} search
448
- * @param {GitHubUser} [user]
452
+ * @param {GitHubUser|null} [user]
449
453
  *
450
454
  * @return {FilterFn}
451
455
  */
@@ -1,4 +1,11 @@
1
1
  /**
2
+ * @typedef { import('probot').Probot } Probot
3
+ * @typedef { import('@octokit/webhooks').EmitterWebhookEventName } WebhookEventName
4
+ */
5
+
6
+ /**
7
+ * A lightweight wrapper around {@link Probot#on} and {@link Probot#onAny}.
8
+ *
2
9
  * @constructor
3
10
  *
4
11
  * @param {import('../../types.js').ProbotApp} app
@@ -7,8 +14,7 @@
7
14
  export default function WebhookEvents(app, githubApp) {
8
15
 
9
16
  /**
10
- * @template {Function} T
11
- * @param {T} fn
17
+ * @param {(context: import('probot').Context) => any} fn
12
18
  */
13
19
  function ifEnabled(fn) {
14
20
 
@@ -37,8 +43,9 @@ export default function WebhookEvents(app, githubApp) {
37
43
  * Register a event lister for a single
38
44
  * or a number of webhook events.
39
45
  *
40
- * @param {any|any[]} events
41
- * @param {Function} fn listener
46
+ * @template {WebhookEventName} E
47
+ * @param {E | E[]} events
48
+ * @param {(context: import('probot').Context<E>) => any} fn listener
42
49
  */
43
50
  function on(events, fn) {
44
51
  app.on(events, ifEnabled(fn));
@@ -48,7 +55,7 @@ export default function WebhookEvents(app, githubApp) {
48
55
  * Register an event listener for all
49
56
  * webhook events.
50
57
  *
51
- * @param {Function} fn
58
+ * @param {(context: import('probot').Context) => any} fn
52
59
  */
53
60
  function onAny(fn) {
54
61
  app.onAny(ifEnabled(fn));
package/lib/events.js CHANGED
@@ -139,8 +139,8 @@ Events.prototype.createEvent = function(data) {
139
139
  * @param {Object} [data] the event object
140
140
  * @param {...Object} additionalArgs to be passed to the callback functions
141
141
  *
142
- * @return {Promise<boolean>} the events return value, if specified or false if the
143
- * default action was prevented by listeners
142
+ * @return {Promise<boolean|undefined|any>} the events return value, if
143
+ * specified or false if the default action was prevented by listeners
144
144
  */
145
145
  Events.prototype.emit = async function(type, data, ...additionalArgs) {
146
146
 
package/lib/index.js CHANGED
@@ -11,7 +11,7 @@ const appModules = [
11
11
  ? import('./apps/dump-store/s3/index.js')
12
12
  : import('./apps/dump-store/local/index.js')
13
13
  ),
14
- import('./apps/events-sync.js'),
14
+ import('./apps/events-sync/index.js'),
15
15
  import('./apps/github-app/index.js'),
16
16
  import('./apps/github-issues/index.js'),
17
17
  import('./apps/github-comments/index.js'),
@@ -24,11 +24,11 @@ const appModules = [
24
24
  import('./apps/user-access/index.js'),
25
25
  import('./apps/search/index.js'),
26
26
  import('./apps/background-sync/index.js'),
27
- import('./apps/automatic-dev-flow.js'),
27
+ import('./apps/automatic-dev-flow/index.js'),
28
28
  import('./apps/auth-routes/index.js'),
29
29
  import('./apps/board-api-routes/index.js'),
30
30
  import('./apps/board-routes.js'),
31
- import('./apps/reindex-store.js')
31
+ import('./apps/reindex-store/index.js')
32
32
  ];
33
33
 
34
34
  import loadConfig from './load-config.js';
@@ -78,17 +78,25 @@ export default function Wuffle(app, { getRouter }) {
78
78
  });
79
79
 
80
80
  const coreModule = {
81
- 'app': [ 'value', app ],
82
81
  'config': [ 'value', config ],
83
- 'router': [ 'value', router ],
84
82
  'logger': [ 'value', logger ],
85
83
  'columns': [ 'type', Columns ],
86
84
  'store': [ 'type', Store ],
87
85
  'events': [ 'value', events ]
88
86
  };
89
87
 
88
+ const webModule = {
89
+ 'router': [ 'value', router ]
90
+ };
91
+
92
+ const probotModule = {
93
+ 'app': [ 'value', app ],
94
+ };
95
+
90
96
  const injector = new AsyncInjector([
91
97
  coreModule,
98
+ probotModule,
99
+ webModule,
92
100
  ...modules
93
101
  ]);
94
102
 
@@ -103,7 +103,8 @@ function validateSetup() {
103
103
 
104
104
  const setup = new ManifestCreation();
105
105
 
106
- const manifest = JSON.parse(setup.getManifest(setup.pkg, process.env.BASE_URL));
106
+ // TODO(nikku): process.env.BASE_URL may not be defined here
107
+ const manifest = JSON.parse(setup.getManifest(setup.pkg, /** @type { string } */ (process.env.BASE_URL)));
107
108
 
108
109
  return [
109
110
  !manifest.url && new Error('No <url> configured in app.yml'),
@@ -116,7 +116,7 @@ export function parseSearch(str) {
116
116
 
117
117
  do {
118
118
  lastTerm = stack.pop();
119
- } while (!lastTerm.group);
119
+ } while (lastTerm && !lastTerm.group);
120
120
 
121
121
  continue;
122
122
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wuffle",
3
- "version": "0.73.3",
3
+ "version": "0.75.0",
4
4
  "description": "A multi-repository task board for GitHub issues",
5
5
  "author": {
6
6
  "name": "Nico Rehwaldt",
@@ -35,7 +35,7 @@
35
35
  "all": "run-s lint test",
36
36
  "dev": "nodemon",
37
37
  "start": "NODE_ENV=production node ./bin/wuffle",
38
- "test": "mocha 'test/**/*.js' --exit",
38
+ "test": "mocha -r test/helpers/globals.js 'test/**/*.js' --exit",
39
39
  "lint": "run-s lint:*",
40
40
  "lint:eslint": "eslint .",
41
41
  "lint:types": "tsc --pretty",
@@ -61,13 +61,14 @@
61
61
  "@types/compression": "^1.8.1",
62
62
  "@types/express-session": "^1.19.0",
63
63
  "@types/mocha": "^10.0.10",
64
+ "@types/sinon": "^21.0.1",
64
65
  "chai": "^6.2.2",
65
- "graphql": "^16.13.2",
66
+ "graphql": "^16.14.0",
66
67
  "mocha": "^11.7.5",
67
68
  "nock": "^14.0.13",
68
69
  "nodemon": "^3.1.14",
69
70
  "npm-run-all2": "^8.0.4",
70
- "sinon": "^21.1.2",
71
+ "sinon": "^22.0.0",
71
72
  "sinon-chai": "^4.0.0",
72
73
  "typescript": "^5.9.3"
73
74
  },
@@ -82,5 +83,5 @@
82
83
  "index.js",
83
84
  "wuffle.config.example.js"
84
85
  ],
85
- "gitHead": "1d7cdf09524102d300d6230b840959cdd1479e3e"
86
+ "gitHead": "132f68f8372f71a15c4e34b0fd9db837ccc02b6b"
86
87
  }