@ddtcorex/dsh-maestro-review 0.5.0 → 0.5.1
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/README.md +2 -1
- package/lib/ci-coexist.d.ts +6 -4
- package/lib/ci-coexist.d.ts.map +1 -1
- package/lib/ci-coexist.js +6 -4
- package/lib/ci-coexist.js.map +1 -1
- package/lib/events.d.ts +4 -0
- package/lib/events.d.ts.map +1 -1
- package/lib/gitlab-client.d.ts +7 -0
- package/lib/gitlab-client.d.ts.map +1 -1
- package/lib/gitlab-client.js +21 -0
- package/lib/gitlab-client.js.map +1 -1
- package/lib/incremental.d.ts.map +1 -1
- package/lib/incremental.js +3 -2
- package/lib/incremental.js.map +1 -1
- package/lib/orchestrator.d.ts +5 -2
- package/lib/orchestrator.d.ts.map +1 -1
- package/lib/orchestrator.js +44 -11
- package/lib/orchestrator.js.map +1 -1
- package/lib/providers/ci-trigger.d.ts +2 -1
- package/lib/providers/ci-trigger.d.ts.map +1 -1
- package/lib/providers/ci-trigger.js +12 -8
- package/lib/providers/ci-trigger.js.map +1 -1
- package/lib/providers/gitlab.d.ts.map +1 -1
- package/lib/providers/gitlab.js +16 -4
- package/lib/providers/gitlab.js.map +1 -1
- package/lib/review-history.d.ts +2 -1
- package/lib/review-history.d.ts.map +1 -1
- package/lib/review-history.js +67 -40
- package/lib/review-history.js.map +1 -1
- package/lib/review-intake.d.ts +9 -0
- package/lib/review-intake.d.ts.map +1 -1
- package/lib/review-intake.js +34 -1
- package/lib/review-intake.js.map +1 -1
- package/lib/review-signals.d.ts.map +1 -1
- package/lib/review-signals.js +9 -3
- package/lib/review-signals.js.map +1 -1
- package/package.json +1 -1
- package/src/host/ci-coexist.ts +6 -4
- package/src/host/events.ts +4 -0
- package/src/host/gitlab-client.ts +21 -0
- package/src/host/incremental.ts +3 -2
- package/src/host/orchestrator.ts +47 -11
- package/src/host/providers/ci-trigger.ts +14 -10
- package/src/host/providers/gitlab.ts +19 -5
- package/src/host/review-history.ts +65 -35
- package/src/host/review-intake.ts +36 -1
- package/src/host/review-signals.ts +6 -4
- package/templates/source-project.gitlab-ci.yml +1 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review-history.js","sourceRoot":"","sources":["../src/host/review-history.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACjF,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAoBzC,MAAM,WAAW,GAAG,GAAG,CAAA;AACvB,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,GAAG,MAAM,CAAA,CAAC,qDAAqD;AAE9F,MAAM,UAAU,WAAW,CAAC,OAAgB;IAC1C,MAAM,IAAI,GAAG,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,CAAA;IACvE,OAAO,IAAI,CAAC,IAAI,EAAE,oBAAoB,EAAE,cAAc,CAAC,CAAA;AACzD,CAAC;AAGD,KAAK,UAAU,OAAO,CAAC,OAAgB;IACrC,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC,CAAA;QACjF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,EAAE,CAAA;QACrC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAA+B,EAAE,CAC1D,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,OAAQ,KAA4B,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAA;IACxG,CAAC;IAAC,MAAM,CAAC;QACP,iFAAiF;QACjF,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,OAA6B,EAAE,OAAgB;IACrE,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,CAAA;IACjC,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IAC5D,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IAC3F,MAAM,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;AAC1B,CAAC;AAED,SAAS,gBAAgB,CAAC,OAA6B;IACrD,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IACtB,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,GAAG,GAAG,CAAC,CAAC,SAAS,GAAG,gBAAgB,EAAE,CAAC;YACnE,CAAC,CAAC,MAAM,GAAG,QAAQ,CAAA;YACnB,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,2DAA2D,CAAA;YAChF,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,IAAI,GAAG,CAAA;YAClC,OAAO,GAAG,IAAI,CAAA;QAChB,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAAyC,EAAE,OAAgB;IACjG,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"review-history.js","sourceRoot":"","sources":["../src/host/review-history.ts"],"names":[],"mappings":"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"}
|
package/lib/review-intake.d.ts
CHANGED
|
@@ -3,5 +3,14 @@ export interface RouteOptions {
|
|
|
3
3
|
/** When true, an MR update carrying new commits routes a push re-review. */
|
|
4
4
|
pushEnabled?: boolean;
|
|
5
5
|
}
|
|
6
|
+
/** Actionable provider-layer drop reasons. Generic non-review GitLab noise
|
|
7
|
+
* (closes, label edits, ...) intentionally has no reason and stays silent. */
|
|
8
|
+
export type DropReason = 'invalid-identity' | 'push-gate-off';
|
|
9
|
+
/**
|
|
10
|
+
* Name why this webhook body will NOT route at the provider layer, or
|
|
11
|
+
* `undefined` when it routes (or is generic noise the provider ignores).
|
|
12
|
+
* Pure — the provider logs the returned reason with project/mr context.
|
|
13
|
+
*/
|
|
14
|
+
export declare function describeDrop(body: unknown, botUsername: string, options?: RouteOptions): DropReason | undefined;
|
|
6
15
|
export declare function routeGitlabReviewRequest(body: unknown, botUsername: string, options?: RouteOptions): ReviewRequest | undefined;
|
|
7
16
|
//# sourceMappingURL=review-intake.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review-intake.d.ts","sourceRoot":"","sources":["../src/host/review-intake.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA+B,aAAa,EAAe,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"review-intake.d.ts","sourceRoot":"","sources":["../src/host/review-intake.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA+B,aAAa,EAAe,MAAM,aAAa,CAAA;AA2D1F,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED;8EAC8E;AAC9E,MAAM,MAAM,UAAU,GAAG,kBAAkB,GAAG,eAAe,CAAA;AAE7D;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,UAAU,GAAG,SAAS,CAWnH;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,aAAa,GAAG,SAAS,CAsClI"}
|
package/lib/review-intake.js
CHANGED
|
@@ -29,6 +29,19 @@ function isMentioned(text, botUsername) {
|
|
|
29
29
|
const escaped = botUsername.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
30
30
|
return new RegExp(`(^|[^A-Za-z0-9_.-])@${escaped}(?=$|[^A-Za-z0-9_.-])`, 'i').test(text);
|
|
31
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Short head-sha hint for the in-flight key: prefers `last_commit.id`, falls
|
|
34
|
+
* back to `checkout_sha`. Returns `undefined` when the body carries no sha.
|
|
35
|
+
*/
|
|
36
|
+
function shortPushSha(attributes) {
|
|
37
|
+
const lastCommit = record(attributes.last_commit);
|
|
38
|
+
const raw = typeof lastCommit?.id === 'string' ? lastCommit.id
|
|
39
|
+
: typeof attributes.checkout_sha === 'string' ? attributes.checkout_sha
|
|
40
|
+
: undefined;
|
|
41
|
+
if (raw === undefined || raw.trim() === '')
|
|
42
|
+
return undefined;
|
|
43
|
+
return raw.slice(0, 8);
|
|
44
|
+
}
|
|
32
45
|
function noteScope(attributes) {
|
|
33
46
|
const position = record(attributes.position);
|
|
34
47
|
if (position === undefined)
|
|
@@ -39,6 +52,26 @@ function noteScope(attributes) {
|
|
|
39
52
|
return undefined;
|
|
40
53
|
return { kind: 'discussion', discussionId: attributes.discussion_id, path, line };
|
|
41
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Name why this webhook body will NOT route at the provider layer, or
|
|
57
|
+
* `undefined` when it routes (or is generic noise the provider ignores).
|
|
58
|
+
* Pure — the provider logs the returned reason with project/mr context.
|
|
59
|
+
*/
|
|
60
|
+
export function describeDrop(body, botUsername, options = {}) {
|
|
61
|
+
const value = record(body);
|
|
62
|
+
if (value === undefined || botUsername.trim() === '')
|
|
63
|
+
return 'invalid-identity';
|
|
64
|
+
const payload = mrPayload(value);
|
|
65
|
+
if (payload === undefined)
|
|
66
|
+
return 'invalid-identity';
|
|
67
|
+
if (value.object_kind === 'merge_request') {
|
|
68
|
+
const attributes = record(value.object_attributes);
|
|
69
|
+
const hasNewCommits = typeof attributes?.oldrev === 'string' && attributes.oldrev !== '';
|
|
70
|
+
if (hasNewCommits && options.pushEnabled !== true)
|
|
71
|
+
return 'push-gate-off';
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
42
75
|
export function routeGitlabReviewRequest(body, botUsername, options = {}) {
|
|
43
76
|
const value = record(body);
|
|
44
77
|
if (value === undefined || botUsername.trim() === '')
|
|
@@ -56,7 +89,7 @@ export function routeGitlabReviewRequest(body, botUsername, options = {}) {
|
|
|
56
89
|
if (options.pushEnabled === true) {
|
|
57
90
|
const hasNewCommits = typeof attributes.oldrev === 'string' && attributes.oldrev !== '';
|
|
58
91
|
if (hasNewCommits) {
|
|
59
|
-
return { ...payload, trigger: 'push', mode: 'quick', scope: { kind: 'mr' } };
|
|
92
|
+
return { ...payload, trigger: 'push', mode: 'quick', scope: { kind: 'mr' }, pushSha: shortPushSha(attributes) };
|
|
60
93
|
}
|
|
61
94
|
}
|
|
62
95
|
const reviewerChange = changes === undefined ? undefined : record(changes.reviewers);
|
package/lib/review-intake.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review-intake.js","sourceRoot":"","sources":["../src/host/review-intake.ts"],"names":[],"mappings":"AAIA,SAAS,MAAM,CAAC,KAAc;IAC5B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAmB,CAAC,CAAC,CAAC,SAAS,CAAA;AAC/G,CAAC;AAED,SAAS,SAAS,CAAC,IAAgB;IACjC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACpC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;IACjD,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAA;IACtE,IAAI,OAAO,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS;WAC5C,OAAO,OAAO,CAAC,EAAE,KAAK,QAAQ,IAAI,OAAO,OAAO,CAAC,mBAAmB,KAAK,QAAQ;WACjF,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,aAAa,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAA;IACjG,OAAO;QACL,SAAS,EAAE,OAAO,CAAC,EAAE;QACrB,WAAW,EAAE,OAAO,CAAC,mBAAmB;QACxC,KAAK,EAAE,MAAM,CAAC,GAAG;QACjB,YAAY,EAAE,MAAM,CAAC,aAAa;KACnC,CAAA;AACH,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IACpC,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;QAChC,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAA;QAC7B,OAAO,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IACrG,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,WAAmB;IACpD,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAA;IAClE,OAAO,IAAI,MAAM,CAAC,uBAAuB,OAAO,uBAAuB,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAC1F,CAAC;AAED,SAAS,SAAS,CAAC,UAAsB;IACvC,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAA;IAC5C,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;IACjD,MAAM,IAAI,GAAG,OAAO,QAAQ,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAA;IAC1F,MAAM,IAAI,GAAG,OAAO,QAAQ,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAA;IAC1F,IAAI,OAAO,UAAU,CAAC,aAAa,KAAK,QAAQ,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAA;IAC1H,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;AACnF,CAAC;
|
|
1
|
+
{"version":3,"file":"review-intake.js","sourceRoot":"","sources":["../src/host/review-intake.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review-signals.d.ts","sourceRoot":"","sources":["../src/host/review-signals.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"review-signals.d.ts","sourceRoot":"","sources":["../src/host/review-signals.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,MAAM,WAAW,aAAa;IAC5B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACtB,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACvD;AA0BD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,aAAa,CAgBrJ"}
|
package/lib/review-signals.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MR award-emoji acknowledgements: the MR shows "eyes" while a review runs and
|
|
3
|
+
* a final marker when it completes or fails. Signalling is best-effort — any
|
|
4
|
+
* GitLab error is swallowed so it can never fail the review itself.
|
|
5
|
+
*/
|
|
1
6
|
import { gitlabAuthHeaders } from './gitlab-auth.js';
|
|
7
|
+
import { fetchWithTimeout } from './gitlab-client.js';
|
|
2
8
|
async function award(baseUrl, token, projectId, mrIid, name) {
|
|
3
|
-
await
|
|
9
|
+
await fetchWithTimeout(`${baseUrl}/api/v4/projects/${projectId}/merge_requests/${mrIid}/award_emoji`, {
|
|
4
10
|
method: 'POST',
|
|
5
11
|
headers: { ...gitlabAuthHeaders(token), 'Content-Type': 'application/json' },
|
|
6
12
|
body: JSON.stringify({ name }),
|
|
@@ -8,7 +14,7 @@ async function award(baseUrl, token, projectId, mrIid, name) {
|
|
|
8
14
|
}
|
|
9
15
|
/** Remove only this bot's stale running markers; other users' awards stay untouched. */
|
|
10
16
|
async function unawardOwn(baseUrl, token, projectId, mrIid, botUsername) {
|
|
11
|
-
const response = await
|
|
17
|
+
const response = await fetchWithTimeout(`${baseUrl}/api/v4/projects/${projectId}/merge_requests/${mrIid}/award_emoji`, {
|
|
12
18
|
headers: gitlabAuthHeaders(token),
|
|
13
19
|
});
|
|
14
20
|
if (!response.ok)
|
|
@@ -17,7 +23,7 @@ async function unawardOwn(baseUrl, token, projectId, mrIid, botUsername) {
|
|
|
17
23
|
for (const awardItem of Array.isArray(awards) ? awards : []) {
|
|
18
24
|
if (awardItem.name !== 'eyes' || awardItem.user?.username !== botUsername || typeof awardItem.id !== 'number')
|
|
19
25
|
continue;
|
|
20
|
-
await
|
|
26
|
+
await fetchWithTimeout(`${baseUrl}/api/v4/projects/${projectId}/merge_requests/${mrIid}/award_emoji/${awardItem.id}`, {
|
|
21
27
|
method: 'DELETE',
|
|
22
28
|
headers: gitlabAuthHeaders(token),
|
|
23
29
|
}).catch(() => { });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review-signals.js","sourceRoot":"","sources":["../src/host/review-signals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"review-signals.js","sourceRoot":"","sources":["../src/host/review-signals.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAOrD,KAAK,UAAU,KAAK,CAAC,OAAe,EAAE,KAAa,EAAE,SAAiB,EAAE,KAAa,EAAE,IAAY;IACjG,MAAM,gBAAgB,CAAC,GAAG,OAAO,oBAAoB,SAAS,mBAAmB,KAAK,cAAc,EAAE;QACpG,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,GAAG,iBAAiB,CAAC,KAAK,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC5E,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC;KAC/B,CAAC,CAAA;AACJ,CAAC;AAED,wFAAwF;AACxF,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,KAAa,EAAE,SAAiB,EAAE,KAAa,EAAE,WAAmB;IAC7G,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,GAAG,OAAO,oBAAoB,SAAS,mBAAmB,KAAK,cAAc,EAAE;QACrH,OAAO,EAAE,iBAAiB,CAAC,KAAK,CAAC;KAClC,CAAC,CAAA;IACF,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,OAAM;IACxB,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAwE,CAAA;IAC7G,KAAK,MAAM,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAC5D,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,IAAI,SAAS,CAAC,IAAI,EAAE,QAAQ,KAAK,WAAW,IAAI,OAAO,SAAS,CAAC,EAAE,KAAK,QAAQ;YAAE,SAAQ;QACvH,MAAM,gBAAgB,CAAC,GAAG,OAAO,oBAAoB,SAAS,mBAAmB,KAAK,gBAAgB,SAAS,CAAC,EAAE,EAAE,EAAE;YACpH,MAAM,EAAE,QAAQ;YAChB,OAAO,EAAE,iBAAiB,CAAC,KAAK,CAAC;SAClC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IACpB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAkG;IACpI,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,OAAO,CAAA;IACjE,OAAO;QACL,KAAK,CAAC,KAAK;YACT,IAAI,CAAC;gBACH,MAAM,UAAU,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,CAAC,CAAA;gBAC/D,MAAM,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;YACvD,CAAC;YAAC,MAAM,CAAC,CAAC,4CAA4C,CAAC,CAAC;QAC1D,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,OAAO;YAClB,IAAI,CAAC;gBACH,MAAM,UAAU,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,CAAC,CAAA;gBAC/D,MAAM,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;YACzG,CAAC;YAAC,MAAM,CAAC,CAAC,4CAA4C,CAAC,CAAC;QAC1D,CAAC;KACF,CAAA;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ddtcorex/dsh-maestro-review",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.1",
|
|
5
5
|
"description": "Maestro Review — pluggable ReviewProvider (GitLab/GitHub) + orchestrator for automated MR review",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./lib/index.js",
|
package/src/host/ci-coexist.ts
CHANGED
|
@@ -2,10 +2,12 @@ import { gitlabAuthHeaders } from './gitlab-auth.js'
|
|
|
2
2
|
import { parseReviewMarker } from './review-marker.js'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Coexistence checks (spec §4): the CI flow yields to
|
|
6
|
-
* the same head SHA
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* Coexistence checks (spec §4): the CI flow yields to a completed review of
|
|
6
|
+
* the same head SHA carrying a review marker (i.e. an earlier CI review —
|
|
7
|
+
* webhook reviews post marker-free and stay invisible here) and to an
|
|
8
|
+
* in-flight review (eyes running-marker). Fetch failures fail open toward
|
|
9
|
+
* running — a missing signal must never block a review, only a present one
|
|
10
|
+
* skips it.
|
|
9
11
|
*/
|
|
10
12
|
export async function hasCompletedReviewForSha(
|
|
11
13
|
fetcher: typeof fetch, baseUrl: string, token: string, projectId: number, mrIid: number, sha: string,
|
package/src/host/events.ts
CHANGED
|
@@ -30,6 +30,10 @@ export interface ReviewRequest extends MrOpenedPayload {
|
|
|
30
30
|
* webhook producer never sets it — webhook comments stay marker-free.
|
|
31
31
|
*/
|
|
32
32
|
headSha?: string
|
|
33
|
+
/** Short (8-char) head-sha hint for `push` triggers, taken from the webhook
|
|
34
|
+
* body — feeds the in-flight key so two concurrent pushes stop deduping
|
|
35
|
+
* each other. Absent when the body carries no sha. */
|
|
36
|
+
pushSha?: string
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
export interface ReviewResult {
|
|
@@ -47,6 +47,27 @@ export function selectFileDiff(diffs: GitlabDiff[], path: string): string | unde
|
|
|
47
47
|
return `--- ${d.old_path}\n+++ ${d.new_path}\n${d.diff}`
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
/**
|
|
51
|
+
* `fetch` with a hard ceiling: aborts the request after `ms` (default 15s)
|
|
52
|
+
* and throws `GitLab API timeout after <ms>ms` on abort. The timer is always
|
|
53
|
+
* cleared on settle. Pre-agent lookups degrade the throw to `undefined` at
|
|
54
|
+
* their own call site; post-agent callers let it reach `writeFailedReport`.
|
|
55
|
+
*/
|
|
56
|
+
export async function fetchWithTimeout(
|
|
57
|
+
url: string, init: RequestInit | undefined, ms = 15_000,
|
|
58
|
+
): Promise<Response> {
|
|
59
|
+
const controller = new AbortController()
|
|
60
|
+
const timer = setTimeout(() => controller.abort(), ms)
|
|
61
|
+
try {
|
|
62
|
+
return await fetch(url, { ...init, signal: controller.signal })
|
|
63
|
+
} catch (err) {
|
|
64
|
+
if ((err as Error)?.name === 'AbortError') throw new Error(`GitLab API timeout after ${ms}ms`)
|
|
65
|
+
throw err
|
|
66
|
+
} finally {
|
|
67
|
+
clearTimeout(timer)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
50
71
|
interface GitlabDiffRefs {
|
|
51
72
|
base_sha: string
|
|
52
73
|
start_sha: string
|
package/src/host/incremental.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { gitlabAuthHeaders } from './gitlab-auth.js'
|
|
2
|
+
import { fetchWithTimeout } from './gitlab-client.js'
|
|
2
3
|
export interface CompareCommit {
|
|
3
4
|
short_id?: string
|
|
4
5
|
title?: string
|
|
@@ -56,7 +57,7 @@ export async function fetchMrDetailHeadSha(
|
|
|
56
57
|
baseUrl: string, token: string, projectId: number, mrIid: number,
|
|
57
58
|
): Promise<string | undefined> {
|
|
58
59
|
try {
|
|
59
|
-
const response = await
|
|
60
|
+
const response = await fetchWithTimeout(
|
|
60
61
|
`${baseUrl}/api/v4/projects/${projectId}/merge_requests/${mrIid}`,
|
|
61
62
|
{ headers: gitlabAuthHeaders(token) },
|
|
62
63
|
)
|
|
@@ -73,7 +74,7 @@ export async function fetchCompare(
|
|
|
73
74
|
baseUrl: string, token: string, projectId: number, from: string, to: string,
|
|
74
75
|
): Promise<CompareResult | undefined> {
|
|
75
76
|
try {
|
|
76
|
-
const response = await
|
|
77
|
+
const response = await fetchWithTimeout(
|
|
77
78
|
`${baseUrl}/api/v4/projects/${projectId}/repository/compare?from=${encodeURIComponent(from)}&to=${encodeURIComponent(to)}`,
|
|
78
79
|
{ headers: gitlabAuthHeaders(token) },
|
|
79
80
|
)
|
package/src/host/orchestrator.ts
CHANGED
|
@@ -524,7 +524,8 @@ const inFlightKeys = new Set<string>()
|
|
|
524
524
|
|
|
525
525
|
function reviewKey(payload: ReviewRequest): string {
|
|
526
526
|
const scope = payload.scope.kind === 'mr' ? 'mr' : `discussion:${payload.scope.discussionId}`
|
|
527
|
-
|
|
527
|
+
const sha = typeof payload.pushSha === 'string' && payload.pushSha !== '' ? `:${payload.pushSha}` : ''
|
|
528
|
+
return `${payload.projectId}:${payload.mrIid}:${payload.mode}:${scope}:${payload.trigger}${sha}`
|
|
528
529
|
}
|
|
529
530
|
|
|
530
531
|
/**
|
|
@@ -640,7 +641,10 @@ export async function runReviewAndAudit(payload: ReviewRequest, deps: ReviewAndA
|
|
|
640
641
|
assertSafeId(payload.projectId, 'projectId')
|
|
641
642
|
assertSafeId(payload.mrIid, 'mrIid')
|
|
642
643
|
const key = reviewKey(payload)
|
|
643
|
-
if (inFlightKeys.has(key))
|
|
644
|
+
if (inFlightKeys.has(key)) {
|
|
645
|
+
console.error(`maestro-orchestrator: deduped duplicate in-flight review key=${key} trigger=${payload.trigger}`)
|
|
646
|
+
return ''
|
|
647
|
+
}
|
|
644
648
|
inFlightKeys.add(key)
|
|
645
649
|
try {
|
|
646
650
|
const worktreePath = await deps.ensureWorktree(deps.localRepoPath, payload.sourceBranch, payload.projectId, payload.mrIid, reviewKeyHash(payload))
|
|
@@ -711,7 +715,10 @@ export async function runDiffOnlyReview(payload: ReviewRequest, deps: DiffOnlyRe
|
|
|
711
715
|
assertSafeId(payload.projectId, 'projectId')
|
|
712
716
|
assertSafeId(payload.mrIid, 'mrIid')
|
|
713
717
|
const key = reviewKey(payload)
|
|
714
|
-
if (inFlightKeys.has(key))
|
|
718
|
+
if (inFlightKeys.has(key)) {
|
|
719
|
+
console.error(`maestro-orchestrator: deduped duplicate in-flight review key=${key} trigger=${payload.trigger}`)
|
|
720
|
+
return ''
|
|
721
|
+
}
|
|
715
722
|
inFlightKeys.add(key)
|
|
716
723
|
try {
|
|
717
724
|
const { summary, failures } = await deps.runReviewer(payload)
|
|
@@ -741,12 +748,18 @@ export async function runDiffOnlyReview(payload: ReviewRequest, deps: DiffOnlyRe
|
|
|
741
748
|
}
|
|
742
749
|
}
|
|
743
750
|
|
|
744
|
-
/** Decline a Deep request that lacks the local mapping it requires.
|
|
745
|
-
|
|
751
|
+
/** Decline a Deep request that lacks the local mapping it requires.
|
|
752
|
+
* Resolves `true` when the decline was posted, `false` when a duplicate
|
|
753
|
+
* in-flight review is already handling this key (caller must not record a
|
|
754
|
+
* completion for work it did not do). */
|
|
755
|
+
export async function declineUnmappedDeepReview(payload: ReviewRequest, deps: ReviewCommentDeps): Promise<boolean> {
|
|
746
756
|
assertSafeId(payload.projectId, 'projectId')
|
|
747
757
|
assertSafeId(payload.mrIid, 'mrIid')
|
|
748
758
|
const key = reviewKey(payload)
|
|
749
|
-
if (inFlightKeys.has(key))
|
|
759
|
+
if (inFlightKeys.has(key)) {
|
|
760
|
+
console.error(`maestro-orchestrator: deduped duplicate in-flight review key=${key} trigger=${payload.trigger}`)
|
|
761
|
+
return false
|
|
762
|
+
}
|
|
750
763
|
inFlightKeys.add(key)
|
|
751
764
|
const depsWithUrl = deps as unknown as { gitlabBaseUrl?: string; projectPath?: string }
|
|
752
765
|
const baseUrl = depsWithUrl.gitlabBaseUrl
|
|
@@ -761,6 +774,7 @@ export async function declineUnmappedDeepReview(payload: ReviewRequest, deps: Re
|
|
|
761
774
|
console.error(`maestro-orchestrator: posting review comment failed: ${err instanceof Error ? err.message : String(err)}`)
|
|
762
775
|
await deps.writeFailedReport(payload.mrIid, body)
|
|
763
776
|
}
|
|
777
|
+
return true
|
|
764
778
|
} finally {
|
|
765
779
|
inFlightKeys.delete(key)
|
|
766
780
|
}
|
|
@@ -1203,25 +1217,29 @@ export function apply(ctx: Context, config: Config): void {
|
|
|
1203
1217
|
// Unmapped reviewer assignments remain no-ops. Only an explicit mention
|
|
1204
1218
|
// may opt into the intentionally limited, diff-only fallback below.
|
|
1205
1219
|
if (mapping === undefined && payload.trigger !== 'mention') {
|
|
1220
|
+
console.error(`maestro-orchestrator: drop unmapped project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`)
|
|
1206
1221
|
return { ok: true, failures: [], durationMs: Date.now() - t0 }
|
|
1207
1222
|
}
|
|
1208
1223
|
const triggers = resolveReviewTriggers(userConfig, mapping)
|
|
1209
|
-
// Gated-off auto-triggers stay fully silent: no history, no signals, no comment.
|
|
1224
|
+
// Gated-off auto-triggers stay fully silent: no history, no signals, no comment (host log only).
|
|
1210
1225
|
if (payload.trigger === 'reviewer-assignment' && !triggers.onAssign) {
|
|
1226
|
+
console.error(`maestro-orchestrator: drop assign-gate-off project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`)
|
|
1211
1227
|
return { ok: true, failures: [], durationMs: Date.now() - t0 }
|
|
1212
1228
|
}
|
|
1213
1229
|
if (payload.trigger === 'push' && !triggers.onPush) {
|
|
1230
|
+
console.error(`maestro-orchestrator: drop push-gate-off project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`)
|
|
1214
1231
|
return { ok: true, failures: [], durationMs: Date.now() - t0 }
|
|
1215
1232
|
}
|
|
1216
1233
|
// A push only re-reviews an MR that already has a completed review;
|
|
1217
1234
|
// otherwise every newly opened MR would be reviewed twice.
|
|
1218
1235
|
if (payload.trigger === 'push' && !(await hasCompletedReview(payload.projectId, payload.mrIid))) {
|
|
1236
|
+
console.error(`maestro-orchestrator: drop push-no-completed-history project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`)
|
|
1219
1237
|
return { ok: true, failures: [], durationMs: Date.now() - t0 }
|
|
1220
1238
|
}
|
|
1221
1239
|
const { gitlabToken } = effective
|
|
1222
1240
|
if (gitlabToken === undefined) {
|
|
1223
1241
|
const message = `MR !${String(payload.mrIid)} for project ${payload.projectPath} has no GitLab token — set one in Maestro Settings or MAESTRO_GITLAB_TOKEN`
|
|
1224
|
-
console.error(`maestro-orchestrator: ${message}`)
|
|
1242
|
+
console.error(`maestro-orchestrator: drop missing-token project=${payload.projectPath} mr=!${String(payload.mrIid)} trigger=${payload.trigger} — ${message}`)
|
|
1225
1243
|
return { ok: false, failures: [message], durationMs: Date.now() - t0 }
|
|
1226
1244
|
}
|
|
1227
1245
|
const resolved = { ...effective, gitlabToken }
|
|
@@ -1307,7 +1325,7 @@ export function apply(ctx: Context, config: Config): void {
|
|
|
1307
1325
|
: undefined
|
|
1308
1326
|
await signals?.start()
|
|
1309
1327
|
const postComment = async (body: string) => {
|
|
1310
|
-
const response = await
|
|
1328
|
+
const response = await GitlabClient.fetchWithTimeout(
|
|
1311
1329
|
`${resolved.gitlabBaseUrl}/api/v4/projects/${payload.projectId}/merge_requests/${payload.mrIid}/notes`,
|
|
1312
1330
|
{
|
|
1313
1331
|
method: 'POST',
|
|
@@ -1318,7 +1336,7 @@ export function apply(ctx: Context, config: Config): void {
|
|
|
1318
1336
|
if (!response.ok) throw new Error(`GitLab API error ${response.status}: ${await response.text()}`)
|
|
1319
1337
|
}
|
|
1320
1338
|
const replyToDiscussion = async (discussionId: string, body: string) => {
|
|
1321
|
-
const response = await
|
|
1339
|
+
const response = await GitlabClient.fetchWithTimeout(
|
|
1322
1340
|
`${resolved.gitlabBaseUrl}/api/v4/projects/${payload.projectId}/merge_requests/${payload.mrIid}/discussions/${encodeURIComponent(discussionId)}/notes`,
|
|
1323
1341
|
{
|
|
1324
1342
|
method: 'POST',
|
|
@@ -1333,7 +1351,13 @@ export function apply(ctx: Context, config: Config): void {
|
|
|
1333
1351
|
// CI-deep (spec §3) skips the decline and falls through to the clone
|
|
1334
1352
|
// branch below; every other unmapped deep review still declines here.
|
|
1335
1353
|
if (payload.mode === 'deep' && !shouldCiDeepReview(payload)) {
|
|
1336
|
-
await declineUnmappedDeepReview(payload, { postComment, replyToDiscussion, writeFailedReport, gitlabBaseUrl: resolved.gitlabBaseUrl } as unknown as ReviewCommentDeps)
|
|
1354
|
+
const declined = await declineUnmappedDeepReview(payload, { postComment, replyToDiscussion, writeFailedReport, gitlabBaseUrl: resolved.gitlabBaseUrl } as unknown as ReviewCommentDeps)
|
|
1355
|
+
if (!declined) {
|
|
1356
|
+
console.error(`maestro-orchestrator: deduped duplicate in-flight review project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`)
|
|
1357
|
+
await recordReviewFinish(historyId, { status: 'completed', summary: 'Duplicate in-flight review deduped — see the active run.' })
|
|
1358
|
+
await signals?.finish('completed')
|
|
1359
|
+
return { ok: true, summary: 'Duplicate in-flight review deduped — see the active run.', failures: [], durationMs: Date.now() - t0 }
|
|
1360
|
+
}
|
|
1337
1361
|
await recordReviewFinish(historyId, { status: 'completed', summary: 'Deep review declined (unmapped project)' })
|
|
1338
1362
|
notifyTelegram('completed', 'Deep review declined (unmapped project)')
|
|
1339
1363
|
await signals?.finish('completed')
|
|
@@ -1413,6 +1437,12 @@ export function apply(ctx: Context, config: Config): void {
|
|
|
1413
1437
|
writeFailedReport,
|
|
1414
1438
|
gitlabBaseUrl: resolved.gitlabBaseUrl,
|
|
1415
1439
|
} as unknown as DiffOnlyReviewDeps)
|
|
1440
|
+
if (diffBody === '') {
|
|
1441
|
+
console.error(`maestro-orchestrator: deduped duplicate in-flight review project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`)
|
|
1442
|
+
await recordReviewFinish(historyId, { status: 'completed', summary: 'Duplicate in-flight review deduped — see the active run.' })
|
|
1443
|
+
await signals?.finish('completed')
|
|
1444
|
+
return { ok: true, summary: 'Duplicate in-flight review deduped — see the active run.', failures: [], durationMs: Date.now() - t0 }
|
|
1445
|
+
}
|
|
1416
1446
|
const summary = summarize(diffBody)
|
|
1417
1447
|
const branchNote = `fallback diff-only: branch ${payload.sourceBranch} not found on origin — ${summary ?? ''}`.trim()
|
|
1418
1448
|
await recordReviewFinish(historyId, { status: 'completed', summary: branchNote })
|
|
@@ -1423,6 +1453,12 @@ export function apply(ctx: Context, config: Config): void {
|
|
|
1423
1453
|
throw err
|
|
1424
1454
|
}
|
|
1425
1455
|
}
|
|
1456
|
+
if (fullBody === '') {
|
|
1457
|
+
console.error(`maestro-orchestrator: deduped duplicate in-flight review project=${payload.projectPath} mr=!${payload.mrIid} trigger=${payload.trigger}`)
|
|
1458
|
+
await recordReviewFinish(historyId, { status: 'completed', summary: 'Duplicate in-flight review deduped — see the active run.' })
|
|
1459
|
+
await signals?.finish('completed')
|
|
1460
|
+
return { ok: true, summary: 'Duplicate in-flight review deduped — see the active run.', failures: [], durationMs: Date.now() - t0 }
|
|
1461
|
+
}
|
|
1426
1462
|
await recordReviewFinish(historyId, { status: 'completed', summary: summarize(fullBody) })
|
|
1427
1463
|
notifyTelegram('completed', summarize(fullBody))
|
|
1428
1464
|
await signals?.finish('completed')
|
|
@@ -64,15 +64,19 @@ export async function fetchMrSourceBranch(config: CiEnvConfig, fetcher: typeof f
|
|
|
64
64
|
return (await fetchMrDetail(config, fetcher)).sourceBranch
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
/** MR detail pieces CI needs in one call: source branch (worktree) + head SHA (push-gate). */
|
|
68
|
-
export async function fetchMrDetail(config: CiEnvConfig, fetcher: typeof fetch = fetch): Promise<{ sourceBranch: string; headSha: string }> {
|
|
67
|
+
/** MR detail pieces CI needs in one call: source branch (worktree) + head SHA (push-gate) + project path (comment header/link). */
|
|
68
|
+
export async function fetchMrDetail(config: CiEnvConfig, fetcher: typeof fetch = fetch): Promise<{ sourceBranch: string; headSha: string; projectPath: string }> {
|
|
69
69
|
const url = `${config.gitlabBaseUrl}/api/v4/projects/${config.sourceProjectId}/merge_requests/${config.mrIid}`
|
|
70
70
|
const res = await fetcher(url, { headers: gitlabAuthHeaders(config.gitlabToken) })
|
|
71
71
|
if (!res.ok) throw new Error(`GitLab API error ${res.status}: ${await res.text()}`)
|
|
72
|
-
const body = await res.json() as { source_branch?: string; sha?: string }
|
|
72
|
+
const body = await res.json() as { source_branch?: string; sha?: string; references?: { full?: string } }
|
|
73
73
|
if (typeof body.source_branch !== 'string') throw new Error('GitLab merge request response is missing source_branch')
|
|
74
74
|
if (typeof body.sha !== 'string') throw new Error('GitLab merge request response is missing sha')
|
|
75
|
-
|
|
75
|
+
// references.full looks like "group/sub/project!123" — the real path feeds the
|
|
76
|
+
// comment header and View-MR link. Absent on old servers: fall back to project/<id>.
|
|
77
|
+
const full = body.references?.full
|
|
78
|
+
const projectPath = typeof full === 'string' && full.includes('!') ? full.slice(0, full.indexOf('!')) : `project/${config.sourceProjectId}`
|
|
79
|
+
return { sourceBranch: body.source_branch, headSha: body.sha, projectPath }
|
|
76
80
|
}
|
|
77
81
|
|
|
78
82
|
export async function runCiTrigger(
|
|
@@ -84,7 +88,7 @@ export async function runCiTrigger(
|
|
|
84
88
|
history?: { lastCompletedReview(projectId: number, mrIid: number): Promise<{ headSha?: string } | undefined> }
|
|
85
89
|
} = {},
|
|
86
90
|
): Promise<ReviewResult> {
|
|
87
|
-
const { sourceBranch, headSha } = await fetchMrDetail(config, deps.fetcher)
|
|
91
|
+
const { sourceBranch, headSha, projectPath } = await fetchMrDetail(config, deps.fetcher)
|
|
88
92
|
// Push-gate (mirror of the webhook autoRereviewOnPush semantics): the bridge fires
|
|
89
93
|
// on every MR pipeline, so skip when this exact head SHA already completed — and
|
|
90
94
|
// skip new pushes too unless REVIEW_ON_PUSH=1. A re-run then gets the H6 incremental
|
|
@@ -106,12 +110,12 @@ export async function runCiTrigger(
|
|
|
106
110
|
} else if (await hasRunningEyes(coFetcher, config.gitlabBaseUrl, config.gitlabToken, config.sourceProjectId, config.mrIid)) {
|
|
107
111
|
result = { ok: true, summary: 'another review is running — skipping', failures: [], durationMs: 0 }
|
|
108
112
|
} else {
|
|
109
|
-
//
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
+
// The reviewer-ci profile's own projectMappings is always [], so the
|
|
114
|
+
// orchestrator's mapping lookup on projectPath never matches regardless
|
|
115
|
+
// of its exact value — but the real path feeds the comment header and
|
|
116
|
+
// View-MR link, so prefer it over the synthetic project/<id> fallback.
|
|
113
117
|
const request: ReviewRequest = {
|
|
114
|
-
projectPath
|
|
118
|
+
projectPath,
|
|
115
119
|
projectId: config.sourceProjectId,
|
|
116
120
|
mrIid: config.mrIid,
|
|
117
121
|
sourceBranch,
|
|
@@ -4,7 +4,7 @@ import z from '@deepseek-ai/schemastery'
|
|
|
4
4
|
import { loadUserConfig } from '../config-store.js'
|
|
5
5
|
import { secretsMatch } from '../secure-compare.js'
|
|
6
6
|
import type { MrOpenedPayload, ReviewRequest as OrchestratorReviewRequest } from '../events.js'
|
|
7
|
-
import { routeGitlabReviewRequest } from '../review-intake.js'
|
|
7
|
+
import { describeDrop, routeGitlabReviewRequest } from '../review-intake.js'
|
|
8
8
|
import type { ReviewProvider, ReviewRequest } from './interface.js'
|
|
9
9
|
|
|
10
10
|
export const name = 'maestro-review-webhook'
|
|
@@ -127,10 +127,24 @@ export function apply(ctx: Context, config: Config): void {
|
|
|
127
127
|
}
|
|
128
128
|
let body: GitlabMrWebhookBody; try { body = JSON.parse(raw) } catch { res.writeHead(400).end(); return }
|
|
129
129
|
const userConfig = await loadUserConfig()
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
130
|
+
const botUsername = userConfig.botUsername ?? config.botUsername ?? 'maestro'
|
|
131
|
+
if ((body.object_kind === 'merge_request' || body.object_kind === 'note') && !hasValidGitlabMrIdentity(body)) {
|
|
132
|
+
console.error(`maestro-review-webhook: drop invalid-identity object_kind=${(body as { object_kind?: unknown }).object_kind ?? 'unknown'}`)
|
|
133
|
+
res.writeHead(400).end(); return
|
|
134
|
+
}
|
|
135
|
+
// The orchestrator is the sole push gate (resolveReviewTriggers);
|
|
136
|
+
// intake always emits so per-project overrides keep working.
|
|
137
|
+
const request = routeGitlabReviewRequest(body, botUsername, { pushEnabled: true })
|
|
138
|
+
if (request === undefined) {
|
|
139
|
+
const reason = describeDrop(body, botUsername, { pushEnabled: true })
|
|
140
|
+
if (reason !== undefined) {
|
|
141
|
+
const project = (body as { project?: { path_with_namespace?: unknown } }).project
|
|
142
|
+
const source = (body as { object_attributes?: { iid?: unknown } }).object_attributes
|
|
143
|
+
console.error(`maestro-review-webhook: drop ${reason} project=${typeof project?.path_with_namespace === 'string' ? project.path_with_namespace : 'unknown'} mr=!${typeof source?.iid === 'number' ? source.iid : '?'}`)
|
|
144
|
+
}
|
|
145
|
+
} else {
|
|
146
|
+
ctx.emit('maestro/review-request', request)
|
|
147
|
+
}
|
|
134
148
|
res.writeHead(200).end()
|
|
135
149
|
})
|
|
136
150
|
}
|