@meshxdata/fops 0.1.27 → 0.1.29
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/CHANGELOG.md +4 -2887
- package/package.json +1 -1
- package/src/commands/lifecycle.js +44 -7
- package/src/doctor.js +1 -1
- package/src/setup/wizard.js +2 -2
package/package.json
CHANGED
|
@@ -22,8 +22,8 @@ function resolveServiceName(root, input) {
|
|
|
22
22
|
export function registerLifecycleCommands(program, registry) {
|
|
23
23
|
program
|
|
24
24
|
.command("up")
|
|
25
|
-
.description("Start
|
|
26
|
-
.argument("[component]", "Component to
|
|
25
|
+
.description("Start Foundation services (all or specific component)")
|
|
26
|
+
.argument("[component]", "Component to start (backend, frontend, watcher, processor, scheduler, storage, hive, traefik, data). Add [branch] to checkout first.")
|
|
27
27
|
.argument("[branch]", "Git branch to checkout in that component (e.g. FOU-2072)")
|
|
28
28
|
.option("-d, --detach", "Run in background", true)
|
|
29
29
|
.option("--k3s", "Include k3s Kubernetes services (default: true for local)", true)
|
|
@@ -51,13 +51,28 @@ export function registerLifecycleCommands(program, registry) {
|
|
|
51
51
|
|
|
52
52
|
program
|
|
53
53
|
.command("down")
|
|
54
|
-
.description("Stop all
|
|
54
|
+
.description("Stop Foundation services (all or specific)")
|
|
55
|
+
.argument("[services...]", "Optional: stop only these services (e.g. watcher, backend)")
|
|
55
56
|
.option("--clean", "Remove volumes and orphans (make clean)")
|
|
56
|
-
.action(async (opts) => {
|
|
57
|
+
.action(async (services, opts) => {
|
|
57
58
|
const root = requireRoot(program);
|
|
58
59
|
const { execa } = await import("execa");
|
|
59
60
|
await runHook(registry, "before:down", { root });
|
|
60
|
-
|
|
61
|
+
|
|
62
|
+
// Resolve short service names to docker compose service names
|
|
63
|
+
const serviceNames = (services || []).filter(Boolean).flatMap((s) => {
|
|
64
|
+
const sub = COMPONENT_SUBMODULES[s];
|
|
65
|
+
if (sub) return sub.restart;
|
|
66
|
+
return [s.startsWith("foundation-") ? s : `foundation-${s}`];
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
if (serviceNames.length) {
|
|
70
|
+
// Stop specific services only
|
|
71
|
+
console.log(chalk.cyan(` Stopping ${serviceNames.join(", ")}...`));
|
|
72
|
+
await dockerCompose(root, ["stop", "-t", "5", ...serviceNames], { timeout: 60000 });
|
|
73
|
+
// Remove the stopped containers so they don't show as "exited"
|
|
74
|
+
await dockerCompose(root, ["rm", "-f", ...serviceNames], { timeout: 30000 });
|
|
75
|
+
} else if (opts.clean) {
|
|
61
76
|
const result = await dockerCompose(root, ["down", "-v", "--remove-orphans", "-t", "5"], { timeout: 120000 });
|
|
62
77
|
if (result?.timedOut) {
|
|
63
78
|
console.log(chalk.yellow(" Compose down timed out — force-killing containers..."));
|
|
@@ -403,6 +418,11 @@ async function runUp(program, registry, opts) {
|
|
|
403
418
|
|
|
404
419
|
// Optional: checkout a component submodule to a specific branch before starting (e.g. fops up backend FOU-2072)
|
|
405
420
|
const comp = opts.component && COMPONENT_SUBMODULES[opts.component];
|
|
421
|
+
if (opts.component && !comp) {
|
|
422
|
+
console.error(chalk.red(`\n Unknown component: ${opts.component}`));
|
|
423
|
+
console.error(chalk.dim(` Available: ${Object.keys(COMPONENT_SUBMODULES).join(", ")}\n`));
|
|
424
|
+
process.exit(1);
|
|
425
|
+
}
|
|
406
426
|
if (comp && opts.branch) {
|
|
407
427
|
const componentDir = path.join(root, comp.dir);
|
|
408
428
|
if (!fs.existsSync(path.join(componentDir, ".git"))) {
|
|
@@ -705,6 +725,23 @@ async function runUp(program, registry, opts) {
|
|
|
705
725
|
}
|
|
706
726
|
} catch {}
|
|
707
727
|
|
|
728
|
+
// Ensure credentials/kubeconfig.yaml exists as a file (not a directory).
|
|
729
|
+
// Docker will auto-create the mount target as a directory if the file is missing,
|
|
730
|
+
// which causes k3s to fail with "is a directory" on startup.
|
|
731
|
+
const credentialsDir = path.join(root, "credentials");
|
|
732
|
+
const kubeconfigPath = path.join(credentialsDir, "kubeconfig.yaml");
|
|
733
|
+
fs.mkdirSync(credentialsDir, { recursive: true });
|
|
734
|
+
try {
|
|
735
|
+
const stat = fs.statSync(kubeconfigPath);
|
|
736
|
+
if (stat.isDirectory()) {
|
|
737
|
+
fs.rmSync(kubeconfigPath, { recursive: true, force: true });
|
|
738
|
+
fs.writeFileSync(kubeconfigPath, "");
|
|
739
|
+
}
|
|
740
|
+
} catch {
|
|
741
|
+
// File doesn't exist — create it
|
|
742
|
+
fs.writeFileSync(kubeconfigPath, "");
|
|
743
|
+
}
|
|
744
|
+
|
|
708
745
|
// Clean up internal MinIO metadata directory to avoid migration constraint violations
|
|
709
746
|
const minioSysDir = path.join(root, "storage-data", ".minio.sys");
|
|
710
747
|
if (fs.existsSync(minioSysDir)) {
|
|
@@ -902,8 +939,8 @@ async function runUp(program, registry, opts) {
|
|
|
902
939
|
startSpinner();
|
|
903
940
|
}
|
|
904
941
|
|
|
905
|
-
// When fops up <component>
|
|
906
|
-
const componentOnlyUp = comp
|
|
942
|
+
// When fops up <component> [branch], only pull and up that component — avoid full stack rebuild
|
|
943
|
+
const componentOnlyUp = !!comp;
|
|
907
944
|
|
|
908
945
|
// Pull images only when --pull is passed (or use `fops pull` separately)
|
|
909
946
|
if (opts.pull) {
|
package/src/doctor.js
CHANGED
|
@@ -558,7 +558,7 @@ export async function runDoctor(opts = {}, registry = null) {
|
|
|
558
558
|
} else {
|
|
559
559
|
fail("Claude CLI not found", "install globally: npm install -g @anthropic-ai/claude-code", async () => {
|
|
560
560
|
console.log(chalk.cyan(" ▶ npm install -g @anthropic-ai/claude-code"));
|
|
561
|
-
await execa("npm", ["install", "-g", "@anthropic-ai/claude-code"], { stdio: "inherit", timeout: 300_000 });
|
|
561
|
+
await execa("npm", ["install", "-g", "--loglevel=error", "@anthropic-ai/claude-code"], { stdio: "inherit", timeout: 300_000 });
|
|
562
562
|
});
|
|
563
563
|
}
|
|
564
564
|
}
|
package/src/setup/wizard.js
CHANGED
|
@@ -67,9 +67,9 @@ async function installTool(name, { brew, brewCask, winget, apt, npm: npmPkg } =
|
|
|
67
67
|
const cmd = needsSudo ? `sudo npm install -g ${pkg}` : `npm install -g ${pkg}`;
|
|
68
68
|
console.log(ACCENT(` ▶ ${cmd}`));
|
|
69
69
|
if (needsSudo) {
|
|
70
|
-
await execa("sudo", ["npm", "install", "-g", pkg], { stdio: "inherit", timeout: 300_000 });
|
|
70
|
+
await execa("sudo", ["npm", "install", "-g", "--loglevel=error", pkg], { stdio: "inherit", timeout: 300_000 });
|
|
71
71
|
} else {
|
|
72
|
-
await execa("npm", ["install", "-g", pkg], { stdio: "inherit", timeout: 300_000 });
|
|
72
|
+
await execa("npm", ["install", "-g", "--loglevel=error", pkg], { stdio: "inherit", timeout: 300_000 });
|
|
73
73
|
}
|
|
74
74
|
return true;
|
|
75
75
|
}
|