@agent-relay/factory 0.1.79 → 0.1.81
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 +39 -5
- package/dist/cli/fleet.d.ts +8 -2
- package/dist/cli/fleet.d.ts.map +1 -1
- package/dist/cli/fleet.js +40 -4
- package/dist/cli/fleet.js.map +1 -1
- package/dist/config/schema.d.ts +9 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +14 -3
- package/dist/config/schema.js.map +1 -1
- package/dist/fleet/relay-fleet-client.d.ts +5 -0
- package/dist/fleet/relay-fleet-client.d.ts.map +1 -1
- package/dist/fleet/relay-fleet-client.js +57 -12
- package/dist/fleet/relay-fleet-client.js.map +1 -1
- package/dist/github/gh-identity.d.ts +44 -0
- package/dist/github/gh-identity.d.ts.map +1 -0
- package/dist/github/gh-identity.js +31 -0
- package/dist/github/gh-identity.js.map +1 -0
- package/dist/github/index.d.ts +3 -1
- package/dist/github/index.d.ts.map +1 -1
- package/dist/github/index.js +2 -1
- package/dist/github/index.js.map +1 -1
- package/dist/github/merge-gate.d.ts +22 -1
- package/dist/github/merge-gate.d.ts.map +1 -1
- package/dist/github/merge-gate.js +103 -24
- package/dist/github/merge-gate.js.map +1 -1
- package/dist/github/probe-closer.d.ts +4 -3
- package/dist/github/probe-closer.d.ts.map +1 -1
- package/dist/github/probe-closer.js +37 -28
- package/dist/github/probe-closer.js.map +1 -1
- package/dist/github/standalone-babysitter.d.ts +7 -3
- package/dist/github/standalone-babysitter.d.ts.map +1 -1
- package/dist/github/standalone-babysitter.js +16 -46
- package/dist/github/standalone-babysitter.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/intake/notion.d.ts +36 -6
- package/dist/intake/notion.d.ts.map +1 -1
- package/dist/intake/notion.js +74 -16
- package/dist/intake/notion.js.map +1 -1
- package/dist/orchestrator/factory.d.ts +32 -5
- package/dist/orchestrator/factory.d.ts.map +1 -1
- package/dist/orchestrator/factory.js +424 -243
- package/dist/orchestrator/factory.js.map +1 -1
- package/dist/ports/fleet.d.ts +6 -0
- package/dist/ports/fleet.d.ts.map +1 -1
- package/dist/ports/mount.d.ts +1 -0
- package/dist/ports/mount.d.ts.map +1 -1
- package/dist/ports/state.d.ts +17 -0
- package/dist/ports/state.d.ts.map +1 -1
- package/dist/state/file-state-store.d.ts +1 -0
- package/dist/state/file-state-store.d.ts.map +1 -1
- package/dist/state/file-state-store.js +22 -1
- package/dist/state/file-state-store.js.map +1 -1
- package/dist/state/in-memory-state-store.d.ts +1 -0
- package/dist/state/in-memory-state-store.d.ts.map +1 -1
- package/dist/state/in-memory-state-store.js +15 -1
- package/dist/state/in-memory-state-store.js.map +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether the configured identity permits mutating GitHub through local `gh`.
|
|
3
|
+
*
|
|
4
|
+
* This helper governs mutations only. Read provenance is not an authorship
|
|
5
|
+
* concern, although a capability-specific adapter may still reject reads when
|
|
6
|
+
* its runtime has no `gh` binary (for example Notion intake in the cloud
|
|
7
|
+
* container).
|
|
8
|
+
*/
|
|
9
|
+
export function localGhMutationAllowed(identity) {
|
|
10
|
+
return identity !== 'app';
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The refusal text for a local-`gh` mutation blocked by `github.identity: "app"`.
|
|
14
|
+
*
|
|
15
|
+
* @param operation what Factory was about to do, in caller-facing terms.
|
|
16
|
+
* @param capability the server-side operation Relayfile Cloud would need to
|
|
17
|
+
* expose on the connected App surface for this write to be
|
|
18
|
+
* performed as the app instead of refused.
|
|
19
|
+
*/
|
|
20
|
+
export function localGhMutationRefusal(operation, capability) {
|
|
21
|
+
return `GitHub identity "app" refuses ${operation} through the local gh CLI, which would attribute the write to the operator's account instead of the workspace GitHub App. ` +
|
|
22
|
+
`Performing it as the app requires the connected write capability "${capability}", which the Relayfile GitHub connection does not expose. ` +
|
|
23
|
+
'Set github.identity to "user" or "auto" to deliberately accept local-user attribution for this operation.';
|
|
24
|
+
}
|
|
25
|
+
/** Throw the standard refusal when `identity` forbids a local-`gh` mutation. */
|
|
26
|
+
export function assertLocalGhMutationAllowed(identity, operation, capability) {
|
|
27
|
+
if (localGhMutationAllowed(identity))
|
|
28
|
+
return;
|
|
29
|
+
throw new Error(localGhMutationRefusal(operation, capability));
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=gh-identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gh-identity.js","sourceRoot":"","sources":["../../src/github/gh-identity.ts"],"names":[],"mappings":"AAwBA;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CAAC,QAA6B;IAClE,OAAO,QAAQ,KAAK,KAAK,CAAA;AAC3B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAiB,EAAE,UAAkB;IAC1E,OAAO,iCAAiC,SAAS,4HAA4H;QAC3K,qEAAqE,UAAU,4DAA4D;QAC3I,2GAA2G,CAAA;AAC/G,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,4BAA4B,CAC1C,QAA6B,EAC7B,SAAiB,EACjB,UAAkB;IAElB,IAAI,sBAAsB,CAAC,QAAQ,CAAC;QAAE,OAAM;IAC5C,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAA;AAChE,CAAC"}
|
package/dist/github/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { GhCliGithubMergeGate, GithubMergeGate, defaultGhRunner, evaluateGithubMergeGate, } from './merge-gate.js';
|
|
1
|
+
export { GhCliGithubMergeGate, GithubMergeGate, MountedGithubMergeGate, defaultGhRunner, evaluateGithubMergeGate, } from './merge-gate.js';
|
|
2
|
+
export { assertLocalGhMutationAllowed, localGhMutationAllowed, localGhMutationRefusal, } from './gh-identity.js';
|
|
2
3
|
export { closeProbePr, } from './probe-closer.js';
|
|
3
4
|
export { explicitLinkedIssueKey, parseStandaloneBabysitTarget, readStandalonePullRequest, standaloneBabysitterAgentName, } from './standalone-babysitter.js';
|
|
4
5
|
export { ROUTED_PR_BABYSITTER_ACTIVATION_ENABLED, discoverRoutedPullRequests, routedPrIdentity, routedPrRepos, } from './routed-pr-babysitter.js';
|
|
@@ -6,4 +7,5 @@ export type { GhRunner, GhRunResult, GithubMergeInput, GithubMergeGateInput, Git
|
|
|
6
7
|
export type { CloseProbePrInput, CloseProbePrResult, } from './probe-closer.js';
|
|
7
8
|
export type { StandaloneBabysitTarget, StandalonePullRequest, } from './standalone-babysitter.js';
|
|
8
9
|
export type { RoutedPrCandidate, RoutedPrDiscoveryReport } from './routed-pr-babysitter.js';
|
|
10
|
+
export type { GithubWriteIdentity } from './gh-identity.js';
|
|
9
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/github/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,uBAAuB,GACxB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,YAAY,GACb,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,sBAAsB,EACtB,4BAA4B,EAC5B,yBAAyB,EACzB,6BAA6B,GAC9B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,uCAAuC,EACvC,0BAA0B,EAC1B,gBAAgB,EAChB,aAAa,GACd,MAAM,wBAAwB,CAAA;AAC/B,YAAY,EACV,QAAQ,EACR,WAAW,EACX,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,IAAI,mBAAmB,GACvC,MAAM,cAAc,CAAA;AACrB,YAAY,EACV,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,gBAAgB,CAAA;AACvB,YAAY,EACV,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,yBAAyB,CAAA;AAChC,YAAY,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/github/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,sBAAsB,EACtB,eAAe,EACf,uBAAuB,GACxB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,YAAY,GACb,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,sBAAsB,EACtB,4BAA4B,EAC5B,yBAAyB,EACzB,6BAA6B,GAC9B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,uCAAuC,EACvC,0BAA0B,EAC1B,gBAAgB,EAChB,aAAa,GACd,MAAM,wBAAwB,CAAA;AAC/B,YAAY,EACV,QAAQ,EACR,WAAW,EACX,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,IAAI,mBAAmB,GACvC,MAAM,cAAc,CAAA;AACrB,YAAY,EACV,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,gBAAgB,CAAA;AACvB,YAAY,EACV,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,yBAAyB,CAAA;AAChC,YAAY,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAA;AACxF,YAAY,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA"}
|
package/dist/github/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { GhCliGithubMergeGate, GithubMergeGate, defaultGhRunner, evaluateGithubMergeGate, } from './merge-gate.js';
|
|
1
|
+
export { GhCliGithubMergeGate, GithubMergeGate, MountedGithubMergeGate, defaultGhRunner, evaluateGithubMergeGate, } from './merge-gate.js';
|
|
2
|
+
export { assertLocalGhMutationAllowed, localGhMutationAllowed, localGhMutationRefusal, } from './gh-identity.js';
|
|
2
3
|
export { closeProbePr, } from './probe-closer.js';
|
|
3
4
|
export { explicitLinkedIssueKey, parseStandaloneBabysitTarget, readStandalonePullRequest, standaloneBabysitterAgentName, } from './standalone-babysitter.js';
|
|
4
5
|
export { ROUTED_PR_BABYSITTER_ACTIVATION_ENABLED, discoverRoutedPullRequests, routedPrIdentity, routedPrRepos, } from './routed-pr-babysitter.js';
|
package/dist/github/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/github/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,uBAAuB,GACxB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,YAAY,GACb,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,sBAAsB,EACtB,4BAA4B,EAC5B,yBAAyB,EACzB,6BAA6B,GAC9B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,uCAAuC,EACvC,0BAA0B,EAC1B,gBAAgB,EAChB,aAAa,GACd,MAAM,wBAAwB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/github/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,sBAAsB,EACtB,eAAe,EACf,uBAAuB,GACxB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,YAAY,GACb,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACL,sBAAsB,EACtB,4BAA4B,EAC5B,yBAAyB,EACzB,6BAA6B,GAC9B,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,uCAAuC,EACvC,0BAA0B,EAC1B,gBAAgB,EAChB,aAAa,GACd,MAAM,wBAAwB,CAAA"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { MountClient } from '../ports/index.js';
|
|
2
|
+
import { type GithubWriteIdentity } from './gh-identity.js';
|
|
1
3
|
export interface GhRunResult {
|
|
2
4
|
stdout: string;
|
|
3
5
|
stderr?: string;
|
|
@@ -7,6 +9,8 @@ export interface GithubMergeGateInput {
|
|
|
7
9
|
repo: string;
|
|
8
10
|
number: number;
|
|
9
11
|
expectedHeadSha?: string;
|
|
12
|
+
/** Exact mounted PR metadata path returned by discovery. */
|
|
13
|
+
path?: string;
|
|
10
14
|
}
|
|
11
15
|
export interface GithubMergeInput {
|
|
12
16
|
repo: string;
|
|
@@ -37,11 +41,28 @@ export interface GithubMergeGate {
|
|
|
37
41
|
}
|
|
38
42
|
export declare class GhCliGithubMergeGate implements GithubMergeGate {
|
|
39
43
|
#private;
|
|
40
|
-
|
|
44
|
+
/**
|
|
45
|
+
* @param identity the configured `github.identity`. `check` is a read and
|
|
46
|
+
* ignores it; `merge` mutates GitHub and refuses under exact `app` rather
|
|
47
|
+
* than squash-merging as the operator's own account. Defaults to `auto`
|
|
48
|
+
* so a directly-constructed gate keeps its historical behavior.
|
|
49
|
+
*/
|
|
50
|
+
constructor(run?: GhRunner, identity?: GithubWriteIdentity);
|
|
41
51
|
check(input: GithubMergeGateInput): Promise<GithubMergeGateVerdict>;
|
|
42
52
|
merge(input: GithubMergeInput): Promise<GithubMergeResult>;
|
|
43
53
|
}
|
|
44
54
|
export declare const GithubMergeGate: typeof GhCliGithubMergeGate;
|
|
55
|
+
/**
|
|
56
|
+
* Reads provider-authoritative merge readiness from the GitHub App projection
|
|
57
|
+
* and delegates the guarded mutation separately. Discovery passes the exact PR
|
|
58
|
+
* path, so this adds one read and never scans the pulls tree.
|
|
59
|
+
*/
|
|
60
|
+
export declare class MountedGithubMergeGate implements GithubMergeGate {
|
|
61
|
+
#private;
|
|
62
|
+
constructor(mount: Pick<MountClient, 'readFile'>, mutation?: Pick<GithubMergeGate, 'merge'>);
|
|
63
|
+
check(input: GithubMergeGateInput): Promise<GithubMergeGateVerdict>;
|
|
64
|
+
merge(input: GithubMergeInput): Promise<GithubMergeResult>;
|
|
65
|
+
}
|
|
45
66
|
export declare function evaluateGithubMergeGate(input: GithubMergeGateInput, live: unknown): GithubMergeGateVerdict;
|
|
46
67
|
export declare const defaultGhRunner: GhRunner;
|
|
47
68
|
//# sourceMappingURL=merge-gate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge-gate.d.ts","sourceRoot":"","sources":["../../src/github/merge-gate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"merge-gate.d.ts","sourceRoot":"","sources":["../../src/github/merge-gate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAE3C,OAAO,EAAkD,KAAK,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAIxG,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,WAAW,CAAC,CAAA;AAE/D,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,eAAe,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,OAAO,GAAG,QAAQ,CAAA;IAC3B,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE;QACJ,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,gBAAgB,CAAC,EAAE,MAAM,CAAA;QACzB,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,WAAW,EAAE,MAAM,EAAE,CAAA;KACtB,CAAA;CACF;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAA;IACnE,KAAK,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAA;CAC3D;AAED,qBAAa,oBAAqB,YAAW,eAAe;;IAI1D;;;;;OAKG;gBACS,GAAG,GAAE,QAA0B,EAAE,QAAQ,GAAE,mBAA4B;IAK7E,KAAK,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAOnE,KAAK,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAwCjE;AAED,eAAO,MAAM,eAAe,6BAAuB,CAAA;AAEnD;;;;GAIG;AACH,qBAAa,sBAAuB,YAAW,eAAe;;gBAK1D,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,EACpC,QAAQ,GAAE,IAAI,CAAC,eAAe,EAAE,OAAO,CAA8B;IAMjE,KAAK,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAgBnE,KAAK,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAGjE;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,oBAAoB,EAC3B,IAAI,EAAE,OAAO,GACZ,sBAAsB,CA4DxB;AAED,eAAO,MAAM,eAAe,EAAE,QAS7B,CAAA"}
|
|
@@ -1,34 +1,36 @@
|
|
|
1
1
|
import { execFile } from 'node:child_process';
|
|
2
2
|
import { promisify } from 'node:util';
|
|
3
|
+
import { wrappedPayload } from '../writeback/shared.js';
|
|
4
|
+
import { localGhMutationAllowed, localGhMutationRefusal } from './gh-identity.js';
|
|
3
5
|
const execFileAsync = promisify(execFile);
|
|
4
6
|
export class GhCliGithubMergeGate {
|
|
5
7
|
#run;
|
|
6
|
-
|
|
8
|
+
#identity;
|
|
9
|
+
/**
|
|
10
|
+
* @param identity the configured `github.identity`. `check` is a read and
|
|
11
|
+
* ignores it; `merge` mutates GitHub and refuses under exact `app` rather
|
|
12
|
+
* than squash-merging as the operator's own account. Defaults to `auto`
|
|
13
|
+
* so a directly-constructed gate keeps its historical behavior.
|
|
14
|
+
*/
|
|
15
|
+
constructor(run = defaultGhRunner, identity = 'auto') {
|
|
7
16
|
this.#run = run;
|
|
17
|
+
this.#identity = identity;
|
|
8
18
|
}
|
|
9
19
|
async check(input) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
'pr',
|
|
13
|
-
'view',
|
|
14
|
-
String(input.number),
|
|
15
|
-
'--repo',
|
|
16
|
-
input.repo,
|
|
17
|
-
'--json',
|
|
18
|
-
'mergeable,mergeStateStatus,statusCheckRollup,headRefOid,reviewDecision',
|
|
19
|
-
]);
|
|
20
|
-
if (result.stdout.trim().length === 0) {
|
|
21
|
-
return refuse('gh returned empty output', { checkStates: [] });
|
|
22
|
-
}
|
|
23
|
-
return evaluateGithubMergeGate(input, parseGhJson(result.stdout));
|
|
24
|
-
}
|
|
25
|
-
catch (error) {
|
|
26
|
-
return refuse(`gh merge gate failed: ${error instanceof Error ? error.message : String(error)}`, {
|
|
27
|
-
checkStates: [],
|
|
28
|
-
});
|
|
29
|
-
}
|
|
20
|
+
throw new Error(`GitHub merge-gate readiness for ${input.repo}#${input.number} requires mounted PR metadata; ` +
|
|
21
|
+
'the local-gh adapter supports mutations only and Factory will not disguise a missing read capability as REFUSE');
|
|
30
22
|
}
|
|
31
23
|
async merge(input) {
|
|
24
|
+
// Fail closed before spawning `gh`. A guarded merge run through the local
|
|
25
|
+
// CLI is recorded by GitHub as the operator merging, which is precisely
|
|
26
|
+
// the split audit trail `github.identity: "app"` exists to remove. There
|
|
27
|
+
// is no app-authored merge to fall through to, so refuse and say why.
|
|
28
|
+
if (!localGhMutationAllowed(this.#identity)) {
|
|
29
|
+
return {
|
|
30
|
+
merged: false,
|
|
31
|
+
reason: localGhMutationRefusal(`the guarded squash merge of ${input.repo}#${input.number}`, 'mergePullRequest'),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
32
34
|
try {
|
|
33
35
|
const result = await this.#run([
|
|
34
36
|
'pr',
|
|
@@ -57,6 +59,34 @@ export class GhCliGithubMergeGate {
|
|
|
57
59
|
}
|
|
58
60
|
}
|
|
59
61
|
export const GithubMergeGate = GhCliGithubMergeGate;
|
|
62
|
+
/**
|
|
63
|
+
* Reads provider-authoritative merge readiness from the GitHub App projection
|
|
64
|
+
* and delegates the guarded mutation separately. Discovery passes the exact PR
|
|
65
|
+
* path, so this adds one read and never scans the pulls tree.
|
|
66
|
+
*/
|
|
67
|
+
export class MountedGithubMergeGate {
|
|
68
|
+
#mount;
|
|
69
|
+
#mutation;
|
|
70
|
+
constructor(mount, mutation = new GhCliGithubMergeGate()) {
|
|
71
|
+
this.#mount = mount;
|
|
72
|
+
this.#mutation = mutation;
|
|
73
|
+
}
|
|
74
|
+
async check(input) {
|
|
75
|
+
const path = input.path ?? mountedPullByIdPath(input.repo, input.number);
|
|
76
|
+
let content;
|
|
77
|
+
try {
|
|
78
|
+
content = (await this.#mount.readFile(path)).content;
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
throw mountedMergeGateCapabilityError(input, `could not read ${path}: ${error instanceof Error ? error.message : String(error)}`);
|
|
82
|
+
}
|
|
83
|
+
const live = mountedMergeGateFields(content, input);
|
|
84
|
+
return evaluateGithubMergeGate(input, live);
|
|
85
|
+
}
|
|
86
|
+
async merge(input) {
|
|
87
|
+
return this.#mutation.merge(input);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
60
90
|
export function evaluateGithubMergeGate(input, live) {
|
|
61
91
|
const record = asRecord(live);
|
|
62
92
|
const mergeable = stringValue(record.mergeable);
|
|
@@ -110,12 +140,61 @@ export function evaluateGithubMergeGate(input, live) {
|
|
|
110
140
|
};
|
|
111
141
|
}
|
|
112
142
|
export const defaultGhRunner = async (args) => {
|
|
113
|
-
//
|
|
114
|
-
//
|
|
143
|
+
// Mutation-only compatibility runner. Merge-gate reads now come from the
|
|
144
|
+
// mounted App projection. Retire this when `GithubConnectionWrite` exposes
|
|
145
|
+
// a server-side `mergePullRequest` capability so Factory still holds no
|
|
146
|
+
// GitHub credential. Until then `merge` refuses under
|
|
147
|
+
// `github.identity: "app"` rather than merging as the operator (see
|
|
148
|
+
// ./gh-identity). Tracked on AgentWorkforce/factory#221.
|
|
115
149
|
const { stdout, stderr } = await execFileAsync('gh', args, { maxBuffer: 1024 * 1024 });
|
|
116
150
|
return { stdout, stderr };
|
|
117
151
|
};
|
|
118
|
-
const
|
|
152
|
+
const mountedPullByIdPath = (repo, number) => {
|
|
153
|
+
const [owner, name, ...extra] = repo.split('/');
|
|
154
|
+
if (!owner || !name || extra.length > 0 || !Number.isSafeInteger(number) || number <= 0) {
|
|
155
|
+
throw new Error(`Invalid GitHub pull request identity ${repo}#${number}`);
|
|
156
|
+
}
|
|
157
|
+
return `/github/repos/${encodeURIComponent(owner)}__${encodeURIComponent(name)}/pulls/by-id/${number}.json`;
|
|
158
|
+
};
|
|
159
|
+
const mountedMergeGateFields = (content, input) => {
|
|
160
|
+
let payload;
|
|
161
|
+
try {
|
|
162
|
+
payload = wrappedPayload(content);
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
throw mountedMergeGateCapabilityError(input, `could not parse mounted PR metadata: ${error instanceof Error ? error.message : String(error)}`);
|
|
166
|
+
}
|
|
167
|
+
const explicitNumber = numberValue(payload.number);
|
|
168
|
+
if (explicitNumber !== undefined && explicitNumber !== input.number) {
|
|
169
|
+
throw mountedMergeGateCapabilityError(input, `mounted PR record number is ${explicitNumber}, expected ${input.number}`);
|
|
170
|
+
}
|
|
171
|
+
const head = asRecord(payload.head);
|
|
172
|
+
const mergeable = normalizeMergeable(payload.mergeable);
|
|
173
|
+
const mergeStateStatus = normalizedString(payload.mergeStateStatus ?? payload.merge_state_status ?? payload.mergeable_state);
|
|
174
|
+
const headRefOid = stringValue(payload.headRefOid) ?? stringValue(head.sha);
|
|
175
|
+
const reviewDecision = normalizedString(payload.reviewDecision ?? payload.review_decision);
|
|
176
|
+
const statusCheckRollup = payload.statusCheckRollup ?? payload.status_check_rollup;
|
|
177
|
+
const missing = [
|
|
178
|
+
['mergeable', mergeable],
|
|
179
|
+
['mergeStateStatus', mergeStateStatus],
|
|
180
|
+
['headRefOid', headRefOid],
|
|
181
|
+
['reviewDecision', reviewDecision],
|
|
182
|
+
['statusCheckRollup', Array.isArray(statusCheckRollup) ? statusCheckRollup : undefined],
|
|
183
|
+
].flatMap(([name, value]) => value === undefined ? [name] : []);
|
|
184
|
+
if (missing.length > 0) {
|
|
185
|
+
throw mountedMergeGateCapabilityError(input, `mounted PR metadata is missing ${missing.join(', ')}`);
|
|
186
|
+
}
|
|
187
|
+
return { mergeable, mergeStateStatus, headRefOid, reviewDecision, statusCheckRollup };
|
|
188
|
+
};
|
|
189
|
+
const mountedMergeGateCapabilityError = (input, detail) => new Error(`GitHub merge-gate capability unavailable for ${input.repo}#${input.number}: ${detail}; ` +
|
|
190
|
+
'Factory requires the authenticated mounted PR projection and does not fall back to local gh');
|
|
191
|
+
const normalizeMergeable = (value) => {
|
|
192
|
+
if (typeof value === 'boolean')
|
|
193
|
+
return value ? 'MERGEABLE' : 'CONFLICTING';
|
|
194
|
+
return normalizedString(value);
|
|
195
|
+
};
|
|
196
|
+
const normalizedString = (value) => typeof value === 'string' && value.trim() ? value.trim().toUpperCase() : undefined;
|
|
197
|
+
const numberValue = (value) => typeof value === 'number' && Number.isSafeInteger(value) && value > 0 ? value : undefined;
|
|
119
198
|
const refuse = (reason, live) => ({
|
|
120
199
|
verdict: 'REFUSE',
|
|
121
200
|
ready: false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge-gate.js","sourceRoot":"","sources":["../../src/github/merge-gate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"merge-gate.js","sourceRoot":"","sources":["../../src/github/merge-gate.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import type { GithubConnectionWrite } from '../ports/index.js';
|
|
2
|
-
import { type GhRunner } from './merge-gate.js';
|
|
1
|
+
import type { GithubConnectionWrite, MountClient } from '../ports/index.js';
|
|
3
2
|
export interface CloseProbePrInput {
|
|
4
3
|
repo: string;
|
|
5
4
|
prNumber: number;
|
|
6
5
|
expectedIssueKey: string;
|
|
7
6
|
requireTitleMarker?: boolean;
|
|
8
7
|
githubWrite?: GithubConnectionWrite;
|
|
9
|
-
|
|
8
|
+
/** Exact mounted PR metadata path returned by discovery. */
|
|
9
|
+
path?: string;
|
|
10
|
+
mount?: Pick<MountClient, 'readFile'>;
|
|
10
11
|
}
|
|
11
12
|
export interface CloseProbePrResult {
|
|
12
13
|
repo: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"probe-closer.d.ts","sourceRoot":"","sources":["../../src/github/probe-closer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,
|
|
1
|
+
{"version":3,"file":"probe-closer.d.ts","sourceRoot":"","sources":["../../src/github/probe-closer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAKlE,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,gBAAgB,EAAE,MAAM,CAAA;IACxB,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,WAAW,CAAC,EAAE,qBAAqB,CAAA;IACnC,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAA;CACtC;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,QAAQ,CAAA;CAChB;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAmBxF"}
|
|
@@ -1,41 +1,45 @@
|
|
|
1
1
|
import { containsIssueKey } from '../issue-key-match.js';
|
|
2
|
-
import {
|
|
2
|
+
import { wrappedPayload } from '../writeback/shared.js';
|
|
3
3
|
const FACTORY_E2E_MARKER = '[factory-e2e]';
|
|
4
4
|
export async function closeProbePr(input) {
|
|
5
5
|
const githubWrite = input.githubWrite;
|
|
6
6
|
if (!githubWrite) {
|
|
7
7
|
throw new Error('GitHub write path not available on this mount — connect GitHub to your workspace');
|
|
8
8
|
}
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
if (!input.mount) {
|
|
10
|
+
throw new Error(`Mounted GitHub PR read path is unavailable for ${input.repo}#${input.prNumber}; ` +
|
|
11
|
+
'Factory will not fall back to the local gh CLI');
|
|
12
|
+
}
|
|
13
|
+
const before = await viewPr(input.mount, input);
|
|
11
14
|
const beforeState = assertClosableProbe(before, input);
|
|
12
15
|
if (beforeState === 'CLOSED') {
|
|
13
16
|
return { repo: input.repo, prNumber: input.prNumber, state: 'CLOSED' };
|
|
14
17
|
}
|
|
15
18
|
await githubWrite.closePullRequest({ repo: input.repo, number: input.prNumber });
|
|
16
|
-
const after = await viewPr(run, input);
|
|
17
|
-
const afterState = stringValue(after.state);
|
|
18
|
-
if (normalizeState(afterState) !== 'CLOSED') {
|
|
19
|
-
throw new Error(`Refusing to report probe PR closed: live state is ${afterState ?? 'unknown'}`);
|
|
20
|
-
}
|
|
21
19
|
return { repo: input.repo, prNumber: input.prNumber, state: 'CLOSED' };
|
|
22
20
|
}
|
|
23
|
-
const viewPr = async (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
'--json',
|
|
33
|
-
'state,headRefName,body,title',
|
|
34
|
-
]);
|
|
35
|
-
if (!result.stdout.trim()) {
|
|
36
|
-
throw new Error(`Unable to guard probe PR #${input.prNumber}: gh returned empty output`);
|
|
21
|
+
const viewPr = async (mount, input) => {
|
|
22
|
+
const path = input.path ?? pullByIdPath(input.repo, input.prNumber);
|
|
23
|
+
let content;
|
|
24
|
+
try {
|
|
25
|
+
content = (await mount.readFile(path)).content;
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
throw new Error(`Unable to guard probe PR ${input.repo}#${input.prNumber} from mounted metadata at ${path}: ` +
|
|
29
|
+
`${error instanceof Error ? error.message : String(error)}`);
|
|
37
30
|
}
|
|
38
|
-
|
|
31
|
+
const payload = wrappedPayload(content);
|
|
32
|
+
const explicitNumber = numberValue(payload.number);
|
|
33
|
+
if (explicitNumber !== undefined && explicitNumber !== input.prNumber) {
|
|
34
|
+
throw new Error(`Unable to guard probe PR ${input.repo}#${input.prNumber}: mounted record at ${path} identifies PR #${explicitNumber}`);
|
|
35
|
+
}
|
|
36
|
+
const head = recordValue(payload.head);
|
|
37
|
+
return {
|
|
38
|
+
state: stringValue(payload.state),
|
|
39
|
+
headRefName: stringValue(payload.headRefName) ?? stringValue(payload.head_ref) ?? stringValue(head.ref),
|
|
40
|
+
body: stringValue(payload.body),
|
|
41
|
+
title: stringValue(payload.title),
|
|
42
|
+
};
|
|
39
43
|
};
|
|
40
44
|
const assertClosableProbe = (live, input) => {
|
|
41
45
|
const state = stringValue(live.state);
|
|
@@ -58,10 +62,15 @@ const assertClosableProbe = (live, input) => {
|
|
|
58
62
|
const hasFactoryE2eMarker = (title) => title === FACTORY_E2E_MARKER || title.startsWith(`${FACTORY_E2E_MARKER} `);
|
|
59
63
|
const normalizeState = (state) => state?.toUpperCase();
|
|
60
64
|
const stringValue = (value) => typeof value === 'string' ? value : undefined;
|
|
61
|
-
const
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
const pullByIdPath = (repo, number) => {
|
|
66
|
+
const [owner, name, ...extra] = repo.split('/');
|
|
67
|
+
if (!owner || !name || extra.length > 0 || !Number.isSafeInteger(number) || number <= 0) {
|
|
68
|
+
throw new Error(`Invalid GitHub pull request identity ${repo}#${number}`);
|
|
69
|
+
}
|
|
70
|
+
return `/github/repos/${encodeURIComponent(owner)}__${encodeURIComponent(name)}/pulls/by-id/${number}.json`;
|
|
66
71
|
};
|
|
72
|
+
const numberValue = (value) => typeof value === 'number' && Number.isSafeInteger(value) && value > 0 ? value : undefined;
|
|
73
|
+
const recordValue = (value) => value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
74
|
+
? value
|
|
75
|
+
: {};
|
|
67
76
|
//# sourceMappingURL=probe-closer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"probe-closer.js","sourceRoot":"","sources":["../../src/github/probe-closer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAErD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"probe-closer.js","sourceRoot":"","sources":["../../src/github/probe-closer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { GhRunner } from './merge-gate.js';
|
|
2
1
|
import type { MountClient } from '../ports/index.js';
|
|
3
2
|
export interface StandaloneBabysitTarget {
|
|
4
3
|
repo?: string;
|
|
@@ -21,14 +20,19 @@ export interface StandalonePullRequest {
|
|
|
21
20
|
crossRepository?: boolean;
|
|
22
21
|
maintainerCanModify?: boolean;
|
|
23
22
|
filesChanged?: string[];
|
|
24
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Where this PR's metadata was read from. Standalone babysitting requires a
|
|
25
|
+
* complete authenticated mounted projection and never shells out to local
|
|
26
|
+
* gh in the production control-plane container.
|
|
27
|
+
*/
|
|
28
|
+
source: 'mount';
|
|
25
29
|
}
|
|
26
30
|
export declare function parseStandaloneBabysitTarget(value: string | undefined): StandaloneBabysitTarget;
|
|
27
31
|
export declare function readStandalonePullRequest(mount: MountClient, target: {
|
|
28
32
|
repo: string;
|
|
29
33
|
prNumber: number;
|
|
30
34
|
url?: string;
|
|
31
|
-
}
|
|
35
|
+
}): Promise<StandalonePullRequest>;
|
|
32
36
|
export declare function standaloneBabysitterAgentName(repo: string, prNumber: number): string;
|
|
33
37
|
export declare function explicitLinkedIssueKey(body: string): string | undefined;
|
|
34
38
|
//# sourceMappingURL=standalone-babysitter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standalone-babysitter.d.ts","sourceRoot":"","sources":["../../src/github/standalone-babysitter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"standalone-babysitter.d.ts","sourceRoot":"","sources":["../../src/github/standalone-babysitter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAE3C,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB;;;;OAIG;IACH,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,uBAAuB,CA6C/F;AAED,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACvD,OAAO,CAAC,qBAAqB,CAAC,CAQhC;AAED,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CASpF;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CASvE"}
|
|
@@ -42,34 +42,13 @@ export function parseStandaloneBabysitTarget(value) {
|
|
|
42
42
|
url: `https://github.com/${repo}/pull/${match[3]}`,
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
|
-
export async function readStandalonePullRequest(mount, target
|
|
45
|
+
export async function readStandalonePullRequest(mount, target) {
|
|
46
46
|
const mounted = await readPullRequestFromMount(mount, target);
|
|
47
|
-
let ghFailure;
|
|
48
|
-
try {
|
|
49
|
-
const result = await ghRunner([
|
|
50
|
-
'pr',
|
|
51
|
-
'view',
|
|
52
|
-
String(target.prNumber),
|
|
53
|
-
'--repo',
|
|
54
|
-
target.repo,
|
|
55
|
-
'--json',
|
|
56
|
-
'number,title,body,state,isDraft,url,headRefName,headRefOid,headRepository,headRepositoryOwner,baseRefName,isCrossRepository,maintainerCanModify,files',
|
|
57
|
-
]);
|
|
58
|
-
const parsed = parsePullRequestPayload(JSON.parse(result.stdout), target);
|
|
59
|
-
if (parsed) {
|
|
60
|
-
const merged = mergePullMetadata(mounted, parsed);
|
|
61
|
-
if (hasRequiredPullMetadata(merged)) {
|
|
62
|
-
return { ...merged, source: mounted ? 'mount+gh' : 'gh' };
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
catch (error) {
|
|
67
|
-
ghFailure = error instanceof Error ? error.message : String(error);
|
|
68
|
-
}
|
|
69
47
|
if (mounted && hasRequiredPullMetadata(mounted))
|
|
70
48
|
return mounted;
|
|
71
|
-
const
|
|
72
|
-
throw new Error(`Unable to read complete metadata for ${target.repo} PR #${target.prNumber} from the connected GitHub mount
|
|
49
|
+
const missing = missingRequiredPullMetadata(mounted);
|
|
50
|
+
throw new Error(`Unable to read complete metadata for ${target.repo} PR #${target.prNumber} from the connected GitHub mount: ` +
|
|
51
|
+
`missing ${missing.join(', ')}; Factory does not fall back to local gh`);
|
|
73
52
|
}
|
|
74
53
|
export function standaloneBabysitterAgentName(repo, prNumber) {
|
|
75
54
|
const slug = repo
|
|
@@ -177,27 +156,18 @@ const hasRequiredPullMetadata = (pr) => Boolean(pr.title.trim()) &&
|
|
|
177
156
|
Boolean(pr.headRepo?.trim()) &&
|
|
178
157
|
Boolean(pr.baseRef?.trim()) &&
|
|
179
158
|
pr.crossRepository !== undefined;
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
headRef: live.headRef ?? mounted.headRef,
|
|
193
|
-
headSha: live.headSha ?? mounted.headSha,
|
|
194
|
-
baseRef: live.baseRef ?? mounted.baseRef,
|
|
195
|
-
headRepo: live.headRepo ?? mounted.headRepo,
|
|
196
|
-
crossRepository: live.crossRepository ?? mounted.crossRepository,
|
|
197
|
-
maintainerCanModify: live.maintainerCanModify ?? mounted.maintainerCanModify,
|
|
198
|
-
filesChanged: live.filesChanged ?? mounted.filesChanged,
|
|
199
|
-
};
|
|
200
|
-
}
|
|
159
|
+
const missingRequiredPullMetadata = (pr) => !pr
|
|
160
|
+
? ['PR record']
|
|
161
|
+
: [
|
|
162
|
+
['title', pr.title.trim() || undefined],
|
|
163
|
+
['state', pr.state?.trim()],
|
|
164
|
+
['draft', pr.draft],
|
|
165
|
+
['headRef', pr.headRef?.trim()],
|
|
166
|
+
['headSha', pr.headSha?.trim()],
|
|
167
|
+
['headRepo', pr.headRepo?.trim()],
|
|
168
|
+
['baseRef', pr.baseRef?.trim()],
|
|
169
|
+
['crossRepository', pr.crossRepository],
|
|
170
|
+
].flatMap(([name, value]) => value === undefined ? [String(name)] : []);
|
|
201
171
|
function changedFiles(value) {
|
|
202
172
|
if (!Array.isArray(value))
|
|
203
173
|
return undefined;
|