@eudiplo/cli 8.0.1 → 8.0.2-main.4c3e735
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 +5 -1
- package/dist/commands/config/validate/schemas.d.ts.map +1 -1
- package/dist/commands/config/validate/schemas.js +3 -3
- package/dist/commands/config/validate/schemas.js.map +1 -1
- package/dist/commands/deployment/action.d.ts +1 -1
- package/dist/commands/deployment/action.d.ts.map +1 -1
- package/dist/commands/deployment/action.js.map +1 -1
- package/dist/commands/deployment/index.d.ts.map +1 -1
- package/dist/commands/deployment/index.js +7 -4
- package/dist/commands/deployment/index.js.map +1 -1
- package/dist/commands/open/action.d.ts +9 -0
- package/dist/commands/open/action.d.ts.map +1 -0
- package/dist/commands/open/action.js +41 -0
- package/dist/commands/open/action.js.map +1 -0
- package/dist/commands/open/index.d.ts +5 -0
- package/dist/commands/open/index.d.ts.map +1 -0
- package/dist/commands/open/index.js +15 -0
- package/dist/commands/open/index.js.map +1 -0
- package/dist/commands/upgrade/action.d.ts +3 -0
- package/dist/commands/upgrade/action.d.ts.map +1 -0
- package/dist/commands/upgrade/action.js +95 -0
- package/dist/commands/upgrade/action.js.map +1 -0
- package/dist/commands/upgrade/index.d.ts +5 -0
- package/dist/commands/upgrade/index.d.ts.map +1 -0
- package/dist/commands/upgrade/index.js +15 -0
- package/dist/commands/upgrade/index.js.map +1 -0
- package/dist/index.js +632 -87
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +4 -0
- package/dist/runtime.js.map +1 -1
- package/dist/sea-assets.d.ts +1 -0
- package/dist/sea-assets.d.ts.map +1 -1
- package/dist/sea-assets.js +17 -0
- package/dist/sea-assets.js.map +1 -1
- package/dist/services/browser.d.ts +30 -0
- package/dist/services/browser.d.ts.map +1 -0
- package/dist/services/browser.js +102 -0
- package/dist/services/browser.js.map +1 -0
- package/dist/services/compose-args.d.ts +28 -0
- package/dist/services/compose-args.d.ts.map +1 -0
- package/dist/services/compose-args.js +117 -0
- package/dist/services/compose-args.js.map +1 -0
- package/dist/services/compose-project.d.ts.map +1 -1
- package/dist/services/compose-project.js +5 -5
- package/dist/services/compose-project.js.map +1 -1
- package/dist/services/compose-upgrade.d.ts +40 -0
- package/dist/services/compose-upgrade.d.ts.map +1 -0
- package/dist/services/compose-upgrade.js +102 -0
- package/dist/services/compose-upgrade.js.map +1 -0
- package/dist/services/deployment-drivers.d.ts +8 -1
- package/dist/services/deployment-drivers.d.ts.map +1 -1
- package/dist/services/deployment-drivers.js +85 -19
- package/dist/services/deployment-drivers.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/templates/schemas/KeyChainConfigFile.schema.json +7 -3
- package/templates/schemas/KeyChainImportDto.schema.json +7 -3
package/dist/index.js
CHANGED
|
@@ -2980,7 +2980,7 @@ var require_compile = __commonJS({
|
|
|
2980
2980
|
const schOrFunc = root.refs[ref];
|
|
2981
2981
|
if (schOrFunc)
|
|
2982
2982
|
return schOrFunc;
|
|
2983
|
-
let _sch =
|
|
2983
|
+
let _sch = resolve9.call(this, root, ref);
|
|
2984
2984
|
if (_sch === void 0) {
|
|
2985
2985
|
const schema = (_a2 = root.localRefs) === null || _a2 === void 0 ? void 0 : _a2[ref];
|
|
2986
2986
|
const { schemaId } = this.opts;
|
|
@@ -3007,7 +3007,7 @@ var require_compile = __commonJS({
|
|
|
3007
3007
|
function sameSchemaEnv(s1, s2) {
|
|
3008
3008
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3009
3009
|
}
|
|
3010
|
-
function
|
|
3010
|
+
function resolve9(root, ref) {
|
|
3011
3011
|
let sch;
|
|
3012
3012
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3013
3013
|
ref = sch;
|
|
@@ -3832,7 +3832,7 @@ var require_fast_uri = __commonJS({
|
|
|
3832
3832
|
}
|
|
3833
3833
|
return uri;
|
|
3834
3834
|
}
|
|
3835
|
-
function
|
|
3835
|
+
function resolve9(baseURI, relativeURI, options) {
|
|
3836
3836
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3837
3837
|
const {
|
|
3838
3838
|
parsed: baseParsed,
|
|
@@ -4194,7 +4194,7 @@ var require_fast_uri = __commonJS({
|
|
|
4194
4194
|
var fastUri = {
|
|
4195
4195
|
SCHEMES,
|
|
4196
4196
|
normalize,
|
|
4197
|
-
resolve:
|
|
4197
|
+
resolve: resolve9,
|
|
4198
4198
|
resolveComponent,
|
|
4199
4199
|
equal,
|
|
4200
4200
|
serialize,
|
|
@@ -13617,6 +13617,10 @@ function requiredSchemaFiles() {
|
|
|
13617
13617
|
// src/sea-assets.ts
|
|
13618
13618
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
13619
13619
|
import { getAsset, isSea } from "node:sea";
|
|
13620
|
+
var templatesBaseUrl = new URL("../templates/", import.meta.url);
|
|
13621
|
+
function templateAssetUrl(relativePath) {
|
|
13622
|
+
return new URL(relativePath, templatesBaseUrl);
|
|
13623
|
+
}
|
|
13620
13624
|
async function readCliTextAsset(assetKey, fileUrl) {
|
|
13621
13625
|
if (isSea()) {
|
|
13622
13626
|
return getAsset(assetKey, "utf8");
|
|
@@ -13665,10 +13669,7 @@ async function loadBundledConfigSchemaTexts() {
|
|
|
13665
13669
|
for (const schemaFile of manifest) {
|
|
13666
13670
|
const text = await readCliTextAsset(
|
|
13667
13671
|
`templates/schemas/${schemaFile}`,
|
|
13668
|
-
() =>
|
|
13669
|
-
`../../../../templates/schemas/${schemaFile}`,
|
|
13670
|
-
import.meta.url
|
|
13671
|
-
)
|
|
13672
|
+
() => templateAssetUrl(`schemas/${schemaFile}`)
|
|
13672
13673
|
);
|
|
13673
13674
|
schemas.set(schemaFile, text);
|
|
13674
13675
|
}
|
|
@@ -13677,10 +13678,7 @@ async function loadBundledConfigSchemaTexts() {
|
|
|
13677
13678
|
async function readSchemaManifest() {
|
|
13678
13679
|
const text = await readCliTextAsset(
|
|
13679
13680
|
manifestAssetKey,
|
|
13680
|
-
() =>
|
|
13681
|
-
"../../../../templates/schemas.manifest.json",
|
|
13682
|
-
import.meta.url
|
|
13683
|
-
)
|
|
13681
|
+
() => templateAssetUrl("schemas.manifest.json")
|
|
13684
13682
|
);
|
|
13685
13683
|
const parsed = JSON.parse(text);
|
|
13686
13684
|
if (!Array.isArray(parsed) || !parsed.every((item) => typeof item === "string")) {
|
|
@@ -20635,7 +20633,7 @@ function resolveImageTag(imageTagOverride) {
|
|
|
20635
20633
|
async function createComposeFile() {
|
|
20636
20634
|
return readCliTextAsset(
|
|
20637
20635
|
"templates/docker-compose.yml",
|
|
20638
|
-
|
|
20636
|
+
templateAssetUrl("docker-compose.yml")
|
|
20639
20637
|
);
|
|
20640
20638
|
}
|
|
20641
20639
|
function createNoClientComposeOverride() {
|
|
@@ -20662,10 +20660,7 @@ async function copyBundledDemoConfig(targetDirectory, force) {
|
|
|
20662
20660
|
});
|
|
20663
20661
|
const contents = await readCliBinaryAsset(
|
|
20664
20662
|
`templates/demo-config/${normalized}`,
|
|
20665
|
-
|
|
20666
|
-
`../../templates/demo-config/${normalized}`,
|
|
20667
|
-
import.meta.url
|
|
20668
|
-
)
|
|
20663
|
+
templateAssetUrl(`demo-config/${normalized}`)
|
|
20669
20664
|
);
|
|
20670
20665
|
await writeFile3(destinationPath, contents, { mode: 384 });
|
|
20671
20666
|
}
|
|
@@ -20693,10 +20688,7 @@ async function readDemoConfigManifest() {
|
|
|
20693
20688
|
try {
|
|
20694
20689
|
const manifestText = await readCliTextAsset(
|
|
20695
20690
|
demoConfigManifestAssetKey,
|
|
20696
|
-
|
|
20697
|
-
"../../templates/demo-config.manifest.json",
|
|
20698
|
-
import.meta.url
|
|
20699
|
-
)
|
|
20691
|
+
templateAssetUrl("demo-config.manifest.json")
|
|
20700
20692
|
);
|
|
20701
20693
|
const parsed = JSON.parse(manifestText);
|
|
20702
20694
|
if (Array.isArray(parsed) && parsed.every((item) => typeof item === "string")) {
|
|
@@ -20705,10 +20697,7 @@ async function readDemoConfigManifest() {
|
|
|
20705
20697
|
} catch {
|
|
20706
20698
|
try {
|
|
20707
20699
|
const localManifest = await readFile6(
|
|
20708
|
-
|
|
20709
|
-
"../../templates/demo-config.manifest.json",
|
|
20710
|
-
import.meta.url
|
|
20711
|
-
),
|
|
20700
|
+
templateAssetUrl("demo-config.manifest.json"),
|
|
20712
20701
|
"utf8"
|
|
20713
20702
|
);
|
|
20714
20703
|
const parsed = JSON.parse(localManifest);
|
|
@@ -21561,8 +21550,107 @@ function createConfigCommand(context, setExitCode) {
|
|
|
21561
21550
|
|
|
21562
21551
|
// src/services/deployment-drivers.ts
|
|
21563
21552
|
import { access as access2, mkdir as mkdir6, rm as rm4, stat as stat2, unlink as unlink2, writeFile as writeFile5 } from "node:fs/promises";
|
|
21564
|
-
import { delimiter, join as join10, resolve as
|
|
21553
|
+
import { delimiter, join as join10, resolve as resolve6 } from "node:path";
|
|
21565
21554
|
import { spawn } from "node:child_process";
|
|
21555
|
+
|
|
21556
|
+
// src/services/compose-args.ts
|
|
21557
|
+
import { resolve as resolve5 } from "node:path";
|
|
21558
|
+
var SERVICE_NAME = /^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/;
|
|
21559
|
+
var DURATION = /^(\d+(\.\d+)?(ns|us|µs|ms|s|m|h))+$/;
|
|
21560
|
+
var TIMESTAMP = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:\d{2})?)?$/;
|
|
21561
|
+
function assertServiceName(service) {
|
|
21562
|
+
if (!SERVICE_NAME.test(service)) {
|
|
21563
|
+
throw new Error(
|
|
21564
|
+
`Invalid service name ${JSON.stringify(service)}. Service names start with a letter or digit and contain only letters, digits, ".", "_" and "-".`
|
|
21565
|
+
);
|
|
21566
|
+
}
|
|
21567
|
+
}
|
|
21568
|
+
function assertSince(since) {
|
|
21569
|
+
const isDuration = DURATION.test(since);
|
|
21570
|
+
const isTimestamp = TIMESTAMP.test(since) && !Number.isNaN(Date.parse(since));
|
|
21571
|
+
if (!isDuration && !isTimestamp) {
|
|
21572
|
+
throw new Error(
|
|
21573
|
+
`Invalid --since value ${JSON.stringify(since)}. Use a duration such as 10m or 2h30m, or a timestamp such as 2026-09-01T12:00:00Z.`
|
|
21574
|
+
);
|
|
21575
|
+
}
|
|
21576
|
+
}
|
|
21577
|
+
function assertTail(tail) {
|
|
21578
|
+
if (!Number.isInteger(tail) || tail < 0) {
|
|
21579
|
+
throw new Error("--tail must be a whole number of lines, 0 or more.");
|
|
21580
|
+
}
|
|
21581
|
+
}
|
|
21582
|
+
function buildComposeBaseArgs(instance, projectDirectory, composeFiles) {
|
|
21583
|
+
const args = ["compose"];
|
|
21584
|
+
if (instance.envFile) {
|
|
21585
|
+
args.push("--env-file", resolve5(projectDirectory, instance.envFile));
|
|
21586
|
+
}
|
|
21587
|
+
for (const composeFile of composeFiles) {
|
|
21588
|
+
args.push("-f", resolve5(projectDirectory, composeFile));
|
|
21589
|
+
}
|
|
21590
|
+
for (const profile of instance.composeProfiles ?? []) {
|
|
21591
|
+
args.push("--profile", profile);
|
|
21592
|
+
}
|
|
21593
|
+
if (instance.projectName) {
|
|
21594
|
+
args.push("--project-name", instance.projectName);
|
|
21595
|
+
}
|
|
21596
|
+
return args;
|
|
21597
|
+
}
|
|
21598
|
+
function buildComposePsArgs() {
|
|
21599
|
+
return ["ps"];
|
|
21600
|
+
}
|
|
21601
|
+
function buildComposeListServicesArgs() {
|
|
21602
|
+
return ["config", "--services"];
|
|
21603
|
+
}
|
|
21604
|
+
function buildComposeLogsArgs(service, options = {}) {
|
|
21605
|
+
const args = ["logs"];
|
|
21606
|
+
if (options.follow === true) {
|
|
21607
|
+
args.push("--follow");
|
|
21608
|
+
}
|
|
21609
|
+
if (options.tail !== void 0) {
|
|
21610
|
+
assertTail(options.tail);
|
|
21611
|
+
args.push("--tail", String(options.tail));
|
|
21612
|
+
}
|
|
21613
|
+
if (options.since !== void 0) {
|
|
21614
|
+
assertSince(options.since);
|
|
21615
|
+
args.push("--since", options.since);
|
|
21616
|
+
}
|
|
21617
|
+
if (service !== void 0) {
|
|
21618
|
+
assertServiceName(service);
|
|
21619
|
+
args.push(service);
|
|
21620
|
+
}
|
|
21621
|
+
return args;
|
|
21622
|
+
}
|
|
21623
|
+
function buildComposePullArgs(service) {
|
|
21624
|
+
const args = ["pull"];
|
|
21625
|
+
if (service !== void 0) {
|
|
21626
|
+
assertServiceName(service);
|
|
21627
|
+
args.push(service);
|
|
21628
|
+
}
|
|
21629
|
+
return args;
|
|
21630
|
+
}
|
|
21631
|
+
function buildComposeUpArgs() {
|
|
21632
|
+
return ["up", "-d"];
|
|
21633
|
+
}
|
|
21634
|
+
function buildComposeRestartArgs(service) {
|
|
21635
|
+
const args = ["restart"];
|
|
21636
|
+
if (service !== void 0) {
|
|
21637
|
+
assertServiceName(service);
|
|
21638
|
+
args.push(service);
|
|
21639
|
+
}
|
|
21640
|
+
return args;
|
|
21641
|
+
}
|
|
21642
|
+
function parseServiceList(stdout) {
|
|
21643
|
+
return stdout.split(/\r?\n/).map((line) => line.trim()).filter((line) => SERVICE_NAME.test(line)).sort();
|
|
21644
|
+
}
|
|
21645
|
+
function assertKnownService(service, known) {
|
|
21646
|
+
if (!known.includes(service)) {
|
|
21647
|
+
throw new Error(
|
|
21648
|
+
`Unknown service ${service}. Services in this project: ${known.join(", ") || "none"}.`
|
|
21649
|
+
);
|
|
21650
|
+
}
|
|
21651
|
+
}
|
|
21652
|
+
|
|
21653
|
+
// src/services/deployment-drivers.ts
|
|
21566
21654
|
var drivers = {
|
|
21567
21655
|
compose: {
|
|
21568
21656
|
target: "compose",
|
|
@@ -21578,7 +21666,7 @@ var drivers = {
|
|
|
21578
21666
|
for (const composeFile of getComposeFiles(instance)) {
|
|
21579
21667
|
let found = true;
|
|
21580
21668
|
try {
|
|
21581
|
-
await access2(
|
|
21669
|
+
await access2(resolve6(projectDirectory, composeFile));
|
|
21582
21670
|
} catch {
|
|
21583
21671
|
found = false;
|
|
21584
21672
|
}
|
|
@@ -21596,8 +21684,41 @@ var drivers = {
|
|
|
21596
21684
|
down(options) {
|
|
21597
21685
|
return runCompose(["down", ...options.args], options);
|
|
21598
21686
|
},
|
|
21599
|
-
logs(options) {
|
|
21600
|
-
|
|
21687
|
+
async logs(options) {
|
|
21688
|
+
const service = await resolveComposeService(options);
|
|
21689
|
+
const { follow, tail } = readLogOptions(options.flags);
|
|
21690
|
+
const since = typeof options.flags.since === "string" ? options.flags.since : void 0;
|
|
21691
|
+
return runCompose(
|
|
21692
|
+
[
|
|
21693
|
+
...buildComposeLogsArgs(service, { follow, tail, since }),
|
|
21694
|
+
...options.args
|
|
21695
|
+
],
|
|
21696
|
+
options
|
|
21697
|
+
);
|
|
21698
|
+
},
|
|
21699
|
+
async ps(options) {
|
|
21700
|
+
return runCompose(
|
|
21701
|
+
[...buildComposePsArgs(), ...options.args],
|
|
21702
|
+
options
|
|
21703
|
+
);
|
|
21704
|
+
},
|
|
21705
|
+
async pull(options) {
|
|
21706
|
+
const service = await resolveComposeService(options);
|
|
21707
|
+
return runCompose(
|
|
21708
|
+
[...buildComposePullArgs(service), ...options.args],
|
|
21709
|
+
options
|
|
21710
|
+
);
|
|
21711
|
+
},
|
|
21712
|
+
async restart(options) {
|
|
21713
|
+
assertWritable(options);
|
|
21714
|
+
const service = await resolveComposeService(options);
|
|
21715
|
+
const restartArgs = buildComposeRestartArgs(service);
|
|
21716
|
+
const runtime = await resolveComposeRuntime(options.context.env);
|
|
21717
|
+
options.context.stdout.write(
|
|
21718
|
+
`Restarting ${service ?? "all services"} of ${options.instanceName}${runtime ? ` with ${runtime.name} compose` : ""}
|
|
21719
|
+
`
|
|
21720
|
+
);
|
|
21721
|
+
return runCompose([...restartArgs, ...options.args], options);
|
|
21601
21722
|
}
|
|
21602
21723
|
},
|
|
21603
21724
|
external: {
|
|
@@ -21617,7 +21738,11 @@ var drivers = {
|
|
|
21617
21738
|
);
|
|
21618
21739
|
return runKubectl(
|
|
21619
21740
|
[
|
|
21620
|
-
...buildLogsArgs(
|
|
21741
|
+
...buildLogsArgs(
|
|
21742
|
+
scope,
|
|
21743
|
+
workload,
|
|
21744
|
+
readLogOptions(options.flags)
|
|
21745
|
+
),
|
|
21621
21746
|
...options.args
|
|
21622
21747
|
],
|
|
21623
21748
|
options
|
|
@@ -21645,14 +21770,17 @@ var drivers = {
|
|
|
21645
21770
|
[...buildRestartArgs(scope, workload), ...options.args],
|
|
21646
21771
|
options
|
|
21647
21772
|
);
|
|
21648
|
-
if (restarted !== 0 || options.flags
|
|
21773
|
+
if (restarted !== 0 || options.flags["no-wait"] === true) {
|
|
21649
21774
|
return restarted;
|
|
21650
21775
|
}
|
|
21651
21776
|
return runKubectl(buildRolloutStatusArgs(scope, workload), options);
|
|
21652
21777
|
}
|
|
21653
21778
|
}
|
|
21654
21779
|
};
|
|
21655
|
-
function assertWritable({
|
|
21780
|
+
function assertWritable({
|
|
21781
|
+
instance,
|
|
21782
|
+
instanceName
|
|
21783
|
+
}) {
|
|
21656
21784
|
if (instance.readOnly === true) {
|
|
21657
21785
|
throw new Error(
|
|
21658
21786
|
`Instance ${instanceName} is registered read-only. Re-register it without --read-only to allow changes.`
|
|
@@ -21858,7 +21986,10 @@ function unreadyEndpoints(stdout) {
|
|
|
21858
21986
|
(endpoint) => isRecord3(endpoint) && // An omitted ready condition means ready, per the API contract.
|
|
21859
21987
|
(!isRecord3(endpoint.conditions) || endpoint.conditions.ready !== false)
|
|
21860
21988
|
);
|
|
21861
|
-
readyByService.set(
|
|
21989
|
+
readyByService.set(
|
|
21990
|
+
service,
|
|
21991
|
+
(readyByService.get(service) ?? false) || ready
|
|
21992
|
+
);
|
|
21862
21993
|
}
|
|
21863
21994
|
return [...readyByService.entries()].filter(([, ready]) => !ready).map(([service]) => service).sort();
|
|
21864
21995
|
}
|
|
@@ -21986,7 +22117,7 @@ async function ensureComposeProject(cwd, options) {
|
|
|
21986
22117
|
composeProfiles: composeProfiles(options),
|
|
21987
22118
|
envFile: envFileName,
|
|
21988
22119
|
projectName: mode === "demo" ? "eudiplo-demo" : "eudiplo",
|
|
21989
|
-
projectDirectory:
|
|
22120
|
+
projectDirectory: resolve6(cwd)
|
|
21990
22121
|
};
|
|
21991
22122
|
}
|
|
21992
22123
|
async function ensureProjectDirectory(directory) {
|
|
@@ -22040,23 +22171,14 @@ function unsupportedCommand(command, target) {
|
|
|
22040
22171
|
}
|
|
22041
22172
|
async function runCompose(args, { instance, context }) {
|
|
22042
22173
|
const projectDirectory = instance.projectDirectory ?? context.cwd;
|
|
22043
|
-
const composeArgs = [
|
|
22044
|
-
|
|
22045
|
-
|
|
22046
|
-
|
|
22047
|
-
|
|
22048
|
-
)
|
|
22049
|
-
|
|
22050
|
-
|
|
22051
|
-
composeArgs.push("-f", resolve5(projectDirectory, composeFile));
|
|
22052
|
-
}
|
|
22053
|
-
for (const profile of instance.composeProfiles ?? []) {
|
|
22054
|
-
composeArgs.push("--profile", profile);
|
|
22055
|
-
}
|
|
22056
|
-
if (instance.projectName) {
|
|
22057
|
-
composeArgs.push("--project-name", instance.projectName);
|
|
22058
|
-
}
|
|
22059
|
-
composeArgs.push(...args);
|
|
22174
|
+
const composeArgs = [
|
|
22175
|
+
...buildComposeBaseArgs(
|
|
22176
|
+
instance,
|
|
22177
|
+
projectDirectory,
|
|
22178
|
+
getComposeFiles(instance)
|
|
22179
|
+
),
|
|
22180
|
+
...args
|
|
22181
|
+
];
|
|
22060
22182
|
const composeRuntime = await resolveComposeRuntime(context.env);
|
|
22061
22183
|
if (!composeRuntime) {
|
|
22062
22184
|
context.stderr.write(
|
|
@@ -22078,6 +22200,64 @@ async function runCompose(args, { instance, context }) {
|
|
|
22078
22200
|
child.on("close", (code) => resolveProcess(code ?? 1));
|
|
22079
22201
|
});
|
|
22080
22202
|
}
|
|
22203
|
+
async function captureCompose(args, { instance, context }) {
|
|
22204
|
+
const projectDirectory = instance.projectDirectory ?? context.cwd;
|
|
22205
|
+
const composeRuntime = await resolveComposeRuntime(context.env);
|
|
22206
|
+
if (!composeRuntime) {
|
|
22207
|
+
throw new Error(
|
|
22208
|
+
"Docker or Podman was not found in a supported install location."
|
|
22209
|
+
);
|
|
22210
|
+
}
|
|
22211
|
+
const composeArgs = [
|
|
22212
|
+
...buildComposeBaseArgs(
|
|
22213
|
+
instance,
|
|
22214
|
+
projectDirectory,
|
|
22215
|
+
getComposeFiles(instance)
|
|
22216
|
+
),
|
|
22217
|
+
...args
|
|
22218
|
+
];
|
|
22219
|
+
return new Promise((resolveProcess) => {
|
|
22220
|
+
const child = spawn(composeRuntime.command, composeArgs, {
|
|
22221
|
+
cwd: projectDirectory,
|
|
22222
|
+
env: context.env,
|
|
22223
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
22224
|
+
});
|
|
22225
|
+
let stdout = "";
|
|
22226
|
+
let stderr = "";
|
|
22227
|
+
child.stdout?.on("data", (chunk) => {
|
|
22228
|
+
stdout += String(chunk);
|
|
22229
|
+
});
|
|
22230
|
+
child.stderr?.on("data", (chunk) => {
|
|
22231
|
+
stderr += String(chunk);
|
|
22232
|
+
});
|
|
22233
|
+
child.on(
|
|
22234
|
+
"error",
|
|
22235
|
+
(error) => resolveProcess({ code: 1, stdout, stderr: error.message })
|
|
22236
|
+
);
|
|
22237
|
+
child.on(
|
|
22238
|
+
"close",
|
|
22239
|
+
(code) => resolveProcess({ code: code ?? 1, stdout, stderr })
|
|
22240
|
+
);
|
|
22241
|
+
});
|
|
22242
|
+
}
|
|
22243
|
+
async function resolveComposeService(options) {
|
|
22244
|
+
const service = readServiceFlag(options.flags);
|
|
22245
|
+
if (service === void 0) {
|
|
22246
|
+
return void 0;
|
|
22247
|
+
}
|
|
22248
|
+
assertServiceName(service);
|
|
22249
|
+
const listed = await captureCompose(
|
|
22250
|
+
buildComposeListServicesArgs(),
|
|
22251
|
+
options
|
|
22252
|
+
);
|
|
22253
|
+
if (listed.code !== 0) {
|
|
22254
|
+
throw new Error(
|
|
22255
|
+
`Could not list Compose services: ${listed.stderr.trim() || `exit code ${listed.code}`}`
|
|
22256
|
+
);
|
|
22257
|
+
}
|
|
22258
|
+
assertKnownService(service, parseServiceList(listed.stdout));
|
|
22259
|
+
return service;
|
|
22260
|
+
}
|
|
22081
22261
|
async function resolveComposeRuntime(env) {
|
|
22082
22262
|
const preferredRuntime = parsePreferredRuntime(
|
|
22083
22263
|
env.EUDIPLO_CONTAINER_RUNTIME
|
|
@@ -22175,7 +22355,7 @@ async function removeIfExists(path2) {
|
|
|
22175
22355
|
}
|
|
22176
22356
|
|
|
22177
22357
|
// src/services/project-directory.ts
|
|
22178
|
-
import { resolve as
|
|
22358
|
+
import { resolve as resolve7 } from "node:path";
|
|
22179
22359
|
function resolveProjectDirectory(parsed, context, promptedDirectory) {
|
|
22180
22360
|
const positionalDirectory = parsed.subject;
|
|
22181
22361
|
const flagDirectory = readStringFlag(parsed.flags, "directory");
|
|
@@ -22187,7 +22367,7 @@ function resolveProjectDirectory(parsed, context, promptedDirectory) {
|
|
|
22187
22367
|
"Specify the project directory either positionally or with --directory."
|
|
22188
22368
|
);
|
|
22189
22369
|
}
|
|
22190
|
-
return
|
|
22370
|
+
return resolve7(
|
|
22191
22371
|
context.cwd,
|
|
22192
22372
|
positionalDirectory ?? flagDirectory ?? promptedDirectory ?? "."
|
|
22193
22373
|
);
|
|
@@ -22313,45 +22493,52 @@ var descriptions = {
|
|
|
22313
22493
|
down: "Stop the selected Compose deployment",
|
|
22314
22494
|
logs: "Stream logs for the selected deployment",
|
|
22315
22495
|
ps: "List the running containers or pods for the selected deployment",
|
|
22316
|
-
restart: "Restart the workloads of the selected deployment"
|
|
22496
|
+
restart: "Restart the workloads of the selected deployment",
|
|
22497
|
+
pull: "Download the configured images without changing configuration"
|
|
22317
22498
|
};
|
|
22318
22499
|
var serviceScoped = /* @__PURE__ */ new Set([
|
|
22319
22500
|
"logs",
|
|
22320
|
-
"restart"
|
|
22501
|
+
"restart",
|
|
22502
|
+
"pull"
|
|
22321
22503
|
]);
|
|
22322
22504
|
function createDeploymentCommands(context, setExitCode) {
|
|
22323
|
-
return ["up", "down", "logs", "ps", "restart"].map(
|
|
22324
|
-
|
|
22325
|
-
|
|
22326
|
-
|
|
22327
|
-
|
|
22328
|
-
|
|
22329
|
-
|
|
22330
|
-
|
|
22331
|
-
|
|
22332
|
-
|
|
22333
|
-
|
|
22334
|
-
|
|
22335
|
-
|
|
22336
|
-
|
|
22337
|
-
|
|
22338
|
-
|
|
22339
|
-
|
|
22340
|
-
|
|
22341
|
-
)
|
|
22505
|
+
return ["up", "down", "logs", "ps", "restart", "pull"].map(
|
|
22506
|
+
(name) => {
|
|
22507
|
+
const command = new Command(name).description(descriptions[name]).argument(
|
|
22508
|
+
"[args...]",
|
|
22509
|
+
"additional arguments passed to the deployment runtime"
|
|
22510
|
+
).option("--instance <name>", "select a configured instance");
|
|
22511
|
+
if (serviceScoped.has(name)) {
|
|
22512
|
+
command.option(
|
|
22513
|
+
"--service <name>",
|
|
22514
|
+
"select a single service (Compose) or configured workload (Kubernetes)"
|
|
22515
|
+
);
|
|
22516
|
+
}
|
|
22517
|
+
if (name === "logs") {
|
|
22518
|
+
command.option("--follow", "stream new output as it arrives").option("--tail <lines>", "number of recent lines to show").option(
|
|
22519
|
+
"--since <time>",
|
|
22520
|
+
"show logs since a duration (10m, 2h) or timestamp (Compose instances)"
|
|
22521
|
+
);
|
|
22522
|
+
}
|
|
22523
|
+
if (name === "restart") {
|
|
22524
|
+
command.option(
|
|
22525
|
+
"--no-wait",
|
|
22526
|
+
"return without waiting for the rollout to finish (Kubernetes instances)"
|
|
22527
|
+
);
|
|
22528
|
+
}
|
|
22529
|
+
return command.action(async (args, options) => {
|
|
22530
|
+
const { config } = await loadCliState(context);
|
|
22531
|
+
setExitCode(
|
|
22532
|
+
await runDriverCommand(
|
|
22533
|
+
config,
|
|
22534
|
+
name,
|
|
22535
|
+
parsedArgs(name, void 0, args, options),
|
|
22536
|
+
context
|
|
22537
|
+
)
|
|
22538
|
+
);
|
|
22539
|
+
});
|
|
22342
22540
|
}
|
|
22343
|
-
|
|
22344
|
-
const { config } = await loadCliState(context);
|
|
22345
|
-
setExitCode(
|
|
22346
|
-
await runDriverCommand(
|
|
22347
|
-
config,
|
|
22348
|
-
name,
|
|
22349
|
-
parsedArgs(name, void 0, args, options),
|
|
22350
|
-
context
|
|
22351
|
-
)
|
|
22352
|
-
);
|
|
22353
|
-
});
|
|
22354
|
-
});
|
|
22541
|
+
);
|
|
22355
22542
|
}
|
|
22356
22543
|
|
|
22357
22544
|
// src/services/diagnostics.ts
|
|
@@ -23031,6 +23218,146 @@ function createInstanceCommand(context, setExitCode) {
|
|
|
23031
23218
|
return instance;
|
|
23032
23219
|
}
|
|
23033
23220
|
|
|
23221
|
+
// src/services/browser.ts
|
|
23222
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
23223
|
+
import { access as access3 } from "node:fs/promises";
|
|
23224
|
+
import { delimiter as delimiter2, join as join11 } from "node:path";
|
|
23225
|
+
function assertWebUrl(value) {
|
|
23226
|
+
let url;
|
|
23227
|
+
try {
|
|
23228
|
+
url = new URL(value);
|
|
23229
|
+
} catch {
|
|
23230
|
+
throw new Error(`${value} is not a valid absolute URL.`);
|
|
23231
|
+
}
|
|
23232
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
23233
|
+
throw new Error(
|
|
23234
|
+
`Refusing to open ${value}: only http and https URLs are supported.`
|
|
23235
|
+
);
|
|
23236
|
+
}
|
|
23237
|
+
return url;
|
|
23238
|
+
}
|
|
23239
|
+
async function chooseLauncher(url, { platform, env, which }) {
|
|
23240
|
+
const browser = env.BROWSER?.trim();
|
|
23241
|
+
if (browser && !/\s|%s/.test(browser)) {
|
|
23242
|
+
const command = await which(browser);
|
|
23243
|
+
if (command) {
|
|
23244
|
+
return { command, args: [url] };
|
|
23245
|
+
}
|
|
23246
|
+
}
|
|
23247
|
+
if (platform === "darwin") {
|
|
23248
|
+
return { command: "open", args: [url] };
|
|
23249
|
+
}
|
|
23250
|
+
if (platform === "win32") {
|
|
23251
|
+
return {
|
|
23252
|
+
command: "rundll32.exe",
|
|
23253
|
+
args: ["url.dll,FileProtocolHandler", url]
|
|
23254
|
+
};
|
|
23255
|
+
}
|
|
23256
|
+
if (env.WSL_DISTRO_NAME) {
|
|
23257
|
+
const wslview = await which("wslview");
|
|
23258
|
+
if (wslview) {
|
|
23259
|
+
return { command: wslview, args: [url] };
|
|
23260
|
+
}
|
|
23261
|
+
}
|
|
23262
|
+
if (env.DISPLAY || env.WAYLAND_DISPLAY) {
|
|
23263
|
+
const xdgOpen = await which("xdg-open");
|
|
23264
|
+
if (xdgOpen) {
|
|
23265
|
+
return { command: xdgOpen, args: [url] };
|
|
23266
|
+
}
|
|
23267
|
+
}
|
|
23268
|
+
return void 0;
|
|
23269
|
+
}
|
|
23270
|
+
function launchBrowser(launcher) {
|
|
23271
|
+
return new Promise((resolveLaunch) => {
|
|
23272
|
+
const child = spawn2(launcher.command, launcher.args, {
|
|
23273
|
+
detached: true,
|
|
23274
|
+
stdio: "ignore"
|
|
23275
|
+
});
|
|
23276
|
+
child.once("error", () => resolveLaunch(false));
|
|
23277
|
+
child.once("spawn", () => {
|
|
23278
|
+
child.unref();
|
|
23279
|
+
resolveLaunch(true);
|
|
23280
|
+
});
|
|
23281
|
+
});
|
|
23282
|
+
}
|
|
23283
|
+
function pathLookup(env, platform = process.platform) {
|
|
23284
|
+
const extensions = platform === "win32" ? ["", ...(env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(";")] : [""];
|
|
23285
|
+
return async (name) => {
|
|
23286
|
+
const entries = (env.PATH ?? "").split(delimiter2).filter(Boolean);
|
|
23287
|
+
for (const entry of entries) {
|
|
23288
|
+
for (const extension of extensions) {
|
|
23289
|
+
const candidate = join11(entry, `${name}${extension}`);
|
|
23290
|
+
try {
|
|
23291
|
+
await access3(candidate);
|
|
23292
|
+
return candidate;
|
|
23293
|
+
} catch {
|
|
23294
|
+
}
|
|
23295
|
+
}
|
|
23296
|
+
}
|
|
23297
|
+
return void 0;
|
|
23298
|
+
};
|
|
23299
|
+
}
|
|
23300
|
+
|
|
23301
|
+
// src/commands/open/action.ts
|
|
23302
|
+
var defaultDependencies = {
|
|
23303
|
+
platform: process.platform,
|
|
23304
|
+
launch: launchBrowser
|
|
23305
|
+
};
|
|
23306
|
+
function resolveOpenTarget(instanceName, instance, docs) {
|
|
23307
|
+
if (docs) {
|
|
23308
|
+
const base = instance.url.endsWith("/") ? instance.url : `${instance.url}/`;
|
|
23309
|
+
return assertWebUrl(new URL("api/docs", base).href).href;
|
|
23310
|
+
}
|
|
23311
|
+
if (!instance.clientUrl) {
|
|
23312
|
+
throw new Error(
|
|
23313
|
+
`Instance ${instanceName} has no web client URL. Use --docs to open the API documentation instead.`
|
|
23314
|
+
);
|
|
23315
|
+
}
|
|
23316
|
+
return assertWebUrl(instance.clientUrl).href;
|
|
23317
|
+
}
|
|
23318
|
+
async function runOpenCommand(config, parsed, context, dependencies = defaultDependencies) {
|
|
23319
|
+
const [instanceName, instance] = resolveInstance(config, parsed);
|
|
23320
|
+
const url = resolveOpenTarget(
|
|
23321
|
+
instanceName,
|
|
23322
|
+
instance,
|
|
23323
|
+
parsed.flags.docs === true
|
|
23324
|
+
);
|
|
23325
|
+
if (parsed.flags.print === true || context.interactive !== true) {
|
|
23326
|
+
context.stdout.write(`${url}
|
|
23327
|
+
`);
|
|
23328
|
+
return 0;
|
|
23329
|
+
}
|
|
23330
|
+
const launcher = await chooseLauncher(url, {
|
|
23331
|
+
platform: dependencies.platform,
|
|
23332
|
+
env: context.env,
|
|
23333
|
+
which: pathLookup(context.env, dependencies.platform)
|
|
23334
|
+
});
|
|
23335
|
+
if (!launcher || !await dependencies.launch(launcher)) {
|
|
23336
|
+
context.stdout.write(`No browser is available here. Open: ${url}
|
|
23337
|
+
`);
|
|
23338
|
+
return 0;
|
|
23339
|
+
}
|
|
23340
|
+
context.stdout.write(`Opening ${url}
|
|
23341
|
+
`);
|
|
23342
|
+
return 0;
|
|
23343
|
+
}
|
|
23344
|
+
|
|
23345
|
+
// src/commands/open/index.ts
|
|
23346
|
+
function createOpenCommand(context, setExitCode) {
|
|
23347
|
+
return new Command("open").description(
|
|
23348
|
+
"Open the web client of the selected instance in a browser"
|
|
23349
|
+
).option("--instance <name>", "select a configured instance").option("--docs", "open the management API documentation instead").option("--print", "print the URL instead of opening a browser").action(async (options) => {
|
|
23350
|
+
const { config } = await loadCliState(context);
|
|
23351
|
+
setExitCode(
|
|
23352
|
+
await runOpenCommand(
|
|
23353
|
+
config,
|
|
23354
|
+
parsedArgs("open", void 0, [], options),
|
|
23355
|
+
context
|
|
23356
|
+
)
|
|
23357
|
+
);
|
|
23358
|
+
});
|
|
23359
|
+
}
|
|
23360
|
+
|
|
23034
23361
|
// src/commands/status/action.ts
|
|
23035
23362
|
async function runStatusCommand(config, parsed, context) {
|
|
23036
23363
|
const [instanceName, instance] = resolveInstance(config, parsed);
|
|
@@ -23063,13 +23390,229 @@ function createStatusCommand(context, setExitCode) {
|
|
|
23063
23390
|
});
|
|
23064
23391
|
}
|
|
23065
23392
|
|
|
23393
|
+
// src/commands/upgrade/action.ts
|
|
23394
|
+
import { readFile as readFile9, writeFile as writeFile6 } from "node:fs/promises";
|
|
23395
|
+
import { resolve as resolve8 } from "node:path";
|
|
23396
|
+
|
|
23397
|
+
// src/services/compose-upgrade.ts
|
|
23398
|
+
var managedImages = {
|
|
23399
|
+
EUDIPLO_IMAGE: "ghcr.io/openwallet-foundation/eudiplo",
|
|
23400
|
+
EUDIPLO_CLIENT_IMAGE: "ghcr.io/openwallet-foundation/eudiplo-client"
|
|
23401
|
+
};
|
|
23402
|
+
var TAG = /^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/;
|
|
23403
|
+
function assertImageTag(tag) {
|
|
23404
|
+
if (!TAG.test(tag)) {
|
|
23405
|
+
throw new Error(
|
|
23406
|
+
`Invalid image tag ${JSON.stringify(tag)}. Tags contain letters, digits, "_", "." and "-", and cannot start with "." or "-".`
|
|
23407
|
+
);
|
|
23408
|
+
}
|
|
23409
|
+
}
|
|
23410
|
+
function planImageUpgrade(content, tag) {
|
|
23411
|
+
assertImageTag(tag);
|
|
23412
|
+
const found = /* @__PURE__ */ new Set();
|
|
23413
|
+
const changes = [];
|
|
23414
|
+
const lines = content.split("\n").map((line) => {
|
|
23415
|
+
const match = /^(EUDIPLO_IMAGE|EUDIPLO_CLIENT_IMAGE)=(.*?)(\r?)$/.exec(
|
|
23416
|
+
line
|
|
23417
|
+
);
|
|
23418
|
+
if (!match) {
|
|
23419
|
+
return line;
|
|
23420
|
+
}
|
|
23421
|
+
const key = match[1];
|
|
23422
|
+
const value = match[2];
|
|
23423
|
+
const lineEnding = match[3];
|
|
23424
|
+
const repository = managedImages[key];
|
|
23425
|
+
if (found.has(key)) {
|
|
23426
|
+
throw new Error(
|
|
23427
|
+
`${key} is defined more than once in the env file.`
|
|
23428
|
+
);
|
|
23429
|
+
}
|
|
23430
|
+
found.add(key);
|
|
23431
|
+
const prefix = `${repository}:`;
|
|
23432
|
+
const current = value.startsWith(prefix) ? value.slice(prefix.length) : void 0;
|
|
23433
|
+
if (current === void 0 || !TAG.test(current)) {
|
|
23434
|
+
throw new Error(
|
|
23435
|
+
`${key} is set to ${value}, which is not a CLI-managed image. Update it yourself, or restore ${prefix}<tag> to let the CLI manage it.`
|
|
23436
|
+
);
|
|
23437
|
+
}
|
|
23438
|
+
if (current !== tag) {
|
|
23439
|
+
changes.push({ key, repository, from: current, to: tag });
|
|
23440
|
+
}
|
|
23441
|
+
return `${key}=${prefix}${tag}${lineEnding}`;
|
|
23442
|
+
});
|
|
23443
|
+
if (!found.has("EUDIPLO_IMAGE")) {
|
|
23444
|
+
throw new Error(
|
|
23445
|
+
"The env file does not define EUDIPLO_IMAGE, so there is no CLI-managed image to upgrade."
|
|
23446
|
+
);
|
|
23447
|
+
}
|
|
23448
|
+
return { changes, content: lines.join("\n") };
|
|
23449
|
+
}
|
|
23450
|
+
function parseVersion(tag) {
|
|
23451
|
+
const match = /^v?(\d+)\.(\d+)\.(\d+)$/.exec(tag);
|
|
23452
|
+
if (!match) {
|
|
23453
|
+
return void 0;
|
|
23454
|
+
}
|
|
23455
|
+
return {
|
|
23456
|
+
major: Number(match[1]),
|
|
23457
|
+
minor: Number(match[2]),
|
|
23458
|
+
patch: Number(match[3])
|
|
23459
|
+
};
|
|
23460
|
+
}
|
|
23461
|
+
function compareVersions(a, b) {
|
|
23462
|
+
return a.major - b.major || a.minor - b.minor || a.patch - b.patch;
|
|
23463
|
+
}
|
|
23464
|
+
var migrationBaseUrl = "https://docs.eudiplo.dev/migration";
|
|
23465
|
+
function migrationNotes(from, to) {
|
|
23466
|
+
const fromVersion = parseVersion(from);
|
|
23467
|
+
const toVersion = parseVersion(to);
|
|
23468
|
+
if (!fromVersion || !toVersion) {
|
|
23469
|
+
return [
|
|
23470
|
+
`Cannot compare ${from} and ${to} as versions. Check the release notes and ${migrationBaseUrl} before continuing.`
|
|
23471
|
+
];
|
|
23472
|
+
}
|
|
23473
|
+
const order = compareVersions(fromVersion, toVersion);
|
|
23474
|
+
if (order > 0) {
|
|
23475
|
+
return [
|
|
23476
|
+
`${to} is older than ${from}. Downgrades are not supported once database migrations have run; restore a backup instead if you need to go back.`
|
|
23477
|
+
];
|
|
23478
|
+
}
|
|
23479
|
+
const notes = [];
|
|
23480
|
+
for (let major = fromVersion.major + 1; major <= toVersion.major; major++) {
|
|
23481
|
+
notes.push(
|
|
23482
|
+
`Major version ${major}: read ${migrationBaseUrl}/${major - 1}.x-to-${major}.0 first.`
|
|
23483
|
+
);
|
|
23484
|
+
}
|
|
23485
|
+
return notes;
|
|
23486
|
+
}
|
|
23487
|
+
|
|
23488
|
+
// src/commands/upgrade/action.ts
|
|
23489
|
+
async function runUpgradeCommand(config, parsed, context) {
|
|
23490
|
+
const [instanceName, instance] = resolveInstance(config, parsed);
|
|
23491
|
+
if (instance.target !== "compose") {
|
|
23492
|
+
throw new Error(unsupportedCommand("upgrade", instance.target));
|
|
23493
|
+
}
|
|
23494
|
+
const options = {
|
|
23495
|
+
instanceName,
|
|
23496
|
+
instance,
|
|
23497
|
+
args: [],
|
|
23498
|
+
flags: parsed.flags,
|
|
23499
|
+
context
|
|
23500
|
+
};
|
|
23501
|
+
assertWritable(options);
|
|
23502
|
+
const tag = readStringFlag(parsed.flags, "image-tag");
|
|
23503
|
+
if (!tag) {
|
|
23504
|
+
throw new Error("upgrade requires --image-tag <tag>.");
|
|
23505
|
+
}
|
|
23506
|
+
if (!instance.envFile) {
|
|
23507
|
+
throw new Error(
|
|
23508
|
+
`Instance ${instanceName} has no env file, so its images are not managed by the CLI.`
|
|
23509
|
+
);
|
|
23510
|
+
}
|
|
23511
|
+
const envPath = resolve8(
|
|
23512
|
+
instance.projectDirectory ?? context.cwd,
|
|
23513
|
+
instance.envFile
|
|
23514
|
+
);
|
|
23515
|
+
const original = await readEnvFile(envPath);
|
|
23516
|
+
const plan = planImageUpgrade(original, tag);
|
|
23517
|
+
if (plan.changes.length === 0) {
|
|
23518
|
+
context.stdout.write(
|
|
23519
|
+
`${instanceName} already uses image tag ${tag}.
|
|
23520
|
+
`
|
|
23521
|
+
);
|
|
23522
|
+
return 0;
|
|
23523
|
+
}
|
|
23524
|
+
context.stdout.write(`Upgrade ${instanceName}:
|
|
23525
|
+
`);
|
|
23526
|
+
for (const change of plan.changes) {
|
|
23527
|
+
context.stdout.write(
|
|
23528
|
+
` ${change.repository}: ${change.from} -> ${change.to}
|
|
23529
|
+
`
|
|
23530
|
+
);
|
|
23531
|
+
}
|
|
23532
|
+
const notes = new Set(
|
|
23533
|
+
plan.changes.flatMap(
|
|
23534
|
+
(change) => migrationNotes(change.from, change.to)
|
|
23535
|
+
)
|
|
23536
|
+
);
|
|
23537
|
+
for (const note of notes) {
|
|
23538
|
+
context.stdout.write(`Note: ${note}
|
|
23539
|
+
`);
|
|
23540
|
+
}
|
|
23541
|
+
if (!await confirmUpgrade(parsed, context)) {
|
|
23542
|
+
context.stdout.write("Upgrade cancelled. Nothing was changed.\n");
|
|
23543
|
+
return 0;
|
|
23544
|
+
}
|
|
23545
|
+
await writeFile6(envPath, plan.content, "utf8");
|
|
23546
|
+
const pulled = await runCompose(buildComposePullArgs(void 0), options);
|
|
23547
|
+
if (pulled !== 0) {
|
|
23548
|
+
await writeFile6(envPath, original, "utf8");
|
|
23549
|
+
context.stderr.write(
|
|
23550
|
+
`Pulling the new images failed. Restored the previous image tags in ${envPath}.
|
|
23551
|
+
`
|
|
23552
|
+
);
|
|
23553
|
+
return pulled;
|
|
23554
|
+
}
|
|
23555
|
+
const recreated = await runCompose(buildComposeUpArgs(), options);
|
|
23556
|
+
if (recreated !== 0) {
|
|
23557
|
+
context.stderr.write(
|
|
23558
|
+
`The new images were pulled and ${envPath} now uses ${tag}, but recreating the services failed. Fix the error above and run eudiplo up.
|
|
23559
|
+
`
|
|
23560
|
+
);
|
|
23561
|
+
return recreated;
|
|
23562
|
+
}
|
|
23563
|
+
context.stdout.write(`Upgraded ${instanceName} to ${tag}.
|
|
23564
|
+
`);
|
|
23565
|
+
return 0;
|
|
23566
|
+
}
|
|
23567
|
+
async function readEnvFile(path2) {
|
|
23568
|
+
try {
|
|
23569
|
+
return await readFile9(path2, "utf8");
|
|
23570
|
+
} catch (error) {
|
|
23571
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
23572
|
+
throw new Error(`Env file not found: ${path2}`);
|
|
23573
|
+
}
|
|
23574
|
+
throw error;
|
|
23575
|
+
}
|
|
23576
|
+
}
|
|
23577
|
+
async function confirmUpgrade(parsed, context) {
|
|
23578
|
+
if (parsed.flags.yes === true) {
|
|
23579
|
+
return true;
|
|
23580
|
+
}
|
|
23581
|
+
if (context.interactive !== true) {
|
|
23582
|
+
throw new Error("upgrade requires --yes in non-interactive mode.");
|
|
23583
|
+
}
|
|
23584
|
+
const prompter = createPrompter(context);
|
|
23585
|
+
try {
|
|
23586
|
+
const answer = (await prompter.ask("Continue? [y/N]: ")).trim().toLowerCase();
|
|
23587
|
+
return answer === "y" || answer === "yes";
|
|
23588
|
+
} finally {
|
|
23589
|
+
prompter.close();
|
|
23590
|
+
}
|
|
23591
|
+
}
|
|
23592
|
+
|
|
23593
|
+
// src/commands/upgrade/index.ts
|
|
23594
|
+
function createUpgradeCommand(context, setExitCode) {
|
|
23595
|
+
return new Command("upgrade").description(
|
|
23596
|
+
"Upgrade the EUDIPLO application images of a Compose deployment"
|
|
23597
|
+
).requiredOption("--image-tag <tag>", "image tag to upgrade to").option("--instance <name>", "select a configured instance").option("--yes", "upgrade without asking for confirmation").action(async (options) => {
|
|
23598
|
+
const { config } = await loadCliState(context);
|
|
23599
|
+
setExitCode(
|
|
23600
|
+
await runUpgradeCommand(
|
|
23601
|
+
config,
|
|
23602
|
+
parsedArgs("upgrade", void 0, [], options),
|
|
23603
|
+
context
|
|
23604
|
+
)
|
|
23605
|
+
);
|
|
23606
|
+
});
|
|
23607
|
+
}
|
|
23608
|
+
|
|
23066
23609
|
// src/commands/version/action.ts
|
|
23067
23610
|
import { isSea as isSea2 } from "node:sea";
|
|
23068
23611
|
|
|
23069
23612
|
// package.json
|
|
23070
23613
|
var package_default = {
|
|
23071
23614
|
name: "@eudiplo/cli",
|
|
23072
|
-
version: "8.0.
|
|
23615
|
+
version: "8.0.2-main.4c3e735",
|
|
23073
23616
|
description: "Deployment-aware command line tools for EUDIPLO",
|
|
23074
23617
|
private: false,
|
|
23075
23618
|
type: "module",
|
|
@@ -23243,6 +23786,8 @@ function createProgram(context, setExitCode) {
|
|
|
23243
23786
|
for (const command of createDeploymentCommands(context, setExitCode)) {
|
|
23244
23787
|
program2.addCommand(command);
|
|
23245
23788
|
}
|
|
23789
|
+
program2.addCommand(createUpgradeCommand(context, setExitCode));
|
|
23790
|
+
program2.addCommand(createOpenCommand(context, setExitCode));
|
|
23246
23791
|
program2.addCommand(createInstanceCommand(context, setExitCode));
|
|
23247
23792
|
program2.addCommand(createConfigCommand(context, setExitCode));
|
|
23248
23793
|
program2.addCommand(createDoctorCommand(context, setExitCode));
|