wuffle 0.73.2 → 0.73.3

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019-present Nico Rehwaldt
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9
+ of the Software, and to permit persons to whom the Software is furnished to do
10
+ so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,6 +1,3 @@
1
- import { filterIssueOrPull } from '../filters.js';
2
- import { issueIdent } from '../util/meta.js';
3
-
4
1
  const DONE = 'DONE';
5
2
  const EXTERNAL_CONTRIBUTION = 'EXTERNAL_CONTRIBUTION';
6
3
  const IN_PROGRESS = 'IN_PROGRESS';
@@ -27,26 +24,7 @@ export default function(webhookEvents, githubIssues, columns, issueFilter, logge
27
24
  name: 'wuffle:automatic-dev-flow'
28
25
  });
29
26
 
30
- function ifEnabled(webhookHandlerFn) {
31
-
32
- return (context) => {
33
-
34
- const payload = context.payload;
35
-
36
- const issueOrPull = filterIssueOrPull(
37
- payload.issue || payload.pull_request,
38
- payload.repository
39
- );
40
-
41
- if (issueFilter.isIgnored(issueOrPull)) {
42
- log.debug({ issue: issueIdent(issueOrPull) }, 'issue matching ignore filter');
43
-
44
- return;
45
- }
46
-
47
- return webhookHandlerFn(context);
48
- };
49
- }
27
+ const ifEnabled = issueFilter.createWebhookFilter(log);
50
28
 
