@atolis-hq/wake 0.2.42 → 0.2.44
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/dist/src/adapters/github/github-client.js +31 -0
- package/dist/src/adapters/github/github-pull-request-merge-actor.js +29 -0
- package/dist/src/adapters/http/ui-assets.js +4 -0
- package/dist/src/adapters/http/ui-data.js +1 -0
- package/dist/src/core/policy-engine.js +7 -1
- package/dist/src/core/tick-runner.js +222 -1
- package/dist/src/domain/schema.js +19 -0
- package/dist/src/main.js +5 -0
- package/dist/src/version.js +1 -1
- package/package.json +1 -1
|
@@ -194,6 +194,37 @@ export function createGitHubClient(token) {
|
|
|
194
194
|
}),
|
|
195
195
|
});
|
|
196
196
|
},
|
|
197
|
+
async listPullRequestFiles(owner, repo, pullNumber) {
|
|
198
|
+
return fetchPaginatedWithEtag({
|
|
199
|
+
cache: etagCache,
|
|
200
|
+
cacheKey: `pr-files:${owner}/${repo}#${pullNumber}`,
|
|
201
|
+
pages: (headers) => octokit.paginate.iterator(octokit.rest.pulls.listFiles, {
|
|
202
|
+
owner,
|
|
203
|
+
repo,
|
|
204
|
+
pull_number: pullNumber,
|
|
205
|
+
per_page: 100,
|
|
206
|
+
...(headers === undefined ? {} : { headers }),
|
|
207
|
+
}),
|
|
208
|
+
});
|
|
209
|
+
},
|
|
210
|
+
async createPullRequestApproval(owner, repo, pullNumber, body) {
|
|
211
|
+
await octokit.rest.pulls.createReview({
|
|
212
|
+
owner,
|
|
213
|
+
repo,
|
|
214
|
+
pull_number: pullNumber,
|
|
215
|
+
event: 'APPROVE',
|
|
216
|
+
body,
|
|
217
|
+
});
|
|
218
|
+
},
|
|
219
|
+
async enablePullRequestAutoMerge(pullRequestNodeId) {
|
|
220
|
+
await octokit.graphql(`mutation EnableWakeAutoMerge($pullRequestId: ID!) {
|
|
221
|
+
enablePullRequestAutoMerge(input: { pullRequestId: $pullRequestId }) {
|
|
222
|
+
pullRequest {
|
|
223
|
+
id
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}`, { pullRequestId: pullRequestNodeId });
|
|
227
|
+
},
|
|
197
228
|
async replyToReviewComment(owner, repo, pullNumber, commentId, body) {
|
|
198
229
|
return octokit.rest.pulls.createReplyForReviewComment({
|
|
199
230
|
owner,
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
function parseGithubPullRequestResourceUri(resourceUri) {
|
|
2
|
+
const match = /^github:pr:([^/]+)\/([^#]+)#(\d+)$/.exec(resourceUri);
|
|
3
|
+
if (match === null) {
|
|
4
|
+
throw new Error(`Unsupported GitHub pull request resource URI: ${resourceUri}`);
|
|
5
|
+
}
|
|
6
|
+
return {
|
|
7
|
+
owner: match[1],
|
|
8
|
+
repo: match[2],
|
|
9
|
+
pullNumber: Number(match[3]),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export function createGitHubPullRequestMergeActor(input) {
|
|
13
|
+
return {
|
|
14
|
+
async listChangedFiles(resourceUri) {
|
|
15
|
+
const ref = parseGithubPullRequestResourceUri(resourceUri);
|
|
16
|
+
const files = await input.client.listPullRequestFiles(ref.owner, ref.repo, ref.pullNumber);
|
|
17
|
+
return files.map((file) => file.filename);
|
|
18
|
+
},
|
|
19
|
+
async approve(resourceUri, body) {
|
|
20
|
+
const ref = parseGithubPullRequestResourceUri(resourceUri);
|
|
21
|
+
await input.client.createPullRequestApproval(ref.owner, ref.repo, ref.pullNumber, body);
|
|
22
|
+
},
|
|
23
|
+
async enableAutoMerge(resourceUri) {
|
|
24
|
+
const ref = parseGithubPullRequestResourceUri(resourceUri);
|
|
25
|
+
const pr = await input.client.getPullRequest(ref.owner, ref.repo, ref.pullNumber);
|
|
26
|
+
await input.client.enablePullRequestAutoMerge(pr.node_id);
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -56,6 +56,7 @@ export const indexHtml = `<!DOCTYPE html>
|
|
|
56
56
|
.card .title { font-weight: 600; margin-bottom: 0.25rem; }
|
|
57
57
|
.card .meta { color: #9aa2ad; font-size: 0.72rem; }
|
|
58
58
|
.chip { display: inline-block; background: #2c313a; border-radius: 4px; padding: 0.05rem 0.35rem; font-size: 0.68rem; margin-right: 0.2rem; }
|
|
59
|
+
.chip-label { background: transparent; border: 1px solid #3a4150; color: #9aa2ad; margin-bottom: 0.2rem; }
|
|
59
60
|
table { border-collapse: collapse; width: 100%; font-size: 0.8rem; }
|
|
60
61
|
th, td { text-align: left; padding: 0.35rem 0.5rem; border-bottom: 1px solid #2c313a; }
|
|
61
62
|
th { color: #9aa2ad; font-weight: 600; }
|
|
@@ -264,6 +265,9 @@ async function renderBoard(context) {
|
|
|
264
265
|
el('span', { class: 'chip', text: item.stage }),
|
|
265
266
|
document.createTextNode(fmtMs(item.timeInStageMs) + ' in stage'),
|
|
266
267
|
]),
|
|
268
|
+
...(item.labels && item.labels.length > 0
|
|
269
|
+
? [el('div', { class: 'meta' }, item.labels.map((label) => el('span', { class: 'chip chip-label', text: label })))]
|
|
270
|
+
: []),
|
|
267
271
|
el('div', { class: 'meta', text: item.lastRunSentinel ? 'last: ' + item.lastRunAction + ' → ' + item.lastRunSentinel : item.conditionReason }),
|
|
268
272
|
]));
|
|
269
273
|
return el('div', { class: 'col' + (items.length === 0 ? ' col-empty' : '') }, [
|
|
@@ -188,7 +188,13 @@ export function createPolicyEngine() {
|
|
|
188
188
|
if (latestComment?.isBotAuthored === true &&
|
|
189
189
|
latestComment.resourceUri !== undefined &&
|
|
190
190
|
latestComment.body.includes(prReviewApprovalMarker)) {
|
|
191
|
-
return {
|
|
191
|
+
return {
|
|
192
|
+
approved: true,
|
|
193
|
+
pendingAction,
|
|
194
|
+
targetResourceUri: latestComment.resourceUri,
|
|
195
|
+
triggeringCommentId: latestComment.id,
|
|
196
|
+
triggeringCommentBody: latestComment.body,
|
|
197
|
+
};
|
|
192
198
|
}
|
|
193
199
|
if (latestHumanComment === undefined) {
|
|
194
200
|
return null;
|
|
@@ -110,6 +110,202 @@ export function createTickRunner(deps) {
|
|
|
110
110
|
function hasLabel(projection, label) {
|
|
111
111
|
return projection.issue.labels.includes(label);
|
|
112
112
|
}
|
|
113
|
+
function approvedMergePolicyForStage(stage) {
|
|
114
|
+
return (stage?.watch?.find((watch) => watch.onApproved?.merge !== undefined)?.onApproved?.merge ??
|
|
115
|
+
null);
|
|
116
|
+
}
|
|
117
|
+
function escapeRegex(input) {
|
|
118
|
+
return input.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
|
|
119
|
+
}
|
|
120
|
+
function globPatternMatches(pattern, path) {
|
|
121
|
+
const regex = new RegExp(`^${pattern.split('*').map(escapeRegex).join('.*')}$`);
|
|
122
|
+
return regex.test(path);
|
|
123
|
+
}
|
|
124
|
+
function reviewerMessageFromApprovalComment(body) {
|
|
125
|
+
return body
|
|
126
|
+
.replaceAll(prReviewApprovalMarker, '')
|
|
127
|
+
.replaceAll('<!-- wake:pr-review-changes-requested -->', '')
|
|
128
|
+
.trim();
|
|
129
|
+
}
|
|
130
|
+
async function evaluatePrMergeRisk(input) {
|
|
131
|
+
const incumbent = await deps.resourceIndex.resolve(input.targetResourceUri);
|
|
132
|
+
if (incumbent !== undefined && incumbent !== input.projection.workItemKey) {
|
|
133
|
+
return {
|
|
134
|
+
passed: false,
|
|
135
|
+
reason: `Merge policy blocked this PR because ${input.targetResourceUri} is primary-correlated to ${incumbent}, not ${input.projection.workItemKey}.`,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
const blockedLabel = input.policy.blockedLabels.find((label) => input.projection.issue.labels.includes(label));
|
|
139
|
+
if (blockedLabel !== undefined) {
|
|
140
|
+
return {
|
|
141
|
+
passed: false,
|
|
142
|
+
reason: `Merge policy blocked this PR because the work item has blocked label "${blockedLabel}".`,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
if (deps.prMergeActor === undefined) {
|
|
146
|
+
return {
|
|
147
|
+
passed: false,
|
|
148
|
+
reason: 'Merge policy blocked this PR because no pull request merge actor is configured.',
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
const filesChanged = await deps.prMergeActor.listChangedFiles(input.targetResourceUri);
|
|
152
|
+
if (input.policy.maxFilesChanged !== undefined &&
|
|
153
|
+
filesChanged.length > input.policy.maxFilesChanged) {
|
|
154
|
+
return {
|
|
155
|
+
passed: false,
|
|
156
|
+
reason: `Merge policy blocked this PR because it changes ${filesChanged.length} files, exceeding maxFilesChanged ${input.policy.maxFilesChanged}.`,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
for (const pattern of input.policy.blockedPaths) {
|
|
160
|
+
const blockedPath = filesChanged.find((path) => globPatternMatches(pattern, path));
|
|
161
|
+
if (blockedPath !== undefined) {
|
|
162
|
+
return {
|
|
163
|
+
passed: false,
|
|
164
|
+
reason: `Merge policy blocked this PR because changed path "${blockedPath}" matches blockedPaths pattern "${pattern}".`,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return { passed: true, filesChanged };
|
|
169
|
+
}
|
|
170
|
+
async function publishPrMergePolicyBlock(input) {
|
|
171
|
+
const commentId = input.approvalResolution.triggeringCommentId;
|
|
172
|
+
const targetResourceUri = input.approvalResolution.targetResourceUri;
|
|
173
|
+
if (commentId === undefined || targetResourceUri === undefined) {
|
|
174
|
+
return { status: 'idle' };
|
|
175
|
+
}
|
|
176
|
+
const runId = `merge-gate-blocked-${commentId.replace(/[^a-z0-9]+/gi, '-')}`;
|
|
177
|
+
const occurredAt = eventStampNow();
|
|
178
|
+
const blockedEvent = createEventEnvelope({
|
|
179
|
+
eventId: `${runId}-completed`,
|
|
180
|
+
workItemKey: input.projection.workItemKey,
|
|
181
|
+
streamScope: 'work-item',
|
|
182
|
+
direction: 'internal',
|
|
183
|
+
sourceSystem: 'wake',
|
|
184
|
+
sourceEventType: 'wake.run.completed',
|
|
185
|
+
sourceRefs: {
|
|
186
|
+
repo: input.projection.issue.repo,
|
|
187
|
+
issueNumber: input.projection.issue.number,
|
|
188
|
+
runId,
|
|
189
|
+
resourceUri: targetResourceUri,
|
|
190
|
+
},
|
|
191
|
+
occurredAt,
|
|
192
|
+
ingestedAt: occurredAt,
|
|
193
|
+
trigger: 'immediate',
|
|
194
|
+
payload: {
|
|
195
|
+
action: input.approvalResolution.pendingAction,
|
|
196
|
+
sentinel: 'BLOCKED',
|
|
197
|
+
runId,
|
|
198
|
+
reason: 'pr-review-merge-policy-blocked',
|
|
199
|
+
blockReason: 'pr-review-merge-policy-blocked',
|
|
200
|
+
handledCommentId: commentId,
|
|
201
|
+
body: input.reason,
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
const appended = await deps.stateStore.appendEventEnvelope(blockedEvent);
|
|
205
|
+
await projectionUpdater.rebuildFromEvents([appended]);
|
|
206
|
+
const reviewerMessage = reviewerMessageFromApprovalComment(input.approvalResolution.triggeringCommentBody ?? '');
|
|
207
|
+
const body = [reviewerMessage, input.reason].filter((part) => part.length > 0).join('\n\n');
|
|
208
|
+
await deliverOutboundEvent(createEventEnvelope({
|
|
209
|
+
eventId: `${runId}-publish-intent`,
|
|
210
|
+
workItemKey: input.projection.workItemKey,
|
|
211
|
+
streamScope: 'work-item',
|
|
212
|
+
direction: 'outbound',
|
|
213
|
+
sourceSystem: 'wake',
|
|
214
|
+
sourceEventType: 'wake.publish.intent.requested',
|
|
215
|
+
sourceRefs: {
|
|
216
|
+
repo: input.projection.issue.repo,
|
|
217
|
+
issueNumber: input.projection.issue.number,
|
|
218
|
+
runId,
|
|
219
|
+
resourceUri: targetResourceUri,
|
|
220
|
+
},
|
|
221
|
+
occurredAt,
|
|
222
|
+
ingestedAt: occurredAt,
|
|
223
|
+
trigger: 'context-only',
|
|
224
|
+
payload: {
|
|
225
|
+
kind: 'question',
|
|
226
|
+
origin: input.projection.origin ?? 'github',
|
|
227
|
+
body,
|
|
228
|
+
action: input.approvalResolution.pendingAction,
|
|
229
|
+
sentinel: 'BLOCKED',
|
|
230
|
+
runId,
|
|
231
|
+
idempotencyKey: `${commentId}:pr-review-merge-policy-blocked`,
|
|
232
|
+
deliveryState: 'PENDING',
|
|
233
|
+
},
|
|
234
|
+
derivedHints: { stage: input.projection.wake.stage },
|
|
235
|
+
}));
|
|
236
|
+
await deliverOutboundEvent(createLabelsEvent({
|
|
237
|
+
projection: input.projection,
|
|
238
|
+
runId,
|
|
239
|
+
statusLabel: 'wake:status.blocked',
|
|
240
|
+
stageLabel: stageLabelForStage(input.projection.wake.stage),
|
|
241
|
+
workflowLabel: workflowLabelForWorkflowName(input.workflowName),
|
|
242
|
+
occurredAt,
|
|
243
|
+
}));
|
|
244
|
+
return {
|
|
245
|
+
status: 'processed',
|
|
246
|
+
runId,
|
|
247
|
+
sentinel: 'BLOCKED',
|
|
248
|
+
nextStage: null,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
async function performApprovedPrMergeActions(input) {
|
|
252
|
+
if (deps.prMergeActor === undefined ||
|
|
253
|
+
input.approvalResolution.targetResourceUri === undefined ||
|
|
254
|
+
input.approvalResolution.triggeringCommentId === undefined) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const targetResourceUri = input.approvalResolution.targetResourceUri;
|
|
258
|
+
const commentId = input.approvalResolution.triggeringCommentId.replace(/[^a-z0-9]+/gi, '-');
|
|
259
|
+
const reviewBody = reviewerMessageFromApprovalComment(input.approvalResolution.triggeringCommentBody ?? '');
|
|
260
|
+
const approvedEventId = `pr-merge-approved-${commentId}`;
|
|
261
|
+
if (input.mergePolicy.approve &&
|
|
262
|
+
(await deps.stateStore.readEventEnvelope(approvedEventId)) === null) {
|
|
263
|
+
await deps.prMergeActor.approve(targetResourceUri, reviewBody);
|
|
264
|
+
const occurredAt = eventStampNow();
|
|
265
|
+
await deps.stateStore.appendEventEnvelope(createEventEnvelope({
|
|
266
|
+
eventId: approvedEventId,
|
|
267
|
+
workItemKey: input.projection.workItemKey,
|
|
268
|
+
streamScope: 'work-item',
|
|
269
|
+
direction: 'internal',
|
|
270
|
+
sourceSystem: 'wake',
|
|
271
|
+
sourceEventType: 'wake.pr-review.approved',
|
|
272
|
+
sourceRefs: {
|
|
273
|
+
resourceUri: targetResourceUri,
|
|
274
|
+
commentId: input.approvalResolution.triggeringCommentId,
|
|
275
|
+
},
|
|
276
|
+
occurredAt,
|
|
277
|
+
ingestedAt: occurredAt,
|
|
278
|
+
trigger: 'context-only',
|
|
279
|
+
payload: {
|
|
280
|
+
idempotencyKey: `${input.approvalResolution.triggeringCommentId}:pr-review-approval`,
|
|
281
|
+
},
|
|
282
|
+
}));
|
|
283
|
+
}
|
|
284
|
+
const autoMergeEventId = `pr-auto-merge-enabled-${commentId}`;
|
|
285
|
+
if (input.mergePolicy.autoMerge &&
|
|
286
|
+
(await deps.stateStore.readEventEnvelope(autoMergeEventId)) === null) {
|
|
287
|
+
await deps.prMergeActor.enableAutoMerge(targetResourceUri);
|
|
288
|
+
const occurredAt = eventStampNow();
|
|
289
|
+
await deps.stateStore.appendEventEnvelope(createEventEnvelope({
|
|
290
|
+
eventId: autoMergeEventId,
|
|
291
|
+
workItemKey: input.projection.workItemKey,
|
|
292
|
+
streamScope: 'work-item',
|
|
293
|
+
direction: 'internal',
|
|
294
|
+
sourceSystem: 'wake',
|
|
295
|
+
sourceEventType: 'wake.pr-auto-merge.enabled',
|
|
296
|
+
sourceRefs: {
|
|
297
|
+
resourceUri: targetResourceUri,
|
|
298
|
+
commentId: input.approvalResolution.triggeringCommentId,
|
|
299
|
+
},
|
|
300
|
+
occurredAt,
|
|
301
|
+
ingestedAt: occurredAt,
|
|
302
|
+
trigger: 'context-only',
|
|
303
|
+
payload: {
|
|
304
|
+
idempotencyKey: `${input.approvalResolution.triggeringCommentId}:pr-auto-merge`,
|
|
305
|
+
},
|
|
306
|
+
}));
|
|
307
|
+
}
|
|
308
|
+
}
|
|
113
309
|
// Closes the loop on #82's review feedback: rather than scrape a PR link
|
|
114
310
|
// out of the agent's free text, the agent emits a `wake-artifacts` fence
|
|
115
311
|
// (domain/schema.ts's parseRunnerArtifacts) and Wake verifies each claim
|
|
@@ -656,6 +852,27 @@ export function createTickRunner(deps) {
|
|
|
656
852
|
promptContextOverrides = workflowAction?.promptContext;
|
|
657
853
|
}
|
|
658
854
|
else if (approvalResolution.approved) {
|
|
855
|
+
const mergePolicy = approvedMergePolicyForStage(workflow.stages[candidate.wake.stage]);
|
|
856
|
+
if (approvalResolution.targetResourceUri !== undefined && mergePolicy !== null) {
|
|
857
|
+
const risk = await evaluatePrMergeRisk({
|
|
858
|
+
projection: candidate,
|
|
859
|
+
targetResourceUri: approvalResolution.targetResourceUri,
|
|
860
|
+
policy: mergePolicy,
|
|
861
|
+
});
|
|
862
|
+
if (!risk.passed) {
|
|
863
|
+
return await publishPrMergePolicyBlock({
|
|
864
|
+
projection: candidate,
|
|
865
|
+
approvalResolution,
|
|
866
|
+
reason: risk.reason,
|
|
867
|
+
workflowName,
|
|
868
|
+
});
|
|
869
|
+
}
|
|
870
|
+
await performApprovedPrMergeActions({
|
|
871
|
+
projection: candidate,
|
|
872
|
+
approvalResolution,
|
|
873
|
+
mergePolicy,
|
|
874
|
+
});
|
|
875
|
+
}
|
|
659
876
|
const approvalId = `approval-${candidate.issue.number}-${deps.clock.now().getTime()}`;
|
|
660
877
|
const approvedAt = deps.clock.now().toISOString();
|
|
661
878
|
const automaticApproval = approvalResolution.automatic === true;
|
|
@@ -684,7 +901,11 @@ export function createTickRunner(deps) {
|
|
|
684
901
|
nextStage,
|
|
685
902
|
runId: approvalId,
|
|
686
903
|
reason: automaticApproval ? 'auto:approved' : 'human:approved',
|
|
687
|
-
...(automaticApproval
|
|
904
|
+
...(automaticApproval
|
|
905
|
+
? {}
|
|
906
|
+
: {
|
|
907
|
+
handledCommentId: approvalResolution.triggeringCommentId ?? latestHumanCommentId(candidate),
|
|
908
|
+
}),
|
|
688
909
|
...(automaticApproval
|
|
689
910
|
? {
|
|
690
911
|
autoResolution: {
|
|
@@ -377,6 +377,20 @@ const workflowWorkspaceSchema = z.enum(['none', 'read-only', 'branch']);
|
|
|
377
377
|
const workflowTriggerScheduleSchema = z.object({
|
|
378
378
|
cron: z.string().min(1),
|
|
379
379
|
});
|
|
380
|
+
const approvedMergePolicySchema = z
|
|
381
|
+
.object({
|
|
382
|
+
approve: z.boolean().default(false),
|
|
383
|
+
autoMerge: z.boolean().default(false),
|
|
384
|
+
maxFilesChanged: z.number().int().positive().optional(),
|
|
385
|
+
blockedPaths: z.array(z.string().min(1)).default([]),
|
|
386
|
+
blockedLabels: z.array(z.string().min(1)).default([]),
|
|
387
|
+
})
|
|
388
|
+
.default({
|
|
389
|
+
approve: false,
|
|
390
|
+
autoMerge: false,
|
|
391
|
+
blockedPaths: [],
|
|
392
|
+
blockedLabels: [],
|
|
393
|
+
});
|
|
380
394
|
const workflowStageSchema = stageRouteSchema.extend({
|
|
381
395
|
workspace: workflowWorkspaceSchema,
|
|
382
396
|
onDone: identifierSchema,
|
|
@@ -392,6 +406,11 @@ const workflowStageSchema = stageRouteSchema.extend({
|
|
|
392
406
|
.optional(),
|
|
393
407
|
schedule: workflowTriggerScheduleSchema.optional(),
|
|
394
408
|
workflow: identifierSchema,
|
|
409
|
+
onApproved: z
|
|
410
|
+
.object({
|
|
411
|
+
merge: approvedMergePolicySchema.optional(),
|
|
412
|
+
})
|
|
413
|
+
.optional(),
|
|
395
414
|
}))
|
|
396
415
|
.optional(),
|
|
397
416
|
});
|
package/dist/src/main.js
CHANGED
|
@@ -19,6 +19,7 @@ import { createGitHubArtifactVerifier } from './adapters/github/github-artifact-
|
|
|
19
19
|
import { createGitHubClient } from './adapters/github/github-client.js';
|
|
20
20
|
import { createGitHubIssuesWorkSource } from './adapters/github/github-issues-work-source.js';
|
|
21
21
|
import { createGitHubPullRequestActivitySource } from './adapters/github/github-pull-request-activity-source.js';
|
|
22
|
+
import { createGitHubPullRequestMergeActor } from './adapters/github/github-pull-request-merge-actor.js';
|
|
22
23
|
import { runAuditCommand } from './cli/audit-command.js';
|
|
23
24
|
import { runCorrelateCommand } from './cli/correlate-command.js';
|
|
24
25
|
import { runDoctorCommand } from './cli/doctor-command.js';
|
|
@@ -497,6 +498,9 @@ export async function buildRuntime(args) {
|
|
|
497
498
|
const artifactVerifier = prTrackingEnabled && githubClient !== undefined
|
|
498
499
|
? createGitHubArtifactVerifier({ client: githubClient })
|
|
499
500
|
: undefined;
|
|
501
|
+
const prMergeActor = prTrackingEnabled && githubClient !== undefined
|
|
502
|
+
? createGitHubPullRequestMergeActor({ client: githubClient })
|
|
503
|
+
: undefined;
|
|
500
504
|
const ticketingSystem = githubClient !== undefined
|
|
501
505
|
? createGitHubIssuesWorkSource({
|
|
502
506
|
client: githubClient,
|
|
@@ -577,6 +581,7 @@ export async function buildRuntime(args) {
|
|
|
577
581
|
workspaceManager,
|
|
578
582
|
resourceIndex,
|
|
579
583
|
...(artifactVerifier === undefined ? {} : { artifactVerifier }),
|
|
584
|
+
...(prMergeActor === undefined ? {} : { prMergeActor }),
|
|
580
585
|
});
|
|
581
586
|
return {
|
|
582
587
|
config,
|
package/dist/src/version.js
CHANGED