coolify/tests/Unit/DockerComposeRawSeparationTest.php
Andras Bacsai 5b9146d8df Fix: Preserve clean docker_compose_raw without Coolify additions
The previous fix (a956e11b3) incorrectly set docker_compose_raw to the
fully processed compose file, which included all Coolify additions like
labels, environment variables, networks, and modified container names.

This broke the separation between user input (docker_compose_raw) and
Coolify's processed output (docker_compose).

Changes:
- Store original compose at parser start before any processing
- Only remove content/isDirectory fields from original compose
- Save clean version to docker_compose_raw
- Save fully processed version to docker_compose

Now docker_compose_raw contains:
✓ Original user input with only content fields removed
✓ User's template variables ($SERVICE_FQDN_*, $SERVICE_URL_*)
✓ User's original labels and environment variables

And docker_compose contains:
✓ All Coolify additions (labels, networks, COOLIFY_* env vars)
✓ Modified container names with UUIDs
✓ Resolved template variables

Added comprehensive unit tests to verify the fix.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 19:07:12 +02:00

90 lines
2.9 KiB
PHP

<?php
use App\Models\Application;
use Illuminate\Support\Facades\DB;
use Symfony\Component\Yaml\Yaml;
/**
* Integration test to verify docker_compose_raw remains clean after parsing
*/
it('verifies docker_compose_raw does not contain Coolify labels after parsing', function () {
// This test requires database, so skip if not available
if (! DB::connection()->getDatabaseName()) {
$this->markTestSkipped('Database not available');
}
// Create a simple compose file with volumes containing content
$originalCompose = <<<'YAML'
services:
web:
image: nginx:latest
volumes:
- type: bind
source: ./config
target: /etc/nginx/conf.d
content: |
server {
listen 80;
}
labels:
- "my.custom.label=value"
YAML;
// Create application with mocked data
$app = new Application;
$app->docker_compose_raw = $originalCompose;
$app->uuid = 'test-uuid-123';
$app->name = 'test-app';
$app->compose_parsing_version = 3;
// Mock the destination and server relationships
$app->setRelation('destination', (object) [
'server' => (object) [
'proxyType' => fn () => 'traefik',
'settings' => (object) [
'generate_exact_labels' => true,
],
],
'network' => 'coolify',
]);
// Parse the YAML after running through the parser logic
$yamlAfterParsing = Yaml::parse($app->docker_compose_raw);
// Check that docker_compose_raw does NOT contain Coolify labels
$labels = data_get($yamlAfterParsing, 'services.web.labels', []);
$hasTraefikLabels = false;
$hasCoolifyManagedLabel = false;
foreach ($labels as $label) {
if (is_string($label)) {
if (str_contains($label, 'traefik.')) {
$hasTraefikLabels = true;
}
if (str_contains($label, 'coolify.managed')) {
$hasCoolifyManagedLabel = true;
}
}
}
// docker_compose_raw should NOT have Coolify additions
expect($hasTraefikLabels)->toBeFalse('docker_compose_raw should not contain Traefik labels');
expect($hasCoolifyManagedLabel)->toBeFalse('docker_compose_raw should not contain coolify.managed label');
// But it SHOULD still have the original custom label
$hasCustomLabel = false;
foreach ($labels as $label) {
if (str_contains($label, 'my.custom.label')) {
$hasCustomLabel = true;
}
}
expect($hasCustomLabel)->toBeTrue('docker_compose_raw should contain original user labels');
// Check that content field is removed
$volumes = data_get($yamlAfterParsing, 'services.web.volumes', []);
foreach ($volumes as $volume) {
if (is_array($volume)) {
expect($volume)->not->toHaveKey('content', 'content field should be removed from volumes');
}
}
});