@on-par/factory-cli 0.9.5-next.9 → 0.9.5
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/cli/index.d.ts +12 -189
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +45 -994
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/land-pr.d.ts +102 -0
- package/dist/cli/land-pr.d.ts.map +1 -0
- package/dist/cli/land-pr.js +233 -0
- package/dist/cli/land-pr.js.map +1 -0
- package/dist/cli/land-runtime.d.ts +16 -0
- package/dist/cli/land-runtime.d.ts.map +1 -0
- package/dist/cli/land-runtime.js +11 -0
- package/dist/cli/land-runtime.js.map +1 -0
- package/dist/cli/land.d.ts +54 -0
- package/dist/cli/land.d.ts.map +1 -0
- package/dist/cli/land.js +298 -0
- package/dist/cli/land.js.map +1 -0
- package/dist/cli/ship-runtime.d.ts +41 -0
- package/dist/cli/ship-runtime.d.ts.map +1 -0
- package/dist/cli/ship-runtime.js +11 -0
- package/dist/cli/ship-runtime.js.map +1 -0
- package/dist/cli/ship-steps.d.ts +140 -0
- package/dist/cli/ship-steps.d.ts.map +1 -0
- package/dist/cli/ship-steps.js +273 -0
- package/dist/cli/ship-steps.js.map +1 -0
- package/dist/cli/ship.d.ts +41 -0
- package/dist/cli/ship.d.ts.map +1 -0
- package/dist/cli/ship.js +293 -0
- package/dist/cli/ship.js.map +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { Octokit } from '@octokit/rest';
|
|
2
|
+
import type { EventKind, ParkReason } from '@on-par/factory-core';
|
|
3
|
+
import type { CiOutcome, WatchChecksOptions } from '@on-par/factory-core/internal';
|
|
4
|
+
export type CommandRunner = (command: string, options?: {
|
|
5
|
+
cwd?: string;
|
|
6
|
+
timeout?: number;
|
|
7
|
+
}) => Promise<unknown>;
|
|
8
|
+
export declare function squashMergeAndDelete(octokit: Octokit, owner: string, repoName: string, branch: string, prNumber: number,
|
|
9
|
+
/** `sha`: the CI-verified head commit. GitHub refuses the merge if the PR head has moved. */
|
|
10
|
+
opts?: {
|
|
11
|
+
admin?: boolean;
|
|
12
|
+
run?: CommandRunner;
|
|
13
|
+
sha?: string;
|
|
14
|
+
}): Promise<void>;
|
|
15
|
+
export declare class MergeGatedError extends Error {
|
|
16
|
+
readonly issue: number;
|
|
17
|
+
readonly prNumber: number;
|
|
18
|
+
readonly label: string;
|
|
19
|
+
constructor(message: string, issue: number, prNumber: number, label: string);
|
|
20
|
+
}
|
|
21
|
+
export declare class LandConflictError extends Error {
|
|
22
|
+
readonly parkReason: ParkReason;
|
|
23
|
+
}
|
|
24
|
+
export declare class AwaitingReviewError extends Error {
|
|
25
|
+
readonly prNumber: number;
|
|
26
|
+
constructor(message: string, prNumber: number);
|
|
27
|
+
}
|
|
28
|
+
export declare class LandFailureError extends Error {
|
|
29
|
+
readonly code: number;
|
|
30
|
+
constructor(message: string, code: number);
|
|
31
|
+
}
|
|
32
|
+
/** Thrown when watchChecks reports a confirmed CI failure — a completed check run with a
|
|
33
|
+
* non-passing conclusion. A confirmed failing check must never be merged, admin override
|
|
34
|
+
* or not. See CiUnverifiedError for the no-verdict case. */
|
|
35
|
+
export declare class CiFailedError extends Error {
|
|
36
|
+
readonly prNumber: number;
|
|
37
|
+
readonly parkReason: ParkReason;
|
|
38
|
+
constructor(message: string, prNumber: number);
|
|
39
|
+
}
|
|
40
|
+
/** Thrown when the CI watch never reached a green verdict — a deadline timeout, no check runs ever
|
|
41
|
+
* registering, or repeated API failures. A subclass of CiFailedError so every existing guard
|
|
42
|
+
* (parkReasonFor → 'ci-failed', worktree cleanup, cmdLand's exit-0 path) treats "we don't know"
|
|
43
|
+
* exactly like "we know it's red": never merge. */
|
|
44
|
+
export declare class CiUnverifiedError extends CiFailedError {
|
|
45
|
+
}
|
|
46
|
+
/** Thrown when the one infra rerun (#2365) also failed for infrastructure reasons on the same head SHA (#2366).
|
|
47
|
+
* A CiFailedError subclass so every guard still leaves the PR open and unmerged, but it parks as
|
|
48
|
+
* 'ci-infra', which the ADR-0155 steward skips. */
|
|
49
|
+
export declare class CiInfraError extends CiFailedError {
|
|
50
|
+
readonly parkReason: ParkReason;
|
|
51
|
+
}
|
|
52
|
+
/** True when GitHub refused a SHA-pinned merge because the PR head moved past the verified
|
|
53
|
+
* commit (REST 409, or gh's "Head branch was modified"). Retrying as-is can never succeed. */
|
|
54
|
+
export declare function isHeadModifiedMergeError(err: unknown): boolean;
|
|
55
|
+
export declare function isReviewRequiredMergeError(err: unknown, state: {
|
|
56
|
+
mergeStateStatus?: string;
|
|
57
|
+
reviewDecision?: string;
|
|
58
|
+
}): boolean;
|
|
59
|
+
export declare function getPullRequestLandState(octokit: Octokit, owner: string, repoName: string, prNumber: number): Promise<{
|
|
60
|
+
id?: string;
|
|
61
|
+
isDraft?: boolean;
|
|
62
|
+
mergeStateStatus?: string;
|
|
63
|
+
reviewDecision?: string;
|
|
64
|
+
}>;
|
|
65
|
+
export declare function markPullRequestReady(octokit: Octokit, pullRequestId: string): Promise<void>;
|
|
66
|
+
export declare function rebaseDirtyPullRequest(opts: {
|
|
67
|
+
issue: number;
|
|
68
|
+
branch: string;
|
|
69
|
+
worktree: string;
|
|
70
|
+
prNumber: number;
|
|
71
|
+
log: (type: EventKind, msg: string) => void;
|
|
72
|
+
run?: CommandRunner;
|
|
73
|
+
pathExists?: (path: string) => boolean;
|
|
74
|
+
}): Promise<void>;
|
|
75
|
+
/** A critical section runner: the land path takes this instead of owning lock composition,
|
|
76
|
+
* so the locks can be scoped to git mutations and stubbed in tests (#645). */
|
|
77
|
+
export type LandLock = <T>(fn: () => Promise<T>) => Promise<T>;
|
|
78
|
+
export declare function landOpenPullRequest(opts: {
|
|
79
|
+
octokit: Octokit;
|
|
80
|
+
owner: string;
|
|
81
|
+
repoName: string;
|
|
82
|
+
ghRepo: string;
|
|
83
|
+
repoRoot: string;
|
|
84
|
+
issue: number;
|
|
85
|
+
branch: string;
|
|
86
|
+
worktree: string;
|
|
87
|
+
prNumber: number;
|
|
88
|
+
log: (type: EventKind, msg: string) => void;
|
|
89
|
+
run?: CommandRunner;
|
|
90
|
+
pathExists?: (path: string) => boolean;
|
|
91
|
+
sleep?: (ms: number) => Promise<void>;
|
|
92
|
+
skipCI?: boolean;
|
|
93
|
+
adminMerge?: boolean;
|
|
94
|
+
watch?: (opts: WatchChecksOptions) => Promise<CiOutcome>;
|
|
95
|
+
rerun?: (argv: readonly string[]) => Promise<{
|
|
96
|
+
ok: boolean;
|
|
97
|
+
}>;
|
|
98
|
+
withLock?: LandLock;
|
|
99
|
+
/** Materializes an adopted branch only after its locked state re-read confirms it needs rebasing. */
|
|
100
|
+
ensureWorktree?: () => Promise<void>;
|
|
101
|
+
}): Promise<void>;
|
|
102
|
+
//# sourceMappingURL=land-pr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"land-pr.d.ts","sourceRoot":"","sources":["../../src/cli/land-pr.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
// packages/cli/src/cli/land-pr.ts — PR-level land: CI watch, rebase, SHA-pinned squash merge (#2784)
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { shellEscape, watchChecksWithInfraRerun } from '@on-par/factory-core/internal';
|
|
4
|
+
import { landRuntime } from './land-runtime.js';
|
|
5
|
+
export async function squashMergeAndDelete(octokit, owner, repoName, branch, prNumber,
|
|
6
|
+
/** `sha`: the CI-verified head commit. GitHub refuses the merge if the PR head has moved. */
|
|
7
|
+
opts = {}) {
|
|
8
|
+
const { sha } = opts;
|
|
9
|
+
if (opts.admin) {
|
|
10
|
+
const run = opts.run ?? landRuntime().shellOps.exec;
|
|
11
|
+
const pin = sha ? ` --match-head-commit ${shellEscape(sha)}` : '';
|
|
12
|
+
await run(`gh pr merge ${prNumber} --repo ${shellEscape(`${owner}/${repoName}`)} --admin --squash --delete-branch${pin}`);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
await octokit.rest.pulls.merge({
|
|
16
|
+
owner,
|
|
17
|
+
repo: repoName,
|
|
18
|
+
pull_number: prNumber,
|
|
19
|
+
merge_method: 'squash',
|
|
20
|
+
...(sha ? { sha } : {}),
|
|
21
|
+
});
|
|
22
|
+
// Best-effort branch delete: the merge is the source of truth.
|
|
23
|
+
await octokit.rest.git.deleteRef({ owner, repo: repoName, ref: `heads/${branch}` }).catch(() => { });
|
|
24
|
+
}
|
|
25
|
+
export class MergeGatedError extends Error {
|
|
26
|
+
issue;
|
|
27
|
+
prNumber;
|
|
28
|
+
label;
|
|
29
|
+
constructor(message, issue, prNumber, label) {
|
|
30
|
+
super(message);
|
|
31
|
+
this.issue = issue;
|
|
32
|
+
this.prNumber = prNumber;
|
|
33
|
+
this.label = label;
|
|
34
|
+
this.name = 'MergeGatedError';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export class LandConflictError extends Error {
|
|
38
|
+
parkReason = 'conflict';
|
|
39
|
+
}
|
|
40
|
+
export class AwaitingReviewError extends Error {
|
|
41
|
+
prNumber;
|
|
42
|
+
constructor(message, prNumber) {
|
|
43
|
+
super(message);
|
|
44
|
+
this.prNumber = prNumber;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export class LandFailureError extends Error {
|
|
48
|
+
code;
|
|
49
|
+
constructor(message, code) {
|
|
50
|
+
super(message);
|
|
51
|
+
this.code = code;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** Thrown when watchChecks reports a confirmed CI failure — a completed check run with a
|
|
55
|
+
* non-passing conclusion. A confirmed failing check must never be merged, admin override
|
|
56
|
+
* or not. See CiUnverifiedError for the no-verdict case. */
|
|
57
|
+
export class CiFailedError extends Error {
|
|
58
|
+
prNumber;
|
|
59
|
+
parkReason = 'ci-failed';
|
|
60
|
+
constructor(message, prNumber) {
|
|
61
|
+
super(message);
|
|
62
|
+
this.prNumber = prNumber;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** Thrown when the CI watch never reached a green verdict — a deadline timeout, no check runs ever
|
|
66
|
+
* registering, or repeated API failures. A subclass of CiFailedError so every existing guard
|
|
67
|
+
* (parkReasonFor → 'ci-failed', worktree cleanup, cmdLand's exit-0 path) treats "we don't know"
|
|
68
|
+
* exactly like "we know it's red": never merge. */
|
|
69
|
+
export class CiUnverifiedError extends CiFailedError {
|
|
70
|
+
}
|
|
71
|
+
/** Thrown when the one infra rerun (#2365) also failed for infrastructure reasons on the same head SHA (#2366).
|
|
72
|
+
* A CiFailedError subclass so every guard still leaves the PR open and unmerged, but it parks as
|
|
73
|
+
* 'ci-infra', which the ADR-0155 steward skips. */
|
|
74
|
+
export class CiInfraError extends CiFailedError {
|
|
75
|
+
parkReason = 'ci-infra';
|
|
76
|
+
}
|
|
77
|
+
const MAX_MERGE_ATTEMPTS = 5;
|
|
78
|
+
const MERGE_RETRY_BASE_MS = 5_000;
|
|
79
|
+
/** True when GitHub refused a SHA-pinned merge because the PR head moved past the verified
|
|
80
|
+
* commit (REST 409, or gh's "Head branch was modified"). Retrying as-is can never succeed. */
|
|
81
|
+
export function isHeadModifiedMergeError(err) {
|
|
82
|
+
if (err?.status === 409)
|
|
83
|
+
return true;
|
|
84
|
+
const msg = `${err instanceof Error ? err.message : ''}\n${landRuntime().errorDetail(err)}`;
|
|
85
|
+
return /head branch was modified/i.test(msg);
|
|
86
|
+
}
|
|
87
|
+
export function isReviewRequiredMergeError(err, state) {
|
|
88
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
89
|
+
if (/approving review/i.test(msg) || /review is required/i.test(msg))
|
|
90
|
+
return true;
|
|
91
|
+
return state.mergeStateStatus === 'BLOCKED' && state.reviewDecision === 'REVIEW_REQUIRED';
|
|
92
|
+
}
|
|
93
|
+
export async function getPullRequestLandState(octokit, owner, repoName, prNumber) {
|
|
94
|
+
const result = await octokit.graphql(`query PullRequestLandState($owner: String!, $repo: String!, $number: Int!) {
|
|
95
|
+
repository(owner: $owner, name: $repo) {
|
|
96
|
+
pullRequest(number: $number) {
|
|
97
|
+
id
|
|
98
|
+
isDraft
|
|
99
|
+
mergeStateStatus
|
|
100
|
+
reviewDecision
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}`, { owner, repo: repoName, number: prNumber });
|
|
104
|
+
return result.repository?.pullRequest ?? {};
|
|
105
|
+
}
|
|
106
|
+
export async function markPullRequestReady(octokit, pullRequestId) {
|
|
107
|
+
await octokit.graphql(`mutation MarkPullRequestReady($id: ID!) {
|
|
108
|
+
markPullRequestReadyForReview(input: { pullRequestId: $id }) {
|
|
109
|
+
pullRequest { isDraft }
|
|
110
|
+
}
|
|
111
|
+
}`, { id: pullRequestId });
|
|
112
|
+
}
|
|
113
|
+
export async function rebaseDirtyPullRequest(opts) {
|
|
114
|
+
const { issue, branch, worktree, prNumber, log, run = landRuntime().shellOps.exec, pathExists = existsSync } = opts;
|
|
115
|
+
if (!pathExists(worktree)) {
|
|
116
|
+
const msg = `PR #${prNumber} DIRTY on ${branch} and worktree gone`;
|
|
117
|
+
log('conflict', msg);
|
|
118
|
+
throw new LandConflictError(msg);
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
await run('git rebase origin/main', { cwd: worktree });
|
|
122
|
+
await run(`git push --force-with-lease origin ${shellEscape(branch)}`, { cwd: worktree });
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// Best-effort cleanup: the conflict logged below is the error we surface.
|
|
126
|
+
await run('git rebase --abort', { cwd: worktree }).catch(() => { });
|
|
127
|
+
const msg = `rebase conflict on ${branch} — parked`;
|
|
128
|
+
log('conflict', msg);
|
|
129
|
+
throw new LandConflictError(`issue #${issue}: ${msg}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
export async function landOpenPullRequest(opts) {
|
|
133
|
+
const { octokit, owner, repoName, issue, branch, worktree, prNumber, log, run, pathExists, sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)), skipCI = false, adminMerge = process.env.FACTORY_MERGE_ADMIN === '1', watch = landRuntime().internalOps.watchChecks, rerun, withLock = (fn) => fn(), ensureWorktree, } = opts;
|
|
134
|
+
const { errorDetail } = landRuntime();
|
|
135
|
+
/** Watches CI on the PR's current head commit and returns that SHA once it is green, so the
|
|
136
|
+
* merge can be pinned to exactly the commit CI verified. */
|
|
137
|
+
const watchCi = async () => {
|
|
138
|
+
let headSha;
|
|
139
|
+
let outcome;
|
|
140
|
+
try {
|
|
141
|
+
const { data: pr } = await octokit.rest.pulls.get({ owner, repo: repoName, pull_number: prNumber });
|
|
142
|
+
headSha = pr.head.sha;
|
|
143
|
+
outcome = await watchChecksWithInfraRerun({
|
|
144
|
+
octokit,
|
|
145
|
+
owner,
|
|
146
|
+
repo: repoName,
|
|
147
|
+
ref: headSha,
|
|
148
|
+
watch,
|
|
149
|
+
rerun,
|
|
150
|
+
onRescued: ({ runIds }) => log('ci-rescued', `CI rescued for PR #${prNumber} on ${branch}: reran infra-failed run(s) ${runIds.join(', ')} once and the re-watch is green`),
|
|
151
|
+
onRescueFailed: ({ runIds, outcome: failedOutcome }) => log('ci-rescue-failed', `CI rescue failed for PR #${prNumber} on ${branch}: reran infra-failed run(s) ${runIds.join(', ')} once and the re-watch ended ${failedOutcome}`),
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
const msg = `CI watch for ${branch} failed: ${errorDetail(err)} — refusing to merge without a green verdict`;
|
|
156
|
+
log('ci-failed', msg);
|
|
157
|
+
throw new CiUnverifiedError(msg, prNumber);
|
|
158
|
+
}
|
|
159
|
+
if (outcome === 'success')
|
|
160
|
+
return headSha;
|
|
161
|
+
if (outcome === 'infra-failure') {
|
|
162
|
+
const msg = `CI failed again for infrastructure reasons for PR #${prNumber} on ${branch} after one rerun — parked as ci-infra, not merged`;
|
|
163
|
+
log('ci-infra', msg);
|
|
164
|
+
throw new CiInfraError(msg, prNumber);
|
|
165
|
+
}
|
|
166
|
+
if (outcome === 'failure') {
|
|
167
|
+
const msg = `CI failed for PR #${prNumber} on ${branch} — refusing to merge with a failing check`;
|
|
168
|
+
log('ci-failed', msg);
|
|
169
|
+
throw new CiFailedError(msg, prNumber);
|
|
170
|
+
}
|
|
171
|
+
const msg = `CI watch for ${branch} ended ${outcome} — refusing to merge without a green verdict`;
|
|
172
|
+
log('ci-failed', msg);
|
|
173
|
+
throw new CiUnverifiedError(msg, prNumber);
|
|
174
|
+
};
|
|
175
|
+
// The CI watch is a 10-20 minute wait, not a mutation: it must never run under the land
|
|
176
|
+
// locks, or every other lane's setupWorktree serializes behind it (#645).
|
|
177
|
+
let verifiedSha = skipCI ? undefined : await watchCi();
|
|
178
|
+
let state = await getPullRequestLandState(octokit, owner, repoName, prNumber);
|
|
179
|
+
if (state.mergeStateStatus === 'DIRTY') {
|
|
180
|
+
const rebased = await withLock(async () => {
|
|
181
|
+
// Re-check under the lock: a sibling lane may have landed (or rebased this branch)
|
|
182
|
+
// while we waited for it, so the DIRTY verdict read above can be stale.
|
|
183
|
+
state = await getPullRequestLandState(octokit, owner, repoName, prNumber);
|
|
184
|
+
if (state.mergeStateStatus !== 'DIRTY')
|
|
185
|
+
return false;
|
|
186
|
+
await ensureWorktree?.();
|
|
187
|
+
await rebaseDirtyPullRequest({ issue, branch, worktree, prNumber, log, run, pathExists });
|
|
188
|
+
return true;
|
|
189
|
+
});
|
|
190
|
+
if (rebased) {
|
|
191
|
+
if (!skipCI) {
|
|
192
|
+
verifiedSha = await watchCi();
|
|
193
|
+
}
|
|
194
|
+
state = await getPullRequestLandState(octokit, owner, repoName, prNumber);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
for (let attempt = 1;; attempt++) {
|
|
198
|
+
try {
|
|
199
|
+
await withLock(async () => {
|
|
200
|
+
// Same rule as the rebase section: whatever we read before taking the lock (or before
|
|
201
|
+
// the backoff sleep) may be stale, so the attempt decides from a fresh read.
|
|
202
|
+
state = await getPullRequestLandState(octokit, owner, repoName, prNumber);
|
|
203
|
+
if (state.isDraft && state.id) {
|
|
204
|
+
log('land', `PR #${prNumber} still a draft — re-issuing ready-for-review (attempt ${attempt})`);
|
|
205
|
+
await markPullRequestReady(octokit, state.id).catch((err) => log('warn', `ready-for-review flip failed for PR #${prNumber}: ${errorDetail(err)}`));
|
|
206
|
+
}
|
|
207
|
+
await squashMergeAndDelete(octokit, owner, repoName, branch, prNumber, {
|
|
208
|
+
admin: adminMerge,
|
|
209
|
+
run,
|
|
210
|
+
sha: verifiedSha,
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
catch (err) {
|
|
216
|
+
if (verifiedSha && isHeadModifiedMergeError(err)) {
|
|
217
|
+
const msg = `PR #${prNumber} head moved past CI-verified commit ${verifiedSha} — refusing to merge an unverified head`;
|
|
218
|
+
log('ci-failed', msg);
|
|
219
|
+
throw new CiUnverifiedError(msg, prNumber);
|
|
220
|
+
}
|
|
221
|
+
if (isReviewRequiredMergeError(err, state)) {
|
|
222
|
+
log('awaiting-review', `PR #${prNumber} blocked on human review — leaving open for approval`);
|
|
223
|
+
throw new AwaitingReviewError(`PR #${prNumber} awaiting review: ${err.message}`, prNumber);
|
|
224
|
+
}
|
|
225
|
+
if (attempt >= MAX_MERGE_ATTEMPTS)
|
|
226
|
+
throw err;
|
|
227
|
+
log('land', `merge attempt ${attempt}/${MAX_MERGE_ATTEMPTS} failed (${err.message}); mergeStateStatus=${state.mergeStateStatus ?? 'unknown'} — retrying with backoff`);
|
|
228
|
+
// Backoff outside the lock: waiting is not a mutation (#645).
|
|
229
|
+
await sleep(MERGE_RETRY_BASE_MS * 2 ** (attempt - 1));
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=land-pr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"land-pr.js","sourceRoot":"","sources":["../../src/cli/land-pr.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Octokit } from '@octokit/rest';
|
|
2
|
+
import type { CliDeps, ConfigLoaderKey, GitOpKey, InternalOpKey, LaneParkError, ShellOpKey } from './index.js';
|
|
3
|
+
/** index.ts's per-invocation ops, read at call time so cmdLand/main() deps injection reaches the land flow. */
|
|
4
|
+
export interface LandRuntime {
|
|
5
|
+
configLoaders: Required<Pick<CliDeps, ConfigLoaderKey>>;
|
|
6
|
+
gitOps: Required<Pick<CliDeps, GitOpKey>>;
|
|
7
|
+
internalOps: Required<Pick<CliDeps, InternalOpKey>>;
|
|
8
|
+
shellOps: Required<Pick<CliDeps, ShellOpKey>>;
|
|
9
|
+
getOctokit: () => Octokit;
|
|
10
|
+
errorDetail: (err: unknown) => string;
|
|
11
|
+
worktreePathFor: (repoRoot: string, ghRepo: string, issueNum: number, prefix?: string) => string;
|
|
12
|
+
LaneParkError: typeof LaneParkError;
|
|
13
|
+
}
|
|
14
|
+
export declare function setLandRuntime(fn: () => LandRuntime): void;
|
|
15
|
+
export declare function landRuntime(): LandRuntime;
|
|
16
|
+
//# sourceMappingURL=land-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"land-runtime.d.ts","sourceRoot":"","sources":["../../src/cli/land-runtime.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE/G,+GAA+G;AAC/G,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC;IACxD,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC1C,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC;IACpD,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;IAC9C,UAAU,EAAE,MAAM,OAAO,CAAC;IAC1B,WAAW,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC;IACtC,eAAe,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACjG,aAAa,EAAE,OAAO,aAAa,CAAC;CACrC;AAID,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,WAAW,GAAG,IAAI,CAE1D;AAED,wBAAgB,WAAW,IAAI,WAAW,CAGzC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// packages/cli/src/cli/land-runtime.ts — accessor for index.ts's per-invocation ops, so the land flow reads them live without a runtime import cycle (#2784)
|
|
2
|
+
let get;
|
|
3
|
+
export function setLandRuntime(fn) {
|
|
4
|
+
get = fn;
|
|
5
|
+
}
|
|
6
|
+
export function landRuntime() {
|
|
7
|
+
if (!get)
|
|
8
|
+
throw new Error('land runtime not registered: import ./index.js first');
|
|
9
|
+
return get();
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=land-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"land-runtime.js","sourceRoot":"","sources":["../../src/cli/land-runtime.ts"],"names":[],"mappings":"AAAA,6JAA6J;AAiB7J,IAAI,GAAoC,CAAC;AAEzC,MAAM,UAAU,cAAc,CAAC,EAAqB;IAClD,GAAG,GAAG,EAAE,CAAC;AACX,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAClF,OAAO,GAAG,EAAE,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Octokit } from '@octokit/rest';
|
|
2
|
+
import type { FactoryConfig, MergePolicyOverrides } from '@on-par/factory-core';
|
|
3
|
+
import type { getFactoryPaths } from '@on-par/factory-core';
|
|
4
|
+
import { logEvent } from '@on-par/factory-core/internal';
|
|
5
|
+
import type { OpenPullRequestEvidence } from './index.js';
|
|
6
|
+
import { LandFailureError } from './land-pr.js';
|
|
7
|
+
export declare function landIssue(issueNum: number, repoRoot: string, ghRepo: string, paths: ReturnType<typeof getFactoryPaths>, octokit: Octokit, skipCI?: boolean, branchPrefix?: string, opts?: {
|
|
8
|
+
allowGated?: boolean;
|
|
9
|
+
branch?: string;
|
|
10
|
+
}): Promise<{
|
|
11
|
+
branch: string;
|
|
12
|
+
prNumber: number;
|
|
13
|
+
}>;
|
|
14
|
+
export declare function prLookupFailure(issueNum: number, branch: string, err: unknown): LandFailureError;
|
|
15
|
+
export declare function isPrMerged(octokit: Octokit, owner: string, repoName: string, branch: string): Promise<boolean>;
|
|
16
|
+
export declare function findOpenPRNumber(octokit: Octokit, owner: string, repoName: string, branch: string): Promise<number | undefined>;
|
|
17
|
+
export declare function findOpenPRForIssue(octokit: Octokit, owner: string, repoName: string, issueNum: number): Promise<OpenPullRequestEvidence | undefined>;
|
|
18
|
+
/** Consecutive merged-state check failures tolerated before waitForMerge parks the lane.
|
|
19
|
+
* At the shipped 120s poll that is ~20 minutes of 100% failure (ADR: sustained-failure park). */
|
|
20
|
+
export declare const MERGE_CHECK_MAX_CONSECUTIVE_FAILURES = 10;
|
|
21
|
+
/** Wall-clock backstop: continuous merged-state check failure for this long parks the lane even
|
|
22
|
+
* if fewer than MERGE_CHECK_MAX_CONSECUTIVE_FAILURES attempts were made (slower poll cadence). */
|
|
23
|
+
export declare const MERGE_CHECK_FAILURE_BUDGET_MS: number;
|
|
24
|
+
/** True when a merged-state check failure cannot recover by retrying: an expired/revoked token
|
|
25
|
+
* (401) or a token missing `pulls:read` (403 with no rate-limit evidence). */
|
|
26
|
+
export declare function isPermanentMergeCheckError(err: unknown): boolean;
|
|
27
|
+
export type WaitForMergeDeps = {
|
|
28
|
+
createOctokit?: () => Octokit;
|
|
29
|
+
pathExists?: (path: string) => boolean;
|
|
30
|
+
checkMerged?: typeof isPrMerged;
|
|
31
|
+
loadConfig?: (configPath: string) => FactoryConfig;
|
|
32
|
+
land?: (issueNum: number, repoRoot: string, ghRepo: string, paths: ReturnType<typeof getFactoryPaths>, octokit: Octokit, skipCI?: boolean, branchPrefix?: string, opts?: {
|
|
33
|
+
allowGated?: boolean;
|
|
34
|
+
branch?: string;
|
|
35
|
+
}) => Promise<{
|
|
36
|
+
branch: string;
|
|
37
|
+
prNumber: number;
|
|
38
|
+
}>;
|
|
39
|
+
/** ADR-0161 stack layer: land exactly this head branch. */
|
|
40
|
+
landBranch?: string;
|
|
41
|
+
listIssueLabels?: (octokit: Octokit, owner: string, repo: string, issue: number) => Promise<string[]>;
|
|
42
|
+
sleep?: (ms: number) => Promise<void>;
|
|
43
|
+
emitEvent?: typeof logEvent;
|
|
44
|
+
mergeEnabled?: () => boolean;
|
|
45
|
+
writeLine?: (line: string) => void;
|
|
46
|
+
/** Injectable clock so the wall-clock failure budget is testable. Default `() => Date.now()`. */
|
|
47
|
+
now?: () => number;
|
|
48
|
+
/** Per-invocation CLI flag overrides (`--auto-merge`/`--no-auto-merge`). Threaded in by
|
|
49
|
+
* cmdRun rather than read from disk so a live run's merge gate cannot change underneath
|
|
50
|
+
* it (#1400). */
|
|
51
|
+
mergeOverrides?: MergePolicyOverrides;
|
|
52
|
+
};
|
|
53
|
+
export declare function waitForMerge(issue: number, branch: string, repoRoot: string, ghRepo: string, paths: ReturnType<typeof getFactoryPaths>, deps?: WaitForMergeDeps): Promise<void>;
|
|
54
|
+
//# sourceMappingURL=land.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"land.d.ts","sourceRoot":"","sources":["../../src/cli/land.ts"],"names":[],"mappings":"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"}
|