@mittwald/cli 1.9.1 → 1.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/bin/run.js +4 -1
- package/dist/commands/app/create/node.d.ts +1 -3
- package/dist/commands/app/create/php-worker.d.ts +1 -3
- package/dist/commands/app/create/php.d.ts +1 -3
- package/dist/commands/app/create/python.d.ts +1 -3
- package/dist/commands/app/create/static.d.ts +1 -3
- package/dist/commands/app/dependency/update.js +2 -4
- package/dist/commands/app/download.js +2 -2
- package/dist/commands/app/exec.d.ts +17 -0
- package/dist/commands/app/exec.js +71 -0
- package/dist/commands/app/install/contao.d.ts +1 -3
- package/dist/commands/app/install/joomla.d.ts +1 -3
- package/dist/commands/app/install/matomo.d.ts +1 -3
- package/dist/commands/app/install/nextcloud.d.ts +1 -3
- package/dist/commands/app/install/shopware5.d.ts +1 -3
- package/dist/commands/app/install/shopware6.d.ts +1 -3
- package/dist/commands/app/install/typo3.d.ts +1 -3
- package/dist/commands/app/install/wordpress.d.ts +1 -3
- package/dist/commands/app/ssh.d.ts +1 -0
- package/dist/commands/app/ssh.js +15 -1
- package/dist/commands/app/update.js +4 -8
- package/dist/commands/app/upgrade.js +9 -9
- package/dist/commands/backup/create.js +1 -2
- package/dist/commands/backup/download.js +4 -5
- package/dist/commands/container/exec.d.ts +1 -7
- package/dist/commands/container/exec.js +11 -22
- package/dist/commands/container/run.d.ts +4 -2
- package/dist/commands/container/run.js +7 -6
- package/dist/commands/database/mysql/create.js +1 -2
- package/dist/commands/database/mysql/dump.js +1 -2
- package/dist/commands/database/mysql/import.js +1 -2
- package/dist/commands/ddev/init.js +2 -6
- package/dist/commands/extension/install.js +1 -3
- package/dist/commands/login/reset.js +1 -2
- package/dist/commands/mail/address/create.js +1 -4
- package/dist/commands/mail/deliverybox/create.js +1 -4
- package/dist/commands/project/create.js +4 -6
- package/dist/commands/registry/create.js +1 -2
- package/dist/commands/registry/update.js +1 -2
- package/dist/commands/user/api-token/create.js +1 -1
- package/dist/commands/user/ssh-key/create.js +3 -8
- package/dist/commands/user/ssh-key/import.js +2 -3
- package/dist/hooks/prerun/update-brew-check.js +1 -1
- package/dist/lib/basecommands/DeleteBaseCommand.js +4 -4
- package/dist/lib/ddev/init_assert.js +1 -6
- package/dist/lib/ddev/init_database.js +1 -7
- package/dist/lib/ddev/init_projecttype.js +2 -11
- package/dist/lib/intellij/config.d.ts +5 -0
- package/dist/lib/intellij/config.js +295 -0
- package/dist/lib/intellij/config.test.d.ts +1 -0
- package/dist/lib/intellij/config.test.js +262 -0
- package/dist/lib/intellij/config_xml_types.d.ts +72 -0
- package/dist/lib/intellij/config_xml_types.js +2 -0
- package/dist/lib/resources/app/Installer.d.ts +6 -2
- package/dist/lib/resources/app/Installer.js +13 -6
- package/dist/lib/resources/app/flags.js +9 -12
- package/dist/lib/resources/app/install.d.ts +2 -1
- package/dist/lib/resources/app/install.js +3 -1
- package/dist/lib/resources/app/versions.js +1 -4
- package/dist/lib/resources/app/wait.js +1 -3
- package/dist/lib/resources/mail/commons.js +1 -4
- package/dist/lib/resources/ssh/appinstall.d.ts +3 -1
- package/dist/lib/resources/ssh/appinstall.js +1 -0
- package/dist/lib/resources/ssh/environment.d.ts +7 -0
- package/dist/lib/resources/ssh/environment.js +21 -0
- package/dist/rendering/process/components/ProcessStateIcon.js +1 -1
- package/dist/rendering/process/process.d.ts +16 -16
- package/dist/rendering/process/process_exec.d.ts +1 -2
- package/dist/rendering/process/process_fancy.d.ts +9 -9
- package/dist/rendering/process/process_flags.js +4 -0
- package/dist/rendering/process/process_quiet.d.ts +3 -4
- package/dist/rendering/process/process_simple.d.ts +26 -0
- package/dist/rendering/process/process_simple.js +143 -0
- package/dist/rendering/process/process_simple.test.d.ts +1 -0
- package/dist/rendering/process/process_simple.test.js +149 -0
- package/dist/rendering/react/components/AppInstallation/AppBackendAccessHints.d.ts +15 -0
- package/dist/rendering/react/components/AppInstallation/AppBackendAccessHints.js +13 -0
- package/dist/rendering/react/components/AppInstallation/AppDomainConnectionHints.d.ts +12 -0
- package/dist/rendering/react/components/AppInstallation/AppDomainConnectionHints.js +21 -0
- package/dist/rendering/react/components/AppInstallation/AppManagementCommands.d.ts +12 -0
- package/dist/rendering/react/components/AppInstallation/AppManagementCommands.js +17 -0
- package/dist/rendering/react/components/AppInstallation/AppUsageHints.d.ts +17 -0
- package/dist/rendering/react/components/AppInstallation/AppUsageHints.js +23 -0
- package/dist/rendering/react/components/Container/CommandHint.d.ts +14 -0
- package/dist/rendering/react/components/Container/CommandHint.js +13 -0
- package/dist/rendering/react/components/Container/ContainerManagementCommands.d.ts +22 -0
- package/dist/rendering/react/components/Container/ContainerManagementCommands.js +23 -0
- package/dist/rendering/react/components/Container/ContainerUsageHints.d.ts +12 -0
- package/dist/rendering/react/components/Container/ContainerUsageHints.js +35 -0
- package/dist/rendering/react/components/Container/DomainConnectionHints.d.ts +12 -0
- package/dist/rendering/react/components/Container/DomainConnectionHints.js +21 -0
- package/dist/rendering/react/components/Container/InternalConnectionHints.d.ts +12 -0
- package/dist/rendering/react/components/Container/InternalConnectionHints.js +12 -0
- package/dist/rendering/react/components/Container/NoPortsUsageHints.d.ts +12 -0
- package/dist/rendering/react/components/Container/NoPortsUsageHints.js +12 -0
- package/dist/rendering/react/components/Container/PortConnectionHints.d.ts +13 -0
- package/dist/rendering/react/components/Container/PortConnectionHints.js +11 -0
- package/dist/rendering/react/components/Container/PortForwardingHints.d.ts +12 -0
- package/dist/rendering/react/components/Container/PortForwardingHints.js +18 -0
- package/dist/rendering/react/components/Container/types.d.ts +4 -0
- package/dist/rendering/react/components/Container/types.js +1 -0
- package/dist/rendering/react/components/Error/ErrorBox.d.ts +1 -1
- package/dist/rendering/react/components/Error/ErrorBox.js +3 -4
- package/dist/rendering/react/components/Error/GenericError.js +1 -1
- package/dist/rendering/react/components/ErrorBoundary.d.ts +1 -1
- package/dist/rendering/react/components/Success.d.ts +0 -1
- package/dist/rendering/react/components/Success.js +4 -2
- package/dist/rendering/react/styles/useDefaultBoxStyles.d.ts +11 -0
- package/dist/rendering/react/styles/useDefaultBoxStyles.js +23 -0
- package/package.json +6 -5
package/bin/run.js
CHANGED
|
@@ -5,8 +5,6 @@ export declare const nodeInstaller: AppInstaller<"site-title" | "entrypoint">;
|
|
|
5
5
|
export default class InstallNode extends ExecRenderBaseCommand<typeof InstallNode, AppInstallationResult> {
|
|
6
6
|
static description: string;
|
|
7
7
|
static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("entrypoint" | ("wait" | "wait-timeout" | "site-title"))[]>>;
|
|
8
|
-
protected exec(): Promise<
|
|
9
|
-
appInstallationId: string;
|
|
10
|
-
}>;
|
|
8
|
+
protected exec(): Promise<AppInstallationResult>;
|
|
11
9
|
protected render(result: AppInstallationResult): React.ReactNode;
|
|
12
10
|
}
|
|
@@ -5,8 +5,6 @@ export declare const phpWorkerInstaller: AppInstaller<"site-title" | "entrypoint
|
|
|
5
5
|
export default class InstallPhpWorker extends ExecRenderBaseCommand<typeof InstallPhpWorker, AppInstallationResult> {
|
|
6
6
|
static description: string;
|
|
7
7
|
static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("entrypoint" | ("wait" | "wait-timeout" | "site-title"))[]>>;
|
|
8
|
-
protected exec(): Promise<
|
|
9
|
-
appInstallationId: string;
|
|
10
|
-
}>;
|
|
8
|
+
protected exec(): Promise<AppInstallationResult>;
|
|
11
9
|
protected render(result: AppInstallationResult): React.ReactNode;
|
|
12
10
|
}
|
|
@@ -5,8 +5,6 @@ export declare const phpInstaller: AppInstaller<"site-title" | "document-root">;
|
|
|
5
5
|
export default class InstallPhp extends ExecRenderBaseCommand<typeof InstallPhp, AppInstallationResult> {
|
|
6
6
|
static description: string;
|
|
7
7
|
static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("document-root" | ("wait" | "wait-timeout" | "site-title"))[]>>;
|
|
8
|
-
protected exec(): Promise<
|
|
9
|
-
appInstallationId: string;
|
|
10
|
-
}>;
|
|
8
|
+
protected exec(): Promise<AppInstallationResult>;
|
|
11
9
|
protected render(result: AppInstallationResult): React.ReactNode;
|
|
12
10
|
}
|
|
@@ -5,8 +5,6 @@ export declare const pythonInstaller: AppInstaller<"site-title" | "entrypoint">;
|
|
|
5
5
|
export default class InstallPython extends ExecRenderBaseCommand<typeof InstallPython, AppInstallationResult> {
|
|
6
6
|
static description: string;
|
|
7
7
|
static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("entrypoint" | ("wait" | "wait-timeout" | "site-title"))[]>>;
|
|
8
|
-
protected exec(): Promise<
|
|
9
|
-
appInstallationId: string;
|
|
10
|
-
}>;
|
|
8
|
+
protected exec(): Promise<AppInstallationResult>;
|
|
11
9
|
protected render(result: AppInstallationResult): React.ReactNode;
|
|
12
10
|
}
|
|
@@ -5,8 +5,6 @@ export declare const staticInstaller: AppInstaller<"site-title" | "document-root
|
|
|
5
5
|
export default class InstallStatic extends ExecRenderBaseCommand<typeof InstallStatic, AppInstallationResult> {
|
|
6
6
|
static description: string;
|
|
7
7
|
static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("document-root" | ("wait" | "wait-timeout" | "site-title"))[]>>;
|
|
8
|
-
protected exec(): Promise<
|
|
9
|
-
appInstallationId: string;
|
|
10
|
-
}>;
|
|
8
|
+
protected exec(): Promise<AppInstallationResult>;
|
|
11
9
|
protected render(result: AppInstallationResult): React.ReactNode;
|
|
12
10
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { ExecRenderBaseCommand } from "../../../lib/basecommands/ExecRenderBaseCommand.js";
|
|
3
3
|
import { appInstallationArgs } from "../../../lib/resources/app/flags.js";
|
|
4
4
|
import { makeProcessRenderer, processFlags, } from "../../../rendering/process/process_flags.js";
|
|
@@ -6,8 +6,6 @@ import { Flags } from "@oclif/core";
|
|
|
6
6
|
import { assertStatus } from "@mittwald/api-client-commons";
|
|
7
7
|
import { Success } from "../../../rendering/react/components/Success.js";
|
|
8
8
|
import { Range, SemVer } from "semver";
|
|
9
|
-
import { Value } from "../../../rendering/react/components/Value.js";
|
|
10
|
-
import { Text } from "ink";
|
|
11
9
|
export default class Update extends ExecRenderBaseCommand {
|
|
12
10
|
static summary = "Update the dependencies of an app";
|
|
13
11
|
static args = { ...appInstallationArgs };
|
|
@@ -69,7 +67,7 @@ export default class Update extends ExecRenderBaseCommand {
|
|
|
69
67
|
}
|
|
70
68
|
return versions[versions.length - 1];
|
|
71
69
|
});
|
|
72
|
-
process.addInfo(
|
|
70
|
+
process.addInfo(`selected ${systemSoftware.name} version: ${version.externalVersion}`);
|
|
73
71
|
versionsToUpdate[systemSoftware.id] = {
|
|
74
72
|
systemSoftwareVersion: version.id,
|
|
75
73
|
updatePolicy,
|
|
@@ -33,11 +33,11 @@ export class Download extends ExecRenderBaseCommand {
|
|
|
33
33
|
static examples = [
|
|
34
34
|
{
|
|
35
35
|
description: "Download entire app to current working directory",
|
|
36
|
-
command: "$ <%= config.bin %> <%= command.id %> .",
|
|
36
|
+
command: "$ <%= config.bin %> <%= command.id %> --target .",
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
39
|
description: "Download only shared dir from a deployer-managed app",
|
|
40
|
-
command: "<%= config.bin %> <%= command.id %> --remote-sub-directory=shared .",
|
|
40
|
+
command: "<%= config.bin %> <%= command.id %> --remote-sub-directory=shared --target .",
|
|
41
41
|
},
|
|
42
42
|
];
|
|
43
43
|
async exec() {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ExtendedBaseCommand } from "../../lib/basecommands/ExtendedBaseCommand.js";
|
|
2
|
+
export default class Exec extends ExtendedBaseCommand<typeof Exec> {
|
|
3
|
+
static summary: string;
|
|
4
|
+
static description: string;
|
|
5
|
+
static args: {
|
|
6
|
+
command: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
};
|
|
8
|
+
static flags: {
|
|
9
|
+
workdir: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
env: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
"installation-id": import("@oclif/core/interfaces").OptionFlag<string>;
|
|
13
|
+
"ssh-user": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
"ssh-identity-file": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
};
|
|
16
|
+
run(): Promise<void>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import * as child_process from "child_process";
|
|
2
|
+
import { Args, Flags } from "@oclif/core";
|
|
3
|
+
import { ExtendedBaseCommand } from "../../lib/basecommands/ExtendedBaseCommand.js";
|
|
4
|
+
import { sshConnectionFlags } from "../../lib/resources/ssh/flags.js";
|
|
5
|
+
import { sshUsageDocumentation } from "../../lib/resources/ssh/doc.js";
|
|
6
|
+
import { buildSSHClientFlags } from "../../lib/resources/ssh/connection.js";
|
|
7
|
+
import { appInstallationFlags } from "../../lib/resources/app/flags.js";
|
|
8
|
+
import { getSSHConnectionForAppInstallation } from "../../lib/resources/ssh/appinstall.js";
|
|
9
|
+
import shellEscape from "shell-escape";
|
|
10
|
+
import { prepareEnvironmentVariables } from "../../lib/resources/ssh/environment.js";
|
|
11
|
+
export default class Exec extends ExtendedBaseCommand {
|
|
12
|
+
static summary = "Execute a command in an app installation via SSH non-interactively.";
|
|
13
|
+
static description = sshUsageDocumentation;
|
|
14
|
+
static args = {
|
|
15
|
+
command: Args.string({
|
|
16
|
+
description: "Command to execute in the app installation",
|
|
17
|
+
required: true,
|
|
18
|
+
}),
|
|
19
|
+
};
|
|
20
|
+
static flags = {
|
|
21
|
+
...sshConnectionFlags,
|
|
22
|
+
...appInstallationFlags,
|
|
23
|
+
workdir: Flags.string({
|
|
24
|
+
char: "w",
|
|
25
|
+
summary: "working directory where the command will be executed",
|
|
26
|
+
default: undefined,
|
|
27
|
+
}),
|
|
28
|
+
env: Flags.string({
|
|
29
|
+
char: "e",
|
|
30
|
+
summary: "environment variables to set for the command (format: KEY=VALUE)",
|
|
31
|
+
multiple: true,
|
|
32
|
+
multipleNonGreedy: true,
|
|
33
|
+
}),
|
|
34
|
+
quiet: Flags.boolean({
|
|
35
|
+
char: "q",
|
|
36
|
+
summary: "disable informational output, only show command results",
|
|
37
|
+
default: false,
|
|
38
|
+
}),
|
|
39
|
+
};
|
|
40
|
+
async run() {
|
|
41
|
+
const { args, flags } = await this.parse(Exec);
|
|
42
|
+
const appInstallationId = await this.withAppInstallationId(Exec);
|
|
43
|
+
const { host, user, directory } = await getSSHConnectionForAppInstallation(this.apiClient, appInstallationId, flags["ssh-user"]);
|
|
44
|
+
if (!flags.quiet) {
|
|
45
|
+
this.log("executing command on %s as %s", host, user);
|
|
46
|
+
}
|
|
47
|
+
const command = args.command;
|
|
48
|
+
const workdir = flags.workdir ?? directory;
|
|
49
|
+
// Build the command to execute
|
|
50
|
+
let execCommand = "";
|
|
51
|
+
// Add environment variables if provided
|
|
52
|
+
if (flags.env && flags.env.length > 0) {
|
|
53
|
+
execCommand += prepareEnvironmentVariables(flags.env);
|
|
54
|
+
}
|
|
55
|
+
// Change to working directory if specified, otherwise use app directory
|
|
56
|
+
execCommand += `cd ${shellEscape([workdir])} && `;
|
|
57
|
+
// Add the actual command
|
|
58
|
+
execCommand += command;
|
|
59
|
+
const sshArgs = buildSSHClientFlags(user, host, flags, {
|
|
60
|
+
interactive: false,
|
|
61
|
+
});
|
|
62
|
+
const wrappedExecCommand = shellEscape(["/bin/bash", "-c", execCommand]);
|
|
63
|
+
this.debug("running ssh %o, with command %o", sshArgs, wrappedExecCommand);
|
|
64
|
+
const result = child_process.spawnSync("/usr/bin/ssh", [...sshArgs, wrappedExecCommand], {
|
|
65
|
+
stdio: "inherit",
|
|
66
|
+
});
|
|
67
|
+
if (result.status !== 0) {
|
|
68
|
+
this.error(`Command failed with exit code ${result.status}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -4,8 +4,6 @@ import { AppInstallationResult } from "../../../lib/resources/app/Installer.js";
|
|
|
4
4
|
export default class InstallContao extends ExecRenderBaseCommand<typeof InstallContao, AppInstallationResult> {
|
|
5
5
|
static description: string;
|
|
6
6
|
static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("version" | "host" | "admin-user" | "admin-email" | "admin-pass" | "admin-firstname" | "admin-lastname" | ("wait" | "wait-timeout" | "site-title"))[]>>;
|
|
7
|
-
protected exec(): Promise<
|
|
8
|
-
appInstallationId: string;
|
|
9
|
-
}>;
|
|
7
|
+
protected exec(): Promise<AppInstallationResult>;
|
|
10
8
|
protected render(result: AppInstallationResult): React.ReactNode;
|
|
11
9
|
}
|
|
@@ -4,8 +4,6 @@ import { AppInstallationResult } from "../../../lib/resources/app/Installer.js";
|
|
|
4
4
|
export default class InstallJoomla extends ExecRenderBaseCommand<typeof InstallJoomla, AppInstallationResult> {
|
|
5
5
|
static description: string;
|
|
6
6
|
static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("version" | "host" | "admin-user" | "admin-email" | "admin-pass" | "admin-firstname" | "admin-lastname" | ("wait" | "wait-timeout" | "site-title"))[]>>;
|
|
7
|
-
protected exec(): Promise<
|
|
8
|
-
appInstallationId: string;
|
|
9
|
-
}>;
|
|
7
|
+
protected exec(): Promise<AppInstallationResult>;
|
|
10
8
|
protected render(result: AppInstallationResult): React.ReactNode;
|
|
11
9
|
}
|
|
@@ -4,8 +4,6 @@ import { AppInstallationResult } from "../../../lib/resources/app/Installer.js";
|
|
|
4
4
|
export default class InstallMatomo extends ExecRenderBaseCommand<typeof InstallMatomo, AppInstallationResult> {
|
|
5
5
|
static description: string;
|
|
6
6
|
static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("version" | "host" | "admin-user" | "admin-email" | "admin-pass" | ("wait" | "wait-timeout" | "site-title"))[]>>;
|
|
7
|
-
protected exec(): Promise<
|
|
8
|
-
appInstallationId: string;
|
|
9
|
-
}>;
|
|
7
|
+
protected exec(): Promise<AppInstallationResult>;
|
|
10
8
|
protected render(result: AppInstallationResult): React.ReactNode;
|
|
11
9
|
}
|
|
@@ -4,8 +4,6 @@ import { AppInstallationResult } from "../../../lib/resources/app/Installer.js";
|
|
|
4
4
|
export default class InstallNextcloud extends ExecRenderBaseCommand<typeof InstallNextcloud, AppInstallationResult> {
|
|
5
5
|
static description: string;
|
|
6
6
|
static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("version" | "host" | "admin-user" | "admin-email" | "admin-pass" | ("wait" | "wait-timeout" | "site-title"))[]>>;
|
|
7
|
-
protected exec(): Promise<
|
|
8
|
-
appInstallationId: string;
|
|
9
|
-
}>;
|
|
7
|
+
protected exec(): Promise<AppInstallationResult>;
|
|
10
8
|
protected render(result: AppInstallationResult): React.ReactNode;
|
|
11
9
|
}
|
|
@@ -4,8 +4,6 @@ import { AppInstallationResult } from "../../../lib/resources/app/Installer.js";
|
|
|
4
4
|
export default class InstallShopware5 extends ExecRenderBaseCommand<typeof InstallShopware5, AppInstallationResult> {
|
|
5
5
|
static description: string;
|
|
6
6
|
static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("version" | "host" | "admin-user" | "admin-email" | "admin-pass" | "admin-firstname" | "admin-lastname" | "shop-email" | "shop-lang" | "shop-currency" | ("wait" | "wait-timeout" | "site-title"))[]>>;
|
|
7
|
-
protected exec(): Promise<
|
|
8
|
-
appInstallationId: string;
|
|
9
|
-
}>;
|
|
7
|
+
protected exec(): Promise<AppInstallationResult>;
|
|
10
8
|
protected render(result: AppInstallationResult): React.ReactNode;
|
|
11
9
|
}
|
|
@@ -5,8 +5,6 @@ export declare const shopware6Installer: AppInstaller<"version" | "host" | "admi
|
|
|
5
5
|
export default class InstallShopware6 extends ExecRenderBaseCommand<typeof InstallShopware6, AppInstallationResult> {
|
|
6
6
|
static description: string;
|
|
7
7
|
static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("version" | "host" | "admin-user" | "admin-email" | "admin-pass" | "admin-firstname" | "admin-lastname" | "shop-email" | "shop-lang" | "shop-currency" | ("wait" | "wait-timeout" | "site-title"))[]>>;
|
|
8
|
-
protected exec(): Promise<
|
|
9
|
-
appInstallationId: string;
|
|
10
|
-
}>;
|
|
8
|
+
protected exec(): Promise<AppInstallationResult>;
|
|
11
9
|
protected render(result: AppInstallationResult): React.ReactNode;
|
|
12
10
|
}
|
|
@@ -5,8 +5,6 @@ export declare const typo3Installer: AppInstaller<"version" | "host" | "admin-us
|
|
|
5
5
|
export default class InstallTYPO3 extends ExecRenderBaseCommand<typeof InstallTYPO3, AppInstallationResult> {
|
|
6
6
|
static description: string;
|
|
7
7
|
static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("version" | "host" | "admin-user" | "admin-email" | "admin-pass" | "install-mode" | ("wait" | "wait-timeout" | "site-title"))[]>>;
|
|
8
|
-
protected exec(): Promise<
|
|
9
|
-
appInstallationId: string;
|
|
10
|
-
}>;
|
|
8
|
+
protected exec(): Promise<AppInstallationResult>;
|
|
11
9
|
protected render(result: AppInstallationResult): React.ReactNode;
|
|
12
10
|
}
|
|
@@ -5,8 +5,6 @@ export declare const wordpressInstaller: AppInstaller<"version" | "host" | "admi
|
|
|
5
5
|
export default class InstallWordPress extends ExecRenderBaseCommand<typeof InstallWordPress, AppInstallationResult> {
|
|
6
6
|
static description: string;
|
|
7
7
|
static flags: import("@oclif/core/interfaces").FlagInput<import("../../../lib/resources/app/flags.js").RelevantFlags<readonly ("version" | "host" | "admin-user" | "admin-email" | "admin-pass" | ("wait" | "wait-timeout" | "site-title"))[]>>;
|
|
8
|
-
protected exec(): Promise<
|
|
9
|
-
appInstallationId: string;
|
|
10
|
-
}>;
|
|
8
|
+
protected exec(): Promise<AppInstallationResult>;
|
|
11
9
|
protected render(result: AppInstallationResult): React.ReactNode;
|
|
12
10
|
}
|
|
@@ -9,6 +9,7 @@ export default class Ssh extends ExtendedBaseCommand<typeof Ssh> {
|
|
|
9
9
|
cd: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
10
|
info: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
11
|
test: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
"generate-intellij-config": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
13
|
"ssh-user": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
14
|
"ssh-identity-file": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
15
|
};
|
package/dist/commands/app/ssh.js
CHANGED
|
@@ -6,6 +6,7 @@ import { getSSHConnectionForAppInstallation } from "../../lib/resources/ssh/appi
|
|
|
6
6
|
import { sshConnectionFlags, } from "../../lib/resources/ssh/flags.js";
|
|
7
7
|
import { sshWrapperDocumentation } from "../../lib/resources/ssh/doc.js";
|
|
8
8
|
import { buildSSHClientFlags } from "../../lib/resources/ssh/connection.js";
|
|
9
|
+
import { generateIntellijConfigs } from "../../lib/intellij/config.js";
|
|
9
10
|
export default class Ssh extends ExtendedBaseCommand {
|
|
10
11
|
static summary = "Connect to an app via SSH";
|
|
11
12
|
static description = "Establishes an interactive SSH connection to an app installation.\n\n" +
|
|
@@ -24,11 +25,24 @@ export default class Ssh extends ExtendedBaseCommand {
|
|
|
24
25
|
test: Flags.boolean({
|
|
25
26
|
summary: "test connection and exit",
|
|
26
27
|
}),
|
|
28
|
+
"generate-intellij-config": Flags.boolean({
|
|
29
|
+
summary: "generate IntelliJ IDEA SSH and deployment configuration files",
|
|
30
|
+
}),
|
|
27
31
|
};
|
|
28
32
|
async run() {
|
|
29
33
|
const { flags } = await this.parse(Ssh);
|
|
30
34
|
const appInstallationId = await this.withAppInstallationId(Ssh);
|
|
31
|
-
const { host, user, directory } = await getSSHConnectionForAppInstallation(this.apiClient, appInstallationId, flags["ssh-user"]);
|
|
35
|
+
const { host, user, directory, appShortId } = await getSSHConnectionForAppInstallation(this.apiClient, appInstallationId, flags["ssh-user"]);
|
|
36
|
+
if (flags["generate-intellij-config"]) {
|
|
37
|
+
generateIntellijConfigs({
|
|
38
|
+
host,
|
|
39
|
+
user,
|
|
40
|
+
directory,
|
|
41
|
+
appShortId,
|
|
42
|
+
});
|
|
43
|
+
this.log("IntelliJ IDEA configuration files generated in .idea/ directory");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
32
46
|
if (flags.info) {
|
|
33
47
|
this.log("hostname: %o", host);
|
|
34
48
|
this.log("username: %o", user);
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { ExecRenderBaseCommand } from "../../lib/basecommands/ExecRenderBaseCommand.js";
|
|
3
3
|
import { appInstallationArgs, withAppInstallationId, } from "../../lib/resources/app/flags.js";
|
|
4
4
|
import { makeProcessRenderer, processFlags, } from "../../rendering/process/process_flags.js";
|
|
5
5
|
import { Success } from "../../rendering/react/components/Success.js";
|
|
6
|
-
import { Value } from "../../rendering/react/components/Value.js";
|
|
7
6
|
import { Flags } from "@oclif/core";
|
|
8
7
|
export class Update extends ExecRenderBaseCommand {
|
|
9
8
|
static summary = "Update properties of an app installation (use 'upgrade' to update the app version)";
|
|
@@ -56,7 +55,7 @@ function buildUpdateBodyFromFlags(flags) {
|
|
|
56
55
|
const updateBody = {};
|
|
57
56
|
const info = [];
|
|
58
57
|
if (flags.entrypoint) {
|
|
59
|
-
info.push(
|
|
58
|
+
info.push(`setting entrypoint to ${flags.entrypoint}`);
|
|
60
59
|
updateBody.userInputs = [
|
|
61
60
|
...(updateBody.userInputs || []),
|
|
62
61
|
{
|
|
@@ -66,15 +65,12 @@ function buildUpdateBodyFromFlags(flags) {
|
|
|
66
65
|
];
|
|
67
66
|
}
|
|
68
67
|
if (flags["document-root"]) {
|
|
69
|
-
info.push(
|
|
68
|
+
info.push(`setting document root to ${flags["document-root"]}`);
|
|
70
69
|
updateBody.customDocumentRoot = flags["document-root"];
|
|
71
70
|
}
|
|
72
71
|
if (flags.description !== undefined) {
|
|
73
|
-
info.push(
|
|
72
|
+
info.push(`setting description to ${flags.description}`);
|
|
74
73
|
updateBody.description = flags.description;
|
|
75
74
|
}
|
|
76
75
|
return [updateBody, info];
|
|
77
76
|
}
|
|
78
|
-
function UpdateFieldInfo({ name, value }) {
|
|
79
|
-
return (_jsxs(_Fragment, { children: ["setting ", name, " to ", _jsx(Value, { children: value })] }));
|
|
80
|
-
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsxs as _jsxs,
|
|
1
|
+
import { jsxs as _jsxs, Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { ExecRenderBaseCommand } from "../../lib/basecommands/ExecRenderBaseCommand.js";
|
|
3
3
|
import { appInstallationArgs, withAppInstallationId, } from "../../lib/resources/app/flags.js";
|
|
4
4
|
import { projectFlags } from "../../lib/resources/project/flags.js";
|
|
@@ -51,15 +51,15 @@ export class UpgradeApp extends ExecRenderBaseCommand {
|
|
|
51
51
|
ux.exit(1);
|
|
52
52
|
}
|
|
53
53
|
if (!this.flags.force) {
|
|
54
|
-
const confirmed = await process.addConfirmation(
|
|
54
|
+
const confirmed = await process.addConfirmation(`Confirm upgrading ${currentApp.name} ${currentAppVersion.externalVersion} (${currentAppInstallation.description}) to version ${targetAppVersion.externalVersion}`);
|
|
55
55
|
if (!confirmed) {
|
|
56
|
-
process.addInfo(
|
|
56
|
+
process.addInfo("Upgrade will not be triggered.");
|
|
57
57
|
process.complete(_jsx(_Fragment, {}));
|
|
58
58
|
ux.exit(1);
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
else {
|
|
62
|
-
process.addInfo(
|
|
62
|
+
process.addInfo(`Commencing upgrade of ${currentApp.name} ${currentAppVersion.externalVersion} (${currentAppInstallation.description}) to Version ${targetAppVersion.externalVersion}.`);
|
|
63
63
|
}
|
|
64
64
|
const appUpgradePayload = {
|
|
65
65
|
appVersionId: targetAppVersion.id,
|
|
@@ -72,7 +72,7 @@ export class UpgradeApp extends ExecRenderBaseCommand {
|
|
|
72
72
|
});
|
|
73
73
|
if (missingDependencies.data.missingSystemSoftwareDependencies) {
|
|
74
74
|
appUpgradePayload.systemSoftware = {};
|
|
75
|
-
process.addStep(
|
|
75
|
+
process.addStep(`In order to upgrade your ${currentApp.name} to Version ${targetAppVersion.externalVersion} some dependencies need to be upgraded too.`);
|
|
76
76
|
for (const missingSystemSoftwareDependency of missingDependencies.data
|
|
77
77
|
.missingSystemSoftwareDependencies) {
|
|
78
78
|
const dependencyUpdateData = await updateMissingSystemSoftwareDependency(process, this.apiClient, missingSystemSoftwareDependency);
|
|
@@ -81,9 +81,9 @@ export class UpgradeApp extends ExecRenderBaseCommand {
|
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
83
|
if (!this.flags.force) {
|
|
84
|
-
const confirmed = await process.addConfirmation(
|
|
84
|
+
const confirmed = await process.addConfirmation("Do you want to continue?");
|
|
85
85
|
if (!confirmed) {
|
|
86
|
-
process.addInfo(
|
|
86
|
+
process.addInfo("Upgrade will not be triggered.");
|
|
87
87
|
process.complete(_jsx(_Fragment, {}));
|
|
88
88
|
ux.exit(1);
|
|
89
89
|
}
|
|
@@ -136,7 +136,7 @@ export class UpgradeApp extends ExecRenderBaseCommand {
|
|
|
136
136
|
if (semverMatch) {
|
|
137
137
|
return semverMatch;
|
|
138
138
|
}
|
|
139
|
-
process.addInfo(
|
|
139
|
+
process.addInfo("The given target upgrade version does not seem to be a valid upgrade candidate.");
|
|
140
140
|
}
|
|
141
141
|
return await forceTargetVersionSelection(process, this.apiClient, targetAppVersionCandidates, currentApp, currentAppVersion);
|
|
142
142
|
}
|
|
@@ -182,7 +182,7 @@ async function updateMissingSystemSoftwareDependency(process, apiClient, depende
|
|
|
182
182
|
" could not be determined");
|
|
183
183
|
}
|
|
184
184
|
else {
|
|
185
|
-
process.addInfo(
|
|
185
|
+
process.addInfo(`${dependencySoftware.data.name} will be upgraded to Version ${dependencyTargetVersion.externalVersion}.`);
|
|
186
186
|
return {
|
|
187
187
|
dependencySoftwareId: dependencySoftware.data.id,
|
|
188
188
|
dependencyTargetVersionId: dependencyTargetVersion.id,
|
|
@@ -6,7 +6,6 @@ import { Flags } from "@oclif/core";
|
|
|
6
6
|
import { assertStatus } from "@mittwald/api-client-commons";
|
|
7
7
|
import { Success } from "../../rendering/react/components/Success.js";
|
|
8
8
|
import { waitFlags, waitUntil } from "../../lib/wait.js";
|
|
9
|
-
import { Text } from "ink";
|
|
10
9
|
import { expireFlags } from "../../lib/flags/expireFlags.js";
|
|
11
10
|
export class Create extends ExecRenderBaseCommand {
|
|
12
11
|
static summary = "Create a new backup of a project";
|
|
@@ -37,7 +36,7 @@ export class Create extends ExecRenderBaseCommand {
|
|
|
37
36
|
return r.data;
|
|
38
37
|
});
|
|
39
38
|
if (this.flags.wait) {
|
|
40
|
-
const stepWaiting = p.addStep(
|
|
39
|
+
const stepWaiting = p.addStep("waiting for backup to be complete");
|
|
41
40
|
await waitUntil(async () => {
|
|
42
41
|
const backupResponse = await this.apiClient.backup.getProjectBackup({
|
|
43
42
|
projectBackupId: backup.id,
|
|
@@ -3,7 +3,6 @@ import { ExecRenderBaseCommand } from "../../lib/basecommands/ExecRenderBaseComm
|
|
|
3
3
|
import { Flags } from "@oclif/core";
|
|
4
4
|
import { makeProcessRenderer, processFlags, } from "../../rendering/process/process_flags.js";
|
|
5
5
|
import crypto from "crypto";
|
|
6
|
-
import { Text } from "ink";
|
|
7
6
|
import { Value } from "../../rendering/react/components/Value.js";
|
|
8
7
|
import { assertStatus, } from "@mittwald/api-client-commons";
|
|
9
8
|
import { waitUntil } from "../../lib/wait.js";
|
|
@@ -58,11 +57,11 @@ export class Download extends ExecRenderBaseCommand {
|
|
|
58
57
|
const password = await p.runStep("generating password", async () => {
|
|
59
58
|
return crypto.randomBytes(32).toString("ascii").substring(0, 32);
|
|
60
59
|
});
|
|
61
|
-
p.addInfo(
|
|
60
|
+
p.addInfo(`generated password: ${password}`);
|
|
62
61
|
return password;
|
|
63
62
|
}
|
|
64
63
|
if (this.flags["prompt-password"]) {
|
|
65
|
-
return await p.addInput(
|
|
64
|
+
return await p.addInput("enter backup password", true);
|
|
66
65
|
}
|
|
67
66
|
return undefined;
|
|
68
67
|
}
|
|
@@ -79,7 +78,7 @@ export class Download extends ExecRenderBaseCommand {
|
|
|
79
78
|
return r.data;
|
|
80
79
|
});
|
|
81
80
|
if (backup.export && backup.export.phase !== "Expired") {
|
|
82
|
-
p.addInfo(
|
|
81
|
+
p.addInfo("backup download is already prepared");
|
|
83
82
|
}
|
|
84
83
|
else {
|
|
85
84
|
await p.runStep("preparing backup download", async () => {
|
|
@@ -115,7 +114,7 @@ export class Download extends ExecRenderBaseCommand {
|
|
|
115
114
|
const stat = fs.statSync(this.flags.output);
|
|
116
115
|
const range = `bytes=${stat.size}-`;
|
|
117
116
|
reqConfig.headers = { Range: range };
|
|
118
|
-
p.addInfo(
|
|
117
|
+
p.addInfo(`resuming download starting at ${stat.size} bytes`);
|
|
119
118
|
}
|
|
120
119
|
const downloadStep = p.addStep("downloading backup");
|
|
121
120
|
const resp = await axios(backupExport.downloadURL, reqConfig);
|
|
@@ -10,16 +10,10 @@ export default class Exec extends ExtendedBaseCommand<typeof Exec> {
|
|
|
10
10
|
workdir: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
11
|
env: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
12
|
shell: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
14
|
"project-id": import("@oclif/core/interfaces").OptionFlag<string>;
|
|
14
15
|
"ssh-user": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
16
|
"ssh-identity-file": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
17
|
};
|
|
17
|
-
/**
|
|
18
|
-
* Prepare environment variables for the SSH command
|
|
19
|
-
*
|
|
20
|
-
* @param envVars Array of environment variables in KEY=VALUE format
|
|
21
|
-
* @returns Formatted string with export commands
|
|
22
|
-
*/
|
|
23
|
-
private prepareEnvironmentVariables;
|
|
24
18
|
run(): Promise<void>;
|
|
25
19
|
}
|
|
@@ -8,6 +8,7 @@ import { buildSSHClientFlags } from "../../lib/resources/ssh/connection.js";
|
|
|
8
8
|
import { withContainerAndStackId } from "../../lib/resources/container/flags.js";
|
|
9
9
|
import { projectFlags } from "../../lib/resources/project/flags.js";
|
|
10
10
|
import shellEscape from "shell-escape";
|
|
11
|
+
import { prepareEnvironmentVariables } from "../../lib/resources/ssh/environment.js";
|
|
11
12
|
export default class Exec extends ExtendedBaseCommand {
|
|
12
13
|
static summary = "Execute a command in a container via SSH non-interactively.";
|
|
13
14
|
static description = sshUsageDocumentation;
|
|
@@ -33,44 +34,32 @@ export default class Exec extends ExtendedBaseCommand {
|
|
|
33
34
|
char: "e",
|
|
34
35
|
summary: "environment variables to set for the command (format: KEY=VALUE)",
|
|
35
36
|
multiple: true,
|
|
37
|
+
multipleNonGreedy: true,
|
|
36
38
|
}),
|
|
37
39
|
shell: Flags.string({
|
|
38
40
|
summary: "shell to use for the SSH connection",
|
|
39
41
|
default: "/bin/sh",
|
|
40
42
|
}),
|
|
43
|
+
quiet: Flags.boolean({
|
|
44
|
+
char: "q",
|
|
45
|
+
summary: "disable informational output, only show command results",
|
|
46
|
+
default: false,
|
|
47
|
+
}),
|
|
41
48
|
};
|
|
42
|
-
/**
|
|
43
|
-
* Prepare environment variables for the SSH command
|
|
44
|
-
*
|
|
45
|
-
* @param envVars Array of environment variables in KEY=VALUE format
|
|
46
|
-
* @returns Formatted string with export commands
|
|
47
|
-
*/
|
|
48
|
-
prepareEnvironmentVariables(envVars) {
|
|
49
|
-
return (envVars
|
|
50
|
-
.map((env) => {
|
|
51
|
-
const eqIdx = env.indexOf("=");
|
|
52
|
-
if (eqIdx === -1) {
|
|
53
|
-
// If no '=', treat the whole string as key with empty value
|
|
54
|
-
return `export ${shellEscape([env])}=`;
|
|
55
|
-
}
|
|
56
|
-
const key = env.slice(0, eqIdx);
|
|
57
|
-
const value = env.slice(eqIdx + 1);
|
|
58
|
-
return `export ${shellEscape([key])}=${shellEscape([value])}`;
|
|
59
|
-
})
|
|
60
|
-
.join("; ") + "; ");
|
|
61
|
-
}
|
|
62
49
|
async run() {
|
|
63
50
|
const { args, flags } = await this.parse(Exec);
|
|
64
51
|
const [containerId, stackId] = await withContainerAndStackId(this.apiClient, Exec, flags, this.args, this.config);
|
|
65
52
|
const { host, user } = await getSSHConnectionForContainer(this.apiClient, containerId, stackId, flags["ssh-user"]);
|
|
66
|
-
|
|
53
|
+
if (!flags.quiet) {
|
|
54
|
+
this.log("executing command on %s as %s", host, user);
|
|
55
|
+
}
|
|
67
56
|
const command = args.command;
|
|
68
57
|
const workdir = flags.workdir;
|
|
69
58
|
// Build the command to execute
|
|
70
59
|
let execCommand = "";
|
|
71
60
|
// Add environment variables if provided
|
|
72
61
|
if (flags.env && flags.env.length > 0) {
|
|
73
|
-
execCommand +=
|
|
62
|
+
execCommand += prepareEnvironmentVariables(flags.env);
|
|
74
63
|
}
|
|
75
64
|
// Change to working directory if specified
|
|
76
65
|
if (workdir !== undefined) {
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { ReactNode } from "react";
|
|
2
2
|
import { ExecRenderBaseCommand } from "../../lib/basecommands/ExecRenderBaseCommand.js";
|
|
3
|
+
import { MittwaldAPIV2 } from "@mittwald/api-client";
|
|
4
|
+
type ContainerServiceResponse = MittwaldAPIV2.Components.Schemas.ContainerServiceResponse;
|
|
3
5
|
type Result = {
|
|
4
|
-
|
|
6
|
+
service: ContainerServiceResponse;
|
|
5
7
|
};
|
|
6
8
|
export declare class Run extends ExecRenderBaseCommand<typeof Run, Result> {
|
|
7
9
|
static summary: string;
|
|
@@ -56,6 +58,6 @@ export declare class Run extends ExecRenderBaseCommand<typeof Run, Result> {
|
|
|
56
58
|
private buildServiceRequest;
|
|
57
59
|
private getImageAndMeta;
|
|
58
60
|
private getServiceName;
|
|
59
|
-
protected render({
|
|
61
|
+
protected render({ service }: Result): ReactNode;
|
|
60
62
|
}
|
|
61
63
|
export {};
|