Skip to content

Commit 82b3a72

Browse files
chore(es-1464): bring back m2 only command (#7383)
* chore: bring back m2-only cli command * chore: changeset
1 parent a06e5b0 commit 82b3a72

29 files changed

+1079
-0
lines changed

.changeset/modern-cycles-prove.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@vue-storefront/cli": patch
3+
---
4+
5+
[CHANGED] Added back the previously removed `m2-only` command.

packages/cli/src/commands/m2-only.ts

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { intro } from "@clack/prompts";
2+
import { Command } from "@oclif/core";
3+
import picocolors from "picocolors";
4+
import { t } from "i18next";
5+
import { initLogger } from "../domains/generate/logging/logger";
6+
import {
7+
checkDocker,
8+
getMagentoDomainName,
9+
} from "../domains/generate/magento2/docker";
10+
import { getMagentoDetails } from "../domains/generate/magento2/functions";
11+
import { installMagento } from "../domains/generate/magento2/installMagento";
12+
import { simpleLog } from "../domains/generate/magento2/functions/terminalHelpers";
13+
14+
export default class M2Only extends Command {
15+
static override description = "Install local Magento 2 instance";
16+
17+
static override examples = ["<%= config.bin %> <%= command.id %>"];
18+
19+
static override flags = {};
20+
21+
static override args = [];
22+
23+
async run(): Promise<void> {
24+
const { writeLog, deleteLog } = initLogger();
25+
26+
intro("Welcome to the Magento 2 local instance installer!");
27+
28+
await checkDocker(writeLog);
29+
30+
const { magentoDirName, magentoAccessKey, magentoSecretKey } =
31+
await getMagentoDetails();
32+
33+
const magentoDomain = await getMagentoDomainName(
34+
t("command.generate_store.magento.domain")
35+
);
36+
37+
await installMagento({
38+
isInstallMagento: true,
39+
magentoDirName,
40+
magentoDomain,
41+
magentoAccessKey,
42+
magentoSecretKey,
43+
writeLog,
44+
});
45+
46+
deleteLog();
47+
48+
simpleLog("Happy coding! 🎉", picocolors.green);
49+
50+
this.exit(0);
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import fs from "fs";
2+
3+
export const initLogger = () => {
4+
const logFile = fs.createWriteStream("CLI_logs.txt", { flags: "a" });
5+
6+
const writeLog = (message: string) => {
7+
logFile.write(`${message}\n`);
8+
};
9+
10+
const deleteLog = () => {
11+
fs.unlinkSync("CLI_logs.txt");
12+
};
13+
14+
return {
15+
writeLog,
16+
deleteLog,
17+
};
18+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { spawn } from "child_process";
2+
import { t } from "i18next";
3+
import {
4+
logSimpleErrorMessage,
5+
logSimpleInfoMessage,
6+
simpleLog,
7+
} from "../functions/terminalHelpers";
8+
9+
/** Checking if Docker is installed and running on user's machine */
10+
const checkDocker = async (
11+
writeLog: (message: string) => void
12+
): Promise<void> => {
13+
const docker =
14+
process.platform === "darwin"
15+
? spawn("docker", ["info"])
16+
: spawn("sudo", ["docker", "info"]);
17+
18+
docker.stderr.on("data", (data) => {
19+
writeLog(data.toString());
20+
simpleLog(data.toString());
21+
});
22+
23+
const isDockerInstalled = await new Promise((resolve) => {
24+
docker.on("close", (code) => resolve(code === 0));
25+
});
26+
27+
if (!isDockerInstalled) {
28+
writeLog(
29+
"Docker is not installed or not running. Please make sure that prerequisites are complied with and run command again."
30+
);
31+
logSimpleErrorMessage(
32+
"Docker is not installed or not running. Please make sure that prerequisites are complied with and run command again."
33+
);
34+
logSimpleInfoMessage(t("command.generate_store.magento.failed_log"));
35+
process.exit(1);
36+
} else {
37+
writeLog("🐳 Docker is installed and running.");
38+
logSimpleInfoMessage("🐳 Docker is installed and running.");
39+
}
40+
};
41+
42+
export default checkDocker;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import execa from "execa";
2+
3+
const checkExistingDockerContainers = async (magentoDirName = "server") => {
4+
const execaFunc =
5+
process.platform === "darwin"
6+
? execa("docker", ["container", "ls", "--format", "{{.Names}}"])
7+
: execa("sudo", ["docker", "container", "ls", "--format", "{{.Names}}"]);
8+
9+
const { stdout } = await execaFunc;
10+
11+
const isExistingDockerContainers = stdout.includes(magentoDirName);
12+
13+
return isExistingDockerContainers;
14+
};
15+
16+
export default checkExistingDockerContainers;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export { default as checkDocker } from "./checkDocker";
2+
export { default as installMagentoImage } from "./installMagentoImage";
3+
export { default as getMagentoDomainName } from "../prompts/getMagentoDomain";
4+
export { default as checkExistingDockerContainers } from "./checkExistingDockerContainers";
5+
export { default as removeDockerContainer } from "./removeDocker";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import { spawn } from "child_process";
2+
3+
import { note, spinner } from "@clack/prompts";
4+
import picocolors from "picocolors";
5+
import { t } from "i18next";
6+
import {
7+
logSimpleErrorMessage,
8+
logSimpleInfoMessage,
9+
} from "../functions/terminalHelpers";
10+
import removeDockerContainer from "./removeDocker";
11+
12+
/** Handles Magento 2 Docker Image installation */
13+
const installMagentoImage = async (
14+
magentoDirName: string,
15+
magentoDomainName: string,
16+
writeLog: (message: string) => void
17+
): Promise<any> => {
18+
const options = {
19+
cwd: magentoDirName,
20+
};
21+
22+
const sp = spinner();
23+
24+
return new Promise((resolve) => {
25+
const curl = spawn(
26+
"curl",
27+
[
28+
"-s",
29+
"https://raw.githubusercontent.com/markshust/docker-magento/master/lib/onelinesetup",
30+
],
31+
options
32+
);
33+
const bash = spawn("bash", ["-s", "--", magentoDomainName], options);
34+
35+
let stdout = "";
36+
37+
note(t("command.generate_store.magento.note_long"));
38+
39+
sp.start(
40+
picocolors.cyan(t("command.generate_store.progress.docker_start"))
41+
);
42+
43+
curl.stdout.pipe(bash.stdin);
44+
45+
bash.stdout.on("data", (data) => {
46+
if (
47+
data.toString().toLowerCase().includes("system") &&
48+
data.toString().toLowerCase().includes("password")
49+
) {
50+
sp.stop(
51+
picocolors.yellow(t("command.generate_store.magento.password"))
52+
);
53+
}
54+
55+
if (data.toString().includes("Restarting containers to apply updates")) {
56+
sp.start(
57+
picocolors.cyan(t("command.generate_store.progress.docker_start"))
58+
);
59+
}
60+
});
61+
62+
bash.stderr.on("data", async (data) => {
63+
stdout += data.toString();
64+
if (stdout.includes("port is already allocated")) {
65+
sp.stop();
66+
logSimpleErrorMessage(t("command.generate_store.magento.port_busy"));
67+
// delete the directory
68+
await removeDockerContainer(magentoDirName);
69+
}
70+
});
71+
72+
bash.on("exit", async (code) => {
73+
if (code === 0) {
74+
sp.stop(
75+
picocolors.green(t("command.generate_store.progress.docker_end"))
76+
);
77+
resolve(1);
78+
} else {
79+
sp.stop(
80+
picocolors.red(t("command.generate_store.progress.docker_failed"))
81+
);
82+
83+
if (
84+
stdout.includes('Project directory "/var/www/html/." is not empty')
85+
) {
86+
note(t("command.generate_store.magento.image_exists"));
87+
}
88+
// create a log file
89+
writeLog(stdout);
90+
91+
logSimpleInfoMessage(t("command.generate_store.magento.failed_log"));
92+
}
93+
});
94+
});
95+
};
96+
97+
export default installMagentoImage;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { spawn } from "child_process";
2+
import fs from "fs";
3+
4+
// rewrite with exec
5+
const removeDockerContainer = async (magentoDirName: string): Promise<any> => {
6+
const options = {
7+
cwd: magentoDirName,
8+
};
9+
10+
return new Promise(() => {
11+
const removeDocker = spawn("docker-compose", ["rm", "-f"], options);
12+
13+
removeDocker.on("exit", () => {
14+
fs.rmdirSync(magentoDirName, { recursive: true });
15+
});
16+
});
17+
};
18+
19+
export default removeDockerContainer;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { spawn } from "child_process";
2+
import { t } from "i18next";
3+
import {
4+
logSimpleErrorMessage,
5+
logSimpleSuccessMessage,
6+
} from "./terminalHelpers";
7+
8+
const checkNodeVersion = (nodeString: string): boolean => {
9+
const nodeVersion = nodeString.split("v")[1]?.split(".")[0];
10+
const subNodeVersion = nodeString.split("v")[1]?.split(".")[1];
11+
12+
if (Number(nodeVersion) === 16 && Number(subNodeVersion) >= 13) {
13+
return true;
14+
}
15+
16+
return false;
17+
};
18+
19+
/** Checking if Node version is correct as per prerequisites */
20+
const checkNode = async (
21+
writeLog: (message: string) => void
22+
): Promise<void> => {
23+
const node = spawn("node", ["-v"]);
24+
25+
return await new Promise((resolve) => {
26+
node.stdout.on("data", (data) => {
27+
writeLog(data.toString());
28+
if (!checkNodeVersion(data.toString())) {
29+
logSimpleErrorMessage(t("command.generate_store.magento.node_not_ok"));
30+
process.exit(1);
31+
}
32+
});
33+
34+
node.on("close", () => {
35+
writeLog(t("command.generate_store.magento.node_ok"));
36+
logSimpleSuccessMessage(t("command.generate_store.magento.node_ok"));
37+
resolve();
38+
});
39+
});
40+
};
41+
42+
export default checkNode;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { spawn } from "child_process";
2+
import { t } from "i18next";
3+
import {
4+
logSimpleErrorMessage,
5+
logSimpleInfoMessage,
6+
simpleLog,
7+
} from "./terminalHelpers";
8+
9+
const checkYarnVersion = (yarnString: string): boolean => {
10+
const yarnVersion = yarnString.split(".")[0];
11+
12+
if (Number(yarnVersion) === 1 || Number(yarnVersion) === 2) {
13+
return true;
14+
}
15+
16+
return false;
17+
};
18+
19+
/** Checking if Yarn is installed */
20+
const checkYarn = async (
21+
writeLog: (message: string) => void
22+
): Promise<void> => {
23+
const yarn =
24+
process.platform === "win32"
25+
? spawn("yarn.cmd", ["--version"])
26+
: spawn("yarn", ["--version"]);
27+
28+
yarn.stdout.on("data", (data) => {
29+
if (!checkYarnVersion(data.toString())) {
30+
writeLog(t("command.generate_store.magento.yarn_not_ok"));
31+
logSimpleErrorMessage(t("command.generate_store.magento.yarn_not_ok"));
32+
logSimpleInfoMessage(t("command.generate_store.magento.failed_log"));
33+
process.exit(1);
34+
}
35+
});
36+
37+
yarn.stderr.on("data", (data) => {
38+
writeLog(data.toString());
39+
simpleLog(data.toString());
40+
});
41+
42+
const isYarnVersionCorrect = await new Promise((resolve) => {
43+
yarn.on("close", (code) => resolve(code === 0));
44+
});
45+
46+
if (!isYarnVersionCorrect) {
47+
writeLog(t("command.generate_store.magento.yarn_not_ok"));
48+
logSimpleErrorMessage(t("command.generate_store.magento.yarn_not_ok"));
49+
logSimpleInfoMessage(t("command.generate_store.magento.failed_log"));
50+
process.exit(1);
51+
}
52+
};
53+
54+
export default checkYarn;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { spawn } from "child_process";
2+
import fs from "fs";
3+
import path from "path";
4+
5+
/** Copy auth.json file to Docker container */
6+
const copyAuth = async (
7+
magentoDirName: string,
8+
accessKey: string,
9+
secretKey: string
10+
) => {
11+
const options = {
12+
cwd: magentoDirName,
13+
};
14+
15+
const authFile = await fs.readFileSync(
16+
path.join(magentoDirName, "src/auth.json.sample"),
17+
"utf-8"
18+
);
19+
20+
await fs.writeFileSync(
21+
path.join(magentoDirName, "src/auth.json"),
22+
authFile
23+
.replace(/<public-key>/g, accessKey)
24+
.replace(/<private-key>/g, secretKey),
25+
"utf-8"
26+
);
27+
28+
const copyToContainer = spawn(
29+
"bin/copytocontainer",
30+
["src/auth.json"],
31+
options
32+
);
33+
34+
copyToContainer.on("close", () => undefined);
35+
};
36+
37+
export default copyAuth;

0 commit comments

Comments
 (0)