mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-25 01:37:05 +00:00
fix(deploy): preserve compose.override.yml when Mesh is enabled (#1420)
When a single-file stack is opted into Sencho Mesh, the deploy builds an explicit `docker compose -f <base> -f <mesh override>` list. Passing any explicit -f disables Compose's automatic discovery of compose.override.yml (and the docker-compose.override variants), so a user's hand-authored override was silently dropped from the effective deploy once Mesh was on. Resolve the user's override file (first existing variant, with the same stack-name and symlink-containment guards as the base compose file) and insert it between the base and the mesh override, so it layers exactly as Compose's implicit discovery would, with the mesh override still taking precedence. A transient read failure during the lookup degrades to "no override" rather than failing the deploy; a stack-name or containment-guard rejection still aborts. Multi-file Git-source stacks and non-mesh deploys are unaffected.
This commit is contained in:
@@ -117,10 +117,29 @@ export class ComposeService {
|
||||
}
|
||||
if (overridePath) {
|
||||
if (filePrefix.length === 0) {
|
||||
// Single-file stack: passing any -f disables auto-discovery, so name the
|
||||
// base file explicitly before layering the override on top of it.
|
||||
const baseFilename = await FileSystemService.getInstance(this.nodeId).getComposeFilename(stackName);
|
||||
// Single-file stack: passing any -f disables compose's auto-discovery, so name
|
||||
// the base file explicitly, then re-add the user's implicit override (if any) so
|
||||
// it is not silently dropped, before layering the mesh override on top.
|
||||
const fsSvc = FileSystemService.getInstance(this.nodeId);
|
||||
const baseFilename = await fsSvc.getComposeFilename(stackName);
|
||||
args.push('-f', baseFilename);
|
||||
let userOverride: string | null = null;
|
||||
try {
|
||||
userOverride = await fsSvc.getOverrideFilename(stackName);
|
||||
} catch (err) {
|
||||
// Containment-guard rejections (bad stack name / symlink escape) are hard errors:
|
||||
// abort the deploy rather than degrade. The "no override" case returns null rather
|
||||
// than throwing, so any other throw is transient I/O: drop the override and proceed
|
||||
// (logging the consequence) instead of failing the deploy.
|
||||
const code = (err as { code?: string }).code;
|
||||
if (code === 'INVALID_STACK_NAME' || code === 'INVALID_PATH' || code === 'SYMLINK_ESCAPE') {
|
||||
throw err;
|
||||
}
|
||||
console.warn('[ComposeService] could not resolve user compose override; deploying without it:', sanitizeForLog((err as Error).message));
|
||||
}
|
||||
if (userOverride) {
|
||||
args.push('-f', userOverride);
|
||||
}
|
||||
}
|
||||
args.push('-f', overridePath);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user