@geekmidas/cli 10.0.0-alpha.66 → 10.0.0-alpha.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -178
- package/dist/{HostingerProvider-CY_VpVud.mjs → HostingerProvider-D85ayzTi.mjs} +2 -2
- package/dist/{HostingerProvider-CY_VpVud.mjs.map → HostingerProvider-D85ayzTi.mjs.map} +1 -1
- package/dist/{HostingerProvider-BznqRC2S.cjs → HostingerProvider-dxkwynSs.cjs} +2 -2
- package/dist/{HostingerProvider-BznqRC2S.cjs.map → HostingerProvider-dxkwynSs.cjs.map} +1 -1
- package/dist/{LegacyStateStore-BFcTT2QL.cjs → LegacyStateStore-BZiO9-Lw.cjs} +2 -2
- package/dist/{LegacyStateStore-BFcTT2QL.cjs.map → LegacyStateStore-BZiO9-Lw.cjs.map} +1 -1
- package/dist/{LegacyStateStore-CFheFo62.mjs → LegacyStateStore-C39UKwmf.mjs} +2 -2
- package/dist/{LegacyStateStore-CFheFo62.mjs.map → LegacyStateStore-C39UKwmf.mjs.map} +1 -1
- package/dist/{LocalStateStore-BVUexSvu.cjs → LocalStateStore-DHVsZLyF.cjs} +2 -2
- package/dist/{LocalStateStore-BVUexSvu.cjs.map → LocalStateStore-DHVsZLyF.cjs.map} +1 -1
- package/dist/{LocalStateStore-Bm3x9oOg.mjs → LocalStateStore-Dk3Wbvzk.mjs} +2 -2
- package/dist/{LocalStateStore-Bm3x9oOg.mjs.map → LocalStateStore-Dk3Wbvzk.mjs.map} +1 -1
- package/dist/{S3StateStore-CoXBhILd.cjs → S3StateStore--4tYVMAL.cjs} +2 -2
- package/dist/{S3StateStore-CoXBhILd.cjs.map → S3StateStore--4tYVMAL.cjs.map} +1 -1
- package/dist/{S3StateStore-BFHuctWM.mjs → S3StateStore-B_ZF9eHt.mjs} +2 -2
- package/dist/{S3StateStore-BFHuctWM.mjs.map → S3StateStore-B_ZF9eHt.mjs.map} +1 -1
- package/dist/{SSMStateStore-BqCA9TP2.cjs → SSMStateStore-ACZ8hRvZ.cjs} +2 -2
- package/dist/{SSMStateStore-BqCA9TP2.cjs.map → SSMStateStore-ACZ8hRvZ.cjs.map} +1 -1
- package/dist/{SSMStateStore-C1kvHScY.mjs → SSMStateStore-DjPuKqrm.mjs} +2 -2
- package/dist/{SSMStateStore-C1kvHScY.mjs.map → SSMStateStore-DjPuKqrm.mjs.map} +1 -1
- package/dist/{bundler-Dvaiud0h.mjs → bundler-C-w7aGoZ.mjs} +20 -5
- package/dist/bundler-C-w7aGoZ.mjs.map +1 -0
- package/dist/{bundler-orRqUJNZ.cjs → bundler-C1pnNrR0.cjs} +20 -5
- package/dist/bundler-C1pnNrR0.cjs.map +1 -0
- package/dist/{cli-D1JkkOwg.cjs → cli-BLyD4c0O.cjs} +14 -5
- package/dist/cli-BLyD4c0O.cjs.map +1 -0
- package/dist/{cli-CfHm0AO7.mjs → cli-Ce4pLL5O.mjs} +14 -5
- package/dist/cli-Ce4pLL5O.mjs.map +1 -0
- package/dist/{compose-CNQL8BnO.mjs → compose-DFxuYhn6.mjs} +291 -152
- package/dist/compose-DFxuYhn6.mjs.map +1 -0
- package/dist/{compose-jrLy7KGO.cjs → compose-DvsgumY2.cjs} +298 -159
- package/dist/compose-DvsgumY2.cjs.map +1 -0
- package/dist/{config-4XFxX1al.d.cts → config-BnA0kPTY.d.cts} +3 -3
- package/dist/{config-4XFxX1al.d.cts.map → config-BnA0kPTY.d.cts.map} +1 -1
- package/dist/{config-UtKzhpFb.d.mts → config-CxEp_g7j.d.mts} +3 -3
- package/dist/{config-UtKzhpFb.d.mts.map → config-CxEp_g7j.d.mts.map} +1 -1
- package/dist/config.d.cts +3 -3
- package/dist/config.d.mts +3 -3
- package/dist/{credentials-Bzbg23n8.cjs → credentials-BVs7mrtw.cjs} +239 -3
- package/dist/credentials-BVs7mrtw.cjs.map +1 -0
- package/dist/{credentials-Dq1MnWQf.mjs → credentials-pAtB70k3.mjs} +223 -5
- package/dist/credentials-pAtB70k3.mjs.map +1 -0
- package/dist/deploy/public.cjs +21 -17
- package/dist/deploy/public.cjs.map +1 -1
- package/dist/deploy/public.d.cts +15 -4
- package/dist/deploy/public.d.cts.map +1 -1
- package/dist/deploy/public.d.mts +15 -4
- package/dist/deploy/public.d.mts.map +1 -1
- package/dist/deploy/public.mjs +10 -10
- package/dist/{deploy-B7aJi_Ah.cjs → deploy-C08GONYW.cjs} +14 -10
- package/dist/deploy-C08GONYW.cjs.map +1 -0
- package/dist/{deploy-DWn7YfIc.mjs → deploy-D-EVOWvu.mjs} +11 -7
- package/dist/deploy-D-EVOWvu.mjs.map +1 -0
- package/dist/{dokploy-B4LcYG1E.cjs → dokploy-CZ6nfSV9.cjs} +2 -2
- package/dist/{dokploy-B4LcYG1E.cjs.map → dokploy-CZ6nfSV9.cjs.map} +1 -1
- package/dist/{dokploy-DalwLML5.mjs → dokploy-DU-XJsoT.mjs} +2 -2
- package/dist/{dokploy-DalwLML5.mjs.map → dokploy-DU-XJsoT.mjs.map} +1 -1
- package/dist/{encryption-3KlGS1sl.cjs → encryption-CCcBSLZs.cjs} +2 -2
- package/dist/{encryption-3KlGS1sl.cjs.map → encryption-CCcBSLZs.cjs.map} +1 -1
- package/dist/{encryption-CPfENwWO.mjs → encryption-DSiLau1-.mjs} +2 -2
- package/dist/{encryption-CPfENwWO.mjs.map → encryption-DSiLau1-.mjs.map} +1 -1
- package/dist/{engine-DR6KurWX.cjs → engine-BM9Dy_DT.cjs} +141 -209
- package/dist/engine-BM9Dy_DT.cjs.map +1 -0
- package/dist/{engine-CunvOG3s.mjs → engine-llWnMZH5.mjs} +137 -205
- package/dist/engine-llWnMZH5.mjs.map +1 -0
- package/dist/{github-BJ5gh9bw.cjs → github-ZoMam0OH.cjs} +2 -2
- package/dist/{github-BJ5gh9bw.cjs.map → github-ZoMam0OH.cjs.map} +1 -1
- package/dist/{github-MXA9v7Ge.mjs → github-yy6WpHIl.mjs} +2 -2
- package/dist/{github-MXA9v7Ge.mjs.map → github-yy6WpHIl.mjs.map} +1 -1
- package/dist/{index-DD1FfUHh.d.mts → index-CkX89m6S.d.mts} +2 -2
- package/dist/{index-CyApaHVe.d.cts.map → index-CkX89m6S.d.mts.map} +1 -1
- package/dist/{index-CyApaHVe.d.cts → index-EvZBkycu.d.cts} +2 -2
- package/dist/{index-DD1FfUHh.d.mts.map → index-EvZBkycu.d.cts.map} +1 -1
- package/dist/index.cjs +59 -70
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +55 -66
- package/dist/index.mjs.map +1 -1
- package/dist/{migrate-BJBcm4sG.mjs → migrate-BWPuwiXk.mjs} +2 -2
- package/dist/{migrate-BJBcm4sG.mjs.map → migrate-BWPuwiXk.mjs.map} +1 -1
- package/dist/{migrate-CF4J4GQS.cjs → migrate-tOwxQBTI.cjs} +2 -2
- package/dist/{migrate-CF4J4GQS.cjs.map → migrate-tOwxQBTI.cjs.map} +1 -1
- package/dist/openapi.d.cts +1 -1
- package/dist/openapi.d.mts +1 -1
- package/dist/reconcile/public.d.cts +1 -1
- package/dist/reconcile/public.d.mts +1 -1
- package/dist/{resolve-CVmch0wI.cjs → resolve-BymzGtuT.cjs} +4 -4
- package/dist/{resolve-CVmch0wI.cjs.map → resolve-BymzGtuT.cjs.map} +1 -1
- package/dist/{resolve-Db0tNlrW.mjs → resolve-pIvXlZ1h.mjs} +4 -4
- package/dist/{resolve-Db0tNlrW.mjs.map → resolve-pIvXlZ1h.mjs.map} +1 -1
- package/dist/{rollback-DvAo4OKS.mjs → rollback-ZlsbQOvj.mjs} +5 -6
- package/dist/{rollback-DvAo4OKS.mjs.map → rollback-ZlsbQOvj.mjs.map} +1 -1
- package/dist/{rollback-DxJK84hy.cjs → rollback-zdfi6Reg.cjs} +6 -7
- package/dist/{rollback-DxJK84hy.cjs.map → rollback-zdfi6Reg.cjs.map} +1 -1
- package/dist/run-BJLIerMM.mjs +133 -0
- package/dist/run-BJLIerMM.mjs.map +1 -0
- package/dist/run-fVZ-rLnc.cjs +174 -0
- package/dist/run-fVZ-rLnc.cjs.map +1 -0
- package/dist/{runtime-BRqFOvPM.d.cts → runtime-B3jNgeP-.d.mts} +2 -2
- package/dist/{runtime-BRqFOvPM.d.cts.map → runtime-B3jNgeP-.d.mts.map} +1 -1
- package/dist/{runtime-CEk5n4VH.d.mts → runtime-DWThEP-r.d.cts} +2 -2
- package/dist/{runtime-CEk5n4VH.d.mts.map → runtime-DWThEP-r.d.cts.map} +1 -1
- package/dist/{sniffer-BAQhLEsI.mjs → sniffer-BdFeLSmA.mjs} +8 -60
- package/dist/sniffer-BdFeLSmA.mjs.map +1 -0
- package/dist/{sniffer-5xmrkh2a.cjs → sniffer-D66HIvi9.cjs} +7 -77
- package/dist/sniffer-D66HIvi9.cjs.map +1 -0
- package/dist/{sst-B2HbrDR3.mjs → sst-DRi3H5TB.mjs} +3 -3
- package/dist/{sst-B2HbrDR3.mjs.map → sst-DRi3H5TB.mjs.map} +1 -1
- package/dist/{sst-DcfsVH6x.cjs → sst-hBrKouBy.cjs} +5 -5
- package/dist/{sst-DcfsVH6x.cjs.map → sst-hBrKouBy.cjs.map} +1 -1
- package/dist/{state-uuYqnRVO.mjs → state-Bn5JDMFT.mjs} +1717 -1334
- package/dist/state-Bn5JDMFT.mjs.map +1 -0
- package/dist/{state-Y6ATakMX.cjs → state-CHZqCDRC.cjs} +2863 -2354
- package/dist/state-CHZqCDRC.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/{terminal-DUhcZ1ND.mjs → terminal-C3cv-OQu.mjs} +2 -2
- package/dist/{terminal-DUhcZ1ND.mjs.map → terminal-C3cv-OQu.mjs.map} +1 -1
- package/dist/{terminal-CHy_MdjG.cjs → terminal-DjzgLu6m.cjs} +2 -2
- package/dist/{terminal-CHy_MdjG.cjs.map → terminal-DjzgLu6m.cjs.map} +1 -1
- package/dist/{types-CSw2w69a.d.mts → types-CZdCxUCK.d.cts} +64 -2
- package/dist/types-CZdCxUCK.d.cts.map +1 -0
- package/dist/{types-D5WIxRDP.d.cts → types-Da0E3Qv7.d.mts} +63 -3
- package/dist/types-Da0E3Qv7.d.mts.map +1 -0
- package/dist/workspace/index.d.cts +2 -2
- package/dist/workspace/index.d.mts +2 -2
- package/package.json +13 -13
- package/dist/bundler-Dvaiud0h.mjs.map +0 -1
- package/dist/bundler-orRqUJNZ.cjs.map +0 -1
- package/dist/cli-CfHm0AO7.mjs.map +0 -1
- package/dist/cli-D1JkkOwg.cjs.map +0 -1
- package/dist/compose-CNQL8BnO.mjs.map +0 -1
- package/dist/compose-jrLy7KGO.cjs.map +0 -1
- package/dist/credentials-Bzbg23n8.cjs.map +0 -1
- package/dist/credentials-Dq1MnWQf.mjs.map +0 -1
- package/dist/deploy-B7aJi_Ah.cjs.map +0 -1
- package/dist/deploy-DWn7YfIc.mjs.map +0 -1
- package/dist/engine-CunvOG3s.mjs.map +0 -1
- package/dist/engine-DR6KurWX.cjs.map +0 -1
- package/dist/local-BdH4XN0E.cjs +0 -409
- package/dist/local-BdH4XN0E.cjs.map +0 -1
- package/dist/local-CWR4Y_kW.mjs +0 -350
- package/dist/local-CWR4Y_kW.mjs.map +0 -1
- package/dist/sniffer-5xmrkh2a.cjs.map +0 -1
- package/dist/sniffer-BAQhLEsI.mjs.map +0 -1
- package/dist/state-Y6ATakMX.cjs.map +0 -1
- package/dist/state-uuYqnRVO.mjs.map +0 -1
- package/dist/types-CSw2w69a.d.mts.map +0 -1
- package/dist/types-D5WIxRDP.d.cts.map +0 -1
|
@@ -1,197 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as MissingCredential } from "./credentials-Dq1MnWQf.mjs";
|
|
1
|
+
import { i as LocalSandbox, t as MissingCredential } from "./credentials-pAtB70k3.mjs";
|
|
3
2
|
import { a as discriminatedUnion, d as string, l as object, n as array, o as literal, s as looseObject } from "./schemas-Cfhtpdo0.mjs";
|
|
4
3
|
import { c as runWorker, d as output, r as discover } from "./discover-BFoJWKGD.mjs";
|
|
5
4
|
import { i as activeSandbox } from "./sandbox-Dm247NGx.mjs";
|
|
6
5
|
import { t as appKey } from "./derive-B4vDpzgP.mjs";
|
|
7
6
|
import { g as stripPublicPrefix, h as getPublicEnvPrefix, s as getAppBuildOrder } from "./workspace-Be6uBhlF.mjs";
|
|
8
|
-
import { C as
|
|
9
|
-
import { f as StateStoreBusy, m as StateVersionConflict, o as DokployApi, s as DokployApiError, t as sniffAllApps, v as eventError
|
|
7
|
+
import { A as assertExternalServices, C as isMainFrontendApp, D as ExternalServicesNotConfigured, F as reportDevServices, Gt as ownershipMarker, Ht as imageRef, I as encryptSecrets, Kt as projectName, M as externalServices, N as manifestServiceDeclarations, O as STORAGE_KEY_PAIR, Ut as isOwnedBy, V as constructGlobs, Vt as imageName, Wt as markerOf, Xt as toEmbeddableSecrets, Y as applyPostgres, _ as deployDocker, _t as providerOf, a as recordRelease, c as setBackupState, ct as resourceName, d as setGeneratedSecret, f as setPostgresBackupId, gt as eventsBackendFor, ht as cacheBackendFor, i as isDnsVerified, j as devServicesUsed, l as setDnsRecord, m as withGeneratedSecrets, n as getBackupState, o as recordRollback, p as DeployJournal, qt as initStageSecrets, r as getGeneratedSecret, s as setApplicationId, t as createEmptyState, u as setDnsVerification, vt as storageBackendFor, w as resolveHost, zt as applicationName } from "./state-Bn5JDMFT.mjs";
|
|
8
|
+
import { f as StateStoreBusy, m as StateVersionConflict, o as DokployApi, s as DokployApiError, t as sniffAllApps, v as eventError } from "./sniffer-BdFeLSmA.mjs";
|
|
10
9
|
import { o as migrationFiles } from "./provider-D7rQzzzf.mjs";
|
|
11
10
|
import { join } from "node:path";
|
|
12
|
-
import { chmod, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
13
|
-
import { tmpdir } from "node:os";
|
|
14
11
|
import { cacheTable, cloudName, cookieDomain, dependentsOf, externalApiUrl, migrationTargets, mobileOrigins, provideKey, provisionOrder, schemeBase } from "@geekmidas/manifest";
|
|
15
12
|
import { createHash, randomBytes } from "node:crypto";
|
|
16
13
|
import { ownerRole, readerRole, roleStatements } from "@geekmidas/db/pg/roles";
|
|
17
14
|
import { Client } from "pg";
|
|
18
15
|
import { cacheTableStatements } from "@geekmidas/cache/postgres";
|
|
19
16
|
import { lookup } from "node:dns/promises";
|
|
20
|
-
//#region src/deploy/docker.ts
|
|
21
|
-
const logger$3 = output;
|
|
22
|
-
/**
|
|
23
|
-
* The id the Dockerfile templates mount the encrypted credentials under:
|
|
24
|
-
* `RUN --mount=type=secret,id=gkm_credentials`.
|
|
25
|
-
*/
|
|
26
|
-
const CREDENTIALS_SECRET_ID = "gkm_credentials";
|
|
27
|
-
/**
|
|
28
|
-
* Get the full image reference
|
|
29
|
-
*/
|
|
30
|
-
function getImageRef(registry, imageName, tag) {
|
|
31
|
-
if (registry) return `${registry}/${imageName}:${tag}`;
|
|
32
|
-
return `${imageName}:${tag}`;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* The `docker build` argv for an image.
|
|
36
|
-
*
|
|
37
|
-
* One element per value, so nothing in a ref or a build arg is read by a
|
|
38
|
-
* shell, and `--opt=value` rather than `--opt value`, so a value that starts
|
|
39
|
-
* with `-` cannot be taken for one of docker's own flags.
|
|
40
|
-
*
|
|
41
|
-
* @internal Exported for testing
|
|
42
|
-
*/
|
|
43
|
-
function dockerBuildArgs(options) {
|
|
44
|
-
const { dockerfilePath, imageRef, buildArgs = [], credentialsFile } = options;
|
|
45
|
-
return [
|
|
46
|
-
"build",
|
|
47
|
-
"--platform=linux/amd64",
|
|
48
|
-
`--file=${dockerfilePath}`,
|
|
49
|
-
`--tag=${imageRef}`,
|
|
50
|
-
...buildArgs.map((arg) => `--build-arg=${arg}`),
|
|
51
|
-
...credentialsFile ? [`--secret=id=${CREDENTIALS_SECRET_ID},src=${credentialsFile}`] : [],
|
|
52
|
-
"."
|
|
53
|
-
];
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Write the encrypted credentials where `docker build --secret` reads them.
|
|
57
|
-
*
|
|
58
|
-
* Two lines — ciphertext, then IV — so a template can split them with `sed`
|
|
59
|
-
* in any base image. Owner-only, in a directory of its own, and the returned
|
|
60
|
-
* cleanup removes both whatever the build did.
|
|
61
|
-
*
|
|
62
|
-
* @internal Exported for testing
|
|
63
|
-
*/
|
|
64
|
-
async function writeCredentialsFile(credentials) {
|
|
65
|
-
const dir = await mkdtemp(join(tmpdir(), "gkm-credentials-"));
|
|
66
|
-
const path = join(dir, CREDENTIALS_SECRET_ID);
|
|
67
|
-
await writeFile(path, `${credentials.encrypted}\n${credentials.iv}\n`, { mode: 384 });
|
|
68
|
-
await chmod(path, 384);
|
|
69
|
-
return {
|
|
70
|
-
path,
|
|
71
|
-
cleanup: () => rm(dir, {
|
|
72
|
-
recursive: true,
|
|
73
|
-
force: true
|
|
74
|
-
})
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Build Docker image
|
|
79
|
-
* @param imageRef - Full image reference (registry/name:tag)
|
|
80
|
-
* @param buildArgs - Build arguments to pass to docker build
|
|
81
|
-
* @param credentials - Encrypted credentials, passed as a build secret
|
|
82
|
-
*/
|
|
83
|
-
async function buildImage(imageRef, buildArgs, credentials, { cwd, dockerfile, signal, stdio }) {
|
|
84
|
-
logger$3.log(`\n🔨 Building Docker image: ${imageRef}`);
|
|
85
|
-
logger$3.log(" Generating Dockerfile...");
|
|
86
|
-
await dockerCommand({
|
|
87
|
-
slim: true,
|
|
88
|
-
cwd
|
|
89
|
-
});
|
|
90
|
-
const dockerfilePath = dockerfile;
|
|
91
|
-
const secret = credentials ? await writeCredentialsFile(credentials) : void 0;
|
|
92
|
-
try {
|
|
93
|
-
await run("docker", dockerBuildArgs({
|
|
94
|
-
dockerfilePath,
|
|
95
|
-
imageRef,
|
|
96
|
-
buildArgs,
|
|
97
|
-
credentialsFile: secret?.path
|
|
98
|
-
}), {
|
|
99
|
-
cwd,
|
|
100
|
-
env: {
|
|
101
|
-
...process.env,
|
|
102
|
-
DOCKER_BUILDKIT: "1"
|
|
103
|
-
},
|
|
104
|
-
...signal ? { signal } : {},
|
|
105
|
-
...stdio ? { stdio } : {}
|
|
106
|
-
});
|
|
107
|
-
logger$3.log(`✅ Image built: ${imageRef}`);
|
|
108
|
-
} catch (error) {
|
|
109
|
-
throw new DockerBuildFailed(imageRef, error);
|
|
110
|
-
} finally {
|
|
111
|
-
await secret?.cleanup();
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Push Docker image to registry
|
|
116
|
-
*/
|
|
117
|
-
async function pushImage(imageRef, { cwd, signal, stdio }) {
|
|
118
|
-
logger$3.log(`\n☁️ Pushing image: ${imageRef}`);
|
|
119
|
-
try {
|
|
120
|
-
await run("docker", ["push", imageRef], {
|
|
121
|
-
cwd,
|
|
122
|
-
...signal ? { signal } : {},
|
|
123
|
-
...stdio ? { stdio } : {}
|
|
124
|
-
});
|
|
125
|
-
logger$3.log(`✅ Image pushed: ${imageRef}`);
|
|
126
|
-
} catch (error) {
|
|
127
|
-
throw new DockerPushFailed(imageRef, error);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* The digest the registry gave a pushed image, `sha256:…`.
|
|
132
|
-
*
|
|
133
|
-
* A tag can be pushed over — by the next deploy, or by anything else that
|
|
134
|
-
* shares the repository — and the digest is what says which image a stage
|
|
135
|
-
* actually ran. `RepoDigests` has one entry per repository the image was
|
|
136
|
-
* pushed to, so the one for this ref's repository is picked by name.
|
|
137
|
-
*
|
|
138
|
-
* @internal Exported for testing
|
|
139
|
-
*/
|
|
140
|
-
async function pushedDigest(imageRef, { cwd, signal } = { cwd: process.cwd() }) {
|
|
141
|
-
const repository = imageRef.split("@")[0].replace(/:[\w][\w.-]*$/, "");
|
|
142
|
-
const output = await runOutput("docker", [
|
|
143
|
-
"image",
|
|
144
|
-
"inspect",
|
|
145
|
-
"--format={{json .RepoDigests}}",
|
|
146
|
-
imageRef
|
|
147
|
-
], {
|
|
148
|
-
cwd,
|
|
149
|
-
...signal ? { signal } : {}
|
|
150
|
-
});
|
|
151
|
-
let digests;
|
|
152
|
-
try {
|
|
153
|
-
digests = JSON.parse(output.trim() || "[]");
|
|
154
|
-
} catch {
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
if (!Array.isArray(digests)) return void 0;
|
|
158
|
-
return digests.find((entry) => typeof entry === "string" && entry.startsWith(`${repository}@`))?.slice(repository.length + 1);
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Deploy using Docker (build and optionally push image)
|
|
162
|
-
*/
|
|
163
|
-
async function deployDocker(options) {
|
|
164
|
-
const { stage, tag, skipPush, masterKey, config, buildArgs, credentials } = options;
|
|
165
|
-
const imageName = config.imageName;
|
|
166
|
-
const imageRef = validateImageRef(getImageRef(config.registry, imageName, tag));
|
|
167
|
-
const cwd = options.cwd ?? process.cwd();
|
|
168
|
-
const docker = {
|
|
169
|
-
cwd,
|
|
170
|
-
dockerfile: join(cwd, dockerfileOf(config.appName ?? imageName, options.appPath ?? ".")),
|
|
171
|
-
...options.signal ? { signal: options.signal } : {},
|
|
172
|
-
...options.stdio ? { stdio: options.stdio } : {}
|
|
173
|
-
};
|
|
174
|
-
await buildImage(imageRef, buildArgs, credentials, docker);
|
|
175
|
-
let digest;
|
|
176
|
-
if (!skipPush) {
|
|
177
|
-
if (!config.registry) logger$3.warn("\n⚠️ No registry configured. Use --skip-push or configure docker.registry in gkm.config.ts");
|
|
178
|
-
else {
|
|
179
|
-
await pushImage(imageRef, docker);
|
|
180
|
-
digest = await pushedDigest(imageRef, docker);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
logger$3.log("\n✅ Docker deployment ready!");
|
|
184
|
-
logger$3.log(`\n📋 Deployment details:`);
|
|
185
|
-
logger$3.log(` Image: ${imageRef}`);
|
|
186
|
-
logger$3.log(` Stage: ${stage}`);
|
|
187
|
-
if (masterKey) logger$3.log(`\n🔐 Run the container with GKM_MASTER_KEY set to the key with fingerprint ${keyFingerprint(masterKey)}.`);
|
|
188
|
-
return {
|
|
189
|
-
imageRef,
|
|
190
|
-
...digest ? { digest } : {},
|
|
191
|
-
masterKey
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
//#endregion
|
|
195
17
|
//#region src/deploy/ownership.ts
|
|
196
18
|
/**
|
|
197
19
|
* Which Dokploy project a deploy is allowed to deploy into.
|
|
@@ -685,34 +507,47 @@ const PROVISIONERS = {
|
|
|
685
507
|
return { provides: { [provideKey(declaration.id, "url")]: url.toString() } };
|
|
686
508
|
},
|
|
687
509
|
/**
|
|
688
|
-
* A bucket,
|
|
510
|
+
* A bucket: the stage's own, or — allowed — a MinIO stack on the box.
|
|
511
|
+
*
|
|
512
|
+
* A deployed stage's bucket is an external one — S3, R2, any S3-compatible
|
|
513
|
+
* store — whose URL and key pair the stage's secrets hold. Only with
|
|
514
|
+
* `--allow-dev-services minio` does this target run MinIO for one, and
|
|
515
|
+
* then only for a bucket whose URL the stage did not set.
|
|
689
516
|
*
|
|
690
517
|
* Dokploy has first-class primitives for Postgres and Redis and none for
|
|
691
|
-
* object storage, so
|
|
692
|
-
* *writes* rather than configures — a compose file with one
|
|
518
|
+
* object storage, so MinIO is the one kind whose infrastructure this
|
|
519
|
+
* target *writes* rather than configures — a compose file with one
|
|
520
|
+
* service in it.
|
|
693
521
|
*
|
|
694
522
|
* The service is named `cloudName(...)` like everything else, which is not
|
|
695
523
|
* cosmetic here: containers on `dokploy-network` resolve each other by
|
|
696
524
|
* service name, so the name is the address. Calling it `minio` would work
|
|
697
525
|
* for exactly one project on the box and then collide.
|
|
698
526
|
*
|
|
699
|
-
*
|
|
700
|
-
*
|
|
701
|
-
*
|
|
702
|
-
*
|
|
703
|
-
*
|
|
527
|
+
* A stage's own bucket URL may carry a key scoped to that bucket
|
|
528
|
+
* (`s3://KEY:SECRET@bucket`), which the client signs with; the shared
|
|
529
|
+
* `AWS_ACCESS_KEY_ID` pair is passed beside it when the stage set one, for
|
|
530
|
+
* a bucket whose URL has none. The MinIO this provisions uses that pair —
|
|
531
|
+
* the stage's, or one derived for it.
|
|
704
532
|
*/
|
|
705
533
|
objects: async (declaration, context) => {
|
|
706
534
|
if (declaration.kind !== "objects") throw new WrongKind(declaration.kind);
|
|
535
|
+
const key = provideKey(declaration.id, "url");
|
|
536
|
+
const given = context.supplied?.[key];
|
|
537
|
+
if (given !== void 0) return { provides: {
|
|
538
|
+
[key]: given,
|
|
539
|
+
...storageKeys(context.supplied)
|
|
540
|
+
} };
|
|
707
541
|
const backend = context.storage ?? "minio";
|
|
708
542
|
if (backend !== "minio") throw new UnprovisionableBucket(declaration.id, backend);
|
|
543
|
+
if (!context.devServices?.includes("minio")) throw notConfigured(declaration.id, "objects", context);
|
|
709
544
|
const service = serviceName({
|
|
710
545
|
stage: context.stage,
|
|
711
546
|
app: context.scope ?? context.project
|
|
712
547
|
}, declaration.id);
|
|
713
548
|
const bucket = resourceName(declaration.id, declaration.kind, context.stage);
|
|
714
|
-
const user = `${bucket}-root`;
|
|
715
|
-
const password = derivedPassword(context, `objects:${declaration.id}`);
|
|
549
|
+
const user = context.supplied?.AWS_ACCESS_KEY_ID ?? `${bucket}-root`;
|
|
550
|
+
const password = context.supplied?.AWS_SECRET_ACCESS_KEY ?? derivedPassword(context, `objects:${declaration.id}`);
|
|
716
551
|
const { compose } = await context.api.findOrCreateCompose(service, context.projectId, context.environmentId, minioCompose({
|
|
717
552
|
service,
|
|
718
553
|
bucket,
|
|
@@ -721,33 +556,67 @@ const PROVISIONERS = {
|
|
|
721
556
|
}));
|
|
722
557
|
await context.api.deployCompose(compose.composeId);
|
|
723
558
|
return { provides: {
|
|
724
|
-
[
|
|
559
|
+
[key]: s3Url(service, bucket),
|
|
725
560
|
AWS_ACCESS_KEY_ID: user,
|
|
726
561
|
AWS_SECRET_ACCESS_KEY: password,
|
|
727
|
-
AWS_REGION: MINIO_REGION
|
|
562
|
+
AWS_REGION: context.supplied?.AWS_REGION ?? MINIO_REGION
|
|
728
563
|
} };
|
|
729
564
|
},
|
|
730
565
|
/**
|
|
731
566
|
* The address a bucket's objects are served on.
|
|
732
567
|
*
|
|
733
|
-
*
|
|
734
|
-
*
|
|
735
|
-
* target's Caddy has no equivalent here. What this resolves is the address,
|
|
736
|
-
* and the `open` prefixes are applied to the bucket rather than to an edge,
|
|
737
|
-
* so a policy is what makes them public wherever the bucket lives.
|
|
568
|
+
* The stage's own — a CDN, the bucket's domain — when its secrets hold
|
|
569
|
+
* one, which a bucket that is not MinIO's needs.
|
|
738
570
|
*
|
|
739
|
-
*
|
|
740
|
-
*
|
|
741
|
-
*
|
|
571
|
+
* Over MinIO nothing is provisioned: Dokploy runs Traefik, so a second
|
|
572
|
+
* reverse proxy behind the first would terminate TLS twice — which is why
|
|
573
|
+
* the local target's Caddy has no equivalent here. What this resolves is
|
|
574
|
+
* the address, and the `open` prefixes are applied to the bucket rather
|
|
575
|
+
* than to an edge, so a policy is what makes them public wherever the
|
|
576
|
+
* bucket lives. Until a Traefik rule exists it answers on MinIO directly,
|
|
577
|
+
* path-style, which is honest about the shape it has today: the bucket is
|
|
578
|
+
* in the path rather than fronted by a host of its own.
|
|
742
579
|
*/
|
|
743
580
|
"file-server": async (declaration, context) => {
|
|
744
581
|
if (declaration.kind !== "file-server") throw new WrongKind(declaration.kind);
|
|
582
|
+
const key = provideKey(declaration.id, "url");
|
|
583
|
+
const given = context.supplied?.[key];
|
|
584
|
+
if (given !== void 0) return { provides: { [key]: given } };
|
|
745
585
|
const parentUrl = context.provisioned[declaration.of]?.provides[provideKey(declaration.of, "url")];
|
|
746
586
|
if (!parentUrl) throw new UnresolvedParent(declaration.id, declaration.of);
|
|
747
587
|
const endpoint = new URL(parentUrl).searchParams.get("endpoint");
|
|
748
588
|
const bucket = new URL(parentUrl).hostname;
|
|
749
589
|
if (!endpoint) throw new UnresolvedParent(declaration.id, declaration.of);
|
|
750
|
-
return { provides: { [
|
|
590
|
+
return { provides: { [key]: `${endpoint}/${bucket}` } };
|
|
591
|
+
},
|
|
592
|
+
/**
|
|
593
|
+
* Mail: the stage's own SMTP server, or — allowed — Mailpit on the box.
|
|
594
|
+
*
|
|
595
|
+
* Every provider speaks SMTP, so the provider is whatever the stage's
|
|
596
|
+
* `<ID>_URL` names, with the address it sends from beside it. Only with
|
|
597
|
+
* `--allow-dev-services mailpit`, and only where the stage set no URL,
|
|
598
|
+
* does this run Mailpit — which catches every message and delivers none.
|
|
599
|
+
*/
|
|
600
|
+
email: async (declaration, context) => {
|
|
601
|
+
if (declaration.kind !== "email") throw new WrongKind(declaration.kind);
|
|
602
|
+
const key = provideKey(declaration.id, "url");
|
|
603
|
+
const from = provideKey(declaration.id, "from");
|
|
604
|
+
const given = context.supplied?.[key];
|
|
605
|
+
if (given !== void 0) return { provides: {
|
|
606
|
+
[key]: given,
|
|
607
|
+
[from]: supplied(declaration.id, from, context)
|
|
608
|
+
} };
|
|
609
|
+
if (!context.devServices?.includes("mailpit")) throw notConfigured(declaration.id, "email", context);
|
|
610
|
+
const service = serviceName({
|
|
611
|
+
stage: context.stage,
|
|
612
|
+
app: context.scope ?? context.project
|
|
613
|
+
}, declaration.id);
|
|
614
|
+
const { compose } = await context.api.findOrCreateCompose(service, context.projectId, context.environmentId, mailpitCompose(service));
|
|
615
|
+
await context.api.deployCompose(compose.composeId);
|
|
616
|
+
return { provides: {
|
|
617
|
+
[key]: `smtp://${service}:1025`,
|
|
618
|
+
[from]: context.supplied?.[from] ?? `noreply@${context.domain ?? "localhost"}`
|
|
619
|
+
} };
|
|
751
620
|
},
|
|
752
621
|
/**
|
|
753
622
|
* A topic, and below it a queue — the same broker either way.
|
|
@@ -985,6 +854,56 @@ function minioCompose(options) {
|
|
|
985
854
|
""
|
|
986
855
|
].join("\n");
|
|
987
856
|
}
|
|
857
|
+
/**
|
|
858
|
+
* A one-service compose file for Mailpit, on `dokploy-network` so the apps
|
|
859
|
+
* reach it by its service name. It accepts mail from anything on the network
|
|
860
|
+
* and delivers none of it.
|
|
861
|
+
*/
|
|
862
|
+
function mailpitCompose(service) {
|
|
863
|
+
return [
|
|
864
|
+
"services:",
|
|
865
|
+
` ${service}:`,
|
|
866
|
+
" image: axllent/mailpit:latest",
|
|
867
|
+
" environment:",
|
|
868
|
+
" MP_SMTP_AUTH_ACCEPT_ANY: '1'",
|
|
869
|
+
" MP_SMTP_AUTH_ALLOW_INSECURE: '1'",
|
|
870
|
+
" networks:",
|
|
871
|
+
" - dokploy-network",
|
|
872
|
+
"networks:",
|
|
873
|
+
" dokploy-network:",
|
|
874
|
+
" external: true",
|
|
875
|
+
""
|
|
876
|
+
].join("\n");
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* The S3 client's shared keys the stage set, for a bucket that is its own —
|
|
880
|
+
* none when it set none, since a bucket's URL may carry its own key.
|
|
881
|
+
*/
|
|
882
|
+
function storageKeys(values) {
|
|
883
|
+
const keys = {};
|
|
884
|
+
for (const key of [...STORAGE_KEY_PAIR, "AWS_REGION"]) {
|
|
885
|
+
const value = values?.[key];
|
|
886
|
+
if (value !== void 0) keys[key] = value;
|
|
887
|
+
}
|
|
888
|
+
return keys;
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* The error for a bucket or mail the stage configured nothing for — what
|
|
892
|
+
* `validate` already refused, should a provisioner be reached without it.
|
|
893
|
+
*/
|
|
894
|
+
function notConfigured(id, kind, context) {
|
|
895
|
+
const { missing } = externalServices({
|
|
896
|
+
stage: context.stage,
|
|
897
|
+
declarations: [{
|
|
898
|
+
id,
|
|
899
|
+
kind
|
|
900
|
+
}],
|
|
901
|
+
supplied: context.supplied ?? {},
|
|
902
|
+
allow: [],
|
|
903
|
+
...context.domain ? { domain: context.domain } : {}
|
|
904
|
+
});
|
|
905
|
+
return new ExternalServicesNotConfigured(context.stage, missing);
|
|
906
|
+
}
|
|
988
907
|
/** Whether anything reads through a reader on this construct. */
|
|
989
908
|
function readsFrom(manifest, id) {
|
|
990
909
|
return Object.values(manifest).some((declaration) => declaration.kind === "database-reader" && declaration.of === id);
|
|
@@ -1173,6 +1092,8 @@ async function provisionDeclared(options) {
|
|
|
1173
1092
|
cache: cacheBackendFor(providerOf(workspace)),
|
|
1174
1093
|
events: eventsBackendFor(providerOf(workspace)),
|
|
1175
1094
|
storage: storageBackendFor(providerOf(workspace)),
|
|
1095
|
+
...options.devServices ? { devServices: options.devServices } : {},
|
|
1096
|
+
...workspace.deploy?.domains?.[options.stage] ? { domain: workspace.deploy.domains[options.stage] } : {},
|
|
1176
1097
|
addresses: surfaceAddresses(manifest, options.appUrls),
|
|
1177
1098
|
seed: options.seed,
|
|
1178
1099
|
...options.supplied ? { supplied: options.supplied } : {},
|
|
@@ -1273,7 +1194,7 @@ async function createDnsProvider(options) {
|
|
|
1273
1194
|
if (isDnsProvider(config.provider)) return config.provider;
|
|
1274
1195
|
const provider = config.provider;
|
|
1275
1196
|
if (provider === "hostinger") {
|
|
1276
|
-
const { HostingerProvider } = await import("./HostingerProvider-
|
|
1197
|
+
const { HostingerProvider } = await import("./HostingerProvider-D85ayzTi.mjs");
|
|
1277
1198
|
return new HostingerProvider();
|
|
1278
1199
|
}
|
|
1279
1200
|
if (provider === "route53") {
|
|
@@ -2164,8 +2085,18 @@ async function validateDokploy(phase) {
|
|
|
2164
2085
|
secrets: phase.secrets,
|
|
2165
2086
|
ctx
|
|
2166
2087
|
};
|
|
2088
|
+
const stored = await phase.secrets.read();
|
|
2089
|
+
const services = assertExternalServices({
|
|
2090
|
+
stage,
|
|
2091
|
+
declarations: manifestServiceDeclarations(phase.manifest),
|
|
2092
|
+
supplied: stored?.custom ?? {},
|
|
2093
|
+
allow: phase.allowDevServices,
|
|
2094
|
+
...workspace.deploy?.domains?.[stage] ? { domain: workspace.deploy.domains[stage] } : {}
|
|
2095
|
+
});
|
|
2096
|
+
reportDevServices(phase, devServicesUsed(services));
|
|
2167
2097
|
return {
|
|
2168
2098
|
...run,
|
|
2099
|
+
allowDevServices: phase.allowDevServices,
|
|
2169
2100
|
preflight: await preflight(run),
|
|
2170
2101
|
verify: verifySettings(workspace.deploy.dokploy?.verify),
|
|
2171
2102
|
atomic: phase.atomic,
|
|
@@ -2345,7 +2276,8 @@ async function provision(run) {
|
|
|
2345
2276
|
appUrls,
|
|
2346
2277
|
supplied: stageSecrets.custom,
|
|
2347
2278
|
seed: stageSecrets.seed,
|
|
2348
|
-
manifest
|
|
2279
|
+
manifest,
|
|
2280
|
+
devServices: run.allowDevServices
|
|
2349
2281
|
});
|
|
2350
2282
|
declaredEnv = declared.env;
|
|
2351
2283
|
declaredClusters = declared.clusters;
|
|
@@ -3163,4 +3095,4 @@ const MOBILE_SKIP_REASON = "deploys via its framework toolchain";
|
|
|
3163
3095
|
//#endregion
|
|
3164
3096
|
export { RegistryNotConfigured as _, dokployResult as a, releaseDokploy as c, validateDokploy as d, verifyDokploy as f, RegistryAmbiguous as g, HealthCheckTimedOut as h, dokployApi as i, restoreImage as l, DeployMigrationsFailed as m, FrontendDeployFailed as n, planDokploy as o, verifySettings as p, MissingEnvVars as r, provisionDokploy as s, BackendDeployFailed as t, rollbackDokploy as u, RegistryNotFound as v, ProjectNotOwned as y };
|
|
3165
3097
|
|
|
3166
|
-
//# sourceMappingURL=engine-
|
|
3098
|
+
//# sourceMappingURL=engine-llWnMZH5.mjs.map
|