canopycms 0.0.68-int.111 → 0.0.68-int.113
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/branch-health.js +14 -9
- package/dist/cli/cli.js +4 -0
- package/dist/cli/generate-ai-content.js +2 -0
- package/dist/editor/Editor.js +2 -2
- package/dist/editor/components/StagedChangesDrawer.d.ts +37 -0
- package/dist/editor/components/StagedChangesDrawer.js +75 -0
- package/dist/editor/group-manager/GroupCard.d.ts +2 -0
- package/dist/editor/group-manager/GroupCard.js +2 -2
- package/dist/editor/group-manager/GroupForm.js +1 -1
- package/dist/editor/group-manager/InternalGroupsTab.d.ts +1 -0
- package/dist/editor/group-manager/InternalGroupsTab.js +2 -2
- package/dist/editor/group-manager/hooks/useGroupState.d.ts +2 -0
- package/dist/editor/group-manager/hooks/useGroupState.js +18 -1
- package/dist/editor/group-manager/index.js +9 -4
- package/dist/editor/group-manager/types.d.ts +3 -1
- package/dist/editor/hooks/usePermissionManager.js +4 -3
- package/dist/editor/permission-manager/index.js +9 -3
- package/dist/editor/permission-manager/types.d.ts +3 -1
- package/dist/git-manager.d.ts +10 -0
- package/dist/git-manager.js +6 -5
- package/dist/utils/error.js +6 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker/cms-worker.d.ts +39 -124
- package/dist/worker/cms-worker.js +232 -259
- package/dist/worker/git-sync.d.ts +7 -5
- package/dist/worker/git-sync.js +32 -29
- package/dist/worker/github-auth.d.ts +7 -7
- package/dist/worker/github-auth.js +12 -14
- package/dist/worker/github-gateway.d.ts +144 -0
- package/dist/worker/github-gateway.js +370 -0
- package/dist/worker/github-mirror.d.ts +84 -10
- package/dist/worker/github-mirror.js +237 -21
- package/dist/worker/rebase.d.ts +1 -1
- package/dist/worker/rebase.js +1 -6
- package/dist/worker/shared-repo-git.d.ts +6 -0
- package/dist/worker/shared-repo-git.js +8 -0
- package/dist/worker/task-runner.d.ts +2 -2
- package/dist/worker/task-runner.js +77 -127
- package/dist/worker/worker-context.d.ts +12 -40
- package/package.json +1 -1
|
@@ -118,11 +118,10 @@ export declare function recordWorkerStartupFailure(options: {
|
|
|
118
118
|
}): Promise<void>;
|
|
119
119
|
export declare class CmsWorker {
|
|
120
120
|
private config;
|
|
121
|
-
private
|
|
121
|
+
private gateway?;
|
|
122
122
|
private taskDir;
|
|
123
123
|
private remoteGitPath;
|
|
124
124
|
private stateDirectory;
|
|
125
|
-
private githubMirror;
|
|
126
125
|
private contentBranchesPath;
|
|
127
126
|
private resolvedBaseBranch?;
|
|
128
127
|
private settingsBranchResolved?;
|
|
@@ -142,7 +141,6 @@ export declare class CmsWorker {
|
|
|
142
141
|
private contentRoot;
|
|
143
142
|
private log;
|
|
144
143
|
private statusReport?;
|
|
145
|
-
private githubAuth?;
|
|
146
144
|
private lockLostMessage?;
|
|
147
145
|
private statusWriterAtLock?;
|
|
148
146
|
private settleSelfStopped;
|
|
@@ -192,8 +190,8 @@ export declare class CmsWorker {
|
|
|
192
190
|
* Built FRESH on every call, with instance-backed members as functions rather
|
|
193
191
|
* than copied values. See WorkerContext's INVARIANT: a context that captured
|
|
194
192
|
* any of them at construction time would hand the extracted code the pre-test
|
|
195
|
-
* value, which for
|
|
196
|
-
* for real instead of its local fixture repo.
|
|
193
|
+
* value, which for the GitHub gateway means a test's push going to
|
|
194
|
+
* github.com for real instead of its local fixture repo.
|
|
197
195
|
*/
|
|
198
196
|
private ctx;
|
|
199
197
|
/**
|
|
@@ -278,9 +276,19 @@ export declare class CmsWorker {
|
|
|
278
276
|
/**
|
|
279
277
|
* An unconfigured base branch is the one remote.git's HEAD names, which is what the Lambda
|
|
280
278
|
* reads too (GitManager.detectBaseBranch); before remote.git exists, it is GitHub's default
|
|
281
|
-
* branch, which the clone then records as that HEAD.
|
|
279
|
+
* branch, which the clone then records as that HEAD. So it is too when remote.git has no branch
|
|
280
|
+
* outside the settings namespace: no base branch is there for HEAD to name, and ensureRemoteGit
|
|
281
|
+
* replaces it from GitHub unless something in it is at stake. Never assumes 'main'.
|
|
282
282
|
*/
|
|
283
283
|
private resolveBaseBranch;
|
|
284
|
+
/**
|
|
285
|
+
* Check remote.git's config at boot. A refusal is never a case for replacement: it reports that
|
|
286
|
+
* something wrote there, and listing the refs a replacement would lose means running git under
|
|
287
|
+
* that config. The message says so, so System health does not read it as a routine failure.
|
|
288
|
+
*/
|
|
289
|
+
private assertRemoteGitConfig;
|
|
290
|
+
/** Whether the bare repo at `gitDir` has a branch that is not a settings branch. */
|
|
291
|
+
private hasContentBranch;
|
|
284
292
|
/**
|
|
285
293
|
* Point remote.git's HEAD at the base branch this worker uses, so a Lambda left to detect it
|
|
286
294
|
* (GitManager.detectBaseBranch) reads the same name. Only the worker writes it, at boot under
|
|
@@ -337,91 +345,41 @@ export declare class CmsWorker {
|
|
|
337
345
|
* pushed) succeeds and leaves a refs-less repo that `fs.stat` cannot tell from a healthy one, so
|
|
338
346
|
* left unchecked it silently poisons remote.git and the stat short-circuit means it never heals.
|
|
339
347
|
* The base branch is therefore verified right after seeding AND on the already-exists fast
|
|
340
|
-
* path,
|
|
348
|
+
* path, where a poisoned remote.git is replaced (`replacePoisonedRemoteGit`).
|
|
341
349
|
*/
|
|
342
350
|
private ensureRemoteGit;
|
|
343
351
|
/**
|
|
344
|
-
*
|
|
345
|
-
*
|
|
352
|
+
* Replace an existing remote.git that has no base branch with a fresh seed from GitHub, but only
|
|
353
|
+
* when every ref in it names a commit a GitHub branch contains, so replacing it loses no commit;
|
|
354
|
+
* a branch name GitHub lacks, such as a merged branch deleted there, goes. Otherwise refuse,
|
|
355
|
+
* naming the refs at stake: unpushed work such as a settings branch.
|
|
356
|
+
*
|
|
357
|
+
* The refs are compared in the same mirror session that fetches GitHub and seeds the
|
|
358
|
+
* replacement, and listed again just before the swap, since the Lambda can push into remote.git
|
|
359
|
+
* while the seed runs. The swap is two renames, so the name remote.git resolves to the old repo,
|
|
360
|
+
* the new one, or for an instant nothing, never a half-built or half-deleted one.
|
|
361
|
+
*/
|
|
362
|
+
private replacePoisonedRemoteGit;
|
|
363
|
+
/**
|
|
364
|
+
* Seed a new bare repo from GitHub at `<remote.git>.cloning`, verified and configured, and
|
|
365
|
+
* return its path for the caller to rename into place. `check` runs in the mirror session right
|
|
366
|
+
* after the GitHub fetch, and its throw stops the seed. Throws with the staging directory gone.
|
|
346
367
|
*/
|
|
347
|
-
private
|
|
368
|
+
private seedRemoteGitStaging;
|
|
348
369
|
processTaskQueue(): Promise<void>;
|
|
349
370
|
private executeTask;
|
|
350
371
|
private updateBranchMetadata;
|
|
351
372
|
private pushBranchToGitHub;
|
|
352
373
|
/**
|
|
353
|
-
*
|
|
354
|
-
*
|
|
355
|
-
*
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
* `resolveWorkerGitHubAuth` throws for a half-configured credential (both
|
|
359
|
-
* set, neither set, an unusable mint timeout or refresh interval), and a
|
|
360
|
-
* throw during `new CmsWorker(...)` lands BEFORE start()'s catch, which
|
|
361
|
-
* records `lastFatalError` for every entrypoint.
|
|
362
|
-
*
|
|
363
|
-
* Idempotent, and it does NOT replace an `octokit` a test has already
|
|
364
|
-
* assigned onto the instance — see the field's comment.
|
|
365
|
-
*/
|
|
366
|
-
private ensureGitHubAuth;
|
|
367
|
-
/**
|
|
368
|
-
* The Octokit client, built on first use. Every read goes through here rather
|
|
369
|
-
* than touching the field, which the constructor does not populate: a method
|
|
370
|
-
* reached without start() would otherwise see `undefined`.
|
|
371
|
-
* `rebaseActiveBranches()` is exactly that case — apps/test-app's e2e route
|
|
372
|
-
* calls it directly, and its `pollMergeState` dispatch reads `ctx.octokit()`.
|
|
374
|
+
* The worker's GitHub gateway, created on first use: inside start()'s try, or wherever a test
|
|
375
|
+
* entry point first reaches it. Creating it resolves the credential, which throws for a
|
|
376
|
+
* half-configured one (both set, neither set, an unusable mint timeout or refresh interval) --
|
|
377
|
+
* never in the constructor, for the reason `ensureSettingsBranch()` gives. Keeps a gateway a
|
|
378
|
+
* test installed.
|
|
373
379
|
*/
|
|
374
|
-
private
|
|
375
|
-
/**
|
|
376
|
-
|
|
377
|
-
* command. The only other consumer is Octokit, built from the same resolution
|
|
378
|
-
* by `ensureGitHubAuth()` above.
|
|
379
|
-
*
|
|
380
|
-
* Async because under GitHub App auth `resolveGitToken` mints an installation
|
|
381
|
-
* token lasting about an hour. NOTHING may cache what this returns — a URL
|
|
382
|
-
* built from an installation token goes stale with it — and resolving per use
|
|
383
|
-
* is cheap, since `@octokit/auth-app` answers from its own cache until the
|
|
384
|
-
* token is near expiry.
|
|
385
|
-
*
|
|
386
|
-
* A mint failure propagates AS THROWN, carrying the `.status` that
|
|
387
|
-
* `isPermanentTaskFailure` classifies on — see github-auth.ts.
|
|
388
|
-
*
|
|
389
|
-
* Do NOT add a parallel token accessor alongside it. Every instance-backed
|
|
390
|
-
* WorkerContext member stays a function precisely so tests can replace it
|
|
391
|
-
* through the instance (worker-context.ts's INVARIANT); a second credential
|
|
392
|
-
* path would be one nothing stubs.
|
|
393
|
-
*/
|
|
394
|
-
private buildGitHubUrl;
|
|
395
|
-
/**
|
|
396
|
-
* Prove the GitHub App credential works before anything depends on it.
|
|
397
|
-
*
|
|
398
|
-
* Without this the first failure comes out of `ensureRemoteGit`'s bare clone
|
|
399
|
-
* below, whose catch blames the repository ("may be empty, or the base branch
|
|
400
|
-
* may not exist") and sends an operator holding a bad private key looking for
|
|
401
|
-
* a problem that does not exist. Called from start()'s try, so the failure is
|
|
402
|
-
* also recorded as `lastFatalError` and reaches the admin panel. No-op on the
|
|
403
|
-
* token path: a PAT is a literal, so the first real request checks everything
|
|
404
|
-
* this could.
|
|
405
|
-
*
|
|
406
|
-
* FATAL UNLESS THE FAILURE POSITIVELY LOOKS TRANSIENT. Both halves are
|
|
407
|
-
* load-bearing. Not always fatal, because the two credential paths must
|
|
408
|
-
* degrade alike: on the token path a GitHub 502 during boot is absorbed (a
|
|
409
|
-
* warm `remote.git` short-circuits `ensureRemoteGit`, `Promise.allSettled`
|
|
410
|
-
* swallows the initial `syncGit`) so the worker starts and its loops retry,
|
|
411
|
-
* while rethrowing every error class would make the App path exit and systemd
|
|
412
|
-
* crash-loop it until GitHub recovered — each iteration telling the operator
|
|
413
|
-
* to check their private key.
|
|
414
|
-
*
|
|
415
|
-
* But fail CLOSED, via `isTransientAuthFailure` rather than the inverse of
|
|
416
|
-
* `isPermanentTaskFailure`: that classifier defaults a status-less error to
|
|
417
|
-
* transient, which is right on the task path (bounded by `maxRetries`) and
|
|
418
|
-
* wrong here (bounded by nothing). A key that never reaches GitHub at all —
|
|
419
|
-
* the wrong type, or too mangled to sign with — fails locally and
|
|
420
|
-
* status-lessly, so defaulting to transient would boot a worker with a dead
|
|
421
|
-
* credential, record no `lastFatalError`, and show healthy in the admin panel
|
|
422
|
-
* while every task and every sync failed.
|
|
423
|
-
*/
|
|
424
|
-
private preflightGitHubAppAuth;
|
|
380
|
+
private github;
|
|
381
|
+
/** What the in-process gateway is built from; test-utils/worker-gateway.ts builds from it too. */
|
|
382
|
+
private localGitHubGatewayOptions;
|
|
425
383
|
/**
|
|
426
384
|
* The workspace directory for a branch named by its GIT REF name -- the form
|
|
427
385
|
* task payloads carry (`context.branch.name`), not the directory form.
|
|
@@ -460,49 +418,6 @@ export declare class CmsWorker {
|
|
|
460
418
|
protected afterRebaseCompletedForTesting(): Promise<void>;
|
|
461
419
|
private rebaseActiveBranches;
|
|
462
420
|
syncGit(): Promise<void>;
|
|
463
|
-
/**
|
|
464
|
-
* `syncGit`, plus "the credential may have rotated" on the way out.
|
|
465
|
-
*
|
|
466
|
-
* One of `refreshGitHubCredential`'s two call sites, and the one that works
|
|
467
|
-
* when nobody is publishing: it fetches from GitHub every `gitSyncInterval`
|
|
468
|
-
* whether or not anyone is editing, so a credential that has stopped working
|
|
469
|
-
* surfaces here even with no push queued for days.
|
|
470
|
-
*
|
|
471
|
-
* The SYNC failure is what propagates to `scheduleLoop`'s catch;
|
|
472
|
-
* `refreshGitHubCredential` never throws, so nothing it does can replace it.
|
|
473
|
-
*/
|
|
474
|
-
private syncGitWithCredentialRefresh;
|
|
475
|
-
/**
|
|
476
|
-
* Re-read the GitHub credential, because an operation using it just failed.
|
|
477
|
-
*
|
|
478
|
-
* **Two call sites, each covering what the other cannot.** The git-sync loop
|
|
479
|
-
* (`syncGitWithCredentialRefresh`) notices a dead credential when nobody is
|
|
480
|
-
* publishing. `processTaskQueue`'s per-task catch is what saves a publish: a
|
|
481
|
-
* push task spends its retry budget on a 5s/10s/20s backoff, well inside one
|
|
482
|
-
* 5-minute sync interval, so with the sync loop as the only trigger a publish
|
|
483
|
-
* meeting a rotated token fails permanently while the working one is already
|
|
484
|
-
* in the secret store. Every consumer reaches the credential through
|
|
485
|
-
* `ensureGitHubAuth()`, which reads it per use, so a refresh from either site
|
|
486
|
-
* repairs all of them for their NEXT use — but not an attempt already failed.
|
|
487
|
-
*
|
|
488
|
-
* NOT gated on the error looking auth-shaped, at either site: a `git
|
|
489
|
-
* fetch`/`push` rejected for a dead token throws a plain simple-git error
|
|
490
|
-
* (exit 128, no HTTP `.status`) that `isPermanentTaskFailure` reads as
|
|
491
|
-
* transient, so a gate keyed on it would never fire. Two floors bound the
|
|
492
|
-
* cost instead — core's `refreshGitHubTokenMinIntervalMs` (default 60s,
|
|
493
|
-
* enforced by `refreshCredential` in github-auth.ts) and whatever floor the
|
|
494
|
-
* provider keeps (the AWS one reads at most once per five minutes) — and both
|
|
495
|
-
* call sites share both, so a read issued by one throttles the other. On the
|
|
496
|
-
* GitHub App path the refresh is a no-op.
|
|
497
|
-
*
|
|
498
|
-
* **Never throws**: both callers are already reporting the failure that must
|
|
499
|
-
* reach the log. **Bounded by `taskTimeoutMs`**, because the task loop awaits
|
|
500
|
-
* it and a read that never settled would stop every publish queued behind it
|
|
501
|
-
* (an adopter's provider may have no bound at all; the AWS one can take 87s
|
|
502
|
-
* for one `getSecret`). A losing read is not cancelled and may land later, but
|
|
503
|
-
* `refreshCredential` discards a result older than one already applied.
|
|
504
|
-
*/
|
|
505
|
-
private refreshGitHubCredential;
|
|
506
421
|
private pushSettingsBranches;
|
|
507
422
|
private refreshBaseBranchWorkspace;
|
|
508
423
|
private cleanupTrashedBranchDirs;
|