@cat-factory/integrations 0.69.1 → 0.70.0
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/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/modules/compose/ComposeEnvironmentProvider.d.ts +0 -13
- package/dist/modules/compose/ComposeEnvironmentProvider.d.ts.map +1 -1
- package/dist/modules/compose/ComposeEnvironmentProvider.js +4 -138
- package/dist/modules/compose/ComposeEnvironmentProvider.js.map +1 -1
- package/dist/modules/compose/compose-environment.logic.d.ts +8 -0
- package/dist/modules/compose/compose-environment.logic.d.ts.map +1 -1
- package/dist/modules/compose/compose-environment.logic.js.map +1 -1
- package/dist/modules/compose/recipe-runner.d.ts +31 -0
- package/dist/modules/compose/recipe-runner.d.ts.map +1 -0
- package/dist/modules/compose/recipe-runner.js +145 -0
- package/dist/modules/compose/recipe-runner.js.map +1 -0
- package/dist/modules/sharedStack/SharedStackService.d.ts +94 -0
- package/dist/modules/sharedStack/SharedStackService.d.ts.map +1 -0
- package/dist/modules/sharedStack/SharedStackService.js +340 -0
- package/dist/modules/sharedStack/SharedStackService.js.map +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { classifyComposePs, composeExecArgs, healthGateIntervalMs, healthGateTimeoutMs, matchesHttpExpectation, recipeStepIntervalMs, recipeStepTimeoutMs, tailOutput, waitFileExecArgs, } from './compose-environment.logic.js';
|
|
2
|
+
/** Run one recipe setup/teardown step, returning a normalized verdict (never throws). */
|
|
3
|
+
export async function runRecipeStep(step, ctx) {
|
|
4
|
+
const { runtime, scope, env, project } = ctx;
|
|
5
|
+
const timeoutMs = recipeStepTimeoutMs(step);
|
|
6
|
+
try {
|
|
7
|
+
switch (step.kind) {
|
|
8
|
+
case 'compose-exec': {
|
|
9
|
+
const res = await runtime.compose(composeExecArgs(scope, step), {
|
|
10
|
+
env,
|
|
11
|
+
timeoutMs,
|
|
12
|
+
...(step.stdinFile ? { stdin: { project, checkoutFile: step.stdinFile } } : {}),
|
|
13
|
+
});
|
|
14
|
+
return res.code === 0
|
|
15
|
+
? { ok: true }
|
|
16
|
+
: { ok: false, error: tailOutput(res.stderr || res.stdout) || `exit ${res.code}` };
|
|
17
|
+
}
|
|
18
|
+
case 'copy-file': {
|
|
19
|
+
if (!runtime.copyCheckoutFile)
|
|
20
|
+
return { ok: false, error: 'runtime cannot copy checkout files' };
|
|
21
|
+
await runtime.copyCheckoutFile(project, step.from, step.to);
|
|
22
|
+
return { ok: true };
|
|
23
|
+
}
|
|
24
|
+
case 'wait-http':
|
|
25
|
+
return pollUntil(timeoutMs, recipeStepIntervalMs(step), () => probeHttp(step.url, step));
|
|
26
|
+
case 'wait-file':
|
|
27
|
+
return pollUntil(timeoutMs, recipeStepIntervalMs(step), () => probeFile(step, ctx));
|
|
28
|
+
case 'host-command': {
|
|
29
|
+
if (!runtime.hostCommand)
|
|
30
|
+
return { ok: false, error: 'runtime cannot run host commands' };
|
|
31
|
+
const res = await runtime.hostCommand(project, step.command, {
|
|
32
|
+
...(step.workdir ? { workdir: step.workdir } : {}),
|
|
33
|
+
env,
|
|
34
|
+
timeoutMs,
|
|
35
|
+
});
|
|
36
|
+
return res.code === 0
|
|
37
|
+
? { ok: true }
|
|
38
|
+
: { ok: false, error: tailOutput(res.stderr || res.stdout) || `exit ${res.code}` };
|
|
39
|
+
}
|
|
40
|
+
default:
|
|
41
|
+
// A structural guard elsewhere validates the recipe, so a stale/hand-edited config can
|
|
42
|
+
// carry an unknown step kind. Return a clean verdict rather than falling off the switch.
|
|
43
|
+
return {
|
|
44
|
+
ok: false,
|
|
45
|
+
error: `unsupported recipe step kind '${step.kind ?? 'unknown'}'`,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Run the terminal health gate until it passes or its budget elapses (never throws). The gate's own
|
|
55
|
+
* timeout/interval are derived from `gate` here (via {@link healthGateTimeoutMs}/{@link
|
|
56
|
+
* healthGateIntervalMs}), so callers pass only `shortTimeoutMs` — the bound for the individual
|
|
57
|
+
* compose/HTTP probe calls the gate makes — rather than re-deriving the budget at every call site.
|
|
58
|
+
*/
|
|
59
|
+
export async function runHealthGate(gate, ctx, shortTimeoutMs) {
|
|
60
|
+
const { runtime, scope, env } = ctx;
|
|
61
|
+
const timeoutMs = healthGateTimeoutMs(gate);
|
|
62
|
+
const intervalMs = healthGateIntervalMs(gate);
|
|
63
|
+
if (gate.kind === 'http') {
|
|
64
|
+
return pollUntil(timeoutMs, intervalMs, () => probeHttp(gate.url, gate, shortTimeoutMs));
|
|
65
|
+
}
|
|
66
|
+
if (gate.kind === 'compose-exec') {
|
|
67
|
+
return pollUntil(timeoutMs, intervalMs, async () => {
|
|
68
|
+
const res = await runtime.compose(composeExecArgs(scope, { service: gate.service, command: gate.command }), { env, timeoutMs: shortTimeoutMs });
|
|
69
|
+
return {
|
|
70
|
+
done: res.code === 0,
|
|
71
|
+
error: tailOutput(res.stderr || res.stdout) || `exit ${res.code}`,
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
// compose-healthy: poll `ps` until the stack is ready / a service crashed.
|
|
76
|
+
return pollUntil(timeoutMs, intervalMs, async () => {
|
|
77
|
+
const ps = await runtime.compose([...scope, 'ps', '-a', '--format', 'json'], {
|
|
78
|
+
env,
|
|
79
|
+
timeoutMs: shortTimeoutMs,
|
|
80
|
+
});
|
|
81
|
+
const status = ps.code === 0 ? classifyComposePs(ps.stdout) : 'provisioning';
|
|
82
|
+
if (status === 'ready')
|
|
83
|
+
return { done: true };
|
|
84
|
+
if (status === 'failed')
|
|
85
|
+
return { done: false, fatal: true, error: 'a service is unhealthy or crashed' };
|
|
86
|
+
return { done: false, error: 'stack not healthy yet' };
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/** Probe a URL once for a `wait-http` step / `http` gate; a network error is a non-fatal retry. */
|
|
90
|
+
async function probeHttp(url, opts, timeoutMs = 60_000) {
|
|
91
|
+
try {
|
|
92
|
+
const res = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) });
|
|
93
|
+
// Read the body only when a substring is required; otherwise release it so the poll doesn't
|
|
94
|
+
// leave an unconsumed body pinning the connection on every re-probe.
|
|
95
|
+
let body = '';
|
|
96
|
+
if (opts.expectBodyContains)
|
|
97
|
+
body = await res.text();
|
|
98
|
+
else
|
|
99
|
+
await res.body?.cancel();
|
|
100
|
+
return matchesHttpExpectation(res.status, body, opts)
|
|
101
|
+
? { done: true }
|
|
102
|
+
: { done: false, error: `HTTP ${res.status}` };
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
return { done: false, error: err instanceof Error ? err.message : String(err) };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/** Probe a `wait-file` step once — in a container (`test -f`) or the checkout. */
|
|
109
|
+
async function probeFile(step, ctx, shortTimeoutMs = 60_000) {
|
|
110
|
+
const { runtime, scope, env, project } = ctx;
|
|
111
|
+
if (step.service) {
|
|
112
|
+
const res = await runtime.compose(waitFileExecArgs(scope, step.service, step.path), {
|
|
113
|
+
env,
|
|
114
|
+
timeoutMs: shortTimeoutMs,
|
|
115
|
+
});
|
|
116
|
+
return res.code === 0 ? { done: true } : { done: false, error: `not present yet` };
|
|
117
|
+
}
|
|
118
|
+
const exists = (await runtime.checkoutFileExists?.(project, step.path)) ?? false;
|
|
119
|
+
return exists ? { done: true } : { done: false, error: `not present yet` };
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Poll `attempt` until it reports `done` (success) or `fatal` (a definitive failure — stop early),
|
|
123
|
+
* or the budget elapses (timeout failure). Attempts at least once; sleeps `intervalMs` between tries.
|
|
124
|
+
*/
|
|
125
|
+
async function pollUntil(timeoutMs, intervalMs, attempt) {
|
|
126
|
+
const deadline = Date.now() + timeoutMs;
|
|
127
|
+
let lastError = 'timed out';
|
|
128
|
+
for (;;) {
|
|
129
|
+
const res = await attempt();
|
|
130
|
+
if (res.done)
|
|
131
|
+
return { ok: true };
|
|
132
|
+
if (res.fatal)
|
|
133
|
+
return { ok: false, error: res.error ?? 'failed' };
|
|
134
|
+
lastError = res.error ?? lastError;
|
|
135
|
+
if (Date.now() + intervalMs >= deadline) {
|
|
136
|
+
return { ok: false, error: `timed out after ${timeoutMs}ms (${lastError})` };
|
|
137
|
+
}
|
|
138
|
+
await sleep(intervalMs);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/** Sleep `ms` between poll attempts (host-side; recipe execution is local-facade only). */
|
|
142
|
+
function sleep(ms) {
|
|
143
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=recipe-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recipe-runner.js","sourceRoot":"","sources":["../../../src/modules/compose/recipe-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { Clock, CreateSharedStackInput, IdGenerator, RecipeStepRecorder, SharedStack, SharedStackRepository, UpdateSharedStackInput, WorkspaceRepository } from '@cat-factory/kernel';
|
|
2
|
+
import { type ComposeRuntime } from '../compose/compose-environment.logic.js';
|
|
3
|
+
export interface SharedStackServiceDependencies {
|
|
4
|
+
sharedStackRepository: SharedStackRepository;
|
|
5
|
+
workspaceRepository: WorkspaceRepository;
|
|
6
|
+
idGenerator: IdGenerator;
|
|
7
|
+
clock: Clock;
|
|
8
|
+
/**
|
|
9
|
+
* The host Docker seam used to bring a stack UP / tear it DOWN. Wired ONLY on a facade with a
|
|
10
|
+
* host daemon (the local facade); absent on the Worker / plain Node, where CRUD still works but
|
|
11
|
+
* `ensureUp`/`teardown` refuse with a clear "requires the local Docker runtime" error (the
|
|
12
|
+
* documented compose runtime-binding exception — persistence stays symmetric, execution does not).
|
|
13
|
+
*/
|
|
14
|
+
composeRuntime?: ComposeRuntime;
|
|
15
|
+
/**
|
|
16
|
+
* Optional VCS token used to CLONE a stack's repo during bring-up (threaded to the runtime's
|
|
17
|
+
* `checkout` as `token`). Wired on the local facade from the same source-control PAT the agent
|
|
18
|
+
* containers push with, so a shared stack whose `cloneUrl` is a PRIVATE repo can be brought up.
|
|
19
|
+
* Absent ⇒ the clone runs unauthenticated (public repos only), exactly as before.
|
|
20
|
+
*/
|
|
21
|
+
cloneToken?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Optional per-step provisioning-log recorder factory: given a stack, returns a recorder the
|
|
24
|
+
* bring-up streams per-step verdicts through (clone, network, env-file, up, each setup step,
|
|
25
|
+
* health gate), so the Infrastructure "View logs" drawer shows which step ran/died. Absent ⇒ no
|
|
26
|
+
* per-step logging (the status/lastError on the record are still updated).
|
|
27
|
+
*/
|
|
28
|
+
provisioningLog?: (stack: SharedStack) => RecipeStepRecorder;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Lifecycle for a workspace's SHARED STACKS — long-lived compose infra a per-PR consumer
|
|
32
|
+
* environment attaches to over an external network (the acme-shared-services pilot). CRUD is
|
|
33
|
+
* runtime-neutral persistence (works on every facade); the bring-up (`ensureUp`) / teardown drive a
|
|
34
|
+
* host Docker daemon through the injected {@link ComposeRuntime}, so they run ONLY on the local
|
|
35
|
+
* facade.
|
|
36
|
+
*
|
|
37
|
+
* A shared stack is NEVER swept with a run and NEVER TTL-reaped — teardown is a deliberate action.
|
|
38
|
+
* Unlike a per-PR preview env, its committed compose files run AS AUTHORED (host ports kept, no
|
|
39
|
+
* isolation rewrite): it is the operator's own trusted infra, so the trust boundary is configuring
|
|
40
|
+
* the stack, not sandboxing it. `ensureUp` is idempotent + coalesces concurrent callers onto one
|
|
41
|
+
* in-flight bring-up per stack id.
|
|
42
|
+
*/
|
|
43
|
+
export declare class SharedStackService {
|
|
44
|
+
private readonly stacks;
|
|
45
|
+
private readonly workspaceRepository;
|
|
46
|
+
private readonly idGenerator;
|
|
47
|
+
private readonly clock;
|
|
48
|
+
private readonly runtime;
|
|
49
|
+
private readonly cloneToken;
|
|
50
|
+
private readonly provisioningLog;
|
|
51
|
+
private readonly inflight;
|
|
52
|
+
constructor(deps: SharedStackServiceDependencies);
|
|
53
|
+
/** List a workspace's shared stacks (ordered by creation). */
|
|
54
|
+
list(workspaceId: string): Promise<SharedStack[]>;
|
|
55
|
+
/** A single shared stack by id. */
|
|
56
|
+
get(workspaceId: string, id: string): Promise<SharedStack>;
|
|
57
|
+
/** Create a new shared stack (initially `stopped`). */
|
|
58
|
+
create(workspaceId: string, input: CreateSharedStackInput): Promise<SharedStack>;
|
|
59
|
+
/** Patch a shared stack's config. A running stack cannot be reconfigured — tear it down first. */
|
|
60
|
+
update(workspaceId: string, id: string, patch: UpdateSharedStackInput): Promise<SharedStack>;
|
|
61
|
+
/** Remove a shared stack. A running stack must be torn down first (never silently killed). */
|
|
62
|
+
remove(workspaceId: string, id: string): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Bring a shared stack up (idempotent). Already-`running` ⇒ a no-op returning the record.
|
|
65
|
+
* Otherwise: clone/refresh the repo, create its managed networks, `up -d` under its profiles,
|
|
66
|
+
* materialize env-file templates, run the ordered setup steps, then poll the terminal health gate
|
|
67
|
+
* — persisting `running` / `failed` (+ `lastError`) at the end. Concurrent callers coalesce onto
|
|
68
|
+
* one in-flight bring-up. Requires the host Docker runtime (local facade).
|
|
69
|
+
*/
|
|
70
|
+
ensureUp(workspaceId: string, id: string): Promise<SharedStack>;
|
|
71
|
+
/** Tear a shared stack down (`down -v`). A deliberate action; the stack row is preserved. */
|
|
72
|
+
teardown(workspaceId: string, id: string): Promise<SharedStack>;
|
|
73
|
+
/** The stable compose project name for a shared stack (long-lived, NOT per-PR). */
|
|
74
|
+
private projectName;
|
|
75
|
+
/**
|
|
76
|
+
* Is the stack's compose project ACTUALLY up on the daemon right now? A project-name-scoped
|
|
77
|
+
* `compose ps` (no checkout / `-f` needed) classified as `ready`. Used to reconcile a stored
|
|
78
|
+
* `running` against reality before `ensureUp` short-circuits — a failed probe (daemon gone,
|
|
79
|
+
* containers pruned) reads as not-live so the caller re-provisions. Never throws.
|
|
80
|
+
*/
|
|
81
|
+
private isStackLive;
|
|
82
|
+
/** Drive the full bring-up, persisting the terminal `running`/`failed` verdict. */
|
|
83
|
+
private bringUp;
|
|
84
|
+
/**
|
|
85
|
+
* Refuse a stack's `host-command` setup steps unless it opted in (`allowHostCommands`) AND the
|
|
86
|
+
* runtime can run host commands. Returns a blocking message, or null when allowed / none declared.
|
|
87
|
+
*/
|
|
88
|
+
private checkHostCommands;
|
|
89
|
+
/** Write a stack's lifecycle transition (status + lastError, bumping updatedAt) and return it. */
|
|
90
|
+
private persist;
|
|
91
|
+
/** Best-effort per-step provisioning-log entry (never throws; no-op when no recorder is wired). */
|
|
92
|
+
private logStep;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=SharedStackService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SharedStackService.d.ts","sourceRoot":"","sources":["../../../src/modules/sharedStack/SharedStackService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,sBAAsB,EACtB,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACpB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EACL,KAAK,cAAc,EAKpB,MAAM,yCAAyC,CAAA;AAGhD,MAAM,WAAW,8BAA8B;IAC7C,qBAAqB,EAAE,qBAAqB,CAAA;IAC5C,mBAAmB,EAAE,mBAAmB,CAAA;IACxC,WAAW,EAAE,WAAW,CAAA;IACxB,KAAK,EAAE,KAAK,CAAA;IACZ;;;;;OAKG;IACH,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,kBAAkB,CAAA;CAC7D;AAOD;;;;;;;;;;;;GAYG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAqB;IACzD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAa;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAO;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4B;IACpD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA0D;IAG1F,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0C;IAEnE,YAAY,IAAI,EAAE,8BAA8B,EAQ/C;IAED,8DAA8D;IACxD,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAGtD;IAED,mCAAmC;IAC7B,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAG/D;IAED,uDAAuD;IACjD,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,WAAW,CAAC,CAuBrF;IAED,kGAAkG;IAC5F,MAAM,CACV,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,sBAAsB,GAC5B,OAAO,CAAC,WAAW,CAAC,CAwBtB;IAED,8FAA8F;IACxF,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO3D;IAED;;;;;;OAMG;IACG,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAkBpE;IAED,6FAA6F;IACvF,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAcpE;IAID,mFAAmF;IACnF,OAAO,CAAC,WAAW;IAOnB;;;;;OAKG;YACW,WAAW;IAYzB,mFAAmF;YACrE,OAAO;IA8HrB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAWzB,kGAAkG;YACpF,OAAO;IAerB,mGAAmG;YACrF,OAAO;CAmBtB"}
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
import { assertFound, ConflictError, requireWorkspace, ValidationError } from '@cat-factory/kernel';
|
|
2
|
+
import { classifyComposePs, composeFileDir, DEFAULT_RECIPE_HEALTH_GATE, tailOutput, } from '../compose/compose-environment.logic.js';
|
|
3
|
+
import { runHealthGate, runRecipeStep } from '../compose/recipe-runner.js';
|
|
4
|
+
// Bound (ms) for the plain compose calls (network / down / version) so a wedged daemon can't hang
|
|
5
|
+
// a bring-up/teardown forever; `up` clears its own health-gate budget separately.
|
|
6
|
+
const SHORT_TIMEOUT_MS = 60_000;
|
|
7
|
+
const UP_TIMEOUT_MS = 330_000;
|
|
8
|
+
/**
|
|
9
|
+
* Lifecycle for a workspace's SHARED STACKS — long-lived compose infra a per-PR consumer
|
|
10
|
+
* environment attaches to over an external network (the acme-shared-services pilot). CRUD is
|
|
11
|
+
* runtime-neutral persistence (works on every facade); the bring-up (`ensureUp`) / teardown drive a
|
|
12
|
+
* host Docker daemon through the injected {@link ComposeRuntime}, so they run ONLY on the local
|
|
13
|
+
* facade.
|
|
14
|
+
*
|
|
15
|
+
* A shared stack is NEVER swept with a run and NEVER TTL-reaped — teardown is a deliberate action.
|
|
16
|
+
* Unlike a per-PR preview env, its committed compose files run AS AUTHORED (host ports kept, no
|
|
17
|
+
* isolation rewrite): it is the operator's own trusted infra, so the trust boundary is configuring
|
|
18
|
+
* the stack, not sandboxing it. `ensureUp` is idempotent + coalesces concurrent callers onto one
|
|
19
|
+
* in-flight bring-up per stack id.
|
|
20
|
+
*/
|
|
21
|
+
export class SharedStackService {
|
|
22
|
+
stacks;
|
|
23
|
+
workspaceRepository;
|
|
24
|
+
idGenerator;
|
|
25
|
+
clock;
|
|
26
|
+
runtime;
|
|
27
|
+
cloneToken;
|
|
28
|
+
provisioningLog;
|
|
29
|
+
// Coalesce concurrent `ensureUp` for the same stack onto one in-flight bring-up (a second caller
|
|
30
|
+
// must not start a duplicate `up` / re-run non-idempotent setup steps).
|
|
31
|
+
inflight = new Map();
|
|
32
|
+
constructor(deps) {
|
|
33
|
+
this.stacks = deps.sharedStackRepository;
|
|
34
|
+
this.workspaceRepository = deps.workspaceRepository;
|
|
35
|
+
this.idGenerator = deps.idGenerator;
|
|
36
|
+
this.clock = deps.clock;
|
|
37
|
+
this.runtime = deps.composeRuntime;
|
|
38
|
+
this.cloneToken = deps.cloneToken;
|
|
39
|
+
this.provisioningLog = deps.provisioningLog;
|
|
40
|
+
}
|
|
41
|
+
/** List a workspace's shared stacks (ordered by creation). */
|
|
42
|
+
async list(workspaceId) {
|
|
43
|
+
await requireWorkspace(this.workspaceRepository, workspaceId);
|
|
44
|
+
return this.stacks.list(workspaceId);
|
|
45
|
+
}
|
|
46
|
+
/** A single shared stack by id. */
|
|
47
|
+
async get(workspaceId, id) {
|
|
48
|
+
await requireWorkspace(this.workspaceRepository, workspaceId);
|
|
49
|
+
return assertFound(await this.stacks.get(workspaceId, id), 'SharedStack', id);
|
|
50
|
+
}
|
|
51
|
+
/** Create a new shared stack (initially `stopped`). */
|
|
52
|
+
async create(workspaceId, input) {
|
|
53
|
+
await requireWorkspace(this.workspaceRepository, workspaceId);
|
|
54
|
+
const now = this.clock.now();
|
|
55
|
+
const stack = {
|
|
56
|
+
id: this.idGenerator.next('ss'),
|
|
57
|
+
workspaceId,
|
|
58
|
+
name: input.name,
|
|
59
|
+
cloneUrl: input.cloneUrl,
|
|
60
|
+
gitRef: input.gitRef ?? null,
|
|
61
|
+
composeFiles: input.composeFiles,
|
|
62
|
+
composeProfiles: input.composeProfiles,
|
|
63
|
+
envFiles: input.envFiles,
|
|
64
|
+
managedNetworks: input.managedNetworks,
|
|
65
|
+
setupSteps: input.setupSteps,
|
|
66
|
+
healthGate: input.healthGate ?? null,
|
|
67
|
+
allowHostCommands: input.allowHostCommands,
|
|
68
|
+
status: 'stopped',
|
|
69
|
+
lastError: null,
|
|
70
|
+
createdAt: now,
|
|
71
|
+
updatedAt: now,
|
|
72
|
+
};
|
|
73
|
+
await this.stacks.upsert(workspaceId, stack);
|
|
74
|
+
return stack;
|
|
75
|
+
}
|
|
76
|
+
/** Patch a shared stack's config. A running stack cannot be reconfigured — tear it down first. */
|
|
77
|
+
async update(workspaceId, id, patch) {
|
|
78
|
+
await requireWorkspace(this.workspaceRepository, workspaceId);
|
|
79
|
+
const existing = assertFound(await this.stacks.get(workspaceId, id), 'SharedStack', id);
|
|
80
|
+
if (existing.status === 'running' || existing.status === 'starting') {
|
|
81
|
+
throw new ConflictError('Tear the shared stack down before reconfiguring it.');
|
|
82
|
+
}
|
|
83
|
+
const updated = {
|
|
84
|
+
...existing,
|
|
85
|
+
...(patch.name !== undefined ? { name: patch.name } : {}),
|
|
86
|
+
...(patch.cloneUrl !== undefined ? { cloneUrl: patch.cloneUrl } : {}),
|
|
87
|
+
...(patch.gitRef !== undefined ? { gitRef: patch.gitRef } : {}),
|
|
88
|
+
...(patch.composeFiles !== undefined ? { composeFiles: patch.composeFiles } : {}),
|
|
89
|
+
...(patch.composeProfiles !== undefined ? { composeProfiles: patch.composeProfiles } : {}),
|
|
90
|
+
...(patch.envFiles !== undefined ? { envFiles: patch.envFiles } : {}),
|
|
91
|
+
...(patch.managedNetworks !== undefined ? { managedNetworks: patch.managedNetworks } : {}),
|
|
92
|
+
...(patch.setupSteps !== undefined ? { setupSteps: patch.setupSteps } : {}),
|
|
93
|
+
...(patch.healthGate !== undefined ? { healthGate: patch.healthGate } : {}),
|
|
94
|
+
...(patch.allowHostCommands !== undefined
|
|
95
|
+
? { allowHostCommands: patch.allowHostCommands }
|
|
96
|
+
: {}),
|
|
97
|
+
updatedAt: this.clock.now(),
|
|
98
|
+
};
|
|
99
|
+
await this.stacks.upsert(workspaceId, updated);
|
|
100
|
+
return updated;
|
|
101
|
+
}
|
|
102
|
+
/** Remove a shared stack. A running stack must be torn down first (never silently killed). */
|
|
103
|
+
async remove(workspaceId, id) {
|
|
104
|
+
await requireWorkspace(this.workspaceRepository, workspaceId);
|
|
105
|
+
const existing = await this.stacks.get(workspaceId, id);
|
|
106
|
+
if (existing && (existing.status === 'running' || existing.status === 'starting')) {
|
|
107
|
+
throw new ConflictError('Tear the shared stack down before deleting it.');
|
|
108
|
+
}
|
|
109
|
+
await this.stacks.remove(workspaceId, id);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Bring a shared stack up (idempotent). Already-`running` ⇒ a no-op returning the record.
|
|
113
|
+
* Otherwise: clone/refresh the repo, create its managed networks, `up -d` under its profiles,
|
|
114
|
+
* materialize env-file templates, run the ordered setup steps, then poll the terminal health gate
|
|
115
|
+
* — persisting `running` / `failed` (+ `lastError`) at the end. Concurrent callers coalesce onto
|
|
116
|
+
* one in-flight bring-up. Requires the host Docker runtime (local facade).
|
|
117
|
+
*/
|
|
118
|
+
async ensureUp(workspaceId, id) {
|
|
119
|
+
await requireWorkspace(this.workspaceRepository, workspaceId);
|
|
120
|
+
const stack = assertFound(await this.stacks.get(workspaceId, id), 'SharedStack', id);
|
|
121
|
+
if (!this.runtime) {
|
|
122
|
+
throw new ValidationError('Bringing a shared stack up requires the local Docker runtime (unavailable on this deployment).');
|
|
123
|
+
}
|
|
124
|
+
// Idempotent no-op ONLY when the daemon actually still has the stack up. The stored `running`
|
|
125
|
+
// is intent, not liveness — after a host reboot / `docker system prune` the row still says
|
|
126
|
+
// `running` while nothing is up, so trust-but-verify with a cheap `compose ps` before
|
|
127
|
+
// short-circuiting; a stale `running` falls through and re-provisions instead of wedging.
|
|
128
|
+
if (stack.status === 'running' && (await this.isStackLive(stack)))
|
|
129
|
+
return stack;
|
|
130
|
+
const existing = this.inflight.get(id);
|
|
131
|
+
if (existing)
|
|
132
|
+
return existing;
|
|
133
|
+
const run = this.bringUp(workspaceId, stack).finally(() => this.inflight.delete(id));
|
|
134
|
+
this.inflight.set(id, run);
|
|
135
|
+
return run;
|
|
136
|
+
}
|
|
137
|
+
/** Tear a shared stack down (`down -v`). A deliberate action; the stack row is preserved. */
|
|
138
|
+
async teardown(workspaceId, id) {
|
|
139
|
+
await requireWorkspace(this.workspaceRepository, workspaceId);
|
|
140
|
+
const stack = assertFound(await this.stacks.get(workspaceId, id), 'SharedStack', id);
|
|
141
|
+
if (!this.runtime) {
|
|
142
|
+
throw new ValidationError('Tearing a shared stack down requires the local Docker runtime (unavailable on this deployment).');
|
|
143
|
+
}
|
|
144
|
+
const project = this.projectName(stack);
|
|
145
|
+
await this.runtime
|
|
146
|
+
.compose(['-p', project, 'down', '-v', '--remove-orphans'], { timeoutMs: SHORT_TIMEOUT_MS })
|
|
147
|
+
.catch(() => { });
|
|
148
|
+
await this.runtime.cleanupProject?.(project);
|
|
149
|
+
return this.persist(workspaceId, stack, { status: 'stopped', lastError: null });
|
|
150
|
+
}
|
|
151
|
+
// --- internals ----------------------------------------------------------
|
|
152
|
+
/** The stable compose project name for a shared stack (long-lived, NOT per-PR). */
|
|
153
|
+
projectName(stack) {
|
|
154
|
+
return `cf-stack-${stack.id}`
|
|
155
|
+
.toLowerCase()
|
|
156
|
+
.replace(/[^a-z0-9_-]+/g, '-')
|
|
157
|
+
.slice(0, 63);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Is the stack's compose project ACTUALLY up on the daemon right now? A project-name-scoped
|
|
161
|
+
* `compose ps` (no checkout / `-f` needed) classified as `ready`. Used to reconcile a stored
|
|
162
|
+
* `running` against reality before `ensureUp` short-circuits — a failed probe (daemon gone,
|
|
163
|
+
* containers pruned) reads as not-live so the caller re-provisions. Never throws.
|
|
164
|
+
*/
|
|
165
|
+
async isStackLive(stack) {
|
|
166
|
+
const runtime = this.runtime;
|
|
167
|
+
if (!runtime)
|
|
168
|
+
return false;
|
|
169
|
+
const ps = await runtime
|
|
170
|
+
.compose(['-p', this.projectName(stack), 'ps', '-a', '--format', 'json'], {
|
|
171
|
+
timeoutMs: SHORT_TIMEOUT_MS,
|
|
172
|
+
})
|
|
173
|
+
.catch(() => null);
|
|
174
|
+
if (!ps || ps.code !== 0)
|
|
175
|
+
return false;
|
|
176
|
+
return classifyComposePs(ps.stdout) === 'ready';
|
|
177
|
+
}
|
|
178
|
+
/** Drive the full bring-up, persisting the terminal `running`/`failed` verdict. */
|
|
179
|
+
async bringUp(workspaceId, stack) {
|
|
180
|
+
const runtime = this.runtime;
|
|
181
|
+
const record = this.provisioningLog?.(stack);
|
|
182
|
+
await this.persist(workspaceId, stack, { status: 'starting', lastError: null });
|
|
183
|
+
const project = this.projectName(stack);
|
|
184
|
+
if (!runtime.checkout || !runtime.copyCheckoutFile) {
|
|
185
|
+
return this.persist(workspaceId, stack, {
|
|
186
|
+
status: 'failed',
|
|
187
|
+
lastError: 'The runtime cannot clone + write a checkout (shared stacks need a host daemon).',
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
// A `host-command` setup step is refused unless the stack opted in AND the runtime supports it.
|
|
191
|
+
const hostCmdIssue = this.checkHostCommands(stack);
|
|
192
|
+
if (hostCmdIssue) {
|
|
193
|
+
return this.persist(workspaceId, stack, { status: 'failed', lastError: hostCmdIssue });
|
|
194
|
+
}
|
|
195
|
+
// Clone/refresh the stack repo into its own long-lived working tree.
|
|
196
|
+
const cloneStarted = this.clock.now();
|
|
197
|
+
let checkoutDir;
|
|
198
|
+
try {
|
|
199
|
+
;
|
|
200
|
+
({ dir: checkoutDir } = await runtime.checkout(project, {
|
|
201
|
+
cloneUrl: stack.cloneUrl,
|
|
202
|
+
ref: stack.gitRef ?? 'HEAD',
|
|
203
|
+
...(this.cloneToken ? { token: this.cloneToken } : {}),
|
|
204
|
+
}));
|
|
205
|
+
await this.logStep(record, 'clone repo', cloneStarted, { ok: true });
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
const message = `Could not clone the stack repo: ${err instanceof Error ? err.message : String(err)}`;
|
|
209
|
+
await this.logStep(record, 'clone repo', cloneStarted, { ok: false, error: message });
|
|
210
|
+
return this.persist(workspaceId, stack, { status: 'failed', lastError: message });
|
|
211
|
+
}
|
|
212
|
+
// Create the managed networks the stack owns (its consumers attach to these as external).
|
|
213
|
+
for (const network of stack.managedNetworks) {
|
|
214
|
+
const started = this.clock.now();
|
|
215
|
+
const res = (await runtime.ensureNetwork?.(network)) ?? {
|
|
216
|
+
code: 1,
|
|
217
|
+
stdout: '',
|
|
218
|
+
stderr: 'runtime cannot manage networks',
|
|
219
|
+
};
|
|
220
|
+
const ok = res.code === 0;
|
|
221
|
+
await this.logStep(record, `network: ${network}`, started, {
|
|
222
|
+
ok,
|
|
223
|
+
...(ok ? {} : { error: tailOutput(res.stderr || res.stdout) || `exit ${res.code}` }),
|
|
224
|
+
});
|
|
225
|
+
if (!ok) {
|
|
226
|
+
return this.persist(workspaceId, stack, {
|
|
227
|
+
status: 'failed',
|
|
228
|
+
lastError: `Could not create network '${network}': ${tailOutput(res.stderr || res.stdout)}`,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
// Materialize env-file templates BEFORE `up`, each a logged step.
|
|
233
|
+
for (const envFile of stack.envFiles) {
|
|
234
|
+
const started = this.clock.now();
|
|
235
|
+
try {
|
|
236
|
+
await runtime.copyCheckoutFile(project, envFile.template, envFile.target);
|
|
237
|
+
await this.logStep(record, `env-file: ${envFile.target}`, started, { ok: true });
|
|
238
|
+
}
|
|
239
|
+
catch (err) {
|
|
240
|
+
const message = `Could not materialize env file '${envFile.target}': ${err instanceof Error ? err.message : String(err)}`;
|
|
241
|
+
await this.logStep(record, `env-file: ${envFile.target}`, started, {
|
|
242
|
+
ok: false,
|
|
243
|
+
error: message,
|
|
244
|
+
});
|
|
245
|
+
return this.persist(workspaceId, stack, { status: 'failed', lastError: message });
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// The stack runs its committed compose files AS AUTHORED (host ports kept — it is trusted infra,
|
|
249
|
+
// not an isolated per-PR preview). `--project-directory` is the first file's dir so its relative
|
|
250
|
+
// build contexts / binds / env_files resolve as written.
|
|
251
|
+
const composeDir = composeFileDir(stack.composeFiles[0]);
|
|
252
|
+
const projectDir = composeDir ? `${checkoutDir}/${composeDir}` : checkoutDir;
|
|
253
|
+
const files = stack.composeFiles.flatMap((f) => ['-f', `${checkoutDir}/${f}`]);
|
|
254
|
+
const scope = ['-p', project, '--project-directory', projectDir, ...files];
|
|
255
|
+
const env = stack.composeProfiles.length
|
|
256
|
+
? { COMPOSE_PROFILES: stack.composeProfiles.join(',') }
|
|
257
|
+
: {};
|
|
258
|
+
const upStarted = this.clock.now();
|
|
259
|
+
const up = await runtime.compose([...scope, 'up', '-d'], { env, timeoutMs: UP_TIMEOUT_MS });
|
|
260
|
+
const upOk = up.code === 0;
|
|
261
|
+
await this.logStep(record, 'compose up', upStarted, {
|
|
262
|
+
ok: upOk,
|
|
263
|
+
...(upOk ? {} : { error: tailOutput(up.stderr || up.stdout) }),
|
|
264
|
+
});
|
|
265
|
+
if (!upOk) {
|
|
266
|
+
return this.persist(workspaceId, stack, {
|
|
267
|
+
status: 'failed',
|
|
268
|
+
lastError: tailOutput(up.stderr || up.stdout) || 'docker compose up failed',
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
// Ordered setup steps (users sync, connector registration, seed import, …).
|
|
272
|
+
for (const step of stack.setupSteps) {
|
|
273
|
+
const started = this.clock.now();
|
|
274
|
+
const result = await runRecipeStep(step, { runtime, scope, env, project });
|
|
275
|
+
await this.logStep(record, step.name, started, result);
|
|
276
|
+
if (!result.ok) {
|
|
277
|
+
return this.persist(workspaceId, stack, {
|
|
278
|
+
status: 'failed',
|
|
279
|
+
lastError: `Setup step '${step.name}' failed: ${result.error}`,
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
// Terminal health gate.
|
|
284
|
+
const gate = stack.healthGate ?? DEFAULT_RECIPE_HEALTH_GATE;
|
|
285
|
+
const gateStarted = this.clock.now();
|
|
286
|
+
const gateResult = await runHealthGate(gate, { runtime, scope, env }, SHORT_TIMEOUT_MS);
|
|
287
|
+
await this.logStep(record, `health gate (${gate.kind})`, gateStarted, gateResult);
|
|
288
|
+
if (!gateResult.ok) {
|
|
289
|
+
return this.persist(workspaceId, stack, {
|
|
290
|
+
status: 'failed',
|
|
291
|
+
lastError: `Health gate did not pass: ${gateResult.error}`,
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
return this.persist(workspaceId, stack, { status: 'running', lastError: null });
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Refuse a stack's `host-command` setup steps unless it opted in (`allowHostCommands`) AND the
|
|
298
|
+
* runtime can run host commands. Returns a blocking message, or null when allowed / none declared.
|
|
299
|
+
*/
|
|
300
|
+
checkHostCommands(stack) {
|
|
301
|
+
if (!stack.setupSteps.some((s) => s.kind === 'host-command'))
|
|
302
|
+
return null;
|
|
303
|
+
if (!stack.allowHostCommands) {
|
|
304
|
+
return "This stack declares host-command step(s), but host commands are not enabled for it (set 'Allow host commands').";
|
|
305
|
+
}
|
|
306
|
+
if (!this.runtime?.hostCommand) {
|
|
307
|
+
return 'This stack declares host-command step(s), but the runtime cannot run host commands.';
|
|
308
|
+
}
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
/** Write a stack's lifecycle transition (status + lastError, bumping updatedAt) and return it. */
|
|
312
|
+
async persist(workspaceId, stack, change) {
|
|
313
|
+
const updated = {
|
|
314
|
+
...stack,
|
|
315
|
+
status: change.status,
|
|
316
|
+
lastError: change.lastError,
|
|
317
|
+
updatedAt: this.clock.now(),
|
|
318
|
+
};
|
|
319
|
+
await this.stacks.upsert(workspaceId, updated);
|
|
320
|
+
return updated;
|
|
321
|
+
}
|
|
322
|
+
/** Best-effort per-step provisioning-log entry (never throws; no-op when no recorder is wired). */
|
|
323
|
+
async logStep(record, name, startedAt, result) {
|
|
324
|
+
if (!record)
|
|
325
|
+
return;
|
|
326
|
+
try {
|
|
327
|
+
await record({
|
|
328
|
+
name,
|
|
329
|
+
outcome: result.ok ? 'success' : 'failure',
|
|
330
|
+
durationMs: this.clock.now() - startedAt,
|
|
331
|
+
...(result.detail ? { detail: result.detail } : {}),
|
|
332
|
+
...(result.error ? { error: result.error } : {}),
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
catch {
|
|
336
|
+
// best-effort: a log-write failure must never break the bring-up.
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
//# sourceMappingURL=SharedStackService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SharedStackService.js","sourceRoot":"","sources":["../../../src/modules/sharedStack/SharedStackService.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/integrations",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.70.0",
|
|
4
4
|
"description": "External-system integration domain logic for the Agent Architecture Board (GitHub, documents, tasks, environments, runners).",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"ai": "^6.0.219",
|
|
28
28
|
"yaml": "^2.9.0",
|
|
29
|
-
"@cat-factory/contracts": "0.
|
|
30
|
-
"@cat-factory/kernel": "0.
|
|
29
|
+
"@cat-factory/contracts": "0.103.0",
|
|
30
|
+
"@cat-factory/kernel": "0.94.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"typescript": "7.0.1-rc",
|