dokku-compose 0.10.0 → 0.11.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/README.md +1 -0
- package/dist/index.js +50 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -111,6 +111,7 @@ All features are idempotent — running `up` twice produces no changes.
|
|
|
111
111
|
| Feature | Description | Reference |
|
|
112
112
|
|---------|-------------|-----------|
|
|
113
113
|
| Apps | Create and destroy Dokku apps | [apps](docs/reference/apps.md) |
|
|
114
|
+
| Dokku Version | Warn when the server's Dokku version is older than the pinned floor | [dokku](docs/reference/dokku.md) |
|
|
114
115
|
| Environment Variables | Set config vars per app or globally, with full convergence | [config](docs/reference/config.md) |
|
|
115
116
|
| Build | Dockerfile path, build context, app.json, build args | [builder](docs/reference/builder.md) |
|
|
116
117
|
| Docker Options | Custom Docker options per phase (build/deploy/run) | [docker_options](docs/reference/docker_options.md) |
|
package/dist/index.js
CHANGED
|
@@ -154,6 +154,7 @@ function createRunner(opts = {}) {
|
|
|
154
154
|
const controlPath = opts.host ? path.join(os.tmpdir(), `dc-${createHash("sha1").update(opts.host).digest("hex").slice(0, 16)}.sock`) : null;
|
|
155
155
|
const sshControlFlags = controlPath ? ["-o", "ControlMaster=auto", "-o", `ControlPath=${controlPath}`, "-o", "ControlPersist=60"] : [];
|
|
156
156
|
function shellQuote(arg) {
|
|
157
|
+
if (/^[A-Za-z0-9_\-:.,/=@]+$/.test(arg)) return arg;
|
|
157
158
|
return `'${arg.replace(/'/g, "'\\''")}'`;
|
|
158
159
|
}
|
|
159
160
|
async function execDokku(args) {
|
|
@@ -274,6 +275,9 @@ function logDone() {
|
|
|
274
275
|
function logSkip() {
|
|
275
276
|
console.log(`... ${chalk.yellow("already configured")}`);
|
|
276
277
|
}
|
|
278
|
+
function logWarn(context, message) {
|
|
279
|
+
console.warn(chalk.yellow(`[${context.padEnd(12)}] WARN: ${message}`));
|
|
280
|
+
}
|
|
277
281
|
|
|
278
282
|
// src/core/reconcile.ts
|
|
279
283
|
async function reconcile(resource, ctx, target, desired) {
|
|
@@ -392,18 +396,21 @@ var Domains = {
|
|
|
392
396
|
for (const d of added) await ctx.run("domains:add", target, d);
|
|
393
397
|
}
|
|
394
398
|
};
|
|
399
|
+
function parseDeployMounts(raw) {
|
|
400
|
+
return raw.split(/\s+/).filter((s) => s && s !== "-v");
|
|
401
|
+
}
|
|
395
402
|
var Storage = {
|
|
396
403
|
key: "storage",
|
|
397
404
|
read: async (ctx, target) => {
|
|
398
|
-
const raw = await ctx.query("storage:report", target, "--storage-mounts");
|
|
399
|
-
return
|
|
405
|
+
const raw = await ctx.query("storage:report", target, "--storage-deploy-mounts");
|
|
406
|
+
return parseDeployMounts(raw);
|
|
400
407
|
},
|
|
401
408
|
readAll: async (ctx) => {
|
|
402
409
|
const raw = await ctx.query("storage:report");
|
|
403
410
|
const bulk = parseBulkReport(raw, "storage");
|
|
404
411
|
const result = /* @__PURE__ */ new Map();
|
|
405
412
|
for (const [app, report] of bulk) {
|
|
406
|
-
result.set(app, report["mounts"] ?
|
|
413
|
+
result.set(app, report["deploy-mounts"] ? parseDeployMounts(report["deploy-mounts"]) : []);
|
|
407
414
|
}
|
|
408
415
|
return result;
|
|
409
416
|
},
|
|
@@ -814,7 +821,7 @@ async function ensurePlugins(ctx, plugins) {
|
|
|
814
821
|
async function ensureDockerAuth(ctx, config) {
|
|
815
822
|
for (const [server, creds] of Object.entries(config)) {
|
|
816
823
|
logAction("docker-auth", `Logging in to ${server} as ${creds.username}`);
|
|
817
|
-
await ctx.run("registry:login", server, creds.username, creds.password);
|
|
824
|
+
await ctx.run("registry:login", "--global", server, creds.username, creds.password);
|
|
818
825
|
logDone();
|
|
819
826
|
}
|
|
820
827
|
}
|
|
@@ -1012,6 +1019,40 @@ async function exportRedis(ctx) {
|
|
|
1012
1019
|
return services;
|
|
1013
1020
|
}
|
|
1014
1021
|
|
|
1022
|
+
// src/modules/version.ts
|
|
1023
|
+
var SEMVER_RE = /^(\d+)\.(\d+)\.(\d+)/;
|
|
1024
|
+
function parseSemver(input) {
|
|
1025
|
+
const m = input.match(SEMVER_RE);
|
|
1026
|
+
if (!m) throw new Error(`Cannot parse version: ${input}`);
|
|
1027
|
+
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
1028
|
+
}
|
|
1029
|
+
function extractServerVersion(output) {
|
|
1030
|
+
const match = output.match(/(\d+\.\d+\.\d+)/);
|
|
1031
|
+
return match ? match[1] : null;
|
|
1032
|
+
}
|
|
1033
|
+
function compareSemver(a, b) {
|
|
1034
|
+
const [aMaj, aMin, aPatch] = parseSemver(a);
|
|
1035
|
+
const [bMaj, bMin, bPatch] = parseSemver(b);
|
|
1036
|
+
if (aMaj !== bMaj) return aMaj < bMaj ? -1 : 1;
|
|
1037
|
+
if (aMin !== bMin) return aMin < bMin ? -1 : 1;
|
|
1038
|
+
if (aPatch !== bPatch) return aPatch < bPatch ? -1 : 1;
|
|
1039
|
+
return 0;
|
|
1040
|
+
}
|
|
1041
|
+
async function ensureDokkuVersion(ctx, pinned) {
|
|
1042
|
+
if (!pinned) return;
|
|
1043
|
+
const output = await ctx.query("version");
|
|
1044
|
+
const server = extractServerVersion(output);
|
|
1045
|
+
if (!server) {
|
|
1046
|
+
throw new Error(`Cannot parse Dokku server version from output: ${output}`);
|
|
1047
|
+
}
|
|
1048
|
+
if (compareSemver(server, pinned) === -1) {
|
|
1049
|
+
logWarn(
|
|
1050
|
+
"dokku",
|
|
1051
|
+
`server is v${server} but dokku-compose.yml pins >= v${pinned}. Some features may be unavailable.`
|
|
1052
|
+
);
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1015
1056
|
// src/modules/links.ts
|
|
1016
1057
|
function resolveServicePlugin(name, config) {
|
|
1017
1058
|
if (config.postgres?.[name]) return { plugin: "postgres", config: config.postgres[name] };
|
|
@@ -1094,6 +1135,7 @@ async function ensureGlobalNginx(ctx, nginx) {
|
|
|
1094
1135
|
// src/commands/up.ts
|
|
1095
1136
|
async function runUp(ctx, config, appFilter) {
|
|
1096
1137
|
const apps = appFilter.length > 0 ? appFilter : Object.keys(config.apps);
|
|
1138
|
+
await ensureDokkuVersion(ctx, config.dokku?.version);
|
|
1097
1139
|
if (config.plugins) await ensurePlugins(ctx, config.plugins);
|
|
1098
1140
|
if (config.docker_auth) await ensureDockerAuth(ctx, config.docker_auth);
|
|
1099
1141
|
if (config.domains !== void 0) await ensureGlobalDomains(ctx, config.domains);
|
|
@@ -1207,9 +1249,8 @@ var ALL_APP_RESOURCES = [
|
|
|
1207
1249
|
// src/commands/export.ts
|
|
1208
1250
|
async function runExport(ctx, opts) {
|
|
1209
1251
|
const config = { apps: {} };
|
|
1210
|
-
const
|
|
1211
|
-
|
|
1212
|
-
if (versionMatch) config.dokku = { version: versionMatch[1] };
|
|
1252
|
+
const version2 = extractServerVersion(await ctx.query("version"));
|
|
1253
|
+
if (version2) config.dokku = { version: version2 };
|
|
1213
1254
|
const apps = opts.appFilter?.length ? opts.appFilter : await exportApps(ctx);
|
|
1214
1255
|
const networks = await exportNetworks(ctx);
|
|
1215
1256
|
if (networks.length > 0) config.networks = networks;
|
|
@@ -1259,7 +1300,7 @@ function maskSensitiveArgs(cmd) {
|
|
|
1259
1300
|
return `${key}=${maskValue(value)}`;
|
|
1260
1301
|
});
|
|
1261
1302
|
masked = masked.replace(
|
|
1262
|
-
/^(registry:login\s
|
|
1303
|
+
/^(registry:login\s+(?:--global\s+)?\S+\s+\S+\s+)(\S+)/,
|
|
1263
1304
|
(_, prefix, password) => `${prefix}${maskValue(password)}`
|
|
1264
1305
|
);
|
|
1265
1306
|
return masked;
|
|
@@ -1288,6 +1329,7 @@ function maskSensitiveData(data) {
|
|
|
1288
1329
|
import chalk2 from "chalk";
|
|
1289
1330
|
async function computeDiff(ctx, config) {
|
|
1290
1331
|
const result = { apps: {}, services: {}, inSync: true };
|
|
1332
|
+
await ensureDokkuVersion(ctx, config.dokku?.version);
|
|
1291
1333
|
const prefetched = /* @__PURE__ */ new Map();
|
|
1292
1334
|
await Promise.all(
|
|
1293
1335
|
ALL_APP_RESOURCES.filter((r) => !r.forceApply && !r.key.startsWith("_") && r.readAll).map(async (r) => {
|