@oktis-works/cms 0.1.14 → 0.2.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/assets.d.ts +94 -0
- package/dist/assets.d.ts.map +1 -0
- package/dist/assets.js +671 -0
- package/dist/assets.js.map +1 -0
- package/dist/bluegreen.d.ts +121 -0
- package/dist/bluegreen.d.ts.map +1 -0
- package/dist/bluegreen.js +393 -0
- package/dist/bluegreen.js.map +1 -0
- package/dist/commands.d.ts +6 -0
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +116 -61
- package/dist/commands.js.map +1 -1
- package/dist/config-wizard.d.ts +39 -0
- package/dist/config-wizard.d.ts.map +1 -0
- package/dist/config-wizard.js +308 -0
- package/dist/config-wizard.js.map +1 -0
- package/dist/docker.d.ts +148 -0
- package/dist/docker.d.ts.map +1 -0
- package/dist/docker.js +324 -0
- package/dist/docker.js.map +1 -0
- package/dist/doctor.d.ts +2 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +51 -0
- package/dist/doctor.js.map +1 -1
- package/dist/env-file.d.ts +45 -0
- package/dist/env-file.d.ts.map +1 -0
- package/dist/env-file.js +200 -0
- package/dist/env-file.js.map +1 -0
- package/dist/env-schema.d.ts +28 -0
- package/dist/env-schema.d.ts.map +1 -0
- package/dist/env-schema.js +497 -0
- package/dist/env-schema.js.map +1 -0
- package/dist/guards.d.ts +40 -0
- package/dist/guards.d.ts.map +1 -0
- package/dist/guards.js +159 -0
- package/dist/guards.js.map +1 -0
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +12 -3
- package/dist/parser.js.map +1 -1
- package/dist/project-config.js +2 -2
- package/dist/prompt.d.ts +81 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +379 -0
- package/dist/prompt.js.map +1 -0
- package/dist/redeploy.d.ts +109 -0
- package/dist/redeploy.d.ts.map +1 -0
- package/dist/redeploy.js +363 -0
- package/dist/redeploy.js.map +1 -0
- package/dist/scaffold-docs.d.ts +25 -6
- package/dist/scaffold-docs.d.ts.map +1 -1
- package/dist/scaffold-docs.js +711 -33
- package/dist/scaffold-docs.js.map +1 -1
- package/dist/scaffold.d.ts +17 -1
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/scaffold.js +77 -14
- package/dist/scaffold.js.map +1 -1
- package/dist/theme-build.d.ts +35 -0
- package/dist/theme-build.d.ts.map +1 -0
- package/dist/theme-build.js +86 -0
- package/dist/theme-build.js.map +1 -0
- package/dist/update.d.ts +51 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +210 -0
- package/dist/update.js.map +1 -0
- package/package.json +7 -7
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { type Lane } from './assets.js';
|
|
2
|
+
import { type Runner } from './docker.js';
|
|
3
|
+
/** O que o operador escolheu no wizard (ou que as flags decidiram). */
|
|
4
|
+
export interface DeployChoices {
|
|
5
|
+
/** `docker compose build --no-cache` — build limpo, mais lento. */
|
|
6
|
+
noCache: boolean;
|
|
7
|
+
/** `down --remove-orphans` na lane antiga. */
|
|
8
|
+
removeOrphans: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface DeployOptions {
|
|
11
|
+
cwd?: string;
|
|
12
|
+
runner?: Runner;
|
|
13
|
+
log?: (message: string) => void;
|
|
14
|
+
warn?: (message: string) => void;
|
|
15
|
+
/** `pkg@latest` a instalar no host antes do build (vem do scan do update). */
|
|
16
|
+
packages?: string[];
|
|
17
|
+
/**
|
|
18
|
+
* Projeto sem `node_modules` (clone novo): roda `bun install` no passo de
|
|
19
|
+
* pacotes em vez de `bun add` — o `db:migrate` do host precisa das deps.
|
|
20
|
+
*/
|
|
21
|
+
installAll?: boolean;
|
|
22
|
+
choices: DeployChoices;
|
|
23
|
+
/**
|
|
24
|
+
* Verificação final pelo proxy (porta 80). Falha aqui é AVISO, não rollback:
|
|
25
|
+
* o gate autoritativo é o healthcheck de cada contêiner da lane, feito
|
|
26
|
+
* dentro da rede antes do swap.
|
|
27
|
+
*/
|
|
28
|
+
healthProbe?: (url: string) => Promise<boolean>;
|
|
29
|
+
/**
|
|
30
|
+
* Timeouts por passo. Exposto para os testes rodarem em milissegundos —
|
|
31
|
+
* em produção os defaults de 3 min é o que cabe um pull de imagem fria.
|
|
32
|
+
*/
|
|
33
|
+
timeouts?: DeployTimeouts;
|
|
34
|
+
}
|
|
35
|
+
export interface DeployTimeouts {
|
|
36
|
+
/** healthcheck de postgres/redis (puxa imagem no primeiro deploy). */
|
|
37
|
+
dataMs?: number;
|
|
38
|
+
/** healthcheck dos contêineres de edge da lane nova. */
|
|
39
|
+
edgeMs?: number;
|
|
40
|
+
/** espera do SIGTERM do worker antigo (depois do stop_grace_period). */
|
|
41
|
+
stopMs?: number;
|
|
42
|
+
/** intervalo de sondagem em geral. */
|
|
43
|
+
intervalMs?: number;
|
|
44
|
+
}
|
|
45
|
+
export declare const DEFAULT_TIMEOUTS: Required<DeployTimeouts>;
|
|
46
|
+
export interface DeployResult {
|
|
47
|
+
ok: boolean;
|
|
48
|
+
/** Lane servindo ao final. Em falha, a lane que continuou no ar. */
|
|
49
|
+
lane: Lane;
|
|
50
|
+
previousLane: Lane | null;
|
|
51
|
+
/** Arquivos de deploy criados neste passo (nunca sobrescreve os existentes). */
|
|
52
|
+
created: string[];
|
|
53
|
+
message?: string;
|
|
54
|
+
}
|
|
55
|
+
export declare const EDGE_SERVICE: (lane: Lane) => string[];
|
|
56
|
+
export declare const WORKER_SERVICE: (lane: Lane) => string;
|
|
57
|
+
/** URL final da checagem através do proxy. */
|
|
58
|
+
export declare const FINAL_HEALTH_URL = "http://127.0.0.1/health";
|
|
59
|
+
export declare function loadDeployEnv(cwd: string): Record<string, string>;
|
|
60
|
+
/**
|
|
61
|
+
* Grava os arquivos de deploy que faltarem, preservando os que já existem.
|
|
62
|
+
*
|
|
63
|
+
* Não decide nada sobre estado: quem chama diz a `lane` inicial. Isso é o que
|
|
64
|
+
* permite o `okcms init` usá-lo sem tocar no Docker (o `ensureDeployFiles` do
|
|
65
|
+
* deploy, logo abaixo, é que consulta a lane ativa).
|
|
66
|
+
*/
|
|
67
|
+
export declare function writeDeployAssets(cwd: string, lane: Lane, record: Record<string, string>): string[];
|
|
68
|
+
/**
|
|
69
|
+
* Cria os arquivos de deploy que faltarem, preservando os que já existem.
|
|
70
|
+
* Um projeto anterior ao deploy-in-Docker ganha os arquivos aqui mesmo —
|
|
71
|
+
* pedir que o operador rode um outro comando só para criar config é atrito.
|
|
72
|
+
* A lane ativa vem do estado salvo (ou do Docker, em último caso).
|
|
73
|
+
*/
|
|
74
|
+
export declare function ensureDeployFiles(cwd: string, record?: Record<string, string>, runner?: Runner): string[];
|
|
75
|
+
export interface LaneServices {
|
|
76
|
+
edge: string[];
|
|
77
|
+
worker: string[];
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Nomes de serviço da lane, lidos do compose real.
|
|
81
|
+
*
|
|
82
|
+
* O fallback só existe para o caso de o arquivo ter sido editado até sumir os
|
|
83
|
+
* papéis — aí as convenções `api-<lane>` seguram o fluxo em vez de explodir
|
|
84
|
+
* no meio de um deploy.
|
|
85
|
+
*/
|
|
86
|
+
export declare function laneServices(cwd: string, lane: Lane): LaneServices;
|
|
87
|
+
export interface PreflightResult {
|
|
88
|
+
ok: boolean;
|
|
89
|
+
message?: string;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Tudo o que precisa ser verdade ANTES de qualquer `docker compose up`.
|
|
93
|
+
* Fazer isso no meio do fluxo deixaria o projeto com a rede criada, a infra
|
|
94
|
+
* no ar e a build parada — pior do que não ter começado.
|
|
95
|
+
*/
|
|
96
|
+
export declare function preflight(runner?: Runner): PreflightResult;
|
|
97
|
+
export declare const workerContainer: (lane: Lane) => string;
|
|
98
|
+
export declare const edgeContainerNames: (lane: Lane) => string[];
|
|
99
|
+
export interface LaneContainers {
|
|
100
|
+
edge: string[];
|
|
101
|
+
worker: string[];
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Nomes de CONTAINER (não de serviço) da lane, lidos do compose quando
|
|
105
|
+
* possível: é o que o `docker inspect` entende no healthcheck e no dreno.
|
|
106
|
+
*/
|
|
107
|
+
export declare function laneContainers(cwd: string, lane: Lane): LaneContainers;
|
|
108
|
+
/**
|
|
109
|
+
* Como invocar o próprio `okcms db:migrate`.
|
|
110
|
+
*
|
|
111
|
+
* Reexecuta o MESMO binário que está rodando (argv[1]) em vez de depender de
|
|
112
|
+
* PATH/npx: o caminho do projeto instalado é o único que tem as migrations e
|
|
113
|
+
* o `.env` certos, e o host é onde elas devem correr (o container não tem a
|
|
114
|
+
* CLI, por construção).
|
|
115
|
+
*/
|
|
116
|
+
export declare function migrateInvocation(): {
|
|
117
|
+
command: string;
|
|
118
|
+
args: string[];
|
|
119
|
+
};
|
|
120
|
+
export declare function deployBlueGreen(opts: DeployOptions): Promise<DeployResult>;
|
|
121
|
+
//# sourceMappingURL=bluegreen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bluegreen.d.ts","sourceRoot":"","sources":["../src/bluegreen.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
// @oktis-works/cms - Deploy blue/green (F3)
|
|
2
|
+
//
|
|
3
|
+
// O contrato de ordem é o produto deste arquivo. Cada passo existe porque
|
|
4
|
+
// inverter a ordem quebra alguma coisa concreta:
|
|
5
|
+
//
|
|
6
|
+
// 1. arquivos de deploy → sem docker-compose.deploy.yml não há o que subir
|
|
7
|
+
// 2. preflight → docker/compose ausente detectado ANTES de mexer
|
|
8
|
+
// 3. rede + infra → a lane depende de okcms-net, postgres e redis
|
|
9
|
+
// 4. pacotes no host → o db:migrate do passo 6 roda com o pacote novo
|
|
10
|
+
// 5. build da lane nova → imagem nova ainda sem tráfego
|
|
11
|
+
// 6. db:migrate NO HOST → entre build e tráfego; falhou = nada mudou
|
|
12
|
+
// 7. sobe edge da lane → contêineres prontos antes do proxy apontar
|
|
13
|
+
// 8. healthcheck → gate real do blue/green: falhou = rollback
|
|
14
|
+
// 9. swap do nginx → 3 linhas + `nginx -s reload` (conexões vivas)
|
|
15
|
+
// 10. drena worker antigo → SIGTERM + stop_grace_period, ANTES do novo subir
|
|
16
|
+
// 11. sobe worker novo → nunca duas filas consumindo ao mesmo tempo
|
|
17
|
+
// 12. derruba lane antiga → `down` SEM -v: o volume de mídia é compartilhado
|
|
18
|
+
//
|
|
19
|
+
// A CLI NUNCA roda dentro do container (ver `assertHostOnly`): o deploy é
|
|
20
|
+
// sempre a partir do host, contra o socket do Docker local.
|
|
21
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
22
|
+
import { dirname, join } from 'node:path';
|
|
23
|
+
import { deployAssets, portsFromEnv } from './assets.js';
|
|
24
|
+
import { COMPOSE_DEPLOY_FILE, classifyServices, composeAvailable, defaultRunner, detectActiveLane, dockerAvailable, ensureNetwork, infraCompose, isHealthy, laneCompose, otherLane, parseComposeServices, pushLaneState, readLaneState, readUpstreamsLane, reloadProxy, restartProxy, waitStopped, waitForContainer, writeLaneState, writeUpstreams, } from './docker.js';
|
|
25
|
+
import { loadEnvFile } from './env-file.js';
|
|
26
|
+
export const DEFAULT_TIMEOUTS = {
|
|
27
|
+
dataMs: 180_000,
|
|
28
|
+
edgeMs: 180_000,
|
|
29
|
+
stopMs: 60_000,
|
|
30
|
+
intervalMs: 2_000,
|
|
31
|
+
};
|
|
32
|
+
export const EDGE_SERVICE = (lane) => [
|
|
33
|
+
`api-${lane}`,
|
|
34
|
+
`web-${lane}`,
|
|
35
|
+
`admin-${lane}`,
|
|
36
|
+
];
|
|
37
|
+
export const WORKER_SERVICE = (lane) => `worker-${lane}`;
|
|
38
|
+
/** URL final da checagem através do proxy. */
|
|
39
|
+
export const FINAL_HEALTH_URL = 'http://127.0.0.1/health';
|
|
40
|
+
async function defaultHealthProbe(url) {
|
|
41
|
+
const controller = new AbortController();
|
|
42
|
+
const timer = setTimeout(() => controller.abort(), 5_000);
|
|
43
|
+
try {
|
|
44
|
+
const response = await fetch(url, { signal: controller.signal });
|
|
45
|
+
return response.ok;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
clearTimeout(timer);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// Arquivos de deploy
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
export function loadDeployEnv(cwd) {
|
|
58
|
+
return loadEnvFile(join(cwd, '.env')).toRecord();
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Grava os arquivos de deploy que faltarem, preservando os que já existem.
|
|
62
|
+
*
|
|
63
|
+
* Não decide nada sobre estado: quem chama diz a `lane` inicial. Isso é o que
|
|
64
|
+
* permite o `okcms init` usá-lo sem tocar no Docker (o `ensureDeployFiles` do
|
|
65
|
+
* deploy, logo abaixo, é que consulta a lane ativa).
|
|
66
|
+
*/
|
|
67
|
+
export function writeDeployAssets(cwd, lane, record) {
|
|
68
|
+
const created = [];
|
|
69
|
+
for (const asset of deployAssets(lane, portsFromEnv(record))) {
|
|
70
|
+
const path = join(cwd, asset.path);
|
|
71
|
+
if (existsSync(path))
|
|
72
|
+
continue;
|
|
73
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
74
|
+
writeFileSync(path, asset.content, { encoding: 'utf-8', mode: asset.mode ?? 0o644 });
|
|
75
|
+
created.push(asset.path);
|
|
76
|
+
}
|
|
77
|
+
return created;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Cria os arquivos de deploy que faltarem, preservando os que já existem.
|
|
81
|
+
* Um projeto anterior ao deploy-in-Docker ganha os arquivos aqui mesmo —
|
|
82
|
+
* pedir que o operador rode um outro comando só para criar config é atrito.
|
|
83
|
+
* A lane ativa vem do estado salvo (ou do Docker, em último caso).
|
|
84
|
+
*/
|
|
85
|
+
export function ensureDeployFiles(cwd, record = loadDeployEnv(cwd), runner) {
|
|
86
|
+
const active = detectActiveLane(cwd, runner);
|
|
87
|
+
return writeDeployAssets(cwd, active ?? 'blue', record);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Nomes de serviço da lane, lidos do compose real.
|
|
91
|
+
*
|
|
92
|
+
* O fallback só existe para o caso de o arquivo ter sido editado até sumir os
|
|
93
|
+
* papéis — aí as convenções `api-<lane>` seguram o fluxo em vez de explodir
|
|
94
|
+
* no meio de um deploy.
|
|
95
|
+
*/
|
|
96
|
+
export function laneServices(cwd, lane) {
|
|
97
|
+
const file = join(cwd, COMPOSE_DEPLOY_FILE);
|
|
98
|
+
if (existsSync(file)) {
|
|
99
|
+
const parsed = classifyServices(parseComposeServices(readFileSync(file, 'utf-8')), lane);
|
|
100
|
+
if (parsed.edge.length > 0 || parsed.worker.length > 0) {
|
|
101
|
+
return {
|
|
102
|
+
edge: parsed.edge.map((service) => service.name),
|
|
103
|
+
worker: parsed.worker.map((service) => service.name),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return { edge: EDGE_SERVICE(lane), worker: [WORKER_SERVICE(lane)] };
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Tudo o que precisa ser verdade ANTES de qualquer `docker compose up`.
|
|
111
|
+
* Fazer isso no meio do fluxo deixaria o projeto com a rede criada, a infra
|
|
112
|
+
* no ar e a build parada — pior do que não ter começado.
|
|
113
|
+
*/
|
|
114
|
+
export function preflight(runner = defaultRunner) {
|
|
115
|
+
if (!dockerAvailable(runner)) {
|
|
116
|
+
return {
|
|
117
|
+
ok: false,
|
|
118
|
+
message: 'Docker não está acessível.\n' +
|
|
119
|
+
' Instale o Docker Desktop/Engine e confira `docker version`.\n' +
|
|
120
|
+
' Sem ele, use `okcms update --mode download` para só baixar os pacotes.',
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const compose = composeAvailable(runner);
|
|
124
|
+
if (!compose.ok) {
|
|
125
|
+
return {
|
|
126
|
+
ok: false,
|
|
127
|
+
message: 'Docker Compose v2 não está disponível (`docker compose version` falhou).\n' +
|
|
128
|
+
' O deploy usa o plugin Compose v2 — o `docker-compose` legado (v1, Python)\n' +
|
|
129
|
+
' não entende healthcheck nem extensões `x-` dos arquivos gerados.',
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return { ok: true };
|
|
133
|
+
}
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
// Convenções de nome (espelham container_name do compose)
|
|
136
|
+
// ---------------------------------------------------------------------------
|
|
137
|
+
export const workerContainer = (lane) => `okcms-${WORKER_SERVICE(lane)}`;
|
|
138
|
+
export const edgeContainerNames = (lane) => EDGE_SERVICE(lane).map((service) => `okcms-${service}`);
|
|
139
|
+
/**
|
|
140
|
+
* Nomes de CONTAINER (não de serviço) da lane, lidos do compose quando
|
|
141
|
+
* possível: é o que o `docker inspect` entende no healthcheck e no dreno.
|
|
142
|
+
*/
|
|
143
|
+
export function laneContainers(cwd, lane) {
|
|
144
|
+
const file = join(cwd, COMPOSE_DEPLOY_FILE);
|
|
145
|
+
if (existsSync(file)) {
|
|
146
|
+
const matched = parseComposeServices(readFileSync(file, 'utf-8')).filter((service) => service.lane === lane && (service.role === 'edge' || service.role === 'worker'));
|
|
147
|
+
if (matched.length > 0) {
|
|
148
|
+
return {
|
|
149
|
+
edge: matched.filter((s) => s.role === 'edge').map((s) => s.containerName),
|
|
150
|
+
worker: matched.filter((s) => s.role === 'worker').map((s) => s.containerName),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return { edge: edgeContainerNames(lane), worker: [workerContainer(lane)] };
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Como invocar o próprio `okcms db:migrate`.
|
|
158
|
+
*
|
|
159
|
+
* Reexecuta o MESMO binário que está rodando (argv[1]) em vez de depender de
|
|
160
|
+
* PATH/npx: o caminho do projeto instalado é o único que tem as migrations e
|
|
161
|
+
* o `.env` certos, e o host é onde elas devem correr (o container não tem a
|
|
162
|
+
* CLI, por construção).
|
|
163
|
+
*/
|
|
164
|
+
export function migrateInvocation() {
|
|
165
|
+
const entry = process.argv[1];
|
|
166
|
+
if (entry)
|
|
167
|
+
return { command: process.execPath, args: [entry, 'db:migrate'] };
|
|
168
|
+
return { command: 'npx', args: ['okcms', 'db:migrate'] };
|
|
169
|
+
}
|
|
170
|
+
/** `bun add` com queda para `npm install` quando o bun não existe no host. */
|
|
171
|
+
function installPackages(cwd, packages, runner) {
|
|
172
|
+
const bun = runner('bun', ['add', ...packages], { cwd, inherit: true, timeoutMs: 600_000 });
|
|
173
|
+
if (bun.ok || !/ENOENT|not found|spawn/i.test(bun.stderr))
|
|
174
|
+
return bun;
|
|
175
|
+
return runner('npm', ['install', ...packages], { cwd, inherit: true, timeoutMs: 600_000 });
|
|
176
|
+
}
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
// Deploy
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
export async function deployBlueGreen(opts) {
|
|
181
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
182
|
+
const runner = opts.runner ?? defaultRunner;
|
|
183
|
+
const log = opts.log ?? ((message) => void console.log(message));
|
|
184
|
+
const warn = opts.warn ?? ((message) => void console.warn(message));
|
|
185
|
+
const choices = opts.choices;
|
|
186
|
+
const packages = opts.packages ?? [];
|
|
187
|
+
const probe = opts.healthProbe ?? defaultHealthProbe;
|
|
188
|
+
const timeout = { ...DEFAULT_TIMEOUTS, ...opts.timeouts };
|
|
189
|
+
const record = loadDeployEnv(cwd);
|
|
190
|
+
const created = ensureDeployFiles(cwd, record, runner);
|
|
191
|
+
// Quem serve hoje decide para QUAL lane vamos: sempre para a outra, para
|
|
192
|
+
// que a rollback exista. Primeira execução (sem estado) = sem rollback.
|
|
193
|
+
const previous = detectActiveLane(cwd, runner);
|
|
194
|
+
const target = previous ? otherLane(previous) : (readUpstreamsLane(cwd) ?? 'blue');
|
|
195
|
+
const willDrain = previous !== null;
|
|
196
|
+
const plan = [
|
|
197
|
+
'Preflight: docker + compose v2',
|
|
198
|
+
'Rede okcms-net e infraestrutura (postgres, redis, proxy)',
|
|
199
|
+
'Baixar pacotes no host',
|
|
200
|
+
'Build da imagem (lane nova, sem tráfego)',
|
|
201
|
+
'Migrations no host',
|
|
202
|
+
`Subir edge da lane ${target}`,
|
|
203
|
+
`Healthcheck da lane ${target}`,
|
|
204
|
+
'Swap do proxy (nginx -s reload)',
|
|
205
|
+
...(willDrain ? [`Drenar worker da lane ${previous}`] : []),
|
|
206
|
+
`Subir worker da lane ${target}`,
|
|
207
|
+
...(willDrain ? [`Derrubar lane ${previous}`] : []),
|
|
208
|
+
'Registrar estado do deploy',
|
|
209
|
+
];
|
|
210
|
+
const next = (index) => {
|
|
211
|
+
log(`\n[${index}/${plan.length}] ${plan[index - 1]}`);
|
|
212
|
+
};
|
|
213
|
+
const fail = (message) => {
|
|
214
|
+
warn(message);
|
|
215
|
+
return { ok: false, lane: previous ?? target, previousLane: previous, created, message };
|
|
216
|
+
};
|
|
217
|
+
/** Desfaz o que este deploy já fez, deixando o cenário de antes. */
|
|
218
|
+
const restoreUpstreams = () => {
|
|
219
|
+
if (!previous)
|
|
220
|
+
return;
|
|
221
|
+
writeUpstreams(cwd, previous, record);
|
|
222
|
+
const restored = reloadProxy(cwd, runner);
|
|
223
|
+
if (!restored.ok)
|
|
224
|
+
restartProxy(cwd, runner);
|
|
225
|
+
};
|
|
226
|
+
const dropTargetLane = () => {
|
|
227
|
+
const result = laneCompose(cwd, target, ['down', ...(choices.removeOrphans ? ['--remove-orphans'] : [])], runner, true);
|
|
228
|
+
if (!result.ok) {
|
|
229
|
+
warn(` Não foi possível derrubar a lane ${target}: ${result.stderr.trim() || 'falhou'}`);
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
// ---- 1. preflight -------------------------------------------------------
|
|
233
|
+
next(1);
|
|
234
|
+
const ready = preflight(runner);
|
|
235
|
+
if (!ready.ok)
|
|
236
|
+
return fail(ready.message ?? 'Preflight falhou.');
|
|
237
|
+
// ---- 2. rede + infra ----------------------------------------------------
|
|
238
|
+
next(2);
|
|
239
|
+
const network = ensureNetwork(cwd, runner);
|
|
240
|
+
if (!network.ok)
|
|
241
|
+
return fail(`Não foi possível criar a rede okcms-net: ${network.stderr.trim()}`);
|
|
242
|
+
const infra = infraCompose(cwd, ['up', '-d'], runner, true);
|
|
243
|
+
if (!infra.ok) {
|
|
244
|
+
return fail(`Infraestrutura não subiu (docker compose -p okcms up -d):\n${infra.stderr.trim()}`);
|
|
245
|
+
}
|
|
246
|
+
for (const dataContainer of ['okcms-postgres', 'okcms-redis']) {
|
|
247
|
+
const healthy = await waitForContainer(runner, dataContainer, isHealthy, {
|
|
248
|
+
timeoutMs: timeout.dataMs,
|
|
249
|
+
intervalMs: timeout.intervalMs,
|
|
250
|
+
});
|
|
251
|
+
if (!healthy) {
|
|
252
|
+
return fail(`${dataContainer} não ficou saudável em 3min — veja \`docker logs ${dataContainer}\`.`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
log(` ✓ infra pronta (postgres, redis, proxy)`);
|
|
256
|
+
// ---- 3. pacotes no host -------------------------------------------------
|
|
257
|
+
next(3);
|
|
258
|
+
if (opts.installAll) {
|
|
259
|
+
const installed = runner('bun', ['install'], { cwd, inherit: true, timeoutMs: 600_000 });
|
|
260
|
+
if (!installed.ok) {
|
|
261
|
+
return fail(`bun install falhou:\n${installed.stderr.trim()}`);
|
|
262
|
+
}
|
|
263
|
+
log(' ✓ dependências instaladas no host');
|
|
264
|
+
}
|
|
265
|
+
else if (packages.length > 0) {
|
|
266
|
+
const installed = installPackages(cwd, packages, runner);
|
|
267
|
+
if (!installed.ok) {
|
|
268
|
+
return fail(`Falha ao instalar pacotes no host (${installed.command}):\n${installed.stderr.trim()}`);
|
|
269
|
+
}
|
|
270
|
+
log(` ✓ ${packages.length} pacote(s) atualizado(s) no host`);
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
log(' ✓ nada para instalar (pacotes em dia)');
|
|
274
|
+
}
|
|
275
|
+
// ---- 4. build -----------------------------------------------------------
|
|
276
|
+
next(4);
|
|
277
|
+
const buildArgs = ['build', ...(choices.noCache ? ['--no-cache'] : [])];
|
|
278
|
+
const build = laneCompose(cwd, target, buildArgs, runner, true);
|
|
279
|
+
if (!build.ok) {
|
|
280
|
+
return fail(`Build da lane ${target} falhou:\n${build.stderr.trim()}`);
|
|
281
|
+
}
|
|
282
|
+
log(` ✓ imagem okcms/app construída${choices.noCache ? ' (sem cache)' : ''}`);
|
|
283
|
+
// ---- 5. migrations ------------------------------------------------------
|
|
284
|
+
// No HOST, entre o build e qualquer tráfego: falhou aqui = a lane velha
|
|
285
|
+
// continua servindo e o banco não foi tocado por um container novo.
|
|
286
|
+
next(5);
|
|
287
|
+
const migrate = migrateInvocation();
|
|
288
|
+
const migrated = runner(migrate.command, migrate.args, { cwd, inherit: true, timeoutMs: 600_000 });
|
|
289
|
+
if (!migrated.ok) {
|
|
290
|
+
return fail(`Migrations falharam — nada foi trocado, a lane ${previous ?? '(nenhuma)'} continua servindo.\n` +
|
|
291
|
+
`${migrated.stderr.trim()}`);
|
|
292
|
+
}
|
|
293
|
+
// ---- 6. edge da lane nova ----------------------------------------------
|
|
294
|
+
next(6);
|
|
295
|
+
const services = laneServices(cwd, target);
|
|
296
|
+
const up = laneCompose(cwd, target, ['up', '-d', ...services.edge], runner, true);
|
|
297
|
+
if (!up.ok) {
|
|
298
|
+
dropTargetLane();
|
|
299
|
+
return fail(`Lane ${target} não subiu:\n${up.stderr.trim()}`);
|
|
300
|
+
}
|
|
301
|
+
// ---- 7. healthcheck -----------------------------------------------------
|
|
302
|
+
next(7);
|
|
303
|
+
const containers = laneContainers(cwd, target);
|
|
304
|
+
for (const name of containers.edge) {
|
|
305
|
+
const healthy = await waitForContainer(runner, name, isHealthy, {
|
|
306
|
+
timeoutMs: timeout.edgeMs,
|
|
307
|
+
intervalMs: timeout.intervalMs,
|
|
308
|
+
});
|
|
309
|
+
if (!healthy) {
|
|
310
|
+
dropTargetLane();
|
|
311
|
+
return fail(`${name} não ficou saudável — tráfego NÃO foi movido, ` +
|
|
312
|
+
`a lane ${previous ?? '(nenhuma)'} continua servindo.`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
log(` ✓ ${containers.edge.length} contêiner(es) de edge saudável(is)`);
|
|
316
|
+
// ---- 8. swap ------------------------------------------------------------
|
|
317
|
+
next(8);
|
|
318
|
+
writeUpstreams(cwd, target, record);
|
|
319
|
+
const reloaded = reloadProxy(cwd, runner);
|
|
320
|
+
if (!reloaded.ok) {
|
|
321
|
+
const restarted = restartProxy(cwd, runner);
|
|
322
|
+
if (!restarted.ok) {
|
|
323
|
+
restoreUpstreams();
|
|
324
|
+
dropTargetLane();
|
|
325
|
+
return fail(`Proxy não recarregou (${reloaded.stderr.trim() || reloaded.command}) — ` +
|
|
326
|
+
`upstreams restaurados na lane ${previous ?? '(nenhuma)'}.`);
|
|
327
|
+
}
|
|
328
|
+
warn(' nginx -s reload falhou; caiu para docker restart (conexões zeradas).');
|
|
329
|
+
}
|
|
330
|
+
log(` ✓ tráfego agora na lane ${target}`);
|
|
331
|
+
// ---- 9. dreno do worker antigo -----------------------------------------
|
|
332
|
+
if (willDrain) {
|
|
333
|
+
next(9);
|
|
334
|
+
const oldWorkerService = laneServices(cwd, previous).worker[0];
|
|
335
|
+
const oldWorkerContainer = laneContainers(cwd, previous).worker[0];
|
|
336
|
+
if (oldWorkerService) {
|
|
337
|
+
// SIGTERM + stop_grace_period (30s no compose): a fila termina o job em
|
|
338
|
+
// mãos antes de morrer. `kill` direto abandonaria job em processamento.
|
|
339
|
+
laneCompose(cwd, previous, ['stop', oldWorkerService], runner, true);
|
|
340
|
+
if (oldWorkerContainer) {
|
|
341
|
+
await waitStopped(runner, oldWorkerContainer, {
|
|
342
|
+
timeoutMs: timeout.stopMs,
|
|
343
|
+
intervalMs: Math.min(1_000, timeout.intervalMs),
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
log(` ✓ worker da lane ${previous} drenado`);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
// ---- 10. worker novo ----------------------------------------------------
|
|
350
|
+
next(willDrain ? 10 : 9);
|
|
351
|
+
const workerService = services.worker[0];
|
|
352
|
+
if (workerService) {
|
|
353
|
+
const upWorker = laneCompose(cwd, target, ['up', '-d', workerService], runner, true);
|
|
354
|
+
if (!upWorker.ok) {
|
|
355
|
+
warn(` Worker da lane ${target} não subiu: ${upWorker.stderr.trim()}`);
|
|
356
|
+
warn(' A fila fica sem consumidor até o próximo deploy — edge segue no ar.');
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
log(` ✓ worker da lane ${target} no ar`);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
// ---- 11. derruba a lane antiga ------------------------------------------
|
|
363
|
+
if (willDrain) {
|
|
364
|
+
next(11);
|
|
365
|
+
// NB: nunca `-v`. Okcms-storage é compartilhado entre blue e green —
|
|
366
|
+
// derrubar o volume apagaria a mídia no meio do deploy.
|
|
367
|
+
const downArgs = ['down', ...(choices.removeOrphans ? ['--remove-orphans'] : [])];
|
|
368
|
+
const down = laneCompose(cwd, previous, downArgs, runner, true);
|
|
369
|
+
if (!down.ok) {
|
|
370
|
+
warn(` Lane ${previous} não derrubou completamente: ${down.stderr.trim()}`);
|
|
371
|
+
warn(' Rode manualmente: docker compose -p okcms-' + previous + ' down');
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
log(` ✓ lane ${previous} derrubada${choices.removeOrphans ? ' (órfãos removidos)' : ''}`);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
// ---- 12. estado ---------------------------------------------------------
|
|
378
|
+
next(plan.length);
|
|
379
|
+
const state = pushLaneState(readLaneState(cwd), target, record['OKCMS_VERSION'] ?? 'latest');
|
|
380
|
+
writeLaneState(cwd, state);
|
|
381
|
+
const healthy = await probe(FINAL_HEALTH_URL);
|
|
382
|
+
if (!healthy) {
|
|
383
|
+
warn(` Aviso: ${FINAL_HEALTH_URL} não respondeu pelo proxy após o swap.\n` +
|
|
384
|
+
' Os contêineres estão saudáveis (checagem interna); confira o Host/SERVER_NAME.');
|
|
385
|
+
}
|
|
386
|
+
log(`\n Deploy concluído: lane ${target} no ar${previous ? ` (rollback: ${previous})` : ''}.`);
|
|
387
|
+
if (created.length > 0) {
|
|
388
|
+
log(` Arquivos de deploy criados: ${created.join(', ')}`);
|
|
389
|
+
}
|
|
390
|
+
log(' Proxy: http://<host>/ · Admin: http://<host>:8080/');
|
|
391
|
+
return { ok: true, lane: target, previousLane: previous, created };
|
|
392
|
+
}
|
|
393
|
+
//# sourceMappingURL=bluegreen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bluegreen.js","sourceRoot":"","sources":["../src/bluegreen.ts"],"names":[],"mappings":"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"}
|
package/dist/commands.d.ts
CHANGED
|
@@ -4,6 +4,12 @@ export interface Option {
|
|
|
4
4
|
description: string;
|
|
5
5
|
required: boolean;
|
|
6
6
|
default?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Aceita repetição no comando (`--set A=1 --set B=2`). O parser acumula
|
|
9
|
+
* múltiplas ocorrências em `KEY` separadas por `\n` — sem isso a segunda
|
|
10
|
+
* ocorrência sobrescreveria a primeira silenciosamente.
|
|
11
|
+
*/
|
|
12
|
+
repeatable?: boolean;
|
|
7
13
|
}
|
|
8
14
|
export interface Command {
|
|
9
15
|
name: string;
|
package/dist/commands.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7E;AAwCD,eAAO,MAAM,QAAQ,EAAE,OAAO,EAk2B7B,CAAC;AAEF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAE5D"}
|