@cat-factory/integrations 0.38.1 → 0.40.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 +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/dist/modules/compose/ComposeEnvironmentProvider.d.ts +38 -0
- package/dist/modules/compose/ComposeEnvironmentProvider.d.ts.map +1 -0
- package/dist/modules/compose/ComposeEnvironmentProvider.js +260 -0
- package/dist/modules/compose/ComposeEnvironmentProvider.js.map +1 -0
- package/dist/modules/compose/compose-environment-backend.d.ts +5 -0
- package/dist/modules/compose/compose-environment-backend.d.ts.map +1 -0
- package/dist/modules/compose/compose-environment-backend.js +50 -0
- package/dist/modules/compose/compose-environment-backend.js.map +1 -0
- package/dist/modules/compose/compose-environment.logic.d.ts +155 -0
- package/dist/modules/compose/compose-environment.logic.d.ts.map +1 -0
- package/dist/modules/compose/compose-environment.logic.js +376 -0
- package/dist/modules/compose/compose-environment.logic.js.map +1 -0
- package/dist/modules/environments/EnvironmentProvisioningService.d.ts.map +1 -1
- package/dist/modules/environments/EnvironmentProvisioningService.js +5 -0
- package/dist/modules/environments/EnvironmentProvisioningService.js.map +1 -1
- package/dist/modules/environments/custom-manifest-types.d.ts +24 -0
- package/dist/modules/environments/custom-manifest-types.d.ts.map +1 -0
- package/dist/modules/environments/custom-manifest-types.js +41 -0
- package/dist/modules/environments/custom-manifest-types.js.map +1 -0
- package/dist/modules/environments/environment-backends.d.ts +20 -1
- package/dist/modules/environments/environment-backends.d.ts.map +1 -1
- package/dist/modules/environments/environment-backends.js +18 -0
- package/dist/modules/environments/environment-backends.js.map +1 -1
- package/dist/modules/environments/environments.logic.d.ts.map +1 -1
- package/dist/modules/environments/environments.logic.js +2 -0
- package/dist/modules/environments/environments.logic.js.map +1 -1
- package/dist/modules/environments/infra-handler.logic.d.ts +29 -0
- package/dist/modules/environments/infra-handler.logic.d.ts.map +1 -0
- package/dist/modules/environments/infra-handler.logic.js +43 -0
- package/dist/modules/environments/infra-handler.logic.js.map +1 -0
- package/dist/modules/kubernetes/kubernetes-environment-backend.d.ts.map +1 -1
- package/dist/modules/kubernetes/kubernetes-environment-backend.js +3 -0
- package/dist/modules/kubernetes/kubernetes-environment-backend.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import type { EnvironmentManifest, EnvironmentStatus } from '@cat-factory/kernel';
|
|
2
|
+
/** A single `docker compose` invocation result (exit code + captured output). */
|
|
3
|
+
export interface ComposeExecResult {
|
|
4
|
+
code: number;
|
|
5
|
+
stdout: string;
|
|
6
|
+
stderr: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The host seam the provider drives. A facade (local mode) implements it over the docker CLI
|
|
10
|
+
* + a host temp dir; the integrations package stays free of `node:*` so it remains
|
|
11
|
+
* runtime-neutral. `compose(args)` runs `docker compose <args>`; `writeProjectFile` persists a
|
|
12
|
+
* scratch file (the repo's compose file + the generated override) somewhere the daemon reads.
|
|
13
|
+
*/
|
|
14
|
+
export interface ComposeRuntime {
|
|
15
|
+
/**
|
|
16
|
+
* Run `docker compose <args>`; resolves with the exit code + captured stdout/stderr. `timeoutMs`
|
|
17
|
+
* bounds the invocation (a wedged daemon must not hang provision/status/teardown forever); the
|
|
18
|
+
* facade kills the child + surfaces a non-zero result when it elapses.
|
|
19
|
+
*/
|
|
20
|
+
compose(args: string[], opts?: {
|
|
21
|
+
env?: Record<string, string>;
|
|
22
|
+
timeoutMs?: number;
|
|
23
|
+
}): Promise<ComposeExecResult>;
|
|
24
|
+
/** Write a per-project scratch file; returns its absolute host path. */
|
|
25
|
+
writeProjectFile(project: string, fileName: string, content: string): Promise<string>;
|
|
26
|
+
/** Best-effort removal of a project's scratch dir after teardown. Optional. */
|
|
27
|
+
cleanupProject?(project: string): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
/** The flat per-workspace config, read off `manifest.providerConfig`. */
|
|
30
|
+
export interface ComposeEnvironmentConfig {
|
|
31
|
+
label: string;
|
|
32
|
+
/** Path to the compose file (co-located in the PR repo by default). */
|
|
33
|
+
composePath: string;
|
|
34
|
+
/** Read the compose file from a SEPARATE `owner/repo` instead of the PR repo. */
|
|
35
|
+
composeRepo?: string;
|
|
36
|
+
/** Ref to read the separate repo at; absent ⇒ that repo's default branch. */
|
|
37
|
+
composeRef?: string;
|
|
38
|
+
/** The compose service whose port is published + probed for the preview URL. */
|
|
39
|
+
service: string;
|
|
40
|
+
/** The in-container port to publish + probe. */
|
|
41
|
+
port: number;
|
|
42
|
+
/** URL scheme (default `http`). */
|
|
43
|
+
scheme?: 'http' | 'https';
|
|
44
|
+
/** Project-name template (default derived from repo + PR number / block id). */
|
|
45
|
+
projectTemplate?: string;
|
|
46
|
+
/** Optional image ref made available to the compose file as `{{image}}`. */
|
|
47
|
+
imageTemplate?: string;
|
|
48
|
+
/** Optional extra env passed to compose (templated), for `${VAR}` interpolation. */
|
|
49
|
+
envTemplate?: Record<string, string>;
|
|
50
|
+
/** Fallback TTL (ms) after which the env is swept + torn down. */
|
|
51
|
+
defaultTtlMs?: number;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Read the flat Compose config off the stored manifest's `providerConfig`. Validates the two
|
|
55
|
+
* load-bearing fields (service + port); throws a clear error otherwise. The connect form wrote
|
|
56
|
+
* these as strings (the generic descriptor overlay), so `port` is coerced from its string form.
|
|
57
|
+
*/
|
|
58
|
+
export declare function parseComposeEnvConfig(manifest: EnvironmentManifest): ComposeEnvironmentConfig;
|
|
59
|
+
/** Build the stored manifest that carries a Compose env config in its `providerConfig`. */
|
|
60
|
+
export declare function composeConfigToManifest(config: ComposeEnvironmentConfig): EnvironmentManifest;
|
|
61
|
+
/** Replace `{{ key }}` placeholders from `vars`; an unknown key resolves to ''. */
|
|
62
|
+
export declare function renderTemplate(template: string, vars: Record<string, string>): string;
|
|
63
|
+
/** Render every value of an env map through {@link renderTemplate}. */
|
|
64
|
+
export declare function renderEnvMap(env: Record<string, string>, vars: Record<string, string>): Record<string, string>;
|
|
65
|
+
/**
|
|
66
|
+
* Sanitize an arbitrary string into a valid Docker Compose project name: lower-case, only
|
|
67
|
+
* `[a-z0-9_-]`, must start with `[a-z0-9]`, bounded length. Mirrors the k8s namespace
|
|
68
|
+
* sanitize so two stacks can't collide on a malformed name.
|
|
69
|
+
*/
|
|
70
|
+
export declare function sanitizeProjectName(name: string): string;
|
|
71
|
+
/** A short, stable, filesystem-safe digest (djb2 → base36) used to disambiguate project names. */
|
|
72
|
+
export declare function shortHash(input: string): string;
|
|
73
|
+
/**
|
|
74
|
+
* Resolve the per-PR project name. An explicit `projectTemplate` is rendered + sanitized; else
|
|
75
|
+
* the default qualifies the PR number with the repo (a workspace can have many repos that each
|
|
76
|
+
* open a PR with the SAME number — a bare `cf-env-<pr>` would collide on one project and the
|
|
77
|
+
* second PR's `up`/`down` would hit the first's stack) AND, when known, a short digest of the
|
|
78
|
+
* globally-unique block id (so two DIFFERENT workspaces sharing a repo name + PR number on the
|
|
79
|
+
* same host can't collide either). It falls back to the block id, then a bare PR number, for a
|
|
80
|
+
* manual provision.
|
|
81
|
+
*/
|
|
82
|
+
export declare function resolveProjectName(config: ComposeEnvironmentConfig, inputs: Record<string, string>): string;
|
|
83
|
+
/** The `{{var}}` substitution map available to the compose text + env templates. */
|
|
84
|
+
export declare function templateVars(inputs: Record<string, string>, project: string, image: string | undefined): Record<string, string>;
|
|
85
|
+
type ComposeDoc = Record<string, unknown>;
|
|
86
|
+
/**
|
|
87
|
+
* Rewrite a single `ports` entry to its container-only (ephemeral host port) form, dropping any
|
|
88
|
+
* host ip / published host port. `"127.0.0.1:8080:8080"` / `"8080:8080"` / `{ published, target }`
|
|
89
|
+
* all collapse to `"8080"`; a protocol suffix is preserved. Returns null for an unparsable entry.
|
|
90
|
+
*/
|
|
91
|
+
export declare function toEphemeralPortEntry(entry: unknown): string | null;
|
|
92
|
+
/**
|
|
93
|
+
* Force every service's published host ports to ephemeral. Compose MERGES (`-f` overlays) and
|
|
94
|
+
* a base compose file usually pins the web service's host port (`"8080:8080"`) — leaving that in
|
|
95
|
+
* place makes concurrent per-PR stacks collide on one host port, defeating the project-name
|
|
96
|
+
* isolation. So instead of an additive override we rewrite the file: each service's host port is
|
|
97
|
+
* stripped, leaving the container port published to an ephemeral host port. Mutates + returns the doc.
|
|
98
|
+
*/
|
|
99
|
+
export declare function neutralizeHostPorts(doc: ComposeDoc): ComposeDoc;
|
|
100
|
+
/** Guarantee the probed service publishes `port`, so `docker compose port` can read the host binding back. */
|
|
101
|
+
export declare function ensureServicePublishes(doc: ComposeDoc, service: string, port: number): ComposeDoc;
|
|
102
|
+
/**
|
|
103
|
+
* Collect references this backend cannot honor or must refuse, so a provision fails fast with a
|
|
104
|
+
* clear reason instead of silently mis-mounting / over-privileging. The compose file is read
|
|
105
|
+
* checkout-free (no repo on disk), so anything resolved against the repo working tree is broken,
|
|
106
|
+
* and the stack runs on the operator's shared host daemon, so host access is a safety concern:
|
|
107
|
+
* - `build:` — needs the source tree (image-based stacks only).
|
|
108
|
+
* - host bind mounts — resolve against an empty scratch dir; also expose the host filesystem.
|
|
109
|
+
* - relative `env_file` — points into the absent repo tree.
|
|
110
|
+
* - `privileged: true` — refused on the shared host daemon.
|
|
111
|
+
*/
|
|
112
|
+
export declare function collectUnsupportedComposeRefs(doc: ComposeDoc): string[];
|
|
113
|
+
/** The outcome of preparing a repo compose file into a single isolation-safe project file. */
|
|
114
|
+
export interface PreparedCompose {
|
|
115
|
+
/** The rewritten compose file to hand to `docker compose -f` (valid even when `issues` is non-empty). */
|
|
116
|
+
content: string;
|
|
117
|
+
/** Blocking reasons the stack can't be provisioned as-is; non-empty ⇒ the provider fails the provision. */
|
|
118
|
+
issues: string[];
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Turn the (already `{{var}}`-rendered) repo compose text into ONE isolation-safe project file:
|
|
122
|
+
* validate it parses + contains the probed service, surface any unsupported references, force all
|
|
123
|
+
* host ports ephemeral, and guarantee the probed service publishes its port. Returning a single
|
|
124
|
+
* rewritten file (rather than a second `-f` overlay) is what lets us STRIP the base's pinned host
|
|
125
|
+
* ports — an overlay can only add, not remove.
|
|
126
|
+
*/
|
|
127
|
+
export declare function prepareComposeProject(renderedText: string, service: string, port: number): PreparedCompose;
|
|
128
|
+
/**
|
|
129
|
+
* Parse the host port out of `docker compose port <svc> <port>` output (e.g. `0.0.0.0:49153`
|
|
130
|
+
* or `[::]:49153`). Returns null when the service publishes no host port for that target.
|
|
131
|
+
*/
|
|
132
|
+
export declare function parseHostPort(output: string): number | null;
|
|
133
|
+
interface ComposePsRow {
|
|
134
|
+
State?: string;
|
|
135
|
+
Health?: string;
|
|
136
|
+
ExitCode?: number;
|
|
137
|
+
}
|
|
138
|
+
/** Parse `docker compose ps --format json` (a JSON array OR newline-delimited objects). */
|
|
139
|
+
export declare function parseComposePsRows(output: string): ComposePsRow[];
|
|
140
|
+
/**
|
|
141
|
+
* Reduce a `docker compose ps -a` snapshot (the `-a` includes stopped containers) into one
|
|
142
|
+
* lifecycle verdict:
|
|
143
|
+
* - empty ⇒ `failed` (the project is gone / never came up);
|
|
144
|
+
* - any `unhealthy` service, or a container `exited`/`dead` with a non-zero code ⇒ `failed`;
|
|
145
|
+
* - a transient state (`created`/`restarting`/`paused`/`removing`) or a `running` service still
|
|
146
|
+
* `starting` its healthcheck ⇒ `provisioning` (so a brief recreate doesn't flip a healthy env
|
|
147
|
+
* to `failed`);
|
|
148
|
+
* - a clean one-shot that `exited (0)` is treated as complete (neither pending nor failing);
|
|
149
|
+
* - otherwise ⇒ `ready`.
|
|
150
|
+
*/
|
|
151
|
+
export declare function classifyComposePs(output: string): EnvironmentStatus;
|
|
152
|
+
/** A short tail of command output, for a deterministic-failure `lastError`. */
|
|
153
|
+
export declare function tailOutput(output: string, lines?: number): string;
|
|
154
|
+
export {};
|
|
155
|
+
//# sourceMappingURL=compose-environment.logic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose-environment.logic.d.ts","sourceRoot":"","sources":["../../../src/modules/compose/compose-environment.logic.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
import { parse, stringify } from 'yaml';
|
|
2
|
+
const DEFAULT_COMPOSE_PATH = 'docker-compose.yml';
|
|
3
|
+
function optionalString(value) {
|
|
4
|
+
if (typeof value !== 'string')
|
|
5
|
+
return undefined;
|
|
6
|
+
const trimmed = value.trim();
|
|
7
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Read the flat Compose config off the stored manifest's `providerConfig`. Validates the two
|
|
11
|
+
* load-bearing fields (service + port); throws a clear error otherwise. The connect form wrote
|
|
12
|
+
* these as strings (the generic descriptor overlay), so `port` is coerced from its string form.
|
|
13
|
+
*/
|
|
14
|
+
export function parseComposeEnvConfig(manifest) {
|
|
15
|
+
const raw = (manifest.providerConfig ?? {});
|
|
16
|
+
const service = optionalString(raw.service);
|
|
17
|
+
if (!service) {
|
|
18
|
+
throw new Error('Docker Compose environment is missing the web service name (service)');
|
|
19
|
+
}
|
|
20
|
+
const port = Number(raw.port);
|
|
21
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
22
|
+
throw new Error(`Docker Compose environment has an invalid container port: ${String(raw.port)}`);
|
|
23
|
+
}
|
|
24
|
+
const scheme = raw.scheme === 'https' ? 'https' : 'http';
|
|
25
|
+
const envTemplate = raw.envTemplate && typeof raw.envTemplate === 'object'
|
|
26
|
+
? Object.fromEntries(Object.entries(raw.envTemplate).map(([k, val]) => [
|
|
27
|
+
k,
|
|
28
|
+
String(val),
|
|
29
|
+
]))
|
|
30
|
+
: undefined;
|
|
31
|
+
return {
|
|
32
|
+
label: manifest.label,
|
|
33
|
+
composePath: optionalString(raw.composePath) ?? DEFAULT_COMPOSE_PATH,
|
|
34
|
+
composeRepo: optionalString(raw.composeRepo),
|
|
35
|
+
composeRef: optionalString(raw.composeRef),
|
|
36
|
+
service,
|
|
37
|
+
port,
|
|
38
|
+
scheme,
|
|
39
|
+
projectTemplate: optionalString(raw.projectTemplate),
|
|
40
|
+
imageTemplate: optionalString(raw.imageTemplate),
|
|
41
|
+
envTemplate,
|
|
42
|
+
defaultTtlMs: resolveTtlMs(raw.ttlMinutes, manifest.defaultTtlMs),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Resolve the env's auto-teardown TTL (ms). The connect form collects it as `ttlMinutes` (a
|
|
47
|
+
* string) so a leaked compose project is swept off the host instead of running forever; a present
|
|
48
|
+
* `0`/blank/invalid value is an explicit "never expire" (undefined), and an absent field falls
|
|
49
|
+
* back to the manifest's own `defaultTtlMs`.
|
|
50
|
+
*/
|
|
51
|
+
function resolveTtlMs(rawTtlMinutes, manifestDefaultTtlMs) {
|
|
52
|
+
const ttlMinutes = optionalString(rawTtlMinutes);
|
|
53
|
+
if (ttlMinutes === undefined)
|
|
54
|
+
return manifestDefaultTtlMs;
|
|
55
|
+
const minutes = Number(ttlMinutes);
|
|
56
|
+
return Number.isFinite(minutes) && minutes > 0 ? Math.round(minutes * 60_000) : undefined;
|
|
57
|
+
}
|
|
58
|
+
/** Build the stored manifest that carries a Compose env config in its `providerConfig`. */
|
|
59
|
+
export function composeConfigToManifest(config) {
|
|
60
|
+
return {
|
|
61
|
+
providerId: 'compose',
|
|
62
|
+
label: config.label,
|
|
63
|
+
// Inert: the provider always returns a localhost URL, so baseUrl is never fetched and is
|
|
64
|
+
// not SSRF-checked. A placeholder keeps the manifest schema (which requires a non-empty
|
|
65
|
+
// baseUrl + provision + response) satisfied.
|
|
66
|
+
baseUrl: 'http://localhost',
|
|
67
|
+
auth: { type: 'none' },
|
|
68
|
+
provision: { method: 'POST', pathTemplate: '' },
|
|
69
|
+
response: {},
|
|
70
|
+
...(config.defaultTtlMs ? { defaultTtlMs: config.defaultTtlMs } : {}),
|
|
71
|
+
providerConfig: { ...config },
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/** Replace `{{ key }}` placeholders from `vars`; an unknown key resolves to ''. */
|
|
75
|
+
export function renderTemplate(template, vars) {
|
|
76
|
+
return template.replace(/\{\{\s*([a-zA-Z0-9_.]+)\s*\}\}/g, (_m, key) => vars[key] ?? '');
|
|
77
|
+
}
|
|
78
|
+
/** Render every value of an env map through {@link renderTemplate}. */
|
|
79
|
+
export function renderEnvMap(env, vars) {
|
|
80
|
+
return Object.fromEntries(Object.entries(env).map(([k, val]) => [k, renderTemplate(val, vars)]));
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Sanitize an arbitrary string into a valid Docker Compose project name: lower-case, only
|
|
84
|
+
* `[a-z0-9_-]`, must start with `[a-z0-9]`, bounded length. Mirrors the k8s namespace
|
|
85
|
+
* sanitize so two stacks can't collide on a malformed name.
|
|
86
|
+
*/
|
|
87
|
+
export function sanitizeProjectName(name) {
|
|
88
|
+
const cleaned = name
|
|
89
|
+
.toLowerCase()
|
|
90
|
+
.replace(/[^a-z0-9_-]+/g, '-')
|
|
91
|
+
.replace(/^[^a-z0-9]+/, '')
|
|
92
|
+
.replace(/-+$/g, '')
|
|
93
|
+
.slice(0, 63);
|
|
94
|
+
return cleaned.length > 0 ? cleaned : 'cf-env';
|
|
95
|
+
}
|
|
96
|
+
/** A short, stable, filesystem-safe digest (djb2 → base36) used to disambiguate project names. */
|
|
97
|
+
export function shortHash(input) {
|
|
98
|
+
let h = 5381;
|
|
99
|
+
for (let i = 0; i < input.length; i++)
|
|
100
|
+
h = ((h << 5) + h + input.charCodeAt(i)) >>> 0;
|
|
101
|
+
return h.toString(36).slice(0, 6);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Resolve the per-PR project name. An explicit `projectTemplate` is rendered + sanitized; else
|
|
105
|
+
* the default qualifies the PR number with the repo (a workspace can have many repos that each
|
|
106
|
+
* open a PR with the SAME number — a bare `cf-env-<pr>` would collide on one project and the
|
|
107
|
+
* second PR's `up`/`down` would hit the first's stack) AND, when known, a short digest of the
|
|
108
|
+
* globally-unique block id (so two DIFFERENT workspaces sharing a repo name + PR number on the
|
|
109
|
+
* same host can't collide either). It falls back to the block id, then a bare PR number, for a
|
|
110
|
+
* manual provision.
|
|
111
|
+
*/
|
|
112
|
+
export function resolveProjectName(config, inputs) {
|
|
113
|
+
if (config.projectTemplate) {
|
|
114
|
+
return sanitizeProjectName(renderTemplate(config.projectTemplate, inputs));
|
|
115
|
+
}
|
|
116
|
+
if (inputs.repoName && inputs.pullNumber) {
|
|
117
|
+
const base = `cf-env-${inputs.repoName}-${inputs.pullNumber}`;
|
|
118
|
+
return sanitizeProjectName(inputs.blockId ? `${base}-${shortHash(inputs.blockId)}` : base);
|
|
119
|
+
}
|
|
120
|
+
return sanitizeProjectName(`cf-env-${inputs.blockId || inputs.pullNumber || 'env'}`);
|
|
121
|
+
}
|
|
122
|
+
/** The `{{var}}` substitution map available to the compose text + env templates. */
|
|
123
|
+
export function templateVars(inputs, project, image) {
|
|
124
|
+
return { ...inputs, project, ...(image !== undefined ? { image } : {}) };
|
|
125
|
+
}
|
|
126
|
+
function servicesOf(doc) {
|
|
127
|
+
const services = doc.services;
|
|
128
|
+
if (!services || typeof services !== 'object')
|
|
129
|
+
return {};
|
|
130
|
+
return services;
|
|
131
|
+
}
|
|
132
|
+
function asArray(value) {
|
|
133
|
+
if (Array.isArray(value))
|
|
134
|
+
return value;
|
|
135
|
+
if (value === undefined || value === null)
|
|
136
|
+
return [];
|
|
137
|
+
return [value];
|
|
138
|
+
}
|
|
139
|
+
/** The container-target of a normalized (host-stripped) short-form ports entry: `"8080/tcp"` → `8080`. */
|
|
140
|
+
function portTarget(entry) {
|
|
141
|
+
return (entry.split('/')[0] ?? '').trim();
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Rewrite a single `ports` entry to its container-only (ephemeral host port) form, dropping any
|
|
145
|
+
* host ip / published host port. `"127.0.0.1:8080:8080"` / `"8080:8080"` / `{ published, target }`
|
|
146
|
+
* all collapse to `"8080"`; a protocol suffix is preserved. Returns null for an unparsable entry.
|
|
147
|
+
*/
|
|
148
|
+
export function toEphemeralPortEntry(entry) {
|
|
149
|
+
if (typeof entry === 'number')
|
|
150
|
+
return String(entry);
|
|
151
|
+
if (typeof entry === 'string') {
|
|
152
|
+
const [mapping, proto] = entry.split('/');
|
|
153
|
+
const segments = (mapping ?? '').split(':');
|
|
154
|
+
const target = segments[segments.length - 1]?.trim();
|
|
155
|
+
if (!target)
|
|
156
|
+
return null;
|
|
157
|
+
return proto ? `${target}/${proto}` : target;
|
|
158
|
+
}
|
|
159
|
+
if (entry && typeof entry === 'object') {
|
|
160
|
+
const e = entry;
|
|
161
|
+
if (e.target === undefined || e.target === null)
|
|
162
|
+
return null;
|
|
163
|
+
const proto = typeof e.protocol === 'string' ? e.protocol : undefined;
|
|
164
|
+
return proto ? `${String(e.target)}/${proto}` : String(e.target);
|
|
165
|
+
}
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Force every service's published host ports to ephemeral. Compose MERGES (`-f` overlays) and
|
|
170
|
+
* a base compose file usually pins the web service's host port (`"8080:8080"`) — leaving that in
|
|
171
|
+
* place makes concurrent per-PR stacks collide on one host port, defeating the project-name
|
|
172
|
+
* isolation. So instead of an additive override we rewrite the file: each service's host port is
|
|
173
|
+
* stripped, leaving the container port published to an ephemeral host port. Mutates + returns the doc.
|
|
174
|
+
*/
|
|
175
|
+
export function neutralizeHostPorts(doc) {
|
|
176
|
+
for (const service of Object.values(servicesOf(doc))) {
|
|
177
|
+
if (!service || typeof service !== 'object' || !Array.isArray(service.ports))
|
|
178
|
+
continue;
|
|
179
|
+
service.ports = service.ports.map(toEphemeralPortEntry).filter((p) => p !== null);
|
|
180
|
+
}
|
|
181
|
+
return doc;
|
|
182
|
+
}
|
|
183
|
+
/** Guarantee the probed service publishes `port`, so `docker compose port` can read the host binding back. */
|
|
184
|
+
export function ensureServicePublishes(doc, service, port) {
|
|
185
|
+
const svc = servicesOf(doc)[service];
|
|
186
|
+
if (!svc || typeof svc !== 'object')
|
|
187
|
+
return doc;
|
|
188
|
+
const ports = Array.isArray(svc.ports) ? svc.ports.map(String) : [];
|
|
189
|
+
svc.ports = ports.some((p) => portTarget(p) === String(port)) ? ports : [...ports, String(port)];
|
|
190
|
+
return doc;
|
|
191
|
+
}
|
|
192
|
+
function isRelativePath(path) {
|
|
193
|
+
return !path.startsWith('/') && !/^[a-zA-Z]:[\\/]/.test(path);
|
|
194
|
+
}
|
|
195
|
+
function bindMountSource(volume) {
|
|
196
|
+
if (typeof volume === 'string') {
|
|
197
|
+
const segments = volume.split(':');
|
|
198
|
+
if (segments.length < 2)
|
|
199
|
+
return null; // anonymous volume (`/data`) — a container path, not a host bind
|
|
200
|
+
const source = segments[0] ?? '';
|
|
201
|
+
return source.startsWith('.') || source.startsWith('/') || source.startsWith('~')
|
|
202
|
+
? source
|
|
203
|
+
: null;
|
|
204
|
+
}
|
|
205
|
+
if (volume && typeof volume === 'object') {
|
|
206
|
+
const v = volume;
|
|
207
|
+
if (v.type === 'bind')
|
|
208
|
+
return typeof v.source === 'string' ? v.source : 'bind';
|
|
209
|
+
if (v.type === undefined && typeof v.source === 'string') {
|
|
210
|
+
const s = v.source;
|
|
211
|
+
return s.startsWith('.') || s.startsWith('/') || s.startsWith('~') ? s : null;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Collect references this backend cannot honor or must refuse, so a provision fails fast with a
|
|
218
|
+
* clear reason instead of silently mis-mounting / over-privileging. The compose file is read
|
|
219
|
+
* checkout-free (no repo on disk), so anything resolved against the repo working tree is broken,
|
|
220
|
+
* and the stack runs on the operator's shared host daemon, so host access is a safety concern:
|
|
221
|
+
* - `build:` — needs the source tree (image-based stacks only).
|
|
222
|
+
* - host bind mounts — resolve against an empty scratch dir; also expose the host filesystem.
|
|
223
|
+
* - relative `env_file` — points into the absent repo tree.
|
|
224
|
+
* - `privileged: true` — refused on the shared host daemon.
|
|
225
|
+
*/
|
|
226
|
+
export function collectUnsupportedComposeRefs(doc) {
|
|
227
|
+
const issues = [];
|
|
228
|
+
for (const [name, service] of Object.entries(servicesOf(doc))) {
|
|
229
|
+
if (!service || typeof service !== 'object')
|
|
230
|
+
continue;
|
|
231
|
+
if (service.build !== undefined) {
|
|
232
|
+
issues.push(`service '${name}' uses build: — image-based stacks only (no repo is checked out)`);
|
|
233
|
+
}
|
|
234
|
+
if (service.privileged === true) {
|
|
235
|
+
issues.push(`service '${name}' requests privileged: true — refused on the shared host daemon`);
|
|
236
|
+
}
|
|
237
|
+
for (const volume of asArray(service.volumes)) {
|
|
238
|
+
const source = bindMountSource(volume);
|
|
239
|
+
if (source !== null) {
|
|
240
|
+
issues.push(`service '${name}' bind-mounts a host path ('${source}') — unsupported (no repo on disk; use a named volume)`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
for (const entry of asArray(service.env_file)) {
|
|
244
|
+
const path = typeof entry === 'string' ? entry : entry?.path;
|
|
245
|
+
if (typeof path === 'string' && isRelativePath(path)) {
|
|
246
|
+
issues.push(`service '${name}' reads a relative env_file ('${path}') — unsupported (no repo on disk)`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return issues;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Turn the (already `{{var}}`-rendered) repo compose text into ONE isolation-safe project file:
|
|
254
|
+
* validate it parses + contains the probed service, surface any unsupported references, force all
|
|
255
|
+
* host ports ephemeral, and guarantee the probed service publishes its port. Returning a single
|
|
256
|
+
* rewritten file (rather than a second `-f` overlay) is what lets us STRIP the base's pinned host
|
|
257
|
+
* ports — an overlay can only add, not remove.
|
|
258
|
+
*/
|
|
259
|
+
export function prepareComposeProject(renderedText, service, port) {
|
|
260
|
+
let parsed;
|
|
261
|
+
try {
|
|
262
|
+
parsed = parse(renderedText);
|
|
263
|
+
}
|
|
264
|
+
catch (err) {
|
|
265
|
+
return {
|
|
266
|
+
content: renderedText,
|
|
267
|
+
issues: [
|
|
268
|
+
`compose file is not valid YAML: ${err instanceof Error ? err.message : String(err)}`,
|
|
269
|
+
],
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
273
|
+
return { content: renderedText, issues: ['compose file is empty or not a mapping'] };
|
|
274
|
+
}
|
|
275
|
+
const doc = parsed;
|
|
276
|
+
if (!servicesOf(doc)[service]) {
|
|
277
|
+
return { content: renderedText, issues: [`compose file has no service named '${service}'`] };
|
|
278
|
+
}
|
|
279
|
+
const issues = collectUnsupportedComposeRefs(doc);
|
|
280
|
+
neutralizeHostPorts(doc);
|
|
281
|
+
ensureServicePublishes(doc, service, port);
|
|
282
|
+
return { content: stringify(doc), issues };
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Parse the host port out of `docker compose port <svc> <port>` output (e.g. `0.0.0.0:49153`
|
|
286
|
+
* or `[::]:49153`). Returns null when the service publishes no host port for that target.
|
|
287
|
+
*/
|
|
288
|
+
export function parseHostPort(output) {
|
|
289
|
+
const line = output
|
|
290
|
+
.split('\n')
|
|
291
|
+
.map((s) => s.trim())
|
|
292
|
+
.filter(Boolean)
|
|
293
|
+
.pop();
|
|
294
|
+
if (!line)
|
|
295
|
+
return null;
|
|
296
|
+
const match = line.match(/:(\d+)\s*$/);
|
|
297
|
+
if (!match)
|
|
298
|
+
return null;
|
|
299
|
+
const n = Number(match[1]);
|
|
300
|
+
return Number.isInteger(n) && n > 0 && n <= 65535 ? n : null;
|
|
301
|
+
}
|
|
302
|
+
/** Parse `docker compose ps --format json` (a JSON array OR newline-delimited objects). */
|
|
303
|
+
export function parseComposePsRows(output) {
|
|
304
|
+
const trimmed = output.trim();
|
|
305
|
+
if (!trimmed)
|
|
306
|
+
return [];
|
|
307
|
+
try {
|
|
308
|
+
const parsed = JSON.parse(trimmed);
|
|
309
|
+
if (Array.isArray(parsed))
|
|
310
|
+
return parsed;
|
|
311
|
+
return [parsed];
|
|
312
|
+
}
|
|
313
|
+
catch {
|
|
314
|
+
// Newline-delimited JSON objects (older compose).
|
|
315
|
+
const rows = [];
|
|
316
|
+
for (const line of trimmed.split('\n')) {
|
|
317
|
+
const s = line.trim();
|
|
318
|
+
if (!s)
|
|
319
|
+
continue;
|
|
320
|
+
try {
|
|
321
|
+
rows.push(JSON.parse(s));
|
|
322
|
+
}
|
|
323
|
+
catch {
|
|
324
|
+
// ignore an unparsable line
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return rows;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Reduce a `docker compose ps -a` snapshot (the `-a` includes stopped containers) into one
|
|
332
|
+
* lifecycle verdict:
|
|
333
|
+
* - empty ⇒ `failed` (the project is gone / never came up);
|
|
334
|
+
* - any `unhealthy` service, or a container `exited`/`dead` with a non-zero code ⇒ `failed`;
|
|
335
|
+
* - a transient state (`created`/`restarting`/`paused`/`removing`) or a `running` service still
|
|
336
|
+
* `starting` its healthcheck ⇒ `provisioning` (so a brief recreate doesn't flip a healthy env
|
|
337
|
+
* to `failed`);
|
|
338
|
+
* - a clean one-shot that `exited (0)` is treated as complete (neither pending nor failing);
|
|
339
|
+
* - otherwise ⇒ `ready`.
|
|
340
|
+
*/
|
|
341
|
+
export function classifyComposePs(output) {
|
|
342
|
+
const rows = parseComposePsRows(output);
|
|
343
|
+
if (rows.length === 0)
|
|
344
|
+
return 'failed'; // nothing left ⇒ the stack is gone/crashed
|
|
345
|
+
let anyPending = false;
|
|
346
|
+
for (const row of rows) {
|
|
347
|
+
const state = (row.State ?? '').toLowerCase();
|
|
348
|
+
const health = (row.Health ?? '').toLowerCase();
|
|
349
|
+
if (health === 'unhealthy')
|
|
350
|
+
return 'failed';
|
|
351
|
+
if (state.startsWith('running')) {
|
|
352
|
+
if (health === 'starting')
|
|
353
|
+
anyPending = true;
|
|
354
|
+
}
|
|
355
|
+
else if (state.startsWith('exited') || state.startsWith('dead')) {
|
|
356
|
+
if ((row.ExitCode ?? 0) !== 0)
|
|
357
|
+
return 'failed'; // a real crash
|
|
358
|
+
// exit 0 ⇒ a completed one-shot (migration/seed); not pending, not a failure
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
// created / restarting / paused / removing / … ⇒ still settling
|
|
362
|
+
anyPending = true;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return anyPending ? 'provisioning' : 'ready';
|
|
366
|
+
}
|
|
367
|
+
/** A short tail of command output, for a deterministic-failure `lastError`. */
|
|
368
|
+
export function tailOutput(output, lines = 12) {
|
|
369
|
+
return output
|
|
370
|
+
.split('\n')
|
|
371
|
+
.map((s) => s.trimEnd())
|
|
372
|
+
.filter(Boolean)
|
|
373
|
+
.slice(-lines)
|
|
374
|
+
.join('\n');
|
|
375
|
+
}
|
|
376
|
+
//# sourceMappingURL=compose-environment.logic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose-environment.logic.js","sourceRoot":"","sources":["../../../src/modules/compose/compose-environment.logic.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EnvironmentProvisioningService.d.ts","sourceRoot":"","sources":["../../../src/modules/environments/EnvironmentProvisioningService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,KAAK,EAAqB,6BAA6B,EAAE,MAAM,qBAAqB,CAAA;AAC3F,OAAO,KAAK,EAGV,gBAAgB,EAEhB,qBAAqB,EACrB,cAAc,EAEd,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,KAAK,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAErF,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAA;AAMrF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gDAAgD,CAAA;AAO7F,MAAM,WAAW,0CAA0C;IACzD,iBAAiB,EAAE,4BAA4B,CAAA;IAC/C,6BAA6B,EAAE,6BAA6B,CAAA;IAC5D,YAAY,EAAE,YAAY,CAAA;IAC1B,WAAW,EAAE,WAAW,CAAA;IACxB,KAAK,EAAE,KAAK,CAAA;IACZ,wFAAwF;IACxF,SAAS,CAAC,EAAE,eAAe,CAAA;IAC3B,8EAA8E;IAC9E,eAAe,CAAC,EAAE,uBAAuB,CAAA;IACzC;;;;;;OAMG;IACH,qBAAqB,CAAC,EAAE,qBAAqB,CAAA;IAC7C;;;;OAIG;IACH,4BAA4B,CAAC,EAAE,CAC7B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;KAAE,KACpE,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;CACpC;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,qFAAqF;IACrF,OAAO,CAAC,EAAE,gBAAgB,CAAA;CAC3B;AAYD,2EAA2E;AAC3E,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,MAAM,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IACnC,MAAM,EAAE,uBAAuB,GAAG,IAAI,CAAA;IACtC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED,qBAAa,8BAA8B;IAC7B,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,0CAA0C,EAAI;IAEjF,OAAO,KAAK,SAAS,GAEpB;IAED,mFAAmF;IAC7E,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,iBAAiB,CAAC,
|
|
1
|
+
{"version":3,"file":"EnvironmentProvisioningService.d.ts","sourceRoot":"","sources":["../../../src/modules/environments/EnvironmentProvisioningService.ts"],"names":[],"mappings":"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"}
|
|
@@ -108,6 +108,9 @@ export class EnvironmentProvisioningService {
|
|
|
108
108
|
// deployer step's Environment panel shows the actual root cause; fall back only when the
|
|
109
109
|
// provider gave none.
|
|
110
110
|
lastError: provisioned.status === 'failed' ? provisioned.error?.trim() || 'Provisioning failed' : null,
|
|
111
|
+
// Recorded by the deployer step once per-service provision types land (slice 3).
|
|
112
|
+
provisionType: null,
|
|
113
|
+
engine: null,
|
|
111
114
|
});
|
|
112
115
|
await this.deps.environmentRegistryRepository.insert(record);
|
|
113
116
|
// A provider that returns `status:'failed'` (rather than throwing) is still a
|
|
@@ -308,6 +311,8 @@ export class EnvironmentProvisioningService {
|
|
|
308
311
|
createdAt: this.deps.clock.now(),
|
|
309
312
|
expiresAt: null,
|
|
310
313
|
lastError,
|
|
314
|
+
provisionType: null,
|
|
315
|
+
engine: null,
|
|
311
316
|
});
|
|
312
317
|
await this.deps.environmentRegistryRepository.insert(record);
|
|
313
318
|
}
|