@geekmidas/cli 10.0.0-alpha.73 → 10.0.0-alpha.75
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/{LegacyStateStore-D_78eaHM.cjs → LegacyStateStore-BFnXUFlx.cjs} +2 -2
- package/dist/{LegacyStateStore-D_78eaHM.cjs.map → LegacyStateStore-BFnXUFlx.cjs.map} +1 -1
- package/dist/{LegacyStateStore-DTo7z924.mjs → LegacyStateStore-cpt3K1vx.mjs} +2 -2
- package/dist/{LegacyStateStore-DTo7z924.mjs.map → LegacyStateStore-cpt3K1vx.mjs.map} +1 -1
- package/dist/{LocalStateStore-CNjgkRk4.mjs → LocalStateStore-RH9F2ZEy.mjs} +2 -2
- package/dist/{LocalStateStore-CNjgkRk4.mjs.map → LocalStateStore-RH9F2ZEy.mjs.map} +1 -1
- package/dist/{LocalStateStore-BhrlQIXD.cjs → LocalStateStore-zQGZ9b4J.cjs} +2 -2
- package/dist/{LocalStateStore-BhrlQIXD.cjs.map → LocalStateStore-zQGZ9b4J.cjs.map} +1 -1
- package/dist/{S3StateStore-oCxRs6HM.cjs → S3StateStore-CT-ZMlQY.cjs} +2 -2
- package/dist/{S3StateStore-oCxRs6HM.cjs.map → S3StateStore-CT-ZMlQY.cjs.map} +1 -1
- package/dist/{S3StateStore-g2P7T_Mo.mjs → S3StateStore-DBeBc0c0.mjs} +2 -2
- package/dist/{S3StateStore-g2P7T_Mo.mjs.map → S3StateStore-DBeBc0c0.mjs.map} +1 -1
- package/dist/{SSMStateStore-DXp0m7XI.cjs → SSMStateStore-HmsH3c4v.cjs} +2 -2
- package/dist/{SSMStateStore-DXp0m7XI.cjs.map → SSMStateStore-HmsH3c4v.cjs.map} +1 -1
- package/dist/{SSMStateStore-CYenunmK.mjs → SSMStateStore-rnzNfOaV.mjs} +2 -2
- package/dist/{SSMStateStore-CYenunmK.mjs.map → SSMStateStore-rnzNfOaV.mjs.map} +1 -1
- package/dist/{SubscriberGenerator-DZk_pKDh.mjs → SubscriberGenerator-5looQ3gB.mjs} +18 -2
- package/dist/SubscriberGenerator-5looQ3gB.mjs.map +1 -0
- package/dist/{SubscriberGenerator-Bixm28fN.cjs → SubscriberGenerator-CajwOa5W.cjs} +29 -1
- package/dist/SubscriberGenerator-CajwOa5W.cjs.map +1 -0
- package/dist/{add-C1ojB2Yy.cjs → add-CHBin8TF.cjs} +2 -2
- package/dist/{add-C1ojB2Yy.cjs.map → add-CHBin8TF.cjs.map} +1 -1
- package/dist/{add-BiPlBUq3.mjs → add-Cvzdw8cf.mjs} +2 -2
- package/dist/{add-BiPlBUq3.mjs.map → add-Cvzdw8cf.mjs.map} +1 -1
- package/dist/{bundler-C35h0WKt.cjs → bundler-_8AEZhrs.cjs} +5 -5
- package/dist/{bundler-C35h0WKt.cjs.map → bundler-_8AEZhrs.cjs.map} +1 -1
- package/dist/{bundler-C2LZoLdP.mjs → bundler-xjp5RwRS.mjs} +5 -5
- package/dist/{bundler-C2LZoLdP.mjs.map → bundler-xjp5RwRS.mjs.map} +1 -1
- package/dist/{cli-DJVL2sL9.cjs → cli-B4ktxAsM.cjs} +3 -3
- package/dist/{cli-DJVL2sL9.cjs.map → cli-B4ktxAsM.cjs.map} +1 -1
- package/dist/{cli-BfdfyTF6.mjs → cli-BTGfA0B7.mjs} +3 -3
- package/dist/{cli-BfdfyTF6.mjs.map → cli-BTGfA0B7.mjs.map} +1 -1
- package/dist/{compose-9II-0IsK.mjs → compose-DdH2JQJD.mjs} +418 -159
- package/dist/compose-DdH2JQJD.mjs.map +1 -0
- package/dist/{compose-CNnw8meq.cjs → compose-UKyv_1yU.cjs} +440 -157
- package/dist/compose-UKyv_1yU.cjs.map +1 -0
- package/dist/{config-RLuR2o9A.d.cts → config-B38YWicj.d.cts} +3 -3
- package/dist/{config-B8OR_TrO.d.mts.map → config-B38YWicj.d.cts.map} +1 -1
- package/dist/{config-B8OR_TrO.d.mts → config-DA0kRTQe.d.mts} +3 -3
- package/dist/{config-RLuR2o9A.d.cts.map → config-DA0kRTQe.d.mts.map} +1 -1
- package/dist/config.d.cts +3 -3
- package/dist/config.d.mts +3 -3
- package/dist/deploy/public.cjs +7 -6
- package/dist/deploy/public.d.cts +14 -3
- package/dist/deploy/public.d.cts.map +1 -1
- package/dist/deploy/public.d.mts +14 -3
- package/dist/deploy/public.d.mts.map +1 -1
- package/dist/deploy/public.mjs +7 -7
- package/dist/{deploy-nmov4j0B.mjs → deploy-CuSsiFIc.mjs} +21 -5
- package/dist/deploy-CuSsiFIc.mjs.map +1 -0
- package/dist/{deploy-BitZLdnY.cjs → deploy-XUZoA1us.cjs} +26 -4
- package/dist/deploy-XUZoA1us.cjs.map +1 -0
- package/dist/{dokploy-Ce_VTytN.cjs → dokploy-Cvgg_pID.cjs} +2 -2
- package/dist/{dokploy-Ce_VTytN.cjs.map → dokploy-Cvgg_pID.cjs.map} +1 -1
- package/dist/{dokploy-CZ1vZt21.mjs → dokploy-DZXTQX10.mjs} +2 -2
- package/dist/{dokploy-CZ1vZt21.mjs.map → dokploy-DZXTQX10.mjs.map} +1 -1
- package/dist/drivers-BdvtCKc7.cjs +200 -0
- package/dist/drivers-BdvtCKc7.cjs.map +1 -0
- package/dist/drivers-Ch1rJitn.mjs +177 -0
- package/dist/drivers-Ch1rJitn.mjs.map +1 -0
- package/dist/{encryption-CmfPICSN.mjs → encryption-JkeMPugf.mjs} +2 -2
- package/dist/{encryption-CmfPICSN.mjs.map → encryption-JkeMPugf.mjs.map} +1 -1
- package/dist/{encryption-CDGRdcMr.cjs → encryption-w-Ehh9DW.cjs} +2 -2
- package/dist/{encryption-CDGRdcMr.cjs.map → encryption-w-Ehh9DW.cjs.map} +1 -1
- package/dist/{engine-B37qBO5W.mjs → engine-CmozkHxq.mjs} +192 -4
- package/dist/engine-CmozkHxq.mjs.map +1 -0
- package/dist/{engine-DL2-PW6m.cjs → engine-zpWBMsQq.cjs} +195 -7
- package/dist/engine-zpWBMsQq.cjs.map +1 -0
- package/dist/{github-C6qF8kHg.cjs → github-BGdJ-Lnm.cjs} +2 -2
- package/dist/{github-C6qF8kHg.cjs.map → github-BGdJ-Lnm.cjs.map} +1 -1
- package/dist/{github-hjHHm7jM.mjs → github-BNngHoId.mjs} +2 -2
- package/dist/{github-hjHHm7jM.mjs.map → github-BNngHoId.mjs.map} +1 -1
- package/dist/{index-DHyTqGG3.d.mts → index-B-1lLGzy.d.mts} +2 -2
- package/dist/{index-DHyTqGG3.d.mts.map → index-B-1lLGzy.d.mts.map} +1 -1
- package/dist/{index-Dg-UZ4Hm.d.cts → index-vMidfqhU.d.cts} +2 -2
- package/dist/{index-Dg-UZ4Hm.d.cts.map → index-vMidfqhU.d.cts.map} +1 -1
- package/dist/index.cjs +89 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +86 -49
- package/dist/index.mjs.map +1 -1
- package/dist/{migrate-CFFC3esE.mjs → migrate-BLL1RTAj.mjs} +2 -2
- package/dist/{migrate-CFFC3esE.mjs.map → migrate-BLL1RTAj.mjs.map} +1 -1
- package/dist/{migrate-kA_j1TPK.cjs → migrate-CgjlYeun.cjs} +2 -2
- package/dist/{migrate-kA_j1TPK.cjs.map → migrate-CgjlYeun.cjs.map} +1 -1
- package/dist/openapi.d.cts +1 -1
- package/dist/openapi.d.mts +1 -1
- package/dist/{ready-BIuMw6wH.cjs → ready-BB9xS4S9.cjs} +6 -188
- package/dist/ready-BB9xS4S9.cjs.map +1 -0
- package/dist/{ready-C0U0NYfB.mjs → ready-ZZoNskrr.mjs} +5 -169
- package/dist/ready-ZZoNskrr.mjs.map +1 -0
- package/dist/reconcile/public.d.cts +1 -1
- package/dist/reconcile/public.d.mts +1 -1
- package/dist/{resolve-CV4eQkDa.mjs → resolve-DZNx7rLy.mjs} +3 -3
- package/dist/{resolve-CV4eQkDa.mjs.map → resolve-DZNx7rLy.mjs.map} +1 -1
- package/dist/{resolve-E5RfY0bm.cjs → resolve-fevXn-wZ.cjs} +3 -3
- package/dist/{resolve-E5RfY0bm.cjs.map → resolve-fevXn-wZ.cjs.map} +1 -1
- package/dist/{rollback-C-V-Rf4a.mjs → rollback-CLi5Pln_.mjs} +4 -4
- package/dist/{rollback-C-V-Rf4a.mjs.map → rollback-CLi5Pln_.mjs.map} +1 -1
- package/dist/{rollback-QGwomD64.cjs → rollback-Dw-FW3X2.cjs} +4 -4
- package/dist/{rollback-QGwomD64.cjs.map → rollback-Dw-FW3X2.cjs.map} +1 -1
- package/dist/{runtime-CWYLIeCU.d.mts → runtime-BzZD5HHi.d.cts} +2 -2
- package/dist/{runtime-CWYLIeCU.d.mts.map → runtime-BzZD5HHi.d.cts.map} +1 -1
- package/dist/{runtime-CmuQOT6A.d.cts → runtime-Cm6J6L7n.d.mts} +2 -2
- package/dist/{runtime-CmuQOT6A.d.cts.map → runtime-Cm6J6L7n.d.mts.map} +1 -1
- package/dist/{sniffer-BFmdZpZ2.mjs → sniffer-BmCvVyhq.mjs} +59 -7
- package/dist/sniffer-BmCvVyhq.mjs.map +1 -0
- package/dist/{sniffer-C-T7dSMN.cjs → sniffer-bMzrX4cO.cjs} +75 -5
- package/dist/{sniffer-C-T7dSMN.cjs.map → sniffer-bMzrX4cO.cjs.map} +1 -1
- package/dist/{state-DtS2HEfi.mjs → state-BrWIOce_.mjs} +60 -293
- package/dist/state-BrWIOce_.mjs.map +1 -0
- package/dist/{state-DMjFPOhf.cjs → state-kA4Fkufx.cjs} +70 -321
- package/dist/state-kA4Fkufx.cjs.map +1 -0
- package/dist/target/public.cjs +1 -1
- package/dist/target/public.d.cts +2 -2
- package/dist/target/public.d.mts +2 -2
- package/dist/target/public.mjs +1 -1
- package/dist/{types-BLdCL4fB.d.mts → types-Dp9lgx_S.d.mts} +6 -2
- package/dist/{types-BLdCL4fB.d.mts.map → types-Dp9lgx_S.d.mts.map} +1 -1
- package/dist/{types-DwCQCkC-.d.cts → types-TzCChNrA.d.cts} +6 -2
- package/dist/{types-DwCQCkC-.d.cts.map → types-TzCChNrA.d.cts.map} +1 -1
- package/dist/vitest.cjs +1 -1
- package/dist/vitest.mjs +1 -1
- package/dist/workspace/index.d.cts +2 -2
- package/dist/workspace/index.d.mts +2 -2
- package/package.json +17 -17
- package/dist/SubscriberGenerator-Bixm28fN.cjs.map +0 -1
- package/dist/SubscriberGenerator-DZk_pKDh.mjs.map +0 -1
- package/dist/compose-9II-0IsK.mjs.map +0 -1
- package/dist/compose-CNnw8meq.cjs.map +0 -1
- package/dist/deploy-BitZLdnY.cjs.map +0 -1
- package/dist/deploy-nmov4j0B.mjs.map +0 -1
- package/dist/engine-B37qBO5W.mjs.map +0 -1
- package/dist/engine-DL2-PW6m.cjs.map +0 -1
- package/dist/ready-BIuMw6wH.cjs.map +0 -1
- package/dist/ready-C0U0NYfB.mjs.map +0 -1
- package/dist/sniffer-BFmdZpZ2.mjs.map +0 -1
- package/dist/state-DMjFPOhf.cjs.map +0 -1
- package/dist/state-DtS2HEfi.mjs.map +0 -1
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-BhDjJH2R.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { i as run$1, s as gkmHome } from "./run-BJLIerMM.mjs";
|
|
3
3
|
import { d as output, r as discover, u as ConstructGenerator } from "./discover-BPelzeGW.mjs";
|
|
4
4
|
import { t as appKey } from "./derive-B4vDpzgP.mjs";
|
|
5
5
|
import { O as TEST_STAGE, h as getPublicEnvPrefix, n as allConstructGlobs } from "./workspace-C7NqCsQF.mjs";
|
|
6
6
|
import { ConfigNotFound, NotInAnApp, loadWorkspaceAppInfo, loadWorkspaceConfig } from "./config.mjs";
|
|
7
7
|
import { n as runtimeFor, r as generateTelemetryModule } from "./EndpointGenerator-DftalLYg.mjs";
|
|
8
|
-
import { c as runtimeOf } from "./resolve-
|
|
9
|
-
import { a as DEFAULT_STORAGE, i as DEFAULT_EVENTS$1, n as readFakes, r as DEFAULT_CACHE, t as SubscriberGenerator } from "./SubscriberGenerator-
|
|
8
|
+
import { c as runtimeOf } from "./resolve-DZNx7rLy.mjs";
|
|
9
|
+
import { a as DEFAULT_STORAGE, i as DEFAULT_EVENTS$1, n as readFakes, o as holdsEveryCache, r as DEFAULT_CACHE, t as SubscriberGenerator } from "./SubscriberGenerator-5looQ3gB.mjs";
|
|
10
10
|
import { basename, dirname, isAbsolute, join, parse, relative, resolve, sep } from "node:path";
|
|
11
11
|
import { constants, existsSync, readFileSync } from "node:fs";
|
|
12
|
-
import { appendFile, chmod, copyFile, mkdir,
|
|
13
|
-
import { homedir, networkInterfaces
|
|
12
|
+
import { appendFile, chmod, copyFile, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
|
|
13
|
+
import { homedir, networkInterfaces } from "node:os";
|
|
14
14
|
import { promisify } from "node:util";
|
|
15
15
|
import { Cron } from "@geekmidas/constructs/crons";
|
|
16
16
|
import { Queue } from "@geekmidas/constructs/queue";
|
|
@@ -274,7 +274,7 @@ function applicationName(identity, app) {
|
|
|
274
274
|
* old file stays, so an older CLI on the same machine keeps working.
|
|
275
275
|
*/
|
|
276
276
|
/** Key length for AES-256 encryption */
|
|
277
|
-
const KEY_LENGTH
|
|
277
|
+
const KEY_LENGTH = 32;
|
|
278
278
|
/** A keystore project key that is not `<namespace>/<project>`. */
|
|
279
279
|
var KeystoreProjectInvalid = class extends Error {
|
|
280
280
|
key;
|
|
@@ -367,7 +367,7 @@ async function generateKey(stage, project, flag = "w") {
|
|
|
367
367
|
recursive: true,
|
|
368
368
|
mode: 448
|
|
369
369
|
});
|
|
370
|
-
const key = randomBytes(KEY_LENGTH
|
|
370
|
+
const key = randomBytes(KEY_LENGTH).toString("hex");
|
|
371
371
|
await writeFile(keyPath, key, {
|
|
372
372
|
mode: 384,
|
|
373
373
|
encoding: "utf-8",
|
|
@@ -436,8 +436,8 @@ async function getOrCreateKey(stage, project) {
|
|
|
436
436
|
/** Where the files live, relative to the project root. */
|
|
437
437
|
const SECRETS_DIR = ".gkm/secrets";
|
|
438
438
|
/** AES-256-GCM configuration */
|
|
439
|
-
const ALGORITHM
|
|
440
|
-
const IV_LENGTH
|
|
439
|
+
const ALGORITHM = "aes-256-gcm";
|
|
440
|
+
const IV_LENGTH = 12;
|
|
441
441
|
/**
|
|
442
442
|
* A stage's secrets as an encrypted file on this machine:
|
|
443
443
|
* `.gkm/secrets/<stage>.json`, with its key in the CLI's home at
|
|
@@ -505,8 +505,8 @@ function packageName$1(root) {
|
|
|
505
505
|
}
|
|
506
506
|
function encrypt(secrets, keyHex) {
|
|
507
507
|
const key = Buffer.from(keyHex, "hex");
|
|
508
|
-
const iv = randomBytes(IV_LENGTH
|
|
509
|
-
const cipher = createCipheriv(ALGORITHM
|
|
508
|
+
const iv = randomBytes(IV_LENGTH);
|
|
509
|
+
const cipher = createCipheriv(ALGORITHM, key, iv);
|
|
510
510
|
const ciphertext = Buffer.concat([cipher.update(JSON.stringify(secrets), "utf-8"), cipher.final()]);
|
|
511
511
|
return {
|
|
512
512
|
version: 1,
|
|
@@ -517,7 +517,7 @@ function encrypt(secrets, keyHex) {
|
|
|
517
517
|
function decrypt(data, keyHex) {
|
|
518
518
|
const key = Buffer.from(keyHex, "hex");
|
|
519
519
|
const combined = Buffer.from(data.encrypted, "base64");
|
|
520
|
-
const decipher = createDecipheriv(ALGORITHM
|
|
520
|
+
const decipher = createDecipheriv(ALGORITHM, key, Buffer.from(data.iv, "hex"));
|
|
521
521
|
decipher.setAuthTag(combined.subarray(-16));
|
|
522
522
|
const plaintext = Buffer.concat([decipher.update(combined.subarray(0, -16)), decipher.final()]);
|
|
523
523
|
return JSON.parse(plaintext.toString("utf-8"));
|
|
@@ -554,7 +554,7 @@ function isRemoteStore(workspace, stage) {
|
|
|
554
554
|
}
|
|
555
555
|
//#endregion
|
|
556
556
|
//#region src/credentials/index.ts
|
|
557
|
-
const logger$
|
|
557
|
+
const logger$1 = console;
|
|
558
558
|
/**
|
|
559
559
|
* Load environment files
|
|
560
560
|
* @internal Exported for testing
|
|
@@ -605,7 +605,7 @@ async function findAvailablePort(preferredPort, maxAttempts = 10) {
|
|
|
605
605
|
for (let i = 0; i < maxAttempts; i++) {
|
|
606
606
|
const port = preferredPort + i;
|
|
607
607
|
if (await isPortAvailable(port)) return port;
|
|
608
|
-
logger$
|
|
608
|
+
logger$1.log(`⚠️ Port ${port} is in use, trying ${port + 1}...`);
|
|
609
609
|
}
|
|
610
610
|
throw new Error(`Could not find an available port after trying ${maxAttempts} ports starting from ${preferredPort}`);
|
|
611
611
|
}
|
|
@@ -640,7 +640,7 @@ async function loadSecretsForApp(store, stage, appName) {
|
|
|
640
640
|
let secrets = {};
|
|
641
641
|
const stageSecrets = await store.read(stage);
|
|
642
642
|
if (stageSecrets) {
|
|
643
|
-
logger$
|
|
643
|
+
logger$1.log(`🔐 Loading secrets from stage: ${stage}`);
|
|
644
644
|
secrets = toEmbeddableSecrets(stageSecrets);
|
|
645
645
|
}
|
|
646
646
|
if (Object.keys(secrets).length === 0) return {};
|
|
@@ -746,7 +746,7 @@ async function prepareEntryCredentials(options) {
|
|
|
746
746
|
free: isPortAvailable,
|
|
747
747
|
holder: holderOf
|
|
748
748
|
});
|
|
749
|
-
for (const { app, from, to, holder } of assigned.moved) logger$
|
|
749
|
+
for (const { app, from, to, holder } of assigned.moved) logger$1.log(`↪️ ${app}: ${from} is held by ${describeHolder(holder)}, which is not this workspace's — using ${to}`);
|
|
750
750
|
workspace = withAppPorts(workspace, assigned.ports);
|
|
751
751
|
workspaceAppPort = assigned.ports[appName] ?? workspaceAppPort;
|
|
752
752
|
}
|
|
@@ -770,7 +770,7 @@ async function prepareEntryCredentials(options) {
|
|
|
770
770
|
});
|
|
771
771
|
Object.assign(credentials, reconciled.env);
|
|
772
772
|
declaredKeys.push(...Object.keys(reconciled.env));
|
|
773
|
-
if (Object.keys(reconciled.env).length > 0) logger$
|
|
773
|
+
if (Object.keys(reconciled.env).length > 0) logger$1.log(`🔌 Resolved ${Object.keys(reconciled.env).length} declared URL(s)`);
|
|
774
774
|
}
|
|
775
775
|
const secretsDir = join(secretsRoot, ".gkm");
|
|
776
776
|
await mkdir(secretsDir, { recursive: true });
|
|
@@ -1279,23 +1279,22 @@ RUN --mount=type=cache,id=${pm.cacheId},target=${pm.cacheTarget} \\
|
|
|
1279
1279
|
*
|
|
1280
1280
|
* Nothing built on the host reaches the image — `.dockerignore` keeps every
|
|
1281
1281
|
* `dist` out — so a workspace package (a CLI that is a sibling package) is
|
|
1282
|
-
* built here:
|
|
1283
|
-
*
|
|
1282
|
+
* built here: turbo's build of the app's dependencies (`^build`) and nothing
|
|
1283
|
+
* else. The root's own `build` script is never run: the slice holds one app,
|
|
1284
|
+
* and a root `build` that is `gkm build` (what `gkm init` scaffolds) builds
|
|
1285
|
+
* every app the workspace declares, most of which are not in it. The app
|
|
1286
|
+
* itself is built after this, by `gkm build` or its framework.
|
|
1284
1287
|
*/
|
|
1285
1288
|
function builderStage(options, extra = {}) {
|
|
1286
|
-
const {
|
|
1289
|
+
const { turbo, monorepo } = layout(options);
|
|
1287
1290
|
const args = extra.args ?? [];
|
|
1288
1291
|
const argLines = args.length ? `\n# Build-time args: public values the bundler inlines\n${args.map((a) => `ARG ${a}=""`).join("\n")}\n${args.map((a) => `ENV ${a}=$${a}`).join("\n")}\n` : "";
|
|
1289
1292
|
const scopes = [options.turboPackage, ...options.prunePackages ?? []];
|
|
1290
|
-
const dependencies = monorepo ? `\nRUN ${turbo} run build ${scopes.map((s) => `--filter='${s}^...'`).join(" ")}` : "";
|
|
1291
1293
|
return `# Stage 3: Build
|
|
1292
1294
|
FROM deps AS builder
|
|
1293
1295
|
WORKDIR /app
|
|
1294
1296
|
${argLines}
|
|
1295
|
-
COPY --from=pruner /app/out/full/
|
|
1296
|
-
|
|
1297
|
-
# The workspace packages the app depends on, built from source.
|
|
1298
|
-
RUN ${pm.run} --if-present build${dependencies}`;
|
|
1297
|
+
COPY --from=pruner /app/out/full/ ./${monorepo ? `\n# The workspace packages the app depends on, built from source.\nRUN ${turbo} run build ${scopes.map((s) => `--filter='${s}^...'`).join(" ")}` : ""}`;
|
|
1299
1298
|
}
|
|
1300
1299
|
/**
|
|
1301
1300
|
* The PATH a command in the app's directory runs with: the app's binaries,
|
|
@@ -1578,7 +1577,7 @@ ${depsStage(options)}
|
|
|
1578
1577
|
${builderStage(options)}
|
|
1579
1578
|
|
|
1580
1579
|
# Bundle the production server, with the encrypted credentials embedded
|
|
1581
|
-
${credentialsStep(app, `cd ${app} && ${gkmCommand(
|
|
1580
|
+
${credentialsStep(app, `cd ${app} && ${gkmCommand(`build --provider server --production${options.cache ? ` --cache ${options.cache}` : ""}`)}`)}
|
|
1582
1581
|
${externals.stage}
|
|
1583
1582
|
# Production
|
|
1584
1583
|
FROM ${options.baseImage} AS runner
|
|
@@ -2180,7 +2179,8 @@ const CONTAINERS = {
|
|
|
2180
2179
|
*/
|
|
2181
2180
|
const CACHE_CONTAINERS = {
|
|
2182
2181
|
upstash: "redis-http",
|
|
2183
|
-
elasticache: "redis"
|
|
2182
|
+
elasticache: "redis",
|
|
2183
|
+
redis: "redis"
|
|
2184
2184
|
};
|
|
2185
2185
|
/**
|
|
2186
2186
|
* Kinds that resolve a value without anything running.
|
|
@@ -2293,7 +2293,7 @@ function containerFor(kind, events = DEFAULT_EVENTS, cache = DEFAULT_CACHE.aws,
|
|
|
2293
2293
|
if (EVENT_KINDS[kind]) return EVENT_CONTAINERS[events] ?? CONTAINERS.database;
|
|
2294
2294
|
if (kind === "file-server") return edge ? "caddy" : CONTAINERS.objects;
|
|
2295
2295
|
if (kind === "cache") {
|
|
2296
|
-
if (derived) return CONTAINERS.database;
|
|
2296
|
+
if (derived && !holdsEveryCache(cache)) return CONTAINERS.database;
|
|
2297
2297
|
return CACHE_CONTAINERS[cache] ?? CONTAINERS.database;
|
|
2298
2298
|
}
|
|
2299
2299
|
return CONTAINERS[kind];
|
|
@@ -2326,6 +2326,7 @@ function planFor(manifest, stage, order, options = {}) {
|
|
|
2326
2326
|
port: fake.port
|
|
2327
2327
|
} : {}
|
|
2328
2328
|
};
|
|
2329
|
+
const detached = declaration.kind === "cache" && holdsEveryCache(cache);
|
|
2329
2330
|
const container = fake?.image ? fake.key : containerFor(declaration.kind, events, cache, "of" in declaration && typeof declaration.of === "string", options.edge !== false);
|
|
2330
2331
|
if (!container && !CONTAINERLESS[declaration.kind]) continue;
|
|
2331
2332
|
if (container) {
|
|
@@ -2352,11 +2353,11 @@ function planFor(manifest, stage, order, options = {}) {
|
|
|
2352
2353
|
credentials: fake.credentials
|
|
2353
2354
|
} } : {},
|
|
2354
2355
|
...declaration.kind === "external-api" && !fake ? { url: declaration.url } : {},
|
|
2355
|
-
..."of" in declaration ? { of: declaration.of } : {},
|
|
2356
|
+
..."of" in declaration && !detached ? { of: declaration.of } : {},
|
|
2356
2357
|
..."schema" in declaration && declaration.schema ? { schema: declaration.schema } : {},
|
|
2357
2358
|
..."version" in declaration && declaration.version ? { version: declaration.version } : {},
|
|
2358
2359
|
..."roles" in declaration && declaration.roles === false ? { roles: false } : {},
|
|
2359
|
-
..."table" in declaration && declaration.table ? { table: declaration.table } : {}
|
|
2360
|
+
..."table" in declaration && declaration.table && !detached ? { table: declaration.table } : {}
|
|
2360
2361
|
});
|
|
2361
2362
|
}
|
|
2362
2363
|
if (options.edge !== false && resources.some((r) => EDGE_KINDS[r.kind] === true)) containers.add("caddy");
|
|
@@ -2718,7 +2719,8 @@ function urlFor(resource, plan, ports, project, addresses = {}, credential = { m
|
|
|
2718
2719
|
return url ? withTable(url, resource.table ?? cacheTable(resource.id)) : void 0;
|
|
2719
2720
|
}
|
|
2720
2721
|
switch (plan.cache) {
|
|
2721
|
-
case "elasticache":
|
|
2722
|
+
case "elasticache":
|
|
2723
|
+
case "redis": return `redis://${LOCAL_HOST}:${port}`;
|
|
2722
2724
|
default: return `http://:${LOCAL_TOKEN$1}@${LOCAL_HOST}:${port}`;
|
|
2723
2725
|
}
|
|
2724
2726
|
case "queue":
|
|
@@ -5288,58 +5290,6 @@ logger.info({ port }, 'Worker started');
|
|
|
5288
5290
|
`;
|
|
5289
5291
|
}
|
|
5290
5292
|
//#endregion
|
|
5291
|
-
//#region src/secrets/encryption.ts
|
|
5292
|
-
var encryption_exports = /* @__PURE__ */ __exportAll({
|
|
5293
|
-
encryptSecrets: () => encryptSecrets,
|
|
5294
|
-
generateDefineOptions: () => generateDefineOptions,
|
|
5295
|
-
keyFingerprint: () => keyFingerprint
|
|
5296
|
-
});
|
|
5297
|
-
/** AES-256-GCM configuration */
|
|
5298
|
-
const ALGORITHM = "aes-256-gcm";
|
|
5299
|
-
const KEY_LENGTH = 32;
|
|
5300
|
-
const IV_LENGTH = 12;
|
|
5301
|
-
/**
|
|
5302
|
-
* Encrypt secrets for embedding in a bundle.
|
|
5303
|
-
* Uses AES-256-GCM with a randomly generated ephemeral key.
|
|
5304
|
-
*
|
|
5305
|
-
* @param secrets - Key-value pairs to encrypt
|
|
5306
|
-
* @returns Encrypted payload with ephemeral master key
|
|
5307
|
-
*/
|
|
5308
|
-
function encryptSecrets(secrets) {
|
|
5309
|
-
const masterKey = randomBytes(KEY_LENGTH);
|
|
5310
|
-
const iv = randomBytes(IV_LENGTH);
|
|
5311
|
-
const plaintext = JSON.stringify(secrets);
|
|
5312
|
-
const cipher = createCipheriv(ALGORITHM, masterKey, iv);
|
|
5313
|
-
const ciphertext = Buffer.concat([cipher.update(plaintext, "utf-8"), cipher.final()]);
|
|
5314
|
-
const authTag = cipher.getAuthTag();
|
|
5315
|
-
return {
|
|
5316
|
-
encrypted: Buffer.concat([ciphertext, authTag]).toString("base64"),
|
|
5317
|
-
iv: iv.toString("hex"),
|
|
5318
|
-
masterKey: masterKey.toString("hex")
|
|
5319
|
-
};
|
|
5320
|
-
}
|
|
5321
|
-
/**
|
|
5322
|
-
* Generate the define options for tsdown/esbuild.
|
|
5323
|
-
* These will be injected at build time.
|
|
5324
|
-
*/
|
|
5325
|
-
function generateDefineOptions(payload) {
|
|
5326
|
-
return {
|
|
5327
|
-
__GKM_ENCRYPTED_CREDENTIALS__: JSON.stringify(payload.encrypted),
|
|
5328
|
-
__GKM_CREDENTIALS_IV__: JSON.stringify(payload.iv)
|
|
5329
|
-
};
|
|
5330
|
-
}
|
|
5331
|
-
/**
|
|
5332
|
-
* A short, one-way name for a master key: the first 8 hex characters of its
|
|
5333
|
-
* SHA-256.
|
|
5334
|
-
*
|
|
5335
|
-
* Printed where the key itself used to be, so a person can tell which key a
|
|
5336
|
-
* build used — and match it against the one they hold — without the output
|
|
5337
|
-
* carrying a value that decrypts every secret of the stage.
|
|
5338
|
-
*/
|
|
5339
|
-
function keyFingerprint(masterKey) {
|
|
5340
|
-
return createHash("sha256").update(masterKey).digest("hex").slice(0, 8);
|
|
5341
|
-
}
|
|
5342
|
-
//#endregion
|
|
5343
5293
|
//#region src/build/workers.ts
|
|
5344
5294
|
/** A worker with background work and no backend app to build it from. */
|
|
5345
5295
|
var WorkerHasNoApp = class extends Error {
|
|
@@ -5827,7 +5777,7 @@ function validateImageRef(ref) {
|
|
|
5827
5777
|
}
|
|
5828
5778
|
//#endregion
|
|
5829
5779
|
//#region src/docker/index.ts
|
|
5830
|
-
const logger
|
|
5780
|
+
const logger = output;
|
|
5831
5781
|
/** `docker build` failed; what docker printed above says why. */
|
|
5832
5782
|
var DockerBuildFailed = class extends Error {
|
|
5833
5783
|
imageRef;
|
|
@@ -5878,7 +5828,7 @@ async function buildDockerImage(app, buildRoot, options) {
|
|
|
5878
5828
|
const tag = options.tag ?? "latest";
|
|
5879
5829
|
const registry = options.registry;
|
|
5880
5830
|
const fullImageName = validateImageRef(registry ? `${registry}/${app.imageName}:${tag}` : `${app.imageName}:${tag}`);
|
|
5881
|
-
logger
|
|
5831
|
+
logger.log(`\n🐳 Building Docker image: ${fullImageName}`);
|
|
5882
5832
|
try {
|
|
5883
5833
|
await run$1("docker", [
|
|
5884
5834
|
"build",
|
|
@@ -5892,7 +5842,7 @@ async function buildDockerImage(app, buildRoot, options) {
|
|
|
5892
5842
|
DOCKER_BUILDKIT: "1"
|
|
5893
5843
|
}
|
|
5894
5844
|
});
|
|
5895
|
-
logger
|
|
5845
|
+
logger.log(`✅ Docker image built: ${fullImageName}`);
|
|
5896
5846
|
} catch (error) {
|
|
5897
5847
|
throw new DockerBuildFailed(fullImageName, error);
|
|
5898
5848
|
}
|
|
@@ -5905,10 +5855,10 @@ async function pushDockerImage(imageName, options, cwd) {
|
|
|
5905
5855
|
const registry = options.registry;
|
|
5906
5856
|
if (!registry) throw new PushNeedsRegistry(imageName);
|
|
5907
5857
|
const fullImageName = validateImageRef(`${registry}/${imageName}:${tag}`);
|
|
5908
|
-
logger
|
|
5858
|
+
logger.log(`\n🚀 Pushing Docker image: ${fullImageName}`);
|
|
5909
5859
|
try {
|
|
5910
5860
|
await run$1("docker", ["push", fullImageName], { cwd });
|
|
5911
|
-
logger
|
|
5861
|
+
logger.log(`✅ Docker image pushed: ${fullImageName}`);
|
|
5912
5862
|
} catch (error) {
|
|
5913
5863
|
throw new DockerPushFailed(fullImageName, error);
|
|
5914
5864
|
}
|
|
@@ -5920,16 +5870,16 @@ async function pushDockerImage(imageName, options, cwd) {
|
|
|
5920
5870
|
async function workspaceDockerCommand(workspace, manifest, imageNames = {}, background = {}) {
|
|
5921
5871
|
const results = [];
|
|
5922
5872
|
const layout = imageLayout(workspace);
|
|
5923
|
-
logger
|
|
5924
|
-
logger
|
|
5925
|
-
logger
|
|
5873
|
+
logger.log(`\n🐳 Generating Dockerfiles for workspace: ${workspace.name}`);
|
|
5874
|
+
logger.log(` Build root: ${layout.buildRoot}`);
|
|
5875
|
+
logger.log(` Package manager: ${layout.tools.packageManager}${layout.tools.packageManagerVersion ? `@${layout.tools.packageManagerVersion}` : ""}, turbo@${layout.tools.turboVersion}`);
|
|
5926
5876
|
for (const [appName, app] of Object.entries(workspace.apps)) {
|
|
5927
5877
|
if (app.type === "mobile") {
|
|
5928
|
-
logger
|
|
5878
|
+
logger.log(`\n 📱 Skipping Docker for ${appName} (mobile app — deploy via framework toolchain)`);
|
|
5929
5879
|
continue;
|
|
5930
5880
|
}
|
|
5931
5881
|
const buildType = app.entry ? "entry" : app.type;
|
|
5932
|
-
logger
|
|
5882
|
+
logger.log(`\n 📄 Generating Dockerfile for ${appName} (${buildType})`);
|
|
5933
5883
|
const dockerfile = appDockerfile(appName, app, {
|
|
5934
5884
|
layout,
|
|
5935
5885
|
workspaceRoot: workspace.root,
|
|
@@ -5939,7 +5889,7 @@ async function workspaceDockerCommand(workspace, manifest, imageNames = {}, back
|
|
|
5939
5889
|
const dockerfilePath = join(workspace.root, path);
|
|
5940
5890
|
await mkdir(dirname(dockerfilePath), { recursive: true });
|
|
5941
5891
|
await writeFile(dockerfilePath, dockerfile);
|
|
5942
|
-
logger
|
|
5892
|
+
logger.log(` Generated: ${path}`);
|
|
5943
5893
|
results.push({
|
|
5944
5894
|
appName,
|
|
5945
5895
|
type: app.type,
|
|
@@ -5948,7 +5898,7 @@ async function workspaceDockerCommand(workspace, manifest, imageNames = {}, back
|
|
|
5948
5898
|
});
|
|
5949
5899
|
}
|
|
5950
5900
|
for (const worker of manifest ? workerUnits(workspace, manifest, background) : []) {
|
|
5951
|
-
logger
|
|
5901
|
+
logger.log(`\n 📄 Generating Dockerfile for ${worker.name} (worker ${worker.id}, built from ${worker.app})`);
|
|
5952
5902
|
const dockerfile = workerDockerfile(worker, workspace.apps[worker.app], {
|
|
5953
5903
|
layout,
|
|
5954
5904
|
workspaceRoot: workspace.root
|
|
@@ -5957,7 +5907,7 @@ async function workspaceDockerCommand(workspace, manifest, imageNames = {}, back
|
|
|
5957
5907
|
const dockerfilePath = join(workspace.root, path);
|
|
5958
5908
|
await mkdir(dirname(dockerfilePath), { recursive: true });
|
|
5959
5909
|
await writeFile(dockerfilePath, dockerfile);
|
|
5960
|
-
logger
|
|
5910
|
+
logger.log(` Generated: ${path}`);
|
|
5961
5911
|
results.push({
|
|
5962
5912
|
appName: worker.name,
|
|
5963
5913
|
type: "backend",
|
|
@@ -5966,13 +5916,13 @@ async function workspaceDockerCommand(workspace, manifest, imageNames = {}, back
|
|
|
5966
5916
|
});
|
|
5967
5917
|
}
|
|
5968
5918
|
const dockerignorePath = await ensureDockerignore(layout.buildRoot);
|
|
5969
|
-
logger
|
|
5919
|
+
logger.log(`\n Ensured: ${dockerignorePath}`);
|
|
5970
5920
|
const composePath = await writeConstructsCompose(workspace);
|
|
5971
|
-
logger
|
|
5972
|
-
logger
|
|
5921
|
+
logger.log(`\n✅ Generated ${results.length} Dockerfile(s) + ${COMPOSE_PATH}`);
|
|
5922
|
+
logger.log(`\n📋 Build commands (from ${layout.buildRoot}):`);
|
|
5973
5923
|
for (const result of results) {
|
|
5974
5924
|
const icon = result.type === "backend" ? "⚙️" : result.type === "mobile" ? "📱" : "🌐";
|
|
5975
|
-
logger
|
|
5925
|
+
logger.log(` ${icon} docker build -f ${relative(layout.buildRoot, result.dockerfile)} -t ${result.imageName} .`);
|
|
5976
5926
|
}
|
|
5977
5927
|
printRunInstructions(workspace);
|
|
5978
5928
|
return {
|
|
@@ -6001,7 +5951,8 @@ function appDockerfile(appName, app, options) {
|
|
|
6001
5951
|
});
|
|
6002
5952
|
return generateBackendDockerfile({
|
|
6003
5953
|
...image,
|
|
6004
|
-
healthCheckPath: "/health"
|
|
5954
|
+
healthCheckPath: "/health",
|
|
5955
|
+
...options.cache ? { cache: options.cache } : {}
|
|
6005
5956
|
});
|
|
6006
5957
|
}
|
|
6007
5958
|
/** Where `gkm docker` writes a worker's Dockerfile. */
|
|
@@ -6019,7 +5970,8 @@ function workerDockerfile(worker, host, options) {
|
|
|
6019
5970
|
port: WORKER_PORT,
|
|
6020
5971
|
worker: worker.id,
|
|
6021
5972
|
bundle: workerBundleName(worker.id),
|
|
6022
|
-
healthCheckPath: "/health"
|
|
5973
|
+
healthCheckPath: "/health",
|
|
5974
|
+
...options.cache ? { cache: options.cache } : {}
|
|
6023
5975
|
});
|
|
6024
5976
|
}
|
|
6025
5977
|
/**
|
|
@@ -6089,199 +6041,14 @@ async function writeConstructsCompose(workspace) {
|
|
|
6089
6041
|
stage: workspace.stages.local,
|
|
6090
6042
|
start: false
|
|
6091
6043
|
});
|
|
6092
|
-
logger
|
|
6044
|
+
logger.log(` Generated: ${COMPOSE_PATH} (project root)`);
|
|
6093
6045
|
return join(workspace.root, COMPOSE_PATH);
|
|
6094
6046
|
}
|
|
6095
6047
|
function printRunInstructions(workspace) {
|
|
6096
6048
|
const project = existsSync(join(workspace.root, "docker-compose.yml")) ? " -f docker-compose.yml" : "";
|
|
6097
|
-
logger
|
|
6098
|
-
logger
|
|
6099
|
-
logger
|
|
6100
|
-
}
|
|
6101
|
-
//#endregion
|
|
6102
|
-
//#region src/deploy/docker.ts
|
|
6103
|
-
const logger = output;
|
|
6104
|
-
/**
|
|
6105
|
-
* The id the Dockerfile templates mount the encrypted credentials under:
|
|
6106
|
-
* `RUN --mount=type=secret,id=gkm_credentials`.
|
|
6107
|
-
*/
|
|
6108
|
-
const CREDENTIALS_SECRET_ID = "gkm_credentials";
|
|
6109
|
-
/**
|
|
6110
|
-
* Get the full image reference
|
|
6111
|
-
*/
|
|
6112
|
-
function getImageRef(registry, imageName, tag) {
|
|
6113
|
-
if (registry) return `${registry}/${imageName}:${tag}`;
|
|
6114
|
-
return `${imageName}:${tag}`;
|
|
6115
|
-
}
|
|
6116
|
-
/**
|
|
6117
|
-
* The `docker build` argv for an image.
|
|
6118
|
-
*
|
|
6119
|
-
* One element per value, so nothing in a ref or a build arg is read by a
|
|
6120
|
-
* shell, and `--opt=value` rather than `--opt value`, so a value that starts
|
|
6121
|
-
* with `-` cannot be taken for one of docker's own flags.
|
|
6122
|
-
*
|
|
6123
|
-
* @internal Exported for testing
|
|
6124
|
-
*/
|
|
6125
|
-
function dockerBuildArgs(options) {
|
|
6126
|
-
const { dockerfilePath, imageRef, buildArgs = [], credentialsFile } = options;
|
|
6127
|
-
return [
|
|
6128
|
-
"build",
|
|
6129
|
-
"--platform=linux/amd64",
|
|
6130
|
-
`--file=${dockerfilePath}`,
|
|
6131
|
-
`--tag=${imageRef}`,
|
|
6132
|
-
...buildArgs.map((arg) => `--build-arg=${arg}`),
|
|
6133
|
-
...credentialsFile ? [`--secret=id=${CREDENTIALS_SECRET_ID},src=${credentialsFile}`] : [],
|
|
6134
|
-
"."
|
|
6135
|
-
];
|
|
6136
|
-
}
|
|
6137
|
-
/**
|
|
6138
|
-
* The build arg that names which credentials an image embeds: a hash of the
|
|
6139
|
-
* ciphertext, which is not a secret. A BuildKit secret is no part of the
|
|
6140
|
-
* build cache's key, so without it a rebuild with credentials encrypted under
|
|
6141
|
-
* a new key would reuse the layer that embedded the old ones.
|
|
6142
|
-
*/
|
|
6143
|
-
function credentialsBuildArg(credentials) {
|
|
6144
|
-
return `GKM_CIPHERTEXT_HASH=${createHash("sha256").update(`${credentials.encrypted}\n${credentials.iv}`).digest("hex").slice(0, 16)}`;
|
|
6145
|
-
}
|
|
6146
|
-
/** The secret file's content: ciphertext, then IV, one per line. */
|
|
6147
|
-
function credentialsFileContent(credentials) {
|
|
6148
|
-
return `${credentials.encrypted}\n${credentials.iv}\n`;
|
|
6149
|
-
}
|
|
6150
|
-
/**
|
|
6151
|
-
* Write the encrypted credentials where `docker build --secret` reads them.
|
|
6152
|
-
*
|
|
6153
|
-
* Two lines — ciphertext, then IV — so a template can split them with `sed`
|
|
6154
|
-
* in any base image. Owner-only, in a directory of its own, and the returned
|
|
6155
|
-
* cleanup removes both whatever the build did.
|
|
6156
|
-
*
|
|
6157
|
-
* @internal Exported for testing
|
|
6158
|
-
*/
|
|
6159
|
-
async function writeCredentialsFile(credentials) {
|
|
6160
|
-
const dir = await mkdtemp(join(tmpdir(), "gkm-credentials-"));
|
|
6161
|
-
const path = join(dir, CREDENTIALS_SECRET_ID);
|
|
6162
|
-
await writeFile(path, credentialsFileContent(credentials), { mode: 384 });
|
|
6163
|
-
await chmod(path, 384);
|
|
6164
|
-
return {
|
|
6165
|
-
path,
|
|
6166
|
-
cleanup: () => rm(dir, {
|
|
6167
|
-
recursive: true,
|
|
6168
|
-
force: true
|
|
6169
|
-
})
|
|
6170
|
-
};
|
|
6171
|
-
}
|
|
6172
|
-
/**
|
|
6173
|
-
* Build Docker image
|
|
6174
|
-
* @param imageRef - Full image reference (registry/name:tag)
|
|
6175
|
-
* @param buildArgs - Build arguments to pass to docker build
|
|
6176
|
-
* @param credentials - Encrypted credentials, passed as a build secret
|
|
6177
|
-
*/
|
|
6178
|
-
async function buildImage(imageRef, buildArgs, credentials, { cwd, dockerfile, signal, stdio }) {
|
|
6179
|
-
logger.log(`\n🔨 Building Docker image: ${imageRef}`);
|
|
6180
|
-
logger.log(" Generating Dockerfile...");
|
|
6181
|
-
const { buildRoot } = await dockerCommand({ cwd });
|
|
6182
|
-
const dockerfilePath = relative(buildRoot, dockerfile);
|
|
6183
|
-
const secret = credentials ? await writeCredentialsFile(credentials) : void 0;
|
|
6184
|
-
try {
|
|
6185
|
-
await run$1("docker", dockerBuildArgs({
|
|
6186
|
-
dockerfilePath,
|
|
6187
|
-
imageRef,
|
|
6188
|
-
buildArgs: [...buildArgs ?? [], ...credentials ? [credentialsBuildArg(credentials)] : []],
|
|
6189
|
-
credentialsFile: secret?.path
|
|
6190
|
-
}), {
|
|
6191
|
-
cwd: buildRoot,
|
|
6192
|
-
env: {
|
|
6193
|
-
...process.env,
|
|
6194
|
-
DOCKER_BUILDKIT: "1"
|
|
6195
|
-
},
|
|
6196
|
-
...signal ? { signal } : {},
|
|
6197
|
-
...stdio ? { stdio } : {}
|
|
6198
|
-
});
|
|
6199
|
-
logger.log(`✅ Image built: ${imageRef}`);
|
|
6200
|
-
} catch (error) {
|
|
6201
|
-
throw new DockerBuildFailed(imageRef, error);
|
|
6202
|
-
} finally {
|
|
6203
|
-
await secret?.cleanup();
|
|
6204
|
-
}
|
|
6205
|
-
}
|
|
6206
|
-
/**
|
|
6207
|
-
* Push Docker image to registry
|
|
6208
|
-
*/
|
|
6209
|
-
async function pushImage(imageRef, { cwd, signal, stdio }) {
|
|
6210
|
-
logger.log(`\n☁️ Pushing image: ${imageRef}`);
|
|
6211
|
-
try {
|
|
6212
|
-
await run$1("docker", ["push", imageRef], {
|
|
6213
|
-
cwd,
|
|
6214
|
-
...signal ? { signal } : {},
|
|
6215
|
-
...stdio ? { stdio } : {}
|
|
6216
|
-
});
|
|
6217
|
-
logger.log(`✅ Image pushed: ${imageRef}`);
|
|
6218
|
-
} catch (error) {
|
|
6219
|
-
throw new DockerPushFailed(imageRef, error);
|
|
6220
|
-
}
|
|
6221
|
-
}
|
|
6222
|
-
/**
|
|
6223
|
-
* The digest the registry gave a pushed image, `sha256:…`.
|
|
6224
|
-
*
|
|
6225
|
-
* A tag can be pushed over — by the next deploy, or by anything else that
|
|
6226
|
-
* shares the repository — and the digest is what says which image a stage
|
|
6227
|
-
* actually ran. `RepoDigests` has one entry per repository the image was
|
|
6228
|
-
* pushed to, so the one for this ref's repository is picked by name.
|
|
6229
|
-
*
|
|
6230
|
-
* @internal Exported for testing
|
|
6231
|
-
*/
|
|
6232
|
-
async function pushedDigest(imageRef, { cwd, signal } = { cwd: process.cwd() }) {
|
|
6233
|
-
const repository = imageRef.split("@")[0].replace(/:[\w][\w.-]*$/, "");
|
|
6234
|
-
const output = await runOutput("docker", [
|
|
6235
|
-
"image",
|
|
6236
|
-
"inspect",
|
|
6237
|
-
"--format={{json .RepoDigests}}",
|
|
6238
|
-
imageRef
|
|
6239
|
-
], {
|
|
6240
|
-
cwd,
|
|
6241
|
-
...signal ? { signal } : {}
|
|
6242
|
-
});
|
|
6243
|
-
let digests;
|
|
6244
|
-
try {
|
|
6245
|
-
digests = JSON.parse(output.trim() || "[]");
|
|
6246
|
-
} catch {
|
|
6247
|
-
return;
|
|
6248
|
-
}
|
|
6249
|
-
if (!Array.isArray(digests)) return void 0;
|
|
6250
|
-
return digests.find((entry) => typeof entry === "string" && entry.startsWith(`${repository}@`))?.slice(repository.length + 1);
|
|
6251
|
-
}
|
|
6252
|
-
/**
|
|
6253
|
-
* Deploy using Docker (build and optionally push image)
|
|
6254
|
-
*/
|
|
6255
|
-
async function deployDocker(options) {
|
|
6256
|
-
const { stage, tag, skipPush, masterKey, config, buildArgs, credentials } = options;
|
|
6257
|
-
const imageName = config.imageName;
|
|
6258
|
-
const imageRef = validateImageRef(getImageRef(config.registry, imageName, tag));
|
|
6259
|
-
const cwd = options.cwd ?? process.cwd();
|
|
6260
|
-
const docker = {
|
|
6261
|
-
cwd,
|
|
6262
|
-
dockerfile: join(cwd, options.dockerfile ?? dockerfileOf(config.appName ?? imageName, options.appPath ?? ".")),
|
|
6263
|
-
...options.signal ? { signal: options.signal } : {},
|
|
6264
|
-
...options.stdio ? { stdio: options.stdio } : {}
|
|
6265
|
-
};
|
|
6266
|
-
await buildImage(imageRef, buildArgs, credentials, docker);
|
|
6267
|
-
let digest;
|
|
6268
|
-
if (!skipPush) {
|
|
6269
|
-
if (!config.registry) logger.warn("\n⚠️ No registry configured. Use --skip-push or configure docker.registry in gkm.config.ts");
|
|
6270
|
-
else {
|
|
6271
|
-
await pushImage(imageRef, docker);
|
|
6272
|
-
digest = await pushedDigest(imageRef, docker);
|
|
6273
|
-
}
|
|
6274
|
-
}
|
|
6275
|
-
logger.log("\n✅ Docker deployment ready!");
|
|
6276
|
-
logger.log(`\n📋 Deployment details:`);
|
|
6277
|
-
logger.log(` Image: ${imageRef}`);
|
|
6278
|
-
logger.log(` Stage: ${stage}`);
|
|
6279
|
-
if (masterKey) logger.log(`\n🔐 Run the container with GKM_MASTER_KEY set to the key with fingerprint ${keyFingerprint(masterKey)}.`);
|
|
6280
|
-
return {
|
|
6281
|
-
imageRef,
|
|
6282
|
-
...digest ? { digest } : {},
|
|
6283
|
-
masterKey
|
|
6284
|
-
};
|
|
6049
|
+
logger.log("\n📋 Run everything (the apps sit behind the \"apps\" profile):");
|
|
6050
|
+
logger.log(" gkm setup # starts the containers and creates what they hold");
|
|
6051
|
+
logger.log(` docker compose -f ${COMPOSE_PATH}${project} --profile apps up --build`);
|
|
6285
6052
|
}
|
|
6286
6053
|
//#endregion
|
|
6287
6054
|
//#region src/deploy/generated.ts
|
|
@@ -6585,6 +6352,6 @@ function setPostgresBackupId(state, backupId) {
|
|
|
6585
6352
|
if (state.backups) state.backups.postgresBackupId = backupId;
|
|
6586
6353
|
}
|
|
6587
6354
|
//#endregion
|
|
6588
|
-
export {
|
|
6355
|
+
export { LOCAL_CA_PATH as $, imageRef as $t, ExternalServicesNotConfigured as A, DEFAULT_IMAGES as At, suppliedOnly as B, loadSecretsForApp as Bt, NoDomainForStage as C, WORKER_PORT as Ct, otelEnv as D, eventsBackendFor as Dt, isOtlpDestination as E, cacheBackendFor as Et, externalServices as F, createCredentialsPreload as Ft, QueueGenerator as G, FileSecretsStore as Gt, WorkerGenerator as H, isRemoteStore as Ht, manifestServiceDeclarations as I, createEntryWrapper as It, backendsOf as J, projectKey as Jt, CronGenerator as K, getKeyPath as Kt, parseDevServices as L, findAvailablePort as Lt, UnknownDevService as M, fakeKey as Mt, assertExternalServices as N, portKeys as Nt, DEV_SERVICES as O, providerOf as Ot, devServicesUsed as P, primaryPortKey as Pt, workspace_exports as Q, imageName as Qt, reportDevServices as R, isPortAvailable as Rt, validateImageRef as S, TURBO_VERSION as St, resolveHost as T, findBuildRoot as Tt, workerBundleName as U, secretsStoreFor as Ut, workerUnits as V, prepareEntryCredentials as Vt, workerEntryDir as W, store_exports as Wt, derivedContainers as X, applicationName as Xt, constructGlobs as Y, readKey as Yt, reconcileWorkspace as Z, deployIdentity as Zt, appDockerfile as _, planFor as _t, recordRelease as a, maskPassword as an, postgresDatabaseNames as at, workerDockerfile as b, composeBuildPaths as bt, setBackupState as c, withCustomSecret as cn, composeFor as ct, setGeneratedSecret as d, appEnvKeys as dt, isOwnedBy as en, forgetState as et, setPostgresBackupId as f, dockerfileOf as ft, DockerPushFailed as g, localRolePassword as gt, DockerBuildFailed as h, envFor as ht, isDnsVerified as i, initStageSecrets as in, bucketPolicies as it, STORAGE_KEY_PAIR as j, describeServices as jt, DevServicesNeedServerTarget as k, storageBackendFor as kt, setDnsRecord as l, bucketClient as lt, withGeneratedSecrets as m, workerEnvKeys as mt, getBackupState as n, ownershipMarker as nn, applyPolicies as nt, recordRollback as o, storage_exports as on, postgresStatements as ot, DeployJournal as p, networkEnv as pt, FAKE_ENV as q, keystoreProject as qt, getGeneratedSecret as r, projectName as rn, applyPostgres as rt, setApplicationId as s, toEmbeddableSecrets as sn, quoteIdentifier as st, createEmptyState as t, markerOf as tn, applyBuckets as tt, setDnsVerification as u, pgClient as ut, dockerCommand as v, resourceName as vt, isMainFrontendApp as w, detectPackageManager as wt, workerDockerfileOf as x, imageLayout as xt, ensureDockerignore as y, hostFor as yt, requiredStageKeys as z, loadEnvFiles as zt };
|
|
6589
6356
|
|
|
6590
|
-
//# sourceMappingURL=state-
|
|
6357
|
+
//# sourceMappingURL=state-BrWIOce_.mjs.map
|