canopycms 0.11.1 → 0.12.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/CHANGELOG.md +174 -48
- package/dist/api/admin.d.ts +4 -4
- package/dist/api/branch-changes.d.ts +1 -0
- package/dist/api/branch-changes.js +1 -1
- package/dist/api/branch-entry-changes.d.ts +92 -7
- package/dist/api/branch-entry-changes.js +272 -38
- package/dist/api/branch-review.js +45 -13
- package/dist/api/branch-status.d.ts +12 -0
- package/dist/api/branch-status.js +13 -0
- package/dist/api/branch-update-from-base.d.ts +23 -0
- package/dist/api/branch-update-from-base.js +176 -0
- package/dist/api/branch.d.ts +5 -0
- package/dist/api/branch.js +1 -0
- package/dist/api/client.d.ts +17 -2
- package/dist/api/client.js +26 -0
- package/dist/api/comments.d.ts +2 -2
- package/dist/api/content.d.ts +38 -1
- package/dist/api/content.js +41 -5
- package/dist/api/merge-conflicts.d.ts +226 -0
- package/dist/api/merge-conflicts.js +674 -0
- package/dist/api/routes.js +2 -0
- package/dist/api/types.d.ts +7 -3
- package/dist/base-update.d.ts +26 -0
- package/dist/base-update.js +31 -0
- package/dist/branch-metadata-file.d.ts +51 -0
- package/dist/branch-metadata-file.js +11 -0
- package/dist/branch-schema-cache.d.ts +12 -0
- package/dist/branch-schema-cache.js +27 -2
- package/dist/cli/backfill-item-keys.d.ts +77 -0
- package/dist/cli/backfill-item-keys.js +320 -0
- package/dist/cli/cli.d.ts +1 -1
- package/dist/cli/cli.js +9713 -1493
- package/dist/cli/generate-ai-content.js +415 -244
- package/dist/cli/init.js +6 -0
- package/dist/cli/site-config.d.ts +14 -2
- package/dist/cli/site-config.js +20 -4
- package/dist/comment-store.d.ts +8 -0
- package/dist/comment-store.js +28 -0
- package/dist/content-index-generation.d.ts +1 -4
- package/dist/content-index-generation.js +1 -4
- package/dist/content-store.d.ts +65 -3
- package/dist/content-store.js +121 -15
- package/dist/editor/BranchManager.d.ts +4 -1
- package/dist/editor/BranchManager.js +9 -5
- package/dist/editor/Editor.js +549 -53
- package/dist/editor/EntryNavigator.d.ts +10 -2
- package/dist/editor/EntryNavigator.js +12 -4
- package/dist/editor/FormRenderer.d.ts +8 -2
- package/dist/editor/FormRenderer.js +5 -6
- package/dist/editor/base-update-wait.d.ts +74 -0
- package/dist/editor/base-update-wait.js +91 -0
- package/dist/editor/branch-status.js +1 -1
- package/dist/editor/components/BaseUpdateNotice.d.ts +12 -0
- package/dist/editor/components/BaseUpdateNotice.js +24 -0
- package/dist/editor/components/BranchPill.d.ts +4 -1
- package/dist/editor/components/BranchPill.js +5 -2
- package/dist/editor/components/ConflictsGroup.d.ts +100 -0
- package/dist/editor/components/ConflictsGroup.js +364 -0
- package/dist/editor/components/EditorHeader.d.ts +16 -1
- package/dist/editor/components/EditorHeader.js +92 -30
- package/dist/editor/components/EntryChangesDrawer.d.ts +52 -2
- package/dist/editor/components/EntryChangesDrawer.js +164 -162
- package/dist/editor/components/EntryHeader.d.ts +3 -1
- package/dist/editor/components/EntryHeader.js +4 -6
- package/dist/editor/components/GetLatestChangesButton.d.ts +15 -0
- package/dist/editor/components/GetLatestChangesButton.js +29 -0
- package/dist/editor/components/ReleaseHoldButton.d.ts +20 -0
- package/dist/editor/components/ReleaseHoldButton.js +36 -0
- package/dist/editor/components/RetryToastMessage.js +1 -1
- package/dist/editor/components/change-parts.d.ts +51 -0
- package/dist/editor/components/change-parts.js +171 -0
- package/dist/editor/conflict-cards.d.ts +90 -0
- package/dist/editor/conflict-cards.js +279 -0
- package/dist/editor/conflict-choices.d.ts +60 -0
- package/dist/editor/conflict-choices.js +108 -0
- package/dist/editor/conflict-notice.d.ts +25 -0
- package/dist/editor/conflict-notice.js +39 -0
- package/dist/editor/copy.d.ts +20 -0
- package/dist/editor/copy.js +20 -0
- package/dist/editor/entry-diff.d.ts +18 -2
- package/dist/editor/entry-diff.js +26 -32
- package/dist/editor/hooks/useBaseUpdate.d.ts +36 -0
- package/dist/editor/hooks/useBaseUpdate.js +269 -0
- package/dist/editor/hooks/useBranchManager.d.ts +6 -1
- package/dist/editor/hooks/useBranchManager.js +28 -7
- package/dist/editor/hooks/useBranchesData.js +3 -0
- package/dist/editor/hooks/useConflictChoices.d.ts +24 -0
- package/dist/editor/hooks/useConflictChoices.js +75 -0
- package/dist/editor/hooks/useConflictsData.d.ts +26 -0
- package/dist/editor/hooks/useConflictsData.js +89 -0
- package/dist/editor/hooks/useDraftManager.d.ts +5 -0
- package/dist/editor/hooks/useDraftManager.js +24 -8
- package/dist/editor/hooks/useEntryManager.d.ts +9 -0
- package/dist/editor/hooks/useEntryManager.js +5 -0
- package/dist/editor/release-hold.d.ts +12 -0
- package/dist/editor/release-hold.js +39 -0
- package/dist/editor/server-clock.d.ts +4 -0
- package/dist/editor/server-clock.js +15 -0
- package/dist/editor/undo-change.d.ts +52 -0
- package/dist/editor/undo-change.js +241 -0
- package/dist/git-manager.d.ts +5 -0
- package/dist/git-manager.js +30 -0
- package/dist/item-keys.d.ts +13 -0
- package/dist/item-keys.js +36 -14
- package/dist/merge/conflict-path.d.ts +40 -0
- package/dist/merge/conflict-path.js +128 -0
- package/dist/merge/diff3.d.ts +27 -0
- package/dist/merge/diff3.js +113 -0
- package/dist/merge/entry-merge.d.ts +94 -0
- package/dist/merge/entry-merge.js +875 -0
- package/dist/merge/list-alignment.d.ts +52 -0
- package/dist/merge/list-alignment.js +441 -0
- package/dist/merge/text-merge.d.ts +29 -0
- package/dist/merge/text-merge.js +59 -0
- package/dist/merge/value-equality.d.ts +18 -0
- package/dist/merge/value-equality.js +50 -0
- package/dist/merge-conflicts.d.ts +232 -0
- package/dist/merge-conflicts.js +451 -0
- package/dist/operating-mode/client-safe-strategy.d.ts +2 -0
- package/dist/operating-mode/client-safe-strategy.js +6 -0
- package/dist/operating-mode/types.d.ts +5 -0
- package/dist/services.d.ts +16 -1
- package/dist/services.js +82 -22
- package/dist/task-queue/cms-task-queue.d.ts +3 -1
- package/dist/types.d.ts +28 -2
- package/dist/utils/content-serialize.d.ts +18 -1
- package/dist/utils/content-serialize.js +12 -0
- package/dist/utils/content-write-lock.d.ts +3 -3
- package/dist/utils/content-write-lock.js +3 -3
- package/dist/utils/markdown-body-splice.d.ts +1 -1
- package/dist/utils/markdown-body-splice.js +1 -19
- package/dist/utils/markdown-parse.d.ts +9 -0
- package/dist/utils/markdown-parse.js +27 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker/branch-merge.d.ts +53 -37
- package/dist/worker/branch-merge.js +139 -54
- package/dist/worker/cms-worker.d.ts +16 -3
- package/dist/worker/cms-worker.js +59 -12
- package/dist/worker/field-merge.d.ts +65 -0
- package/dist/worker/field-merge.js +636 -0
- package/dist/worker/git-sync.d.ts +1 -1
- package/dist/worker/git-sync.js +7 -6
- package/dist/worker/github-commits.d.ts +42 -10
- package/dist/worker/github-commits.js +287 -47
- package/dist/worker/github-gateway-http.js +17 -9
- package/dist/worker/github-gateway-wire.d.ts +21 -12
- package/dist/worker/github-gateway-wire.js +5 -1
- package/dist/worker/github-gateway.d.ts +10 -1
- package/dist/worker/github-gateway.js +18 -6
- package/dist/worker/github-transfer.d.ts +5 -3
- package/dist/worker/github-transfer.js +8 -5
- package/dist/worker/rebase.d.ts +5 -4
- package/dist/worker/rebase.js +293 -156
- package/dist/worker/task-runner.d.ts +1 -1
- package/dist/worker/task-runner.js +14 -2
- package/dist/worker/worker-context.d.ts +18 -2
- package/package.json +1 -1
|
@@ -9,10 +9,13 @@ export declare const MAX_JSON_REQUEST_BYTES: number;
|
|
|
9
9
|
export declare const MAX_JSON_ANSWER_BYTES: number;
|
|
10
10
|
export declare const fetchRequest: z.ZodObject<{
|
|
11
11
|
have: z.ZodArray<z.ZodString, "many">;
|
|
12
|
+
fresh: z.ZodOptional<z.ZodBoolean>;
|
|
12
13
|
}, "strict", z.ZodTypeAny, {
|
|
13
14
|
have: string[];
|
|
15
|
+
fresh?: boolean | undefined;
|
|
14
16
|
}, {
|
|
15
17
|
have: string[];
|
|
18
|
+
fresh?: boolean | undefined;
|
|
16
19
|
}>;
|
|
17
20
|
export declare const pushRequest: z.ZodObject<{
|
|
18
21
|
branch: z.ZodString;
|
|
@@ -56,13 +59,13 @@ export declare const requests: {
|
|
|
56
59
|
}, "strict", z.ZodTypeAny, {
|
|
57
60
|
title: string;
|
|
58
61
|
base: string;
|
|
59
|
-
head: string;
|
|
60
62
|
body: string;
|
|
63
|
+
head: string;
|
|
61
64
|
}, {
|
|
62
65
|
title: string;
|
|
63
66
|
base: string;
|
|
64
|
-
head: string;
|
|
65
67
|
body: string;
|
|
68
|
+
head: string;
|
|
66
69
|
}>;
|
|
67
70
|
readonly updatePullRequest: z.ZodObject<{
|
|
68
71
|
number: z.ZodNumber;
|
|
@@ -97,15 +100,15 @@ export declare const requests: {
|
|
|
97
100
|
}, "strict", z.ZodTypeAny, {
|
|
98
101
|
title: string;
|
|
99
102
|
base: string;
|
|
100
|
-
head: string;
|
|
101
103
|
body: string;
|
|
104
|
+
head: string;
|
|
102
105
|
markReadyIfDraft?: boolean | undefined;
|
|
103
106
|
mergeSectionIntoBody?: boolean | undefined;
|
|
104
107
|
}, {
|
|
105
108
|
title: string;
|
|
106
109
|
base: string;
|
|
107
|
-
head: string;
|
|
108
110
|
body: string;
|
|
111
|
+
head: string;
|
|
109
112
|
markReadyIfDraft?: boolean | undefined;
|
|
110
113
|
mergeSectionIntoBody?: boolean | undefined;
|
|
111
114
|
}>;
|
|
@@ -211,12 +214,14 @@ export declare const answers: {
|
|
|
211
214
|
body: z.ZodNullable<z.ZodString>;
|
|
212
215
|
mergeable_state: z.ZodOptional<z.ZodString>;
|
|
213
216
|
baseRef: z.ZodOptional<z.ZodString>;
|
|
217
|
+
headSha: z.ZodOptional<z.ZodString>;
|
|
214
218
|
}, "strict", z.ZodTypeAny, {
|
|
215
219
|
merged: boolean;
|
|
216
220
|
state: "open" | "closed";
|
|
217
221
|
body: string | null;
|
|
218
222
|
merged_at: string | null;
|
|
219
223
|
node_id: string;
|
|
224
|
+
headSha?: string | undefined;
|
|
220
225
|
mergeable_state?: string | undefined;
|
|
221
226
|
baseRef?: string | undefined;
|
|
222
227
|
}, {
|
|
@@ -225,6 +230,7 @@ export declare const answers: {
|
|
|
225
230
|
body: string | null;
|
|
226
231
|
merged_at: string | null;
|
|
227
232
|
node_id: string;
|
|
233
|
+
headSha?: string | undefined;
|
|
228
234
|
mergeable_state?: string | undefined;
|
|
229
235
|
baseRef?: string | undefined;
|
|
230
236
|
}>;
|
|
@@ -312,21 +318,21 @@ export declare const answers: {
|
|
|
312
318
|
kind: z.ZodEnum<["auto-scaling", "spot"]>;
|
|
313
319
|
reason: z.ZodString;
|
|
314
320
|
}, "strict", z.ZodTypeAny, {
|
|
315
|
-
kind: "auto-scaling" | "spot";
|
|
316
321
|
reason: string;
|
|
317
|
-
}, {
|
|
318
322
|
kind: "auto-scaling" | "spot";
|
|
323
|
+
}, {
|
|
319
324
|
reason: string;
|
|
325
|
+
kind: "auto-scaling" | "spot";
|
|
320
326
|
}>>;
|
|
321
327
|
}, "strict", z.ZodTypeAny, {
|
|
322
328
|
notice: {
|
|
323
|
-
kind: "auto-scaling" | "spot";
|
|
324
329
|
reason: string;
|
|
330
|
+
kind: "auto-scaling" | "spot";
|
|
325
331
|
} | null;
|
|
326
332
|
}, {
|
|
327
333
|
notice: {
|
|
328
|
-
kind: "auto-scaling" | "spot";
|
|
329
334
|
reason: string;
|
|
335
|
+
kind: "auto-scaling" | "spot";
|
|
330
336
|
} | null;
|
|
331
337
|
}>;
|
|
332
338
|
readonly completeLifecycle: z.ZodObject<{}, "strict", z.ZodTypeAny, {}, {}>;
|
|
@@ -360,15 +366,18 @@ export declare const fetchPoll: z.ZodDiscriminatedUnion<"state", [z.ZodObject<{
|
|
|
360
366
|
/** Every GitHub branch and its tip, as pairs: a `Map` has no JSON form of its own. */
|
|
361
367
|
refs: z.ZodArray<z.ZodTuple<[z.ZodString, z.ZodString], null>, "many">;
|
|
362
368
|
bundleId: z.ZodNullable<z.ZodString>;
|
|
369
|
+
startedAt: z.ZodNumber;
|
|
363
370
|
}, "strict", z.ZodTypeAny, {
|
|
364
371
|
state: "done";
|
|
365
372
|
refs: [string, string][];
|
|
366
373
|
progress: number;
|
|
374
|
+
startedAt: number;
|
|
367
375
|
bundleId: string | null;
|
|
368
376
|
}, {
|
|
369
377
|
state: "done";
|
|
370
378
|
refs: [string, string][];
|
|
371
379
|
progress: number;
|
|
380
|
+
startedAt: number;
|
|
372
381
|
bundleId: string | null;
|
|
373
382
|
}>]>;
|
|
374
383
|
export declare const pushAnswer: z.ZodUnion<[z.ZodObject<{
|
|
@@ -391,15 +400,15 @@ export declare const pushAnswer: z.ZodUnion<[z.ZodObject<{
|
|
|
391
400
|
pastStaleLease: z.ZodBoolean;
|
|
392
401
|
}, "strict", z.ZodTypeAny, {
|
|
393
402
|
kind: "pushed";
|
|
403
|
+
moved: true;
|
|
394
404
|
from: string | null;
|
|
395
405
|
to: string;
|
|
396
|
-
moved: true;
|
|
397
406
|
pastStaleLease: boolean;
|
|
398
407
|
}, {
|
|
399
408
|
kind: "pushed";
|
|
409
|
+
moved: true;
|
|
400
410
|
from: string | null;
|
|
401
411
|
to: string;
|
|
402
|
-
moved: true;
|
|
403
412
|
pastStaleLease: boolean;
|
|
404
413
|
}>, z.ZodObject<{
|
|
405
414
|
kind: z.ZodLiteral<"need-objects">;
|
|
@@ -431,15 +440,15 @@ declare const errorEnvelope: z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
|
|
|
431
440
|
branch: string;
|
|
432
441
|
push: boolean;
|
|
433
442
|
message: string;
|
|
434
|
-
kind: "refusal";
|
|
435
443
|
reason: "settings" | "protected" | "invalid" | "other-settings" | "outside-namespace" | "not-a-commit" | "too-long";
|
|
444
|
+
kind: "refusal";
|
|
436
445
|
operation: "push" | "delete" | "pull-request";
|
|
437
446
|
}, {
|
|
438
447
|
branch: string;
|
|
439
448
|
push: boolean;
|
|
440
449
|
message: string;
|
|
441
|
-
kind: "refusal";
|
|
442
450
|
reason: "settings" | "protected" | "invalid" | "other-settings" | "outside-namespace" | "not-a-commit" | "too-long";
|
|
451
|
+
kind: "refusal";
|
|
443
452
|
operation: "push" | "delete" | "pull-request";
|
|
444
453
|
}>, z.ZodObject<{
|
|
445
454
|
kind: z.ZodLiteral<"push">;
|
|
@@ -37,7 +37,9 @@ const objectId = z.string().regex(/^(?:[0-9a-f]{40}|[0-9a-f]{64})$/, 'not a full
|
|
|
37
37
|
const name = z.string().max(4096);
|
|
38
38
|
const prNumber = z.number().int().safe();
|
|
39
39
|
const message = z.string().max(MAX_MESSAGE_LENGTH);
|
|
40
|
-
export const fetchRequest = z
|
|
40
|
+
export const fetchRequest = z
|
|
41
|
+
.object({ have: z.array(objectId).max(MAX_FETCH_HAVE), fresh: z.boolean().optional() })
|
|
42
|
+
.strict();
|
|
41
43
|
export const pushRequest = z
|
|
42
44
|
.object({
|
|
43
45
|
branch: name,
|
|
@@ -114,6 +116,7 @@ export const answers = {
|
|
|
114
116
|
body: pullRequestText.body.nullable(),
|
|
115
117
|
mergeable_state: z.string().max(64).optional(),
|
|
116
118
|
baseRef: z.string().max(256).optional(),
|
|
119
|
+
headSha: objectId.optional(),
|
|
117
120
|
})
|
|
118
121
|
.strict(),
|
|
119
122
|
createOrUpdatePullRequest: pullRequestRef.extend({ created: z.boolean() }).strict(),
|
|
@@ -187,6 +190,7 @@ export const fetchPoll = z.discriminatedUnion('state', [
|
|
|
187
190
|
/** Every GitHub branch and its tip, as pairs: a `Map` has no JSON form of its own. */
|
|
188
191
|
refs: z.array(z.tuple([name, objectId])).max(1_000_000),
|
|
189
192
|
bundleId: jobId.nullable(),
|
|
193
|
+
startedAt: z.number().int().nonnegative(),
|
|
190
194
|
})
|
|
191
195
|
.strict(),
|
|
192
196
|
]);
|
|
@@ -15,6 +15,11 @@ export interface GitHubFetchResult {
|
|
|
15
15
|
* request's `have` and their history; null when that leaves nothing to send.
|
|
16
16
|
*/
|
|
17
17
|
bundleId: string | null;
|
|
18
|
+
/**
|
|
19
|
+
* When the GitHub fetch `refs` come from began, by the gateway's clock, which is the worker's:
|
|
20
|
+
* they share the instance. A fetch can be joined or reused, so this can predate the request.
|
|
21
|
+
*/
|
|
22
|
+
startedAt: number;
|
|
18
23
|
}
|
|
19
24
|
/** The most `have` IDs one fetch takes. */
|
|
20
25
|
export declare const MAX_FETCH_HAVE = 10000;
|
|
@@ -81,6 +86,8 @@ export type GitHubPullRequest = Pick<RestEndpointMethodTypes['pulls']['get']['re
|
|
|
81
86
|
mergeable_state?: string;
|
|
82
87
|
/** The branch the pull request merges into on GitHub, which a person can change. */
|
|
83
88
|
baseRef?: string;
|
|
89
|
+
/** The pull request's head commit, read with `mergeable_state`. */
|
|
90
|
+
headSha?: string;
|
|
84
91
|
};
|
|
85
92
|
export type GitHubCreateOrUpdatePullRequest = Omit<CreateOrUpdatePullRequestParams, 'octokit' | 'owner' | 'repo' | 'signal'>;
|
|
86
93
|
/**
|
|
@@ -114,10 +121,12 @@ export interface GitHubGateway {
|
|
|
114
121
|
* Fetch every GitHub branch, and answer with all of them and a bundle of the commits `have`
|
|
115
122
|
* lacks. `have` is the caller's own tips, at most {@link MAX_FETCH_HAVE} object IDs; any the
|
|
116
123
|
* gateway does not hold as a commit is ignored. A new fetch replaces a bundle not yet opened.
|
|
117
|
-
* `
|
|
124
|
+
* `fresh` takes no GitHub fetch begun before the request arrived. `onProgress` is told of each
|
|
125
|
+
* sign of life from the gateway's git while the caller waits.
|
|
118
126
|
*/
|
|
119
127
|
fetch(request: {
|
|
120
128
|
have: readonly string[];
|
|
129
|
+
fresh?: boolean;
|
|
121
130
|
}, signal?: AbortSignal, onProgress?: () => void): Promise<GitHubFetchResult>;
|
|
122
131
|
/**
|
|
123
132
|
* The bundle a fetch answered with, readable once. Throws {@link GitHubTransientError}
|
|
@@ -197,11 +197,14 @@ class LocalGitHubGateway {
|
|
|
197
197
|
* own, which repairs a corrupt mirror first ({@link GitHubMirror.heal}), and its failure re-reads
|
|
198
198
|
* the credential when it reached GitHub, whoever started it.
|
|
199
199
|
*/
|
|
200
|
-
async joinGitHubFetch(resolve, signal
|
|
200
|
+
async joinGitHubFetch(resolve, signal,
|
|
201
|
+
/** Join or reuse only a fetch that began at or after this time. */
|
|
202
|
+
notBefore) {
|
|
201
203
|
const current = this.githubFetch;
|
|
202
204
|
const window = this.options.fetchCoalesceMs ?? FETCH_COALESCE_MS;
|
|
203
205
|
const reusable = current !== null &&
|
|
204
206
|
!current.failed &&
|
|
207
|
+
(notBefore === undefined || current.startedAt >= notBefore) &&
|
|
205
208
|
(current.completedAt === null ||
|
|
206
209
|
(Date.now() - current.completedAt < window && this.isCurrent(current.snapshot)));
|
|
207
210
|
const job = reusable ? current : this.startGitHubFetch(resolve);
|
|
@@ -223,7 +226,7 @@ class LocalGitHubGateway {
|
|
|
223
226
|
async afterGitHubFetch(join, fn) {
|
|
224
227
|
for (let attempt = 1;; attempt++) {
|
|
225
228
|
const snapshot = await join();
|
|
226
|
-
const result = await this.mirror.exclusive(async (session) => this.isCurrent(snapshot) ? { value: await fn(session) } : null);
|
|
229
|
+
const result = await this.mirror.exclusive(async (session) => this.isCurrent(snapshot) ? { value: await fn(session, snapshot) } : null);
|
|
227
230
|
if (result !== null)
|
|
228
231
|
return result.value;
|
|
229
232
|
if (attempt === 2) {
|
|
@@ -234,6 +237,7 @@ class LocalGitHubGateway {
|
|
|
234
237
|
/** Start a GitHub fetch, taking its place at once, before the credential resolves. */
|
|
235
238
|
startGitHubFetch(resolve) {
|
|
236
239
|
let reachedGitHub = false;
|
|
240
|
+
const startedAt = Date.now();
|
|
237
241
|
const run = async () => {
|
|
238
242
|
const credential = await resolve();
|
|
239
243
|
const own = {
|
|
@@ -248,12 +252,18 @@ class LocalGitHubGateway {
|
|
|
248
252
|
const pushes = this.pushes;
|
|
249
253
|
await this.mirror.heal(mirror, own);
|
|
250
254
|
await this.mirror.fetchFromGitHub(mirror, own);
|
|
251
|
-
return { generation: this.mirror.generation, pushes };
|
|
255
|
+
return { generation: this.mirror.generation, pushes, startedAt };
|
|
252
256
|
});
|
|
253
257
|
await this.mirror.afterFetch();
|
|
254
258
|
return snapshot;
|
|
255
259
|
};
|
|
256
|
-
const job = {
|
|
260
|
+
const job = {
|
|
261
|
+
failed: false,
|
|
262
|
+
completedAt: null,
|
|
263
|
+
snapshot: null,
|
|
264
|
+
startedAt,
|
|
265
|
+
done: run(),
|
|
266
|
+
};
|
|
257
267
|
job.done.then((snapshot) => {
|
|
258
268
|
job.completedAt = Date.now();
|
|
259
269
|
job.snapshot = snapshot;
|
|
@@ -472,19 +482,20 @@ class LocalGitHubGateway {
|
|
|
472
482
|
}
|
|
473
483
|
}
|
|
474
484
|
fetchOnce(request, signal) {
|
|
485
|
+
const notBefore = request.fresh ? Date.now() : undefined;
|
|
475
486
|
const have = [...new Set(request.have)];
|
|
476
487
|
if (have.length > MAX_FETCH_HAVE) {
|
|
477
488
|
throw new Error(`A fetch takes at most ${MAX_FETCH_HAVE} have IDs, not ${have.length}`);
|
|
478
489
|
}
|
|
479
490
|
for (const id of have)
|
|
480
491
|
assertObjectId(id);
|
|
481
|
-
return this.credentialed(signal, (reach) => this.afterGitHubFetch(() => this.joinGitHubFetch(() => this.credential(reach), signal), async (mirror) => {
|
|
492
|
+
return this.credentialed(signal, (reach) => this.afterGitHubFetch(() => this.joinGitHubFetch(() => this.credential(reach), signal, notBefore), async (mirror, snapshot) => {
|
|
482
493
|
this.mirror.assertUsable();
|
|
483
494
|
const refs = await mirror.heads();
|
|
484
495
|
const file = await this.mirror.outgoingBundlePath();
|
|
485
496
|
const created = await mirror.createBundle(have, file, signal);
|
|
486
497
|
const bundleId = await this.mirror.setPendingBundle(created ? file : null);
|
|
487
|
-
return { refs, bundleId };
|
|
498
|
+
return { refs, bundleId, startedAt: snapshot.startedAt };
|
|
488
499
|
}));
|
|
489
500
|
}
|
|
490
501
|
openBundle(bundleId) {
|
|
@@ -688,6 +699,7 @@ class LocalGitHubGateway {
|
|
|
688
699
|
body: ours ? (data.body ?? '') : null,
|
|
689
700
|
mergeable_state: data.mergeable_state,
|
|
690
701
|
baseRef: data.base.ref,
|
|
702
|
+
headSha: data.head.sha,
|
|
691
703
|
};
|
|
692
704
|
});
|
|
693
705
|
}
|
|
@@ -12,11 +12,13 @@ export interface TransferContext {
|
|
|
12
12
|
/**
|
|
13
13
|
* Fetch every GitHub branch into `remote.git`'s tracking namespace (`GITHUB_TRACKING_REF_PREFIX`),
|
|
14
14
|
* which then holds exactly GitHub's branches. `have` is every tip `remote.git` holds, so the
|
|
15
|
-
* bundle carries only what it lacks.
|
|
16
|
-
*
|
|
15
|
+
* bundle carries only what it lacks. `fresh` takes no GitHub fetch the gateway began before this
|
|
16
|
+
* call. Returns GitHub's branches, when the GitHub fetch they come from began, and what an operator
|
|
17
|
+
* must fix in remote.git for the namespace to keep up, if anything (see {@link moveTrackingRefs}).
|
|
17
18
|
*/
|
|
18
|
-
export declare function fetchGitHubIntoRemoteGit(ctx: TransferContext, signal?: AbortSignal): Promise<{
|
|
19
|
+
export declare function fetchGitHubIntoRemoteGit(ctx: TransferContext, signal?: AbortSignal, fresh?: boolean): Promise<{
|
|
19
20
|
refs: ReadonlyMap<string, string>;
|
|
21
|
+
fetchedAt: number;
|
|
20
22
|
needsOperator: string | null;
|
|
21
23
|
}>;
|
|
22
24
|
/**
|
|
@@ -28,16 +28,19 @@ const MAX_PUSH_RESTARTS = 3;
|
|
|
28
28
|
/**
|
|
29
29
|
* Fetch every GitHub branch into `remote.git`'s tracking namespace (`GITHUB_TRACKING_REF_PREFIX`),
|
|
30
30
|
* which then holds exactly GitHub's branches. `have` is every tip `remote.git` holds, so the
|
|
31
|
-
* bundle carries only what it lacks.
|
|
32
|
-
*
|
|
31
|
+
* bundle carries only what it lacks. `fresh` takes no GitHub fetch the gateway began before this
|
|
32
|
+
* call. Returns GitHub's branches, when the GitHub fetch they come from began, and what an operator
|
|
33
|
+
* must fix in remote.git for the namespace to keep up, if anything (see {@link moveTrackingRefs}).
|
|
33
34
|
*/
|
|
34
|
-
export async function fetchGitHubIntoRemoteGit(ctx, signal) {
|
|
35
|
+
export async function fetchGitHubIntoRemoteGit(ctx, signal, fresh = false) {
|
|
35
36
|
const gitDir = ctx.remoteGitPath;
|
|
36
|
-
const { refs, bundleId } = await ctx
|
|
37
|
+
const { refs, bundleId, startedAt } = await ctx
|
|
38
|
+
.github()
|
|
39
|
+
.fetch({ have: await haveOf(gitDir), fresh }, signal);
|
|
37
40
|
if (bundleId !== null)
|
|
38
41
|
await unbundle(ctx, gitDir, bundleId, signal);
|
|
39
42
|
const needsOperator = await moveTrackingRefs(ctx, gitDir, refs, signal);
|
|
40
|
-
return { refs, needsOperator };
|
|
43
|
+
return { refs, fetchedAt: startedAt, needsOperator };
|
|
41
44
|
}
|
|
42
45
|
/**
|
|
43
46
|
* Seed the new bare repository at `gitDir`, which must not exist yet, with every GitHub branch as
|
package/dist/worker/rebase.d.ts
CHANGED
|
@@ -7,8 +7,9 @@ import type { WorkerContext } from './worker-context.js';
|
|
|
7
7
|
* The rebase loop: the deepest leaf of the git-sync cluster, and the most
|
|
8
8
|
* safety-critical part of the worker. `syncGit` (git-sync.ts) calls
|
|
9
9
|
* `runRebaseCycle` once per cycle; every branch workspace behind the base
|
|
10
|
-
* branch
|
|
11
|
-
*
|
|
10
|
+
* branch takes it in: by a rebase where git and the field merge agree there is
|
|
11
|
+
* nothing to decide, and by a merge (github-commits.ts' `mergeIntoBranch`)
|
|
12
|
+
* wherever there is. Three things make it the part most likely to misbehave under real EFS
|
|
12
13
|
* and spot conditions, all documented at the point they happen:
|
|
13
14
|
*
|
|
14
15
|
* - it holds the [SYNC-C1] cross-host content-write lock for the whole rebase,
|
|
@@ -27,7 +28,7 @@ import type { WorkerContext } from './worker-context.js';
|
|
|
27
28
|
* but still need their PR's resolution polled, and this loop is the only thing
|
|
28
29
|
* that walks every branch workspace.
|
|
29
30
|
*/
|
|
30
|
-
export type RebaseContext = Pick<WorkerContext, 'baseBranch' | 'sanitizedBaseBranch' | 'contentBranchesPath' | 'contentRoot' | 'remoteGitPath' | 'taskDir' | 'taskTimeoutMs' | 'github' | 'ensureStatusReport' | 'afterConflictDetectedForTesting' | 'afterRebaseCompletedForTesting' | 'ensureSettingsBranch' | 'isDraining'>;
|
|
31
|
+
export type RebaseContext = Pick<WorkerContext, 'baseBranch' | 'sanitizedBaseBranch' | 'contentBranchesPath' | 'contentRoot' | 'remoteGitPath' | 'taskDir' | 'taskTimeoutMs' | 'github' | 'ensureStatusReport' | 'afterConflictDetectedForTesting' | 'afterRebaseCompletedForTesting' | 'ensureSettingsBranch' | 'isDraining' | 'requestBranchSync'>;
|
|
31
32
|
/**
|
|
32
33
|
* Per-cycle outcome of `rebaseActiveBranches()`, folded by `syncGit()` into the
|
|
33
34
|
* worker's self-reported status (`WorkerStatusReport.lastGitSync`, see
|
|
@@ -85,4 +86,4 @@ export declare function pollMergeState(ctx: RebaseContext, branchDir: string, br
|
|
|
85
86
|
* that branch's cross-host content-write lock and runs a series of git
|
|
86
87
|
* subprocesses against a shared filesystem.
|
|
87
88
|
*/
|
|
88
|
-
export declare function runRebaseCycle(ctx: RebaseContext, gatewayPolicy?: BranchPolicyDescription, gitHub?: GitHubSnapshot): Promise<RebaseSummary>;
|
|
89
|
+
export declare function runRebaseCycle(ctx: RebaseContext, gatewayPolicy?: BranchPolicyDescription, gitHub?: GitHubSnapshot, requested?: ReadonlySet<string>): Promise<RebaseSummary>;
|