canopycms 0.0.65 → 0.0.66-int.82
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 +1 -3
- package/dist/ai/generate.d.ts +13 -0
- package/dist/ai/generate.js +9 -3
- package/dist/ai/to-plain-text.js +4 -0
- package/dist/ai/types.d.ts +20 -1
- package/dist/api/admin-branch-health.js +13 -12
- package/dist/api/branch.js +2 -2
- package/dist/branch-health.js +1 -1
- package/dist/branch-metadata-file.d.ts +58 -0
- package/dist/branch-metadata-file.js +65 -0
- package/dist/branch-metadata.d.ts +2 -26
- package/dist/branch-metadata.js +6 -33
- package/dist/branch-registry.js +4 -2
- package/dist/build/generate-ai-content.js +103 -0
- package/dist/cli/cli.js +432 -317
- package/dist/cli/generate-ai-content.js +264 -160
- package/dist/content-id-index.js +22 -0
- package/dist/content-listing.js +3 -0
- package/dist/content-reader.d.ts +25 -1
- package/dist/content-reader.js +15 -0
- package/dist/content-store.d.ts +50 -1
- package/dist/content-store.js +102 -4
- package/dist/context.d.ts +36 -4
- package/dist/context.js +15 -4
- package/dist/editor/admin/SystemHealthPanel.js +2 -2
- package/dist/entry-schema.d.ts +22 -0
- package/dist/git-manager.d.ts +9 -8
- package/dist/git-manager.js +35 -9
- package/dist/github-service.d.ts +1 -1
- package/dist/github-service.js +1 -1
- package/dist/paths/branch-name.d.ts +1 -1
- package/dist/paths/branch-name.js +1 -1
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/index.js +1 -1
- package/dist/schema/meta-loader.js +1 -1
- package/dist/services.d.ts +22 -0
- package/dist/types.d.ts +1 -1
- package/dist/url-exclusivity-fixtures.d.ts +76 -0
- package/dist/url-exclusivity-fixtures.js +119 -0
- package/dist/url-path-resolver.js +8 -4
- package/dist/utils/content-write-lock.d.ts +2 -1
- package/dist/utils/content-write-lock.js +2 -1
- package/dist/utils/error.d.ts +17 -0
- package/dist/utils/error.js +17 -0
- package/dist/utils/git.d.ts +1 -1
- package/dist/utils/git.js +1 -1
- package/dist/utils/occ-json-write.js +1 -1
- package/dist/worker/cms-worker.d.ts +22 -288
- package/dist/worker/cms-worker.js +118 -1995
- package/dist/worker/git-sync.d.ts +166 -0
- package/dist/worker/git-sync.js +554 -0
- package/dist/worker/history-rewrite.d.ts +129 -0
- package/dist/worker/history-rewrite.js +216 -0
- package/dist/worker/rebase.d.ts +171 -0
- package/dist/worker/rebase.js +859 -0
- package/dist/worker/task-runner.d.ts +93 -0
- package/dist/worker/task-runner.js +529 -0
- package/dist/worker/worker-context.d.ts +133 -0
- package/dist/worker/worker-context.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { simpleGit } from 'simple-git';
|
|
2
|
+
import { type RebaseContext } from './rebase.js';
|
|
3
|
+
import type { WorkerContext } from './worker-context.js';
|
|
4
|
+
/**
|
|
5
|
+
* The git-sync cluster: everything reachable from `CmsWorker.syncGit()`, the
|
|
6
|
+
* slower of the worker's two poll loops (default 5 minutes, against the task
|
|
7
|
+
* queue's 5 seconds).
|
|
8
|
+
*
|
|
9
|
+
* One cycle, in order: fetch every GitHub branch into the tracking namespace,
|
|
10
|
+
* bring `refs/heads/*` toward it non-destructively (`reconcileTrackedBranches`),
|
|
11
|
+
* push this deployment's own settings branch, fast-forward the base branch's
|
|
12
|
+
* workspace, rebase every branch that is behind it (rebase.ts), then sweep old
|
|
13
|
+
* tasks and expired trashed branch directories.
|
|
14
|
+
*
|
|
15
|
+
* Two of those steps are ordered by something the code enforces, and the rest
|
|
16
|
+
* are not ordered at all:
|
|
17
|
+
*
|
|
18
|
+
* - `pushSettingsBranches` consumes `trackedNames` from
|
|
19
|
+
* `reconcileTrackedBranches`, which is a DATA dependency its signature
|
|
20
|
+
* already enforces -- see its own comment, which says as much.
|
|
21
|
+
* - `runRebaseCycle` must follow `reconcileTrackedBranches`, and this is the
|
|
22
|
+
* one dependency nothing enforces. Branch clones fetch the base tip from
|
|
23
|
+
* `remote.git` (`origin`), and `reconcileTrackedBranches` is what advances
|
|
24
|
+
* `remote.git`'s `refs/heads/*` toward what the fetch above put in the
|
|
25
|
+
* tracking namespace. Reorder them and every branch rebases onto the
|
|
26
|
+
* PREVIOUS cycle's base tip -- not corrupting, but silently a cycle behind.
|
|
27
|
+
*
|
|
28
|
+
* `refreshBaseBranchWorkspace` and the two sweeps are order-independent.
|
|
29
|
+
*
|
|
30
|
+
* What matters more than any of that is that the whole cycle is wrapped so
|
|
31
|
+
* both outcomes record a worker-status.json snapshot, since an operator's only
|
|
32
|
+
* view of this loop is the admin panel.
|
|
33
|
+
*/
|
|
34
|
+
export type GitSyncContext = Pick<WorkerContext, 'baseBranch' | 'sanitizedBaseBranch' | 'contentBranchesPath' | 'remoteGitPath' | 'taskDir' | 'taskTimeoutMs' | 'log' | 'buildGitHubUrl' | 'ensureSettingsBranch' | 'ensureStatusReport' | 'isRunning'> & RebaseContext;
|
|
35
|
+
/**
|
|
36
|
+
* Per-cycle outcome of `reconcileTrackedBranches()` -- the non-destructive
|
|
37
|
+
* replacement for the old `+refs/heads/*:refs/heads/*` fetch refspec (see
|
|
38
|
+
* `GITHUB_TRACKING_REF_PREFIX`'s doc comment for the bug this fixes). Folded
|
|
39
|
+
* by `syncGit()` into the worker's self-reported status
|
|
40
|
+
* (`WorkerStatusReport.lastGitSync.tracked`, see worker-status.ts).
|
|
41
|
+
*/
|
|
42
|
+
export interface TrackedBranchSummary {
|
|
43
|
+
/** GitHub branches with no corresponding local `refs/heads/<name>` yet -- created at GitHub's tip. */
|
|
44
|
+
created: string[];
|
|
45
|
+
/** Local heads that were strict ancestors of GitHub's tip -- fast-forwarded to it. */
|
|
46
|
+
fastForwarded: string[];
|
|
47
|
+
/**
|
|
48
|
+
* Local heads AHEAD of GitHub's tip -- unpushed editor/settings work.
|
|
49
|
+
* Deliberately left untouched; this is exactly what the old refspec used
|
|
50
|
+
* to force-rewind or (with --prune) delete outright.
|
|
51
|
+
*/
|
|
52
|
+
ahead: string[];
|
|
53
|
+
/**
|
|
54
|
+
* Local heads that diverged from GitHub's tip (neither side is an
|
|
55
|
+
* ancestor of the other) -- left untouched and logged. A real collision
|
|
56
|
+
* (e.g. another deployment moved the same branch name); the next push
|
|
57
|
+
* attempt will be rejected non-fast-forward, which is the correct,
|
|
58
|
+
* visible outcome.
|
|
59
|
+
*/
|
|
60
|
+
diverged: string[];
|
|
61
|
+
/**
|
|
62
|
+
* Local heads that diverged from GitHub's tip because THIS worker's rebase
|
|
63
|
+
* loop rewrote them and published the rewrite into `remote.git`, with the
|
|
64
|
+
* GitHub push still outstanding (`BranchMetadata.historyRewrittenFrom` is
|
|
65
|
+
* set). Structurally identical to `diverged` at the ref level, but a known,
|
|
66
|
+
* self-resolving state rather than a cross-deployment collision -- kept in
|
|
67
|
+
* its own bucket so the collision warning stays meaningful.
|
|
68
|
+
*/
|
|
69
|
+
rewritten: string[];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Push THIS deployment's own settings branch (`ensureSettingsBranch()`) from
|
|
73
|
+
* remote.git to GitHub. Non-fatal: a no-op push for an up-to-date branch
|
|
74
|
+
* just succeeds quietly.
|
|
75
|
+
*
|
|
76
|
+
* Deliberately narrowed to one branch — this used to push EVERY local
|
|
77
|
+
* branch matching `canopycms-settings-*`. With the tracking-namespace fetch
|
|
78
|
+
* fix (GITHUB_TRACKING_REF_PREFIX), `reconcileTrackedBranches` creates local
|
|
79
|
+
* heads for branches that exist on GitHub, so ANOTHER deployment's settings
|
|
80
|
+
* branch (sharing this same GitHub repo) can legitimately show up as a
|
|
81
|
+
* local head here too. Pushing it would be this deployment shipping
|
|
82
|
+
* settings state it doesn't own.
|
|
83
|
+
*/
|
|
84
|
+
export declare function pushSettingsBranches(ctx: GitSyncContext, git: ReturnType<typeof simpleGit>, trackedNames: ReadonlySet<string>): Promise<void>;
|
|
85
|
+
/**
|
|
86
|
+
* Bring `refs/heads/*` in `remote.git` toward what was just fetched into
|
|
87
|
+
* `GITHUB_TRACKING_REF_PREFIX` -- WITHOUT ever force-rewinding or deleting
|
|
88
|
+
* a local head. This is the non-destructive replacement for what the old
|
|
89
|
+
* `+refs/heads/*:refs/heads/*` fetch refspec used to do implicitly (and
|
|
90
|
+
* destructively) as part of the fetch itself; see
|
|
91
|
+
* `GITHUB_TRACKING_REF_PREFIX`'s doc comment for the two failure modes
|
|
92
|
+
* that refspec caused.
|
|
93
|
+
*
|
|
94
|
+
* Per tracked branch:
|
|
95
|
+
* - no local `refs/heads/<name>` yet -> create it at the tracked commit
|
|
96
|
+
* (a branch created on GitHub, or by another deployment sharing this
|
|
97
|
+
* GitHub repo, becomes visible locally).
|
|
98
|
+
* - local is a strict ancestor of tracked (behind) -> fast-forward it.
|
|
99
|
+
* - local === tracked -> nothing to do.
|
|
100
|
+
* - tracked is a strict ancestor of local (ahead) -> LEAVE IT ALONE. This
|
|
101
|
+
* is unpushed editor/settings work; the queued push task (or
|
|
102
|
+
* pushSettingsBranches) ships it. This is exactly the branch state the
|
|
103
|
+
* old refspec used to destroy.
|
|
104
|
+
* - neither is an ancestor of the other (diverged) -> LEAVE IT ALONE and
|
|
105
|
+
* count/log it. A real collision (e.g. another deployment moved the
|
|
106
|
+
* same branch name on GitHub); the next push attempt will be rejected
|
|
107
|
+
* non-fast-forward, which is the correct, visible outcome -- this
|
|
108
|
+
* method must never silently pick a winner. The one expected, benign
|
|
109
|
+
* form of this -- our own rebase loop having published a rewrite into
|
|
110
|
+
* remote.git with the GitHub push still queued -- is split out into the
|
|
111
|
+
* `rewritten` bucket so the collision warning stays meaningful.
|
|
112
|
+
*
|
|
113
|
+
* Never deletes a local head: a branch removed on GitHub simply stops
|
|
114
|
+
* being tracked here; the local ref persists until removed through its
|
|
115
|
+
* own explicit path (the sync loop must not be one of them).
|
|
116
|
+
*
|
|
117
|
+
* `remote.git` is bare, so there is no worktree to invalidate by moving
|
|
118
|
+
* these refs -- unlike a non-bare repo, updating the ref that happens to
|
|
119
|
+
* be "checked out" is a non-issue here.
|
|
120
|
+
*
|
|
121
|
+
* Concurrency: `remote.git` is bare and on EFS, and the Lambda pushes into
|
|
122
|
+
* it concurrently (`GitManager.push()`'s `target:target` refspec) while
|
|
123
|
+
* this runs. Every `update-ref` below passes the expected old value (the
|
|
124
|
+
* all-zeros OID for "must not exist yet" on creation, the previously-read
|
|
125
|
+
* SHA for the fast-forward case) so a concurrent Lambda write landing in
|
|
126
|
+
* the gap between the read and the write loses the ref update instead of
|
|
127
|
+
* being silently clobbered -- the branch is simply revisited next cycle.
|
|
128
|
+
*/
|
|
129
|
+
export declare function reconcileTrackedBranches(ctx: GitSyncContext, git: ReturnType<typeof simpleGit>): Promise<{
|
|
130
|
+
summary: TrackedBranchSummary;
|
|
131
|
+
trackedNames: Set<string>;
|
|
132
|
+
}>;
|
|
133
|
+
export declare function syncGit(ctx: GitSyncContext): Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* [C1] Remove `.trash-*` branch directories (created by the admin purge
|
|
136
|
+
* action, api/admin-branch-health.ts) whose name-embedded stamp is older
|
|
137
|
+
* than {@link TRASH_RETENTION_MS}. Names that don't match the expected
|
|
138
|
+
* `.trash-{dirName}-{STAMP}` shape, or whose stamp fails to parse, are
|
|
139
|
+
* left alone (logged once per cycle, not per file, to avoid flooding logs
|
|
140
|
+
* if something odd accumulates) -- purge is the only writer of this
|
|
141
|
+
* naming scheme, so an unparseable name is unexpected and worth a human
|
|
142
|
+
* looking rather than a silent skip.
|
|
143
|
+
*/
|
|
144
|
+
export declare function cleanupTrashedBranchDirs(ctx: Pick<GitSyncContext, 'contentBranchesPath'>): Promise<number>;
|
|
145
|
+
/**
|
|
146
|
+
* Fast-forward the base branch's own working-tree clone
|
|
147
|
+
* (content-branches/<baseBranch>) to match origin/<baseBranch>.
|
|
148
|
+
*
|
|
149
|
+
* Previously this clone was refreshed only incidentally, by the generic
|
|
150
|
+
* rebase loop below (rebaseActiveBranches): for a branch with status
|
|
151
|
+
* 'editing', rebasing onto origin/<baseBranch> degenerates to a
|
|
152
|
+
* fast-forward when the clone IS the base branch. But that loop's skip
|
|
153
|
+
* paths -- a dirty tree, a missing .git -- are silent, which is the
|
|
154
|
+
* suspected live failure mode: a wedged base clone with no diagnosable
|
|
155
|
+
* signal in the logs. This dedicated step makes the refresh explicit,
|
|
156
|
+
* ff-only, and loud, so a stuck base view (an editor forking a new branch
|
|
157
|
+
* "from base" that's actually a stale snapshot) is diagnosable from logs.
|
|
158
|
+
* This runs every sync cycle so the drift window is bounded by
|
|
159
|
+
* gitSyncInterval.
|
|
160
|
+
*
|
|
161
|
+
* ff-only on purpose: this clone must stay a linear mirror of
|
|
162
|
+
* origin/<baseBranch>, so a merge that isn't a fast-forward (diverged
|
|
163
|
+
* local history) is treated as a should-never-happen condition and left
|
|
164
|
+
* untouched rather than force-resolved.
|
|
165
|
+
*/
|
|
166
|
+
export declare function refreshBaseBranchWorkspace(ctx: GitSyncContext): Promise<void>;
|