dockup-cli 1.1.0 → 1.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/commands/agent.js +76 -0
- package/dist/index.js +3 -1
- package/dist/lib/api.js +13 -0
- package/dockupcli.md +26 -0
- package/package.json +1 -1
package/dist/commands/agent.js
CHANGED
|
@@ -38,6 +38,8 @@ __export(agent_exports, {
|
|
|
38
38
|
logsView: () => logsView,
|
|
39
39
|
registryClear: () => registryClear,
|
|
40
40
|
registrySet: () => registrySet,
|
|
41
|
+
resourcesSet: () => resourcesSet,
|
|
42
|
+
resourcesView: () => resourcesView,
|
|
41
43
|
servicesList: () => servicesList,
|
|
42
44
|
statusView: () => statusView
|
|
43
45
|
});
|
|
@@ -326,6 +328,78 @@ async function registryClear(arg, opts) {
|
|
|
326
328
|
(0, import_output.fail)(e.message);
|
|
327
329
|
}
|
|
328
330
|
}
|
|
331
|
+
const CPU_PER_MONTH = 463e-6 * 43200;
|
|
332
|
+
const MEM_PER_GB_PER_MONTH = 231e-6 * 43200;
|
|
333
|
+
const monthlyCost = (cpu, memMB) => Math.round((cpu * CPU_PER_MONTH + memMB / 1024 * MEM_PER_GB_PER_MONTH) * 100) / 100;
|
|
334
|
+
async function resourcesView(arg, opts) {
|
|
335
|
+
applyJson(opts);
|
|
336
|
+
requireAuth();
|
|
337
|
+
const t = target(arg);
|
|
338
|
+
try {
|
|
339
|
+
let memMB, cpu, name, kind;
|
|
340
|
+
if (opts?.db) {
|
|
341
|
+
const d = await import_api.api.getDatabaseDetail(t.projectSlug, t.serviceSlug);
|
|
342
|
+
const s = d.settings || d.database || d;
|
|
343
|
+
memMB = s.memoryLimitMB ?? 1024;
|
|
344
|
+
cpu = s.cpuLimit ?? 1;
|
|
345
|
+
name = d.database?.name || s.name || t.serviceSlug;
|
|
346
|
+
kind = "database";
|
|
347
|
+
} else {
|
|
348
|
+
const s = await import_api.api.getServiceStatus(t.projectSlug, t.serviceSlug);
|
|
349
|
+
memMB = s.memoryLimit ?? 2048;
|
|
350
|
+
cpu = s.cpuLimit ?? 2;
|
|
351
|
+
name = s.name || t.serviceSlug;
|
|
352
|
+
kind = "service";
|
|
353
|
+
}
|
|
354
|
+
const data = {
|
|
355
|
+
target: `${t.projectSlug}/${t.serviceSlug}`,
|
|
356
|
+
kind,
|
|
357
|
+
name,
|
|
358
|
+
cpu,
|
|
359
|
+
memoryMB: memMB,
|
|
360
|
+
estMonthlyUsd: monthlyCost(cpu, memMB),
|
|
361
|
+
limits: { maxCpu: 24, maxMemMB: 24576 }
|
|
362
|
+
};
|
|
363
|
+
(0, import_output.emit)(data, () => {
|
|
364
|
+
console.log(import_chalk.default.cyan(`
|
|
365
|
+
${import_chalk.default.bold(name)} ${import_chalk.default.dim(data.target)} ${import_chalk.default.dim("(" + kind + ")")}
|
|
366
|
+
`));
|
|
367
|
+
console.log(` ${import_chalk.default.dim("CPU:")} ${cpu} vCPU`);
|
|
368
|
+
console.log(` ${import_chalk.default.dim("RAM:")} ${memMB >= 1024 ? memMB / 1024 + " GB" : memMB + " MB"}`);
|
|
369
|
+
console.log(` ${import_chalk.default.dim("Est.:")} $${data.estMonthlyUsd.toFixed(2)}/mo ${import_chalk.default.dim("+ disk")}`);
|
|
370
|
+
console.log();
|
|
371
|
+
});
|
|
372
|
+
} catch (e) {
|
|
373
|
+
(0, import_output.fail)(e.message);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
async function resourcesSet(arg, opts) {
|
|
377
|
+
applyJson(opts);
|
|
378
|
+
requireAuth();
|
|
379
|
+
const t = target(arg);
|
|
380
|
+
const cpu = opts?.cpu !== void 0 ? parseFloat(opts.cpu) : void 0;
|
|
381
|
+
const mem = opts?.memory !== void 0 ? parseInt(opts.memory, 10) : void 0;
|
|
382
|
+
if (cpu === void 0 && mem === void 0) {
|
|
383
|
+
return (0, import_output.fail)("Provide --cpu <vCPU> and/or --memory <MB>.", { code: "bad_args" });
|
|
384
|
+
}
|
|
385
|
+
if (cpu !== void 0 && (isNaN(cpu) || cpu <= 0)) return (0, import_output.fail)("--cpu must be a positive number (max 24).", { code: "bad_args" });
|
|
386
|
+
if (mem !== void 0 && (isNaN(mem) || mem <= 0)) return (0, import_output.fail)("--memory must be MB (e.g. 4096, max 24576).", { code: "bad_args" });
|
|
387
|
+
try {
|
|
388
|
+
if (opts?.db) {
|
|
389
|
+
const res = await import_api.api.setDatabaseResources(t.projectSlug, t.serviceSlug, mem ?? 1024, cpu ?? 1);
|
|
390
|
+
(0, import_output.ok)({ target: `${t.projectSlug}/${t.serviceSlug}`, kind: "database", memoryMB: res.memoryLimitMB, cpu: res.cpuLimit, applied: res.applied, estMonthlyUsd: monthlyCost(res.cpuLimit, res.memoryLimitMB) }, () => {
|
|
391
|
+
console.log(import_chalk.default.green(`\u2713 ${res.cpuLimit} vCPU / ${res.memoryLimitMB} MB`) + import_chalk.default.dim(` ${res.applied ? "(applied)" : "(start db to apply)"} ~$${monthlyCost(res.cpuLimit, res.memoryLimitMB).toFixed(2)}/mo`));
|
|
392
|
+
});
|
|
393
|
+
} else {
|
|
394
|
+
const res = await import_api.api.setServiceResources(t.projectSlug, t.serviceSlug, mem ?? 2048, cpu ?? 2);
|
|
395
|
+
(0, import_output.ok)({ target: `${t.projectSlug}/${t.serviceSlug}`, kind: "service", memoryMB: res.memoryLimit, cpu: res.cpuLimit, applied: res.applied, estMonthlyUsd: monthlyCost(res.cpuLimit, res.memoryLimit) }, () => {
|
|
396
|
+
console.log(import_chalk.default.green(`\u2713 ${res.cpuLimit} vCPU / ${res.memoryLimit} MB`) + import_chalk.default.dim(` ${res.applied ? "(applied)" : "(redeploy to apply)"} ~$${monthlyCost(res.cpuLimit, res.memoryLimit).toFixed(2)}/mo`));
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
} catch (e) {
|
|
400
|
+
(0, import_output.fail)(e.message);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
329
403
|
async function deployTrigger(arg, opts) {
|
|
330
404
|
applyJson(opts);
|
|
331
405
|
requireAuth();
|
|
@@ -351,6 +425,8 @@ async function deployTrigger(arg, opts) {
|
|
|
351
425
|
logsView,
|
|
352
426
|
registryClear,
|
|
353
427
|
registrySet,
|
|
428
|
+
resourcesSet,
|
|
429
|
+
resourcesView,
|
|
354
430
|
servicesList,
|
|
355
431
|
statusView
|
|
356
432
|
});
|
package/dist/index.js
CHANGED
|
@@ -32,7 +32,7 @@ var import_agent = require("./commands/agent");
|
|
|
32
32
|
var import_workspace = require("./commands/workspace");
|
|
33
33
|
var import_database = require("./commands/database");
|
|
34
34
|
const program = new import_commander.Command();
|
|
35
|
-
program.name("dockup").description("Dockup CLI - Deploy from your terminal").version("1.
|
|
35
|
+
program.name("dockup").description("Dockup CLI - Deploy from your terminal").version("1.2.0");
|
|
36
36
|
program.command("login").description("Authenticate with Dockup").option("-t, --token <token>", "Use API token directly").action(import_auth.login);
|
|
37
37
|
program.command("logout").description("Log out from Dockup").action(import_auth.logout);
|
|
38
38
|
program.command("whoami").description("Show current logged in user").action(import_auth.whoami);
|
|
@@ -52,6 +52,8 @@ program.command("deployments [project/service]").alias("history").description("D
|
|
|
52
52
|
const registryCmd = program.command("registry").description("Private registry auth for a private FROM base image");
|
|
53
53
|
registryCmd.command("set [project/service]").description("Set registry credentials (used at build time to pull a private base image)").requiredOption("--url <registry>", "Registry host, e.g. ghcr.io").requiredOption("--user <username>", "Registry username").requiredOption("--token <token>", "PAT / password").option("-j, --json", "Machine-readable JSON output").action(import_agent.registrySet);
|
|
54
54
|
registryCmd.command("clear [project/service]").description("Remove registry credentials").option("-j, --json", "Machine-readable JSON output").action(import_agent.registryClear);
|
|
55
|
+
const resourcesCmd = program.command("resources [project/target]").alias("res").description("View reserved CPU/RAM (use `resources set` to change; --db for databases)").option("--db", "Target a database instead of a service").option("-j, --json", "Machine-readable JSON output").action(import_agent.resourcesView);
|
|
56
|
+
resourcesCmd.command("set [project/target]").description("Set reserved CPU/RAM \u2014 PRO (max 24 vCPU / 24576 MB)").option("--cpu <vcpu>", "vCPU to reserve, e.g. 2").option("--memory <mb>", "RAM in MB to reserve, e.g. 4096").option("--db", "Target a database instead of a service").option("-j, --json", "Machine-readable JSON output").action(import_agent.resourcesSet);
|
|
55
57
|
program.command("deploy [project/service]").description("Trigger a deployment (no git push; use `push` for git+deploy)").option("-b, --branch <branch>", "Branch to deploy").option("-j, --json", "Machine-readable JSON output").action(import_agent.deployTrigger);
|
|
56
58
|
program.command("open").description("Open service in browser").option("-d, --dashboard", "Open dashboard instead of live URL").action(import_open.open);
|
|
57
59
|
const workspaceCmd = program.command("workspace").alias("ws").description("Manage workspaces");
|
package/dist/lib/api.js
CHANGED
|
@@ -238,6 +238,19 @@ class ApiClient {
|
|
|
238
238
|
async clearRegistry(projectSlug, serviceSlug) {
|
|
239
239
|
return this.delete(`/projects/${projectSlug}/services/${serviceSlug}/registry`);
|
|
240
240
|
}
|
|
241
|
+
// ==================== RESOURCES (reserved CPU/RAM) ====================
|
|
242
|
+
// Database detail (project-scoped) — includes memoryLimitMB / cpuLimit.
|
|
243
|
+
async getDatabaseDetail(projectSlug, dbSlug) {
|
|
244
|
+
return this.get(`/projects/${projectSlug}/databases/${dbSlug}`);
|
|
245
|
+
}
|
|
246
|
+
// Set reserved CPU/RAM for a service (PRO). Applied by recreating the container.
|
|
247
|
+
async setServiceResources(projectSlug, serviceSlug, memoryLimit, cpuLimit) {
|
|
248
|
+
return this.post(`/projects/${projectSlug}/services/${serviceSlug}/resources`, { memoryLimit, cpuLimit });
|
|
249
|
+
}
|
|
250
|
+
// Set reserved CPU/RAM for a database (PRO, main-server only).
|
|
251
|
+
async setDatabaseResources(projectSlug, dbSlug, memoryLimitMB, cpuLimit) {
|
|
252
|
+
return this.post(`/projects/${projectSlug}/databases/${dbSlug}/resources`, { memoryLimitMB, cpuLimit });
|
|
253
|
+
}
|
|
241
254
|
}
|
|
242
255
|
const api = new ApiClient();
|
|
243
256
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dockupcli.md
CHANGED
|
@@ -135,6 +135,32 @@ dockup registry clear my-project/my-api --json
|
|
|
135
135
|
- `dockup info --json` shows `registryUrl`, `registryUsername` and
|
|
136
136
|
`hasRegistryAuth` (the password is never exposed).
|
|
137
137
|
|
|
138
|
+
### Resources (reserved CPU & RAM — PRO)
|
|
139
|
+
|
|
140
|
+
Pick how much CPU and RAM a service or database reserves. Billing follows the
|
|
141
|
+
allocation (≈ $20/vCPU + $10/GB per month + disk). Max **24 vCPU / 24576 MB**.
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# View current allocation + estimated monthly cost
|
|
145
|
+
dockup resources my-project/my-api --json
|
|
146
|
+
# → {"target","kind":"service","name","cpu","memoryMB","estMonthlyUsd","limits":{"maxCpu":24,"maxMemMB":24576}}
|
|
147
|
+
|
|
148
|
+
# Set (service). Applied live by recreating the container (no rebuild; data persists).
|
|
149
|
+
dockup resources set my-project/my-api --cpu 2 --memory 4096 --json
|
|
150
|
+
# → {"ok":true,"target","kind":"service","cpu","memoryMB","applied","estMonthlyUsd"}
|
|
151
|
+
|
|
152
|
+
# Databases: add --db (main-server databases only; recreates the container, volume kept)
|
|
153
|
+
dockup resources my-project/my-db --db --json
|
|
154
|
+
dockup resources set my-project/my-db --db --cpu 1 --memory 2048 --json
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
- `--cpu` is vCPU (e.g. `0.5`, `2`, `8`); `--memory` is MB (e.g. `512`, `4096`).
|
|
158
|
+
- Values out of range are clamped to `[0.5 vCPU, 512 MB] … [24 vCPU, 24576 MB]`.
|
|
159
|
+
- PRO only — non-PRO accounts get `403 Upgrade required`.
|
|
160
|
+
- `applied:true` means a running container was recreated immediately; otherwise
|
|
161
|
+
it applies on the next deploy (service) / start (database).
|
|
162
|
+
- `dockup info --json` also surfaces a service's current `memoryLimit`/`cpuLimit`.
|
|
163
|
+
|
|
138
164
|
---
|
|
139
165
|
|
|
140
166
|
## Agent recipes
|