@edgehero/pi-dispatch-receiver 1.3.0 → 1.4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edgehero/pi-dispatch-receiver",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "type": "module",
5
5
  "description": "Webhook receiver for pi-dispatch: the always-on edge that verifies GitHub, GitLab, Forgejo and Azure DevOps deliveries and enqueues (at most) one job per event for the worker.",
6
6
  "keywords": [
@@ -45,7 +45,7 @@
45
45
  },
46
46
  "dependencies": {
47
47
  "@octokit/webhooks": "14.2.0",
48
- "@edgehero/pi-dispatch": "^1.4.0",
48
+ "@edgehero/pi-dispatch": "^1.6.0",
49
49
  "bullmq": "5.80.4",
50
50
  "ioredis": "5.11.1"
51
51
  }
package/src/config.mjs CHANGED
@@ -293,9 +293,9 @@ function loadTriggers(env, readFile, fileExists) {
293
293
  }
294
294
  const group = groups[run.kind];
295
295
  if (on.type === "label") {
296
- group.label.push({ index, predicate: { any: on.any, all: on.all, none: on.none }, flow: run.flow, command: run.command, packages: run.packages, image: run.image, skillsDir: run.skillsDir, instructions: run.instructions, resume: run.resume, secrets: run.secrets, secretsProfile: run.secretsProfile, replicas: run.replicas, repository: run.repository });
296
+ group.label.push({ index, predicate: { any: on.any, all: on.all, none: on.none }, flow: run.flow, command: run.command, packages: run.packages, image: run.image, skillsDir: run.skillsDir, instructions: run.instructions, resume: run.resume, secrets: run.secrets, secretsProfile: run.secretsProfile, waitFor: run.waitFor, replicas: run.replicas, repository: run.repository });
297
297
  } else if (on.type === "comment") {
298
- group.comment = { index, phrase: on.phrase, defaultFlow: run.flow, command: run.command, packages: run.packages, image: run.image, skillsDir: run.skillsDir, instructions: run.instructions, resume: run.resume, secrets: run.secrets, secretsProfile: run.secretsProfile, replicas: run.replicas, repository: run.repository }; // parseTriggers guarantees at most one per forge
298
+ group.comment = { index, phrase: on.phrase, defaultFlow: run.flow, command: run.command, packages: run.packages, image: run.image, skillsDir: run.skillsDir, instructions: run.instructions, resume: run.resume, secrets: run.secrets, secretsProfile: run.secretsProfile, waitFor: run.waitFor, replicas: run.replicas, repository: run.repository }; // parseTriggers guarantees at most one per forge
299
299
  } else if (on.type === "pull_request") {
300
300
  // The close-only split (issue #231): a close rule routes through the close gate (the CLOSER's
301
301
  // resolved authority) and every other PR rule through the author gate, so they live in separate
@@ -304,17 +304,17 @@ function loadTriggers(env, readFile, fileExists) {
304
304
  // split reads the SHARED close-word table, never a re-typed word.
305
305
  const closeWord = PR_CLOSE_ACTIONS[run.kind];
306
306
  if (closeWord !== undefined && on.action.includes(closeWord)) {
307
- group.prClose.push({ index, actions: new Set(on.action), number: on.number, once: on.once, flow: run.flow, command: run.command, packages: run.packages, image: run.image, skillsDir: run.skillsDir, instructions: run.instructions, resume: run.resume, secrets: run.secrets, secretsProfile: run.secretsProfile, replicas: run.replicas });
307
+ group.prClose.push({ index, actions: new Set(on.action), number: on.number, once: on.once, flow: run.flow, command: run.command, packages: run.packages, image: run.image, skillsDir: run.skillsDir, instructions: run.instructions, resume: run.resume, secrets: run.secrets, secretsProfile: run.secretsProfile, waitFor: run.waitFor, replicas: run.replicas });
308
308
  } else {
309
309
  // `reviewStates` is null rather than an empty Set when unnarrowed: the filter tests it for
310
310
  // presence, and an empty Set would read as "no verdict matches" and silently refuse everything.
311
- group.pullRequest.push({ index, actions: new Set(on.action), reviewStates: on.reviewState ? new Set(on.reviewState) : null, predicate: { any: on.any, all: on.all, none: on.none }, flow: run.flow, command: run.command, packages: run.packages, image: run.image, skillsDir: run.skillsDir, instructions: run.instructions, resume: run.resume, secrets: run.secrets, secretsProfile: run.secretsProfile, replicas: run.replicas });
311
+ group.pullRequest.push({ index, actions: new Set(on.action), reviewStates: on.reviewState ? new Set(on.reviewState) : null, predicate: { any: on.any, all: on.all, none: on.none }, flow: run.flow, command: run.command, packages: run.packages, image: run.image, skillsDir: run.skillsDir, instructions: run.instructions, resume: run.resume, secrets: run.secrets, secretsProfile: run.secretsProfile, waitFor: run.waitFor, replicas: run.replicas });
312
312
  }
313
313
  } else if (on.type === "issue") {
314
314
  // The close-trigger kind (issue #231). No predicate and no reviewStates by construction (the
315
315
  // loader refused both), and `number`/`once` ride conditionally-present exactly as the loader
316
316
  // normalized them -- the filter's close route reads them, nothing else does.
317
- group.issue.push({ index, actions: new Set(on.action), number: on.number, once: on.once, flow: run.flow, command: run.command, packages: run.packages, image: run.image, skillsDir: run.skillsDir, instructions: run.instructions, resume: run.resume, secrets: run.secrets, secretsProfile: run.secretsProfile, replicas: run.replicas });
317
+ group.issue.push({ index, actions: new Set(on.action), number: on.number, once: on.once, flow: run.flow, command: run.command, packages: run.packages, image: run.image, skillsDir: run.skillsDir, instructions: run.instructions, resume: run.resume, secrets: run.secrets, secretsProfile: run.secretsProfile, waitFor: run.waitFor, replicas: run.replicas });
318
318
  }
319
319
  }