51
29
  webhookEvents.on([
52
30
  'issues.closed',
@@ -217,25 +217,11 @@ We automatically synchronize all repositories you granted us access to via the G
217
217
 
218
218
  const update = filterIssueOrPull(issueOrPull, repository);
219
219
 
220
- const {
221
- id
222
- } = update;
220
+ foundIssues[update.id] = update;
223
221
 
224
- const existingIssue = await store.getIssueById(id);
225
-
226
- if (existingIssue && existingIssue.updated_at >= update.updated_at) {
227
- foundIssues[id] = null;
228
-
229
- log.debug({
230
- [type]: `${owner}/${repo}#${issueOrPull.number}`
231
- }, 'skipping, as up-to-date');
232
- } else {
233
- foundIssues[id] = update;
234
-
235
- log.debug({
236
- [type]: `${owner}/${repo}#${issueOrPull.number}`
237
- }, 'scheduled for update');
238
- }
222
+ log.debug({
223
+ [type]: `${owner}/${repo}#${issueOrPull.number}`
224
+ }, 'scheduled for update');
239
225
  } catch (err) {
240
226
  log.error({
241
227
  err,
@@ -395,12 +381,21 @@ We automatically synchronize all repositories you granted us access to via the G
395
381
 
396
382
  // update changed issues
397
383
 
398
- await Promise.all(pendingUpdates.map(update => store.updateIssue(update)));
384
+ const updateTasks = pendingUpdates.map(
385
+ update => store.updateIssue(update)
386
+ );
387
+
388
+ // returns the update for updated issues or undefined
389
+ // where issues were not stored (filtered out) - we only filter
390
+ // for actual updated issues
391
+ const updatedIssues = await Promise.all(updateTasks).then(updates => {
392
+ return updates.filter(update => update);
393
+ });
399
394
 
400
- // emit background sync event for all found issues
395
+ // emit background sync event for all updated issues
401
396
 
402
397
  await syncDetails(
403
- Object.keys(foundIssues),
398
+ updatedIssues,
404
399
  getSyncClosedDetailsSince(),
405
400
  getSyncOpenDetailsSince()
406
401
  );
@@ -437,10 +432,12 @@ We automatically synchronize all repositories you granted us access to via the G
437
432
  );
438
433
  }
439
434
 
440
- function syncDetails(issueIds, syncClosedSince, syncOpenSince) {
435
+ function syncDetails(updatedIssues, syncClosedSince, syncOpenSince) {
436
+
437
+ const jobs = updatedIssues.map(async updatedIssue => {
441
438
 
442
- const jobs = issueIds.map(async id => {
443
- const issue = await store.getIssueById(id);
439
+ // ensure we fetch latest version of issue (to prevent de-sync)
440
+ const issue = await store.getIssueById(updatedIssue.id);
444
441
 
445
442
  if (!issue) {
446
443
  return;
@@ -12,8 +12,16 @@ import gql from 'fake-tag';
12
12
  * @param {import('../../events.js').default} events
13
13
  * @param {import('../github-client/GithubClient.js').default} githubClient
14
14
  * @param {import('../../store.js').default} store
15
+ * @param {import('../issue-filter/IssueFilter.js').default} issueFilter
16
+ * @param {import('../../types.js').Logger } logger
15
17
  */
16
- export default function GithubComments(webhookEvents, events, githubClient, store) {
18
+ export default function GithubComments(webhookEvents, events, githubClient, store, issueFilter, logger) {
19
+
20
+ const log = logger.child({
21
+ name: 'wuffle:github-comments'
22
+ });
23
+
24
+ const ifEnabled = issueFilter.createWebhookFilter(log);
17
25
 
18
26
  // issues /////////////////////
19
27
 
@@ -108,7 +116,7 @@ export default function GithubComments(webhookEvents, events, githubClient, stor
108
116
 
109
117
  webhookEvents.on([
110
118
  'issue_comment'
111
- ], async ({ payload }) => {
119
+ ], ifEnabled(async ({ payload }) => {
112
120
  const {
113
121
  action,
114
122
  comment: _comment,
@@ -169,7 +177,7 @@ export default function GithubComments(webhookEvents, events, githubClient, stor
169
177
  ...commentedIssue,
170
178
  comments
171
179
  });
172
- });
180
+ }));
173
181
 
174
182
  }
175
183
 
@@ -11,8 +11,16 @@ import { filterUser, filterPull } from '../../filters.js';
11
11
  * @param {import('../../events.js').default} events
12
12
  * @param {import('../github-client/GithubClient.js').default} githubClient
13
13
  * @param {import('../../store.js').default} store
14
+ * @param {import('../issue-filter/IssueFilter.js').default} issueFilter
15
+ * @param {import('../../types.js').Logger } logger
14
16
  */
15
- export default function GithubReviews(webhookEvents, events, githubClient, store) {
17
+ export default function GithubReviews(webhookEvents, events, githubClient, store, issueFilter, logger) {
18
+
19
+ const log = logger.child({
20
+ name: 'wuffle:github-reviews'
21
+ });
22
+
23
+ const ifEnabled = issueFilter.createWebhookFilter(log);
16
24
 
17
25
  // issues /////////////////////
18
26
 
@@ -54,7 +62,7 @@ export default function GithubReviews(webhookEvents, events, githubClient, store
54
62
 
55
63
  webhookEvents.on([
56
64
  'pull_request_review'
57
- ], async ({ payload }) => {
65
+ ], ifEnabled(async ({ payload }) => {
58
66
  const {
59
67
  action,
60
68
  review: _review,
@@ -102,7 +110,7 @@ export default function GithubReviews(webhookEvents, events, githubClient, store
102
110
  ...pull_request,
103
111
  reviews
104
112
  });
105
- });
113
+ }));
106
114
 
107
115
  }
108
116
 
@@ -11,8 +11,16 @@ import { filterPull } from '../../filters.js';
11
11
  * @param {import('../../events.js').default} events
12
12
  * @param {import('../github-client/GithubClient.js').default} githubClient
13
13
  * @param {import('../../store.js').default} store
14
+ * @param {import('../issue-filter/IssueFilter.js').default} issueFilter
15
+ * @param {import('../../types.js').Logger } logger
14
16
  */
15
- export default function GithubStates(webhookEvents, events, githubClient, store) {
17
+ export default function GithubStatuses(webhookEvents, events, githubClient, store, issueFilter, logger) {
18
+
19
+ const log = logger.child({
20
+ name: 'wuffle:github-statuses'
21
+ });
22
+
23
+ const ifEnabled = issueFilter.createWebhookFilter(log);
16
24
 
17
25
  // issues /////////////////////
18
26
 
@@ -89,7 +97,7 @@ export default function GithubStates(webhookEvents, events, githubClient, store)
89
97
  webhookEvents.on([
90
98
  'pull_request.opened',
91
99
  'pull_request.synchronize'
92
- ], async ({ payload }) => {
100
+ ], ifEnabled(async ({ payload }) => {
93
101
 
94
102
  const {
95
103
  pull_request: _pull_request,
@@ -108,7 +116,7 @@ export default function GithubStates(webhookEvents, events, githubClient, store)
108
116
  id,
109
117
  statuses
110
118
  });
111
- });
119
+ }));
112
120
 
113
121
  webhookEvents.on([
114
122
  'status'
@@ -2,12 +2,14 @@
2
2
  * @typedef { { ignoreFilter?: string } } StoreFilterConfig
3
3
  */
4
4
 
5
+ import { filterIssueOrPull } from '../../filters.js';
6
+ import { issueIdent } from '../../util/meta.js';
7
+
5
8
  /**
6
9
  * An component that configures the store to filter certain elements,
7
10
  * effectively making them invisible to the board and its users.
8
11
  *
9
12
  * @param { StoreFilterConfig } config
10
- *
11
13
  * @param { import('../../store.js').default } store
12
14
  * @param { import('../search/Search.js').default } search
13
15
  * @param { import('../../types.js').Logger } logger
@@ -21,21 +23,50 @@ export default function IssueFilter(config, store, search, logger) {
21
23
  /**
22
24
  * @type { import('../search/Search.js').FilterFn }
23
25
  */
24
- let ignoreFilter = (issue) => false;
26
+ let isIgnored = (issue) => false;
25
27
 
26
28
 
27
29
  if ('ignoreFilter' in config) {
28
30
  const ignoreFilterFn = search.buildFilterFn(config.ignoreFilter);
29
31
 
30
32
  if (ignoreFilterFn) {
31
- ignoreFilter = ignoreFilterFn;
33
+ isIgnored = ignoreFilterFn;
32
34
 
33
- store.setIgnoreFilter(ignoreFilter);
35
+ store.setIgnoreFilter(isIgnored);
34
36
  } else {
35
37
  log.warn('unparseable <ignoreFilter> - please correct your board configuration');
36
38
  }
37
39
  }
38
40
 
41
+ /**
42
+ * @param {import('../../types.js').Logger } log
43
+ *
44
+ * @return { (filterFn) => (any) => any }
45
+ */
46
+ function createWebhookFilter(log) {
47
+
48
+ return function ifEnabled(webhookHandlerFn) {
49
+
50
+ return (context) => {
51
+
52
+ const payload = context.payload;
53
+
54
+ const issueOrPull = filterIssueOrPull(
55
+ payload.issue || payload.pull_request,
56
+ payload.repository
57
+ );
58
+
59
+ if (isIgnored(issueOrPull)) {
60
+ log.debug({ issue: issueIdent(issueOrPull) }, 'issue matching ignore filter');
61
+
62
+ return;
63
+ }
64
+
65
+ return webhookHandlerFn(context);
66
+ };
67
+ };
68
+ };
69
+
39
70
  /**
40
71
  * Figure whether the issue shall be ignored (by ignore filter rules)
41
72
  *
@@ -43,8 +74,12 @@ export default function IssueFilter(config, store, search, logger) {
43
74
  *
44
75
  * @return {boolean} true, if issue shall be ignored
45
76
  */
46
- this.isIgnored = function(issue) {
47
- return ignoreFilter(issue);
48
- };
77
+ this.isIgnored = isIgnored;
49
78
 
79
+ /**
80
+ * @param {import('../../types.js').Logger } log
81
+ *
82
+ * @return { (filterFn) => (any) => any }
83
+ */
84
+ this.createWebhookFilter = createWebhookFilter;
50
85
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wuffle",
3
- "version": "0.73.2",
3
+ "version": "0.73.3",
4
4
  "description": "A multi-repository task board for GitHub issues",
5
5
  "author": {
6
6
  "name": "Nico Rehwaldt",
@@ -81,5 +81,6 @@
81
81
  "app.yml",
82
82
  "index.js",
83
83
  "wuffle.config.example.js"
84
- ]
84
+ ],
85
+ "gitHead": "1d7cdf09524102d300d6230b840959cdd1479e3e"
85
86
  }