diff --git a/source/compose.manager/include/Util.php b/source/compose.manager/include/Util.php index 00f28528..e4f9fe8d 100644 --- a/source/compose.manager/include/Util.php +++ b/source/compose.manager/include/Util.php @@ -1541,9 +1541,8 @@ public static function buildEnvTemplateContent(): string /** * Core override resolution logic shared by both factories. * - * Computes the override filename from the compose file, resolves project - * and indirect override paths while preserving legacy filenames as-is, - * and auto-creates a project override template if needed. + * Computes the override filename from the compose file and resolves + * project and indirect override paths while preserving legacy filenames. * * @param string $projectPath Full path to the stack directory * @param string|null $indirectPath Indirect target directory, or null if not indirect @@ -3098,7 +3097,11 @@ private function getComposeFilePaths(): array } } else { $overridePath = $this->getOverridePath(); - if ($overridePath !== null) { + // Keep the preferred path available through getOverridePath() for + // editor/write operations, but only pass an existing optional + // override to Compose. Missing overrides are normal for older and + // manually created stacks. + if ($overridePath !== null && is_file($overridePath)) { $paths[] = $overridePath; } } diff --git a/tests/unit/ComposeCommandBuilderTest.php b/tests/unit/ComposeCommandBuilderTest.php index f2a53164..fd207771 100644 --- a/tests/unit/ComposeCommandBuilderTest.php +++ b/tests/unit/ComposeCommandBuilderTest.php @@ -71,6 +71,26 @@ public function testBuildForActionUsesDefaultProfilesForUp(): void $this->assertSame($stackDir, $spec['stackPath']); } + public function testBuildForUpAndDownOmitsMissingOptionalOverride(): void + { + $stack = 'missing-override'; + $stackDir = $this->tempRoot . '/' . $stack; + mkdir($stackDir); + file_put_contents($stackDir . '/compose.yaml', "services:\n web:\n image: nginx\n"); + + $info = \StackInfo::fromProject($this->tempRoot, $stack); + $overridePath = $info->getOverridePath(); + + $this->assertNotNull($overridePath); + $this->assertFileDoesNotExist($overridePath); + $upSpec = \ComposeCommandBuilder::buildForAction($info, 'up'); + $downSpec = \ComposeCommandBuilder::buildForAction($info, 'down'); + + $this->assertSame([$stackDir . '/compose.yaml'], $upSpec['composeFiles']); + $this->assertSame([$stackDir . '/compose.yaml'], $downSpec['composeFiles']); + $this->assertSame($overridePath, $info->getOverridePath(), 'The preferred write target must remain available.'); + } + public function testBuildForActionUsesRunningProfilesForUpdate(): void { $stack = 'profiles-update-running'; diff --git a/tests/unit/ExtraComposeFilesTest.php b/tests/unit/ExtraComposeFilesTest.php index a26337bc..21beef14 100644 --- a/tests/unit/ExtraComposeFilesTest.php +++ b/tests/unit/ExtraComposeFilesTest.php @@ -48,9 +48,10 @@ public function testExtraAbsoluteFileIsAppended(): void $spec = \ComposeCommandBuilder::fromProject($this->tempRoot, 'extra-abs', 'up'); - // The plugin auto-creates compose.override.yaml; extras come after it. + // The app-managed override is optional and only included when its file exists. + // With no override file, extras follow the main compose file. $this->assertSame( - [$stackDir . '/compose.yaml', $stackDir . '/compose.override.yaml', $extraFile], + [$stackDir . '/compose.yaml', $extraFile], $spec['composeFiles'] ); } diff --git a/tests/unit/StackInfoTest.php b/tests/unit/StackInfoTest.php index 66f9d693..2496f44e 100644 --- a/tests/unit/StackInfoTest.php +++ b/tests/unit/StackInfoTest.php @@ -1121,9 +1121,11 @@ public function testBuildComposeArgsWithComposeFileInEnv(): void $info = \StackInfo::fromProject($this->tempRoot, $stack); $args = $info->buildComposeArgs(); - $this->assertSame(3, count($args['filePaths'])); + $this->assertCount(2, $args['filePaths']); $this->assertStringContainsString('compose.debug.yaml', $args['files']); $this->assertContains($stackDir . '/compose.debug.yaml', $args['filePaths']); + $this->assertNotContains($stackDir . '/compose.override.yaml', $args['filePaths']); + $this->assertStringNotContainsString($stackDir . '/compose.override.yaml', $args['files']); } public function testProjectLoadsWhenComposeFileIsOnlyDeclaredInDotEnv(): void @@ -1207,16 +1209,15 @@ public function testBuildComposeArgsWithQuotedComposeFileInEnv(): void $info = \StackInfo::fromProject($this->tempRoot, $stack); $args = $info->buildComposeArgs(); - $this->assertSame(4, count($args['filePaths'])); + $this->assertSame(3, count($args['filePaths'])); $this->assertStringContainsString('compose.debug.yaml', $args['files']); $this->assertStringContainsString('compose.extra.yaml', $args['files']); $this->assertContains($stackDir . '/compose.debug.yaml', $args['filePaths']); $this->assertContains($stackDir . '/compose.extra.yaml', $args['filePaths']); - $this->assertContains($stackDir . '/compose.override.yaml', $args['filePaths']); + $this->assertNotContains($stackDir . '/compose.override.yaml', $args['filePaths']); $this->assertSame( implode(PATH_SEPARATOR, [ $stackDir . '/compose.yaml', - $stackDir . '/compose.override.yaml', $stackDir . '/compose.debug.yaml', $stackDir . '/compose.extra.yaml', ]),