320
320
 
@@ -119,6 +119,7 @@ export function filterAzure(subset, triggers, knownFlows, selfId, authorized, de
119
119
  // receiver has no resolver and reaches no vault -- the worker resolves them pre-spend.
120
120
  ...(resolved.secrets !== undefined ? { secrets: resolved.secrets } : {}),
121
121
  ...(resolved.secretsProfile !== undefined ? { secretsProfile: resolved.secretsProfile } : {}),
122
+ ...(resolved.waitFor !== undefined ? { waitFor: resolved.waitFor } : {}),
122
123
  ...(resolved.instructions !== undefined ? { instructions: resolved.instructions } : {}),
123
124
  ...(resolved.resume !== undefined ? { resume: resolved.resume } : {}),
124
125
  // How many independent sandboxes race this flow (REQ-REPLICA-RUNS). At JOB level and conditional for the
@@ -188,6 +189,7 @@ function matchLabelRules(subset, triggers, labels, action) {
188
189
  skillsDir: rule.skillsDir,
189
190
  secrets: rule.secrets,
190
191
  secretsProfile: rule.secretsProfile,
192
+ waitFor: rule.waitFor,
191
193
  instructions: rule.instructions,
192
194
  resume: rule.resume,
193
195
  replicas: rule.replicas,
@@ -231,6 +233,7 @@ function routeComment(subset, triggers, knownFlows, targetType) {
231
233
  skillsDir: triggers.comment.skillsDir,
232
234
  secrets: triggers.comment.secrets,
233
235
  secretsProfile: triggers.comment.secretsProfile,
236
+ waitFor: triggers.comment.waitFor,
234
237
  instructions: triggers.comment.instructions,
235
238
  resume: triggers.comment.resume,
236
239
  replicas: triggers.comment.replicas,
@@ -263,6 +266,7 @@ function routePullRequest(subset, triggers, action) {
263
266
  skillsDir: rule.skillsDir,
264
267
  secrets: rule.secrets,
265
268
  secretsProfile: rule.secretsProfile,
269
+ waitFor: rule.waitFor,
266
270
  instructions: rule.instructions,
267
271
  resume: rule.resume,
268
272
  replicas: rule.replicas,
@@ -133,6 +133,7 @@ export function filterForgejo(eventName, subset, triggers, knownFlows, selfId, a
133
133
  // receiver has no resolver and reaches no vault -- the worker resolves them pre-spend.
134
134
  ...(resolved.secrets !== undefined ? { secrets: resolved.secrets } : {}),
135
135
  ...(resolved.secretsProfile !== undefined ? { secretsProfile: resolved.secretsProfile } : {}),
136
+ ...(resolved.waitFor !== undefined ? { waitFor: resolved.waitFor } : {}),
136
137
  ...(resolved.instructions !== undefined ? { instructions: resolved.instructions } : {}),
137
138
  ...(resolved.resume !== undefined ? { resume: resolved.resume } : {}),
138
139
  // How many independent sandboxes race this flow (REQ-REPLICA-RUNS). At JOB level and conditional for the
@@ -168,6 +169,7 @@ function routeIssueLabel(subset, triggers) {
168
169
  skillsDir: rule.skillsDir,
169
170
  secrets: rule.secrets,
170
171
  secretsProfile: rule.secretsProfile,
172
+ waitFor: rule.waitFor,
171
173
  instructions: rule.instructions,
172
174
  resume: rule.resume,
173
175
  replicas: rule.replicas,
@@ -216,6 +218,7 @@ function routeComment(subset, triggers, knownFlows) {
216
218
  skillsDir: triggers.comment.skillsDir,
217
219
  secrets: triggers.comment.secrets,
218
220
  secretsProfile: triggers.comment.secretsProfile,
221
+ waitFor: triggers.comment.waitFor,
219
222
  instructions: triggers.comment.instructions,
220
223
  resume: triggers.comment.resume,
221
224
  replicas: triggers.comment.replicas,
@@ -246,6 +249,7 @@ function routePullRequest(subset, triggers, action) {
246
249
  skillsDir: rule.skillsDir,
247
250
  secrets: rule.secrets,
248
251
  secretsProfile: rule.secretsProfile,
252
+ waitFor: rule.waitFor,
249
253
  instructions: rule.instructions,
250
254
  resume: rule.resume,
251
255
  replicas: rule.replicas,
@@ -300,6 +304,7 @@ function routeIssueClose(subset, triggers, authorized) {
300
304
  skillsDir: rule.skillsDir,
301
305
  secrets: rule.secrets,
302
306
  secretsProfile: rule.secretsProfile,
307
+ waitFor: rule.waitFor,
303
308
  instructions: rule.instructions,
304
309
  resume: rule.resume,
305
310
  replicas: rule.replicas,
@@ -335,6 +340,7 @@ function routePullRequestClose(subset, triggers, authorized) {
335
340
  skillsDir: rule.skillsDir,
336
341
  secrets: rule.secrets,
337
342
  secretsProfile: rule.secretsProfile,
343
+ waitFor: rule.waitFor,
338
344
  instructions: rule.instructions,
339
345
  resume: rule.resume,
340
346
  replicas: rule.replicas,
@@ -136,6 +136,7 @@ export function filterGitLab(subset, triggers, knownFlows, selfId, authorized, d
136
136
  // receiver has no resolver and reaches no vault -- the worker resolves them pre-spend.
137
137
  ...(resolved.secrets !== undefined ? { secrets: resolved.secrets } : {}),
138
138
  ...(resolved.secretsProfile !== undefined ? { secretsProfile: resolved.secretsProfile } : {}),
139
+ ...(resolved.waitFor !== undefined ? { waitFor: resolved.waitFor } : {}),
139
140
  ...(resolved.instructions !== undefined ? { instructions: resolved.instructions } : {}),
140
141
  // Conditional like packages/image, and for the same reason: an unflagged job's data must stay
141
142
  // byte-identical to today's, so the key is absent rather than present-and-undefined.
@@ -178,6 +179,7 @@ function routeLabel(subset, triggers, targetType) {
178
179
  skillsDir: rule.skillsDir,
179
180
  secrets: rule.secrets,
180
181
  secretsProfile: rule.secretsProfile,
182
+ waitFor: rule.waitFor,
181
183
  instructions: rule.instructions,
182
184
  resume: rule.resume,
183
185
  replicas: rule.replicas,
@@ -241,6 +243,7 @@ function mrResult(subset, rule, matched) {
241
243
  skillsDir: rule.skillsDir,
242
244
  secrets: rule.secrets,
243
245
  secretsProfile: rule.secretsProfile,
246
+ waitFor: rule.waitFor,
244
247
  instructions: rule.instructions,
245
248
  resume: rule.resume,
246
249
  replicas: rule.replicas,
@@ -286,6 +289,7 @@ function routeIssueClose(subset, triggers, authorized) {
286
289
  skillsDir: rule.skillsDir,
287
290
  secrets: rule.secrets,
288
291
  secretsProfile: rule.secretsProfile,
292
+ waitFor: rule.waitFor,
289
293
  instructions: rule.instructions,
290
294
  resume: rule.resume,
291
295
  replicas: rule.replicas,
@@ -319,6 +323,7 @@ function routeMergeRequestClose(subset, triggers, authorized) {
319
323
  skillsDir: rule.skillsDir,
320
324
  secrets: rule.secrets,
321
325
  secretsProfile: rule.secretsProfile,
326
+ waitFor: rule.waitFor,
322
327
  instructions: rule.instructions,
323
328
  resume: rule.resume,
324
329
  replicas: rule.replicas,
@@ -370,6 +375,7 @@ function routeNote(subset, triggers, knownFlows) {
370
375
  skillsDir: triggers.comment.skillsDir,
371
376
  secrets: triggers.comment.secrets,
372
377
  secretsProfile: triggers.comment.secretsProfile,
378
+ waitFor: triggers.comment.waitFor,
373
379
  instructions: triggers.comment.instructions,
374
380
  resume: triggers.comment.resume,
375
381
  replicas: triggers.comment.replicas,
package/src/filter.mjs CHANGED
@@ -155,6 +155,7 @@ export function filter(eventName, subset, cfg, selfId, deliveryId, closerAuthori
155
155
  // receiver has no resolver and reaches no vault -- the worker resolves them pre-spend.
156
156
  ...(resolved.secrets !== undefined ? { secrets: resolved.secrets } : {}),
157
157
  ...(resolved.secretsProfile !== undefined ? { secretsProfile: resolved.secretsProfile } : {}),
158
+ ...(resolved.waitFor !== undefined ? { waitFor: resolved.waitFor } : {}),
158
159
  ...(resolved.instructions !== undefined ? { instructions: resolved.instructions } : {}),
159
160
  // Conditional like packages/image, and for the same reason: an unflagged job's data must stay
160
161
  // byte-identical to today's, so the key is absent rather than present-and-undefined.
@@ -202,6 +203,7 @@ function routeIssueLabel(subset, triggers) {
202
203
  skillsDir: rule.skillsDir,
203
204
  secrets: rule.secrets,
204
205
  secretsProfile: rule.secretsProfile,
206
+ waitFor: rule.waitFor,
205
207
  instructions: rule.instructions,
206
208
  resume: rule.resume,
207
209
  replicas: rule.replicas,
@@ -261,6 +263,7 @@ function routeComment(subset, triggers, knownFlows) {
261
263
  skillsDir: triggers.comment.skillsDir,
262
264
  secrets: triggers.comment.secrets,
263
265
  secretsProfile: triggers.comment.secretsProfile,
266
+ waitFor: triggers.comment.waitFor,
264
267
  instructions: triggers.comment.instructions,
265
268
  resume: triggers.comment.resume,
266
269
  replicas: triggers.comment.replicas,
@@ -358,6 +361,7 @@ function routePullRequest(subset, triggers, action) {
358
361
  skillsDir: rule.skillsDir,
359
362
  secrets: rule.secrets,
360
363
  secretsProfile: rule.secretsProfile,
364
+ waitFor: rule.waitFor,
361
365
  instructions: rule.instructions,
362
366
  resume: rule.resume,
363
367
  replicas: rule.replicas,
@@ -473,6 +477,7 @@ function routeClose(rules, number, closerAuthorized, matchedFor, targetFor) {
473
477
  skillsDir: rule.skillsDir,
474
478
  secrets: rule.secrets,
475
479
  secretsProfile: rule.secretsProfile,
480
+ waitFor: rule.waitFor,
476
481
  instructions: rule.instructions,
477
482
  resume: rule.resume,
478
483
  replicas: rule.replicas,