mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-09-14 11:06:15 +05:00
fix(compose): handle stack up alias in model guard
This commit is contained in:
parent
8e3b9ef89e
commit
69a007a175
@ -214,6 +214,61 @@ services:
|
||||
expect(isStackDeployCommand("-cD remote stack deploy --help")).toBe(false);
|
||||
});
|
||||
|
||||
it("treats stack up as the documented stack deploy alias", () => {
|
||||
expect(isStackDeployCommand("stack up -c docker-compose.yml demo")).toBe(
|
||||
true,
|
||||
);
|
||||
expect(
|
||||
isStackDeployCommand("'stack' 'up' -c docker-compose.yml demo"),
|
||||
).toBe(true);
|
||||
expect(
|
||||
isStackDeployCommand(
|
||||
"--context remote stack up -c docker-compose.yml demo",
|
||||
),
|
||||
).toBe(true);
|
||||
expect(
|
||||
isStackDeployCommand(
|
||||
"--context=remote stack up -c docker-compose.yml demo",
|
||||
),
|
||||
).toBe(true);
|
||||
expect(isStackDeployCommand("-D stack up -c docker-compose.yml demo")).toBe(
|
||||
true,
|
||||
);
|
||||
expect(
|
||||
isStackDeployCommand("st\"ack\" u'p' -c docker-compose.yml demo"),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("does not treat compose commands as stack up", () => {
|
||||
expect(isStackDeployCommand("compose up")).toBe(false);
|
||||
expect(isStackDeployCommand("compose run app stack up")).toBe(false);
|
||||
expect(isStackDeployCommand("compose exec app stack up")).toBe(false);
|
||||
expect(isStackDeployCommand("compose -f stack.yml up")).toBe(false);
|
||||
expect(isStackDeployCommand("--context stack compose up")).toBe(false);
|
||||
});
|
||||
|
||||
it("skips deprecated stack --orchestrator before deploy or up", () => {
|
||||
expect(
|
||||
isStackDeployCommand(
|
||||
"stack --orchestrator swarm deploy -c docker-compose.yml demo",
|
||||
),
|
||||
).toBe(true);
|
||||
expect(
|
||||
isStackDeployCommand(
|
||||
"stack --orchestrator=swarm up -c docker-compose.yml demo",
|
||||
),
|
||||
).toBe(true);
|
||||
expect(
|
||||
isStackDeployCommand(
|
||||
"--context remote stack --orchestrator swarm up -c docker-compose.yml demo",
|
||||
),
|
||||
).toBe(true);
|
||||
expect(isStackDeployCommand("stack --orchestrator deploy")).toBe(false);
|
||||
expect(
|
||||
isStackDeployCommand("stack --orchestrator deploy -c file.yml demo"),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("classifies quoted shell argv the way /bin/sh does", () => {
|
||||
expect(
|
||||
isStackDeployCommand("'stack' 'deploy' -c docker-compose.yml demo"),
|
||||
@ -407,6 +462,50 @@ services:
|
||||
).rejects.toThrow(STACK_COMPOSE_MODELS_ERROR);
|
||||
});
|
||||
|
||||
it("rejects custom stack up commands when models are present", async () => {
|
||||
const models = yaml(spec({ models: { llm: { model: "ai/smollm2" } } }));
|
||||
for (const command of [
|
||||
"stack up -c docker-compose.yml demo",
|
||||
"'stack' 'up' -c docker-compose.yml demo",
|
||||
"--context remote stack up -c docker-compose.yml demo",
|
||||
"--context=remote stack up -c docker-compose.yml demo",
|
||||
"-D stack up -c docker-compose.yml demo",
|
||||
"stack --orchestrator swarm up -c docker-compose.yml demo",
|
||||
"stack --orchestrator=swarm deploy -c docker-compose.yml demo",
|
||||
]) {
|
||||
await expect(
|
||||
writeDeploy(
|
||||
compose({
|
||||
composeType: "docker-compose",
|
||||
command,
|
||||
composeFile: models,
|
||||
}),
|
||||
),
|
||||
).rejects.toThrow(STACK_COMPOSE_MODELS_ERROR);
|
||||
}
|
||||
});
|
||||
|
||||
it("allows compose commands that only resemble stack up", async () => {
|
||||
const models = yaml(spec({ models: { llm: { model: "ai/smollm2" } } }));
|
||||
for (const command of [
|
||||
"compose up",
|
||||
"compose run app stack up",
|
||||
"compose exec app stack up",
|
||||
"compose -f stack.yml up",
|
||||
"--context stack compose up",
|
||||
]) {
|
||||
await expect(
|
||||
writeDeploy(
|
||||
compose({
|
||||
composeType: "docker-compose",
|
||||
command,
|
||||
composeFile: models,
|
||||
}),
|
||||
),
|
||||
).resolves.toContain("base64 -d");
|
||||
}
|
||||
});
|
||||
|
||||
it("does not treat a compose file token containing 'stack deploy' as stack deploy", async () => {
|
||||
await expect(
|
||||
writeDeploy(
|
||||
@ -627,6 +726,27 @@ describe("getBuildComposeCommand stack models", () => {
|
||||
),
|
||||
).rejects.toThrow(STACK_COMPOSE_MODELS_ERROR);
|
||||
});
|
||||
|
||||
it("does not emit stack up when models are present", async () => {
|
||||
await expect(
|
||||
getBuildComposeCommand(
|
||||
buildArgs({
|
||||
composeType: "docker-compose",
|
||||
command: "stack up -c docker-compose.yml demo",
|
||||
composeFile: yaml(spec({ models: { llm: { model: "ai/smollm2" } } })),
|
||||
}),
|
||||
),
|
||||
).rejects.toThrow(STACK_COMPOSE_MODELS_ERROR);
|
||||
await expect(
|
||||
getBuildComposeCommand(
|
||||
buildArgs({
|
||||
composeType: "docker-compose",
|
||||
command: "--context remote stack up -c docker-compose.yml demo",
|
||||
composeFile: yaml(spec({ models: { llm: { model: "ai/smollm2" } } })),
|
||||
}),
|
||||
),
|
||||
).rejects.toThrow(STACK_COMPOSE_MODELS_ERROR);
|
||||
});
|
||||
});
|
||||
|
||||
const fakeDockerArgv = (command: string, pathPrefix: string) => {
|
||||
@ -753,6 +873,13 @@ process.stdout.write(JSON.stringify(process.argv.slice(2)));
|
||||
expect(
|
||||
fakeDockerArgv("'stack' 'deploy' -c file.yml demo", fakePath),
|
||||
).toEqual(["stack", "deploy", "-c", "file.yml", "demo"]);
|
||||
expect(fakeDockerArgv("'stack' 'up' -c file.yml demo", fakePath)).toEqual([
|
||||
"stack",
|
||||
"up",
|
||||
"-c",
|
||||
"file.yml",
|
||||
"demo",
|
||||
]);
|
||||
expect(
|
||||
fakeDockerArgv(
|
||||
'--config "/tmp/docker config" stack deploy -c file.yml demo',
|
||||
|
||||
@ -228,11 +228,28 @@ const skipDockerGlobalOptions = (tokens: string[]) => {
|
||||
return i;
|
||||
};
|
||||
|
||||
const skipStackOrchestratorOption = (tokens: string[], i: number) => {
|
||||
const token = tokens[i];
|
||||
if (!token) return i;
|
||||
if (token === "--orchestrator") {
|
||||
if (i + 1 >= tokens.length) return -1;
|
||||
return i + 2;
|
||||
}
|
||||
if (token.startsWith("--orchestrator=")) return i + 1;
|
||||
return i;
|
||||
};
|
||||
|
||||
// Docker documents `stack up` as an alias of `stack deploy` (CLI 28.5+ / 29.x).
|
||||
// Deprecated `--orchestrator` is a stack-level string flag that may sit between
|
||||
// `stack` and `deploy`/`up`; `stack --orchestrator deploy` consumes `deploy` as
|
||||
// the flag value and is not a deployment.
|
||||
export const isStackDeployCommand = (command: string) => {
|
||||
const tokens = tokenizeDockerCommand(command);
|
||||
const i = skipDockerGlobalOptions(tokens);
|
||||
if (i < 0) return false;
|
||||
return tokens[i] === "stack" && tokens[i + 1] === "deploy";
|
||||
if (i < 0 || tokens[i] !== "stack") return false;
|
||||
const j = skipStackOrchestratorOption(tokens, i + 1);
|
||||
if (j < 0) return false;
|
||||
return tokens[j] === "deploy" || tokens[j] === "up";
|
||||
};
|
||||
|
||||
export const writeDomainsToCompose = async (
|
||||
|
||||
Loading…
Reference in New Issue
Block a user