mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-12 15:53:46 -04:00
fix(previews): keep compose preview data out of production pending changes
Closes #12284
This commit is contained in:
@@ -1507,7 +1507,7 @@ class Application extends BaseModel
|
||||
$previousSnapshot = [];
|
||||
}
|
||||
|
||||
return app(ConfigurationDiffer::class)->diff($previousSnapshot, $currentSnapshot);
|
||||
return app(ConfigurationDiffer::class)->diff(ApplicationConfigurationSnapshot::withoutPreviewVolumes($previousSnapshot, $this), $currentSnapshot);
|
||||
}
|
||||
|
||||
public function hasPendingDeploymentConfigurationChanges(): bool
|
||||
@@ -1551,7 +1551,7 @@ class Application extends BaseModel
|
||||
'configuration_hash' => $hash,
|
||||
'configuration_snapshot' => $snapshot,
|
||||
'configuration_diff' => $previousDeployment?->configuration_snapshot
|
||||
? app(ConfigurationDiffer::class)->diff($previousDeployment->configuration_snapshot, $snapshot)->toArray()
|
||||
? app(ConfigurationDiffer::class)->diff(ApplicationConfigurationSnapshot::withoutPreviewVolumes($previousDeployment->configuration_snapshot, $this), $snapshot)->toArray()
|
||||
: null,
|
||||
]);
|
||||
|
||||
|
||||
@@ -100,6 +100,36 @@ class ApplicationConfigurationSnapshot
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the volumes of Docker Compose preview deployments from a snapshot. Older snapshots
|
||||
* can contain them, because the parser stores preview volumes on the application.
|
||||
*
|
||||
* @param array<string, mixed> $snapshot
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public static function withoutPreviewVolumes(array $snapshot, Application $application): array
|
||||
{
|
||||
if (! is_array(data_get($snapshot, 'sections.storage.items'))) {
|
||||
return $snapshot;
|
||||
}
|
||||
|
||||
$snapshot['sections']['storage']['items'] = collect($snapshot['sections']['storage']['items'])
|
||||
->reject(fn (array $item): bool => str_starts_with((string) data_get($item, 'key'), 'volume_')
|
||||
&& self::isPreviewVolumeName((string) data_get($item, 'compare_value.source'), $application))
|
||||
->values()
|
||||
->all();
|
||||
|
||||
return $snapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
* The compose parser names preview volumes "{uuid}_{volume}-pr-{id}" ("{uuid}-{volume}-pr-{id}" before parser version 3).
|
||||
*/
|
||||
private static function isPreviewVolumeName(string $name, Application $application): bool
|
||||
{
|
||||
return preg_match('/^'.preg_quote($application->uuid, '/').'[_-].+-pr-\d+$/', $name) === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
@@ -237,6 +267,7 @@ class ApplicationConfigurationSnapshot
|
||||
$volumes = $this->application->persistentStorages()
|
||||
->orderBy('id')
|
||||
->get(['id', 'name', 'mount_path', 'host_path'])
|
||||
->reject(fn (LocalPersistentVolume $volume): bool => blank($volume->host_path) && self::isPreviewVolumeName($volume->name, $this->application))
|
||||
->map(function (LocalPersistentVolume $volume): array {
|
||||
$source = $volume->host_path ?: $volume->name;
|
||||
|
||||
|
||||
@@ -2018,6 +2018,10 @@ function applicationParser(Application $resource, int $pull_request_id = 0, ?int
|
||||
$serviceEnvKey = str(normalizeComposeServiceName((string) $forServiceName))->upper();
|
||||
$coolifyEnvironments->put('SERVICE_URL_'.$serviceEnvKey, $coolifyUrl->__toString());
|
||||
$coolifyEnvironments->put('SERVICE_FQDN_'.$serviceEnvKey, $coolifyFqdn);
|
||||
// A preview uses its own domains; the stored variables belong to the main application.
|
||||
if ($isPullRequest) {
|
||||
continue;
|
||||
}
|
||||
$resource->environment_variables()->updateOrCreate([
|
||||
'resourceable_type' => Application::class,
|
||||
'resourceable_id' => $resource->id,
|
||||
@@ -2034,7 +2038,7 @@ function applicationParser(Application $resource, int $pull_request_id = 0, ?int
|
||||
'value' => $coolifyFqdn,
|
||||
'is_preview' => false,
|
||||
]);
|
||||
} else {
|
||||
} elseif (! $isPullRequest) {
|
||||
$resource->environment_variables()->where('resourceable_type', Application::class)
|
||||
->where('resourceable_id', $resource->id)
|
||||
->where('key', 'LIKE', "SERVICE_FQDN_{$serviceNameFormatted}%")
|
||||
@@ -2099,7 +2103,7 @@ function applicationParser(Application $resource, int $pull_request_id = 0, ?int
|
||||
if ($environment->count() > 0) {
|
||||
$environment = $environment->filter(function ($value, $key) {
|
||||
return ! str($key)->startsWith('SERVICE_FQDN_');
|
||||
})->map(function ($value, $key) use ($resource) {
|
||||
})->map(function ($value, $key) use ($resource, $isPullRequest) {
|
||||
// Preserve empty strings and null values with correct Docker Compose semantics:
|
||||
// - Empty string: Variable is set to "" (e.g., HTTP_PROXY="" means "no proxy")
|
||||
// - Null: Variable is unset/removed from container environment (may inherit from host)
|
||||
@@ -2107,8 +2111,9 @@ function applicationParser(Application $resource, int $pull_request_id = 0, ?int
|
||||
// User explicitly wants variable unset - respect that
|
||||
// NEVER override from database - null means "inherit from environment"
|
||||
// Keep as null (will be excluded from container environment)
|
||||
} elseif ($value === '') {
|
||||
// Empty string - allow database override for backward compatibility
|
||||
} elseif ($value === '' && ! ($isPullRequest && str($key)->startsWith('SERVICE_URL_'))) {
|
||||
// Empty string - allow database override for backward compatibility.
|
||||
// The stored service URLs belong to the main application, so a preview does not use them.
|
||||
$dbEnv = $resource->environment_variables()->where('key', $key)->first();
|
||||
// Only use database override if it exists AND has a non-empty value
|
||||
if ($dbEnv && str($dbEnv->value)->isNotEmpty()) {
|
||||
|
||||
@@ -249,3 +249,17 @@ it('parses a preview with a bind mount in development mode', function () {
|
||||
|
||||
expect(json_encode($compose, JSON_UNESCAPED_SLASHES))->toContain('/config/app.conf-pr-42');
|
||||
});
|
||||
|
||||
it('keeps the production service URL variables when it parses a preview', function () {
|
||||
Process::fake();
|
||||
$this->application->update(['docker_compose_domains' => json_encode(['web' => ['domain' => 'https://web.example.com']])]);
|
||||
$this->application->fresh()->parse();
|
||||
$this->preview->update(['docker_compose_domains' => json_encode(['web' => ['domain' => 'https://pr-42.example.com']])]);
|
||||
|
||||
$compose = $this->application->fresh()->parse(pull_request_id: 42, preview_id: $this->preview->id);
|
||||
|
||||
$productionVariables = $this->application->environment_variables()->pluck('value', 'key');
|
||||
expect($productionVariables->get('SERVICE_URL_WEB'))->toBe('https://web.example.com')
|
||||
->and($productionVariables->get('SERVICE_FQDN_WEB'))->toBe('web.example.com')
|
||||
->and(json_encode($compose, JSON_UNESCAPED_SLASHES))->toContain('https://pr-42.example.com');
|
||||
});
|
||||
|
||||
@@ -1386,26 +1386,26 @@
|
||||
required: true
|
||||
SELF_REF: null
|
||||
SERVICE_BASE64_64_WEB: '<generated:SERVICE_BASE64_64_WEB:64>'
|
||||
SERVICE_FQDN_ADMIN: 7.admin.example.com
|
||||
SERVICE_FQDN_ADMIN: referenceapplication0001.10.0.0.1.sslip.io
|
||||
SERVICE_FQDN_ADMIN_8080: null
|
||||
SERVICE_FQDN_API: 7.www.api.example.com
|
||||
SERVICE_FQDN_API_V2: 7.api-v2.example.com
|
||||
SERVICE_FQDN_BLOG: 7.blog.example.com
|
||||
SERVICE_FQDN_MY_APP: 7.my-app.example.com
|
||||
SERVICE_FQDN_WEB: 7.web.example.com
|
||||
SERVICE_FQDN_WEB_3000: null
|
||||
SERVICE_FQDN_API: referenceapplication0001.10.0.0.1.sslip.io/api
|
||||
SERVICE_FQDN_API_V2: api-v2.example.com
|
||||
SERVICE_FQDN_BLOG: blog.example.com
|
||||
SERVICE_FQDN_MY_APP: my-app.example.com
|
||||
SERVICE_FQDN_WEB: web.example.com
|
||||
SERVICE_FQDN_WEB_3000: 'web-referenceapplication0001.10.0.0.1.sslip.io:3000'
|
||||
SERVICE_HEX_32_WEB: '<generated:SERVICE_HEX_32_WEB:32>'
|
||||
SERVICE_PASSWORD_DB: '<generated:SERVICE_PASSWORD_DB:32>'
|
||||
SERVICE_PASSWORD_NOBRACES: '<generated:SERVICE_PASSWORD_NOBRACES:32>'
|
||||
SERVICE_PASSWORD_WEB: '<generated:SERVICE_PASSWORD_WEB:32>'
|
||||
SERVICE_URL_ADMIN: 'https://7.admin.example.com'
|
||||
SERVICE_URL_API: 'https://7.www.api.example.com'
|
||||
SERVICE_URL_API_V2: 'https://7.api-v2.example.com'
|
||||
SERVICE_URL_BLOG: 'https://7.blog.example.com/blog:2368'
|
||||
SERVICE_URL_MY_APP: 'https://7.my-app.example.com'
|
||||
SERVICE_URL_ADMIN: 'https://admin.example.com'
|
||||
SERVICE_URL_API: 'https://www.api.example.com'
|
||||
SERVICE_URL_API_V2: 'https://api-v2.example.com'
|
||||
SERVICE_URL_BLOG: 'https://blog.example.com/blog:2368'
|
||||
SERVICE_URL_MY_APP: 'https://my-app.example.com'
|
||||
SERVICE_URL_MY_APP_80: null
|
||||
SERVICE_URL_WEB: 'https://7.web.example.com'
|
||||
SERVICE_URL_WEB_3000: null
|
||||
SERVICE_URL_WEB: 'https://web.example.com'
|
||||
SERVICE_URL_WEB_3000: 'http://web-referenceapplication0001.10.0.0.1.sslip.io:3000'
|
||||
SERVICE_USER_DB: '<generated:SERVICE_USER_DB:16>'
|
||||
SERVICE_USER_WEB: '<generated:SERVICE_USER_WEB:16>'
|
||||
WITH_DEFAULT: null
|
||||
@@ -2088,23 +2088,23 @@
|
||||
SERVICE_FQDN_ADMIN: referenceapplication0001.10.0.0.1.sslip.io
|
||||
SERVICE_FQDN_ADMIN_8080: null
|
||||
SERVICE_FQDN_API: referenceapplication0001.10.0.0.1.sslip.io/api
|
||||
SERVICE_FQDN_API_V2: 7.api-v2.example.com
|
||||
SERVICE_FQDN_BLOG: 7.blog.example.com
|
||||
SERVICE_FQDN_MY_APP: 7.my-app.example.com
|
||||
SERVICE_FQDN_WEB: 7.web.example.com
|
||||
SERVICE_FQDN_WEB_3000: null
|
||||
SERVICE_FQDN_API_V2: api-v2.example.com
|
||||
SERVICE_FQDN_BLOG: blog.example.com
|
||||
SERVICE_FQDN_MY_APP: my-app.example.com
|
||||
SERVICE_FQDN_WEB: web.example.com
|
||||
SERVICE_FQDN_WEB_3000: 'web-referenceapplication0001.10.0.0.1.sslip.io:3000'
|
||||
SERVICE_HEX_32_WEB: '<generated:SERVICE_HEX_32_WEB:32>'
|
||||
SERVICE_PASSWORD_DB: '<generated:SERVICE_PASSWORD_DB:32>'
|
||||
SERVICE_PASSWORD_NOBRACES: '<generated:SERVICE_PASSWORD_NOBRACES:32>'
|
||||
SERVICE_PASSWORD_WEB: '<generated:SERVICE_PASSWORD_WEB:32>'
|
||||
SERVICE_URL_ADMIN: 'https://7.admin.example.com'
|
||||
SERVICE_URL_API: 'https://7.www.api.example.com'
|
||||
SERVICE_URL_API_V2: 'https://7.api-v2.example.com'
|
||||
SERVICE_URL_BLOG: 'https://7.blog.example.com/blog:2368'
|
||||
SERVICE_URL_MY_APP: 'https://7.my-app.example.com'
|
||||
SERVICE_URL_ADMIN: 'https://admin.example.com'
|
||||
SERVICE_URL_API: 'https://www.api.example.com'
|
||||
SERVICE_URL_API_V2: 'https://api-v2.example.com'
|
||||
SERVICE_URL_BLOG: 'https://blog.example.com/blog:2368'
|
||||
SERVICE_URL_MY_APP: 'https://my-app.example.com'
|
||||
SERVICE_URL_MY_APP_80: null
|
||||
SERVICE_URL_WEB: 'https://7.web.example.com'
|
||||
SERVICE_URL_WEB_3000: null
|
||||
SERVICE_URL_WEB: 'https://web.example.com'
|
||||
SERVICE_URL_WEB_3000: 'http://web-referenceapplication0001.10.0.0.1.sslip.io:3000'
|
||||
SERVICE_USER_DB: '<generated:SERVICE_USER_DB:16>'
|
||||
SERVICE_USER_WEB: '<generated:SERVICE_USER_WEB:16>'
|
||||
WITH_DEFAULT: null
|
||||
|
||||
@@ -1452,26 +1452,26 @@
|
||||
required: true
|
||||
SELF_REF: null
|
||||
SERVICE_BASE64_64_WEB: '<generated:SERVICE_BASE64_64_WEB:64>'
|
||||
SERVICE_FQDN_ADMIN: 7.admin.example.com
|
||||
SERVICE_FQDN_ADMIN: referenceapplication0001.10.0.0.1.sslip.io
|
||||
SERVICE_FQDN_ADMIN_8080: null
|
||||
SERVICE_FQDN_API: 7.www.api.example.com
|
||||
SERVICE_FQDN_API_V2: 7.api-v2.example.com
|
||||
SERVICE_FQDN_BLOG: 7.blog.example.com
|
||||
SERVICE_FQDN_MY_APP: 7.my-app.example.com
|
||||
SERVICE_FQDN_WEB: 7.web.example.com
|
||||
SERVICE_FQDN_WEB_3000: null
|
||||
SERVICE_FQDN_API: referenceapplication0001.10.0.0.1.sslip.io/api
|
||||
SERVICE_FQDN_API_V2: api-v2.example.com
|
||||
SERVICE_FQDN_BLOG: blog.example.com
|
||||
SERVICE_FQDN_MY_APP: my-app.example.com
|
||||
SERVICE_FQDN_WEB: web.example.com
|
||||
SERVICE_FQDN_WEB_3000: 'web-referenceapplication0001.10.0.0.1.sslip.io:3000'
|
||||
SERVICE_HEX_32_WEB: '<generated:SERVICE_HEX_32_WEB:32>'
|
||||
SERVICE_PASSWORD_DB: '<generated:SERVICE_PASSWORD_DB:32>'
|
||||
SERVICE_PASSWORD_NOBRACES: '<generated:SERVICE_PASSWORD_NOBRACES:32>'
|
||||
SERVICE_PASSWORD_WEB: '<generated:SERVICE_PASSWORD_WEB:32>'
|
||||
SERVICE_URL_ADMIN: 'https://7.admin.example.com'
|
||||
SERVICE_URL_API: 'https://7.www.api.example.com'
|
||||
SERVICE_URL_API_V2: 'https://7.api-v2.example.com'
|
||||
SERVICE_URL_BLOG: 'https://7.blog.example.com/blog:2368'
|
||||
SERVICE_URL_MY_APP: 'https://7.my-app.example.com'
|
||||
SERVICE_URL_ADMIN: 'https://admin.example.com'
|
||||
SERVICE_URL_API: 'https://www.api.example.com'
|
||||
SERVICE_URL_API_V2: 'https://api-v2.example.com'
|
||||
SERVICE_URL_BLOG: 'https://blog.example.com/blog:2368'
|
||||
SERVICE_URL_MY_APP: 'https://my-app.example.com'
|
||||
SERVICE_URL_MY_APP_80: null
|
||||
SERVICE_URL_WEB: 'https://7.web.example.com'
|
||||
SERVICE_URL_WEB_3000: null
|
||||
SERVICE_URL_WEB: 'https://web.example.com'
|
||||
SERVICE_URL_WEB_3000: 'http://web-referenceapplication0001.10.0.0.1.sslip.io:3000'
|
||||
SERVICE_USER_DB: '<generated:SERVICE_USER_DB:16>'
|
||||
SERVICE_USER_WEB: '<generated:SERVICE_USER_WEB:16>'
|
||||
WITH_DEFAULT: null
|
||||
@@ -2205,23 +2205,23 @@
|
||||
SERVICE_FQDN_ADMIN: referenceapplication0001.10.0.0.1.sslip.io
|
||||
SERVICE_FQDN_ADMIN_8080: null
|
||||
SERVICE_FQDN_API: referenceapplication0001.10.0.0.1.sslip.io/api
|
||||
SERVICE_FQDN_API_V2: 7.api-v2.example.com
|
||||
SERVICE_FQDN_BLOG: 7.blog.example.com
|
||||
SERVICE_FQDN_MY_APP: 7.my-app.example.com
|
||||
SERVICE_FQDN_WEB: 7.web.example.com
|
||||
SERVICE_FQDN_WEB_3000: null
|
||||
SERVICE_FQDN_API_V2: api-v2.example.com
|
||||
SERVICE_FQDN_BLOG: blog.example.com
|
||||
SERVICE_FQDN_MY_APP: my-app.example.com
|
||||
SERVICE_FQDN_WEB: web.example.com
|
||||
SERVICE_FQDN_WEB_3000: 'web-referenceapplication0001.10.0.0.1.sslip.io:3000'
|
||||
SERVICE_HEX_32_WEB: '<generated:SERVICE_HEX_32_WEB:32>'
|
||||
SERVICE_PASSWORD_DB: '<generated:SERVICE_PASSWORD_DB:32>'
|
||||
SERVICE_PASSWORD_NOBRACES: '<generated:SERVICE_PASSWORD_NOBRACES:32>'
|
||||
SERVICE_PASSWORD_WEB: '<generated:SERVICE_PASSWORD_WEB:32>'
|
||||
SERVICE_URL_ADMIN: 'https://7.admin.example.com'
|
||||
SERVICE_URL_API: 'https://7.www.api.example.com'
|
||||
SERVICE_URL_API_V2: 'https://7.api-v2.example.com'
|
||||
SERVICE_URL_BLOG: 'https://7.blog.example.com/blog:2368'
|
||||
SERVICE_URL_MY_APP: 'https://7.my-app.example.com'
|
||||
SERVICE_URL_ADMIN: 'https://admin.example.com'
|
||||
SERVICE_URL_API: 'https://www.api.example.com'
|
||||
SERVICE_URL_API_V2: 'https://api-v2.example.com'
|
||||
SERVICE_URL_BLOG: 'https://blog.example.com/blog:2368'
|
||||
SERVICE_URL_MY_APP: 'https://my-app.example.com'
|
||||
SERVICE_URL_MY_APP_80: null
|
||||
SERVICE_URL_WEB: 'https://7.web.example.com'
|
||||
SERVICE_URL_WEB_3000: null
|
||||
SERVICE_URL_WEB: 'https://web.example.com'
|
||||
SERVICE_URL_WEB_3000: 'http://web-referenceapplication0001.10.0.0.1.sslip.io:3000'
|
||||
SERVICE_USER_DB: '<generated:SERVICE_USER_DB:16>'
|
||||
SERVICE_USER_WEB: '<generated:SERVICE_USER_WEB:16>'
|
||||
WITH_DEFAULT: null
|
||||
|
||||
@@ -1648,26 +1648,26 @@
|
||||
required: true
|
||||
SELF_REF: null
|
||||
SERVICE_BASE64_64_WEB: '<generated:SERVICE_BASE64_64_WEB:64>'
|
||||
SERVICE_FQDN_ADMIN: 7.admin.example.com
|
||||
SERVICE_FQDN_ADMIN: referenceapplication0001.10.0.0.1.sslip.io
|
||||
SERVICE_FQDN_ADMIN_8080: null
|
||||
SERVICE_FQDN_API: 7.www.api.example.com
|
||||
SERVICE_FQDN_API_V2: 7.api-v2.example.com
|
||||
SERVICE_FQDN_BLOG: 7.blog.example.com
|
||||
SERVICE_FQDN_MY_APP: 7.my-app.example.com
|
||||
SERVICE_FQDN_WEB: 7.web.example.com
|
||||
SERVICE_FQDN_WEB_3000: null
|
||||
SERVICE_FQDN_API: referenceapplication0001.10.0.0.1.sslip.io/api
|
||||
SERVICE_FQDN_API_V2: api-v2.example.com
|
||||
SERVICE_FQDN_BLOG: blog.example.com
|
||||
SERVICE_FQDN_MY_APP: my-app.example.com
|
||||
SERVICE_FQDN_WEB: web.example.com
|
||||
SERVICE_FQDN_WEB_3000: 'web-referenceapplication0001.10.0.0.1.sslip.io:3000'
|
||||
SERVICE_HEX_32_WEB: '<generated:SERVICE_HEX_32_WEB:32>'
|
||||
SERVICE_PASSWORD_DB: '<generated:SERVICE_PASSWORD_DB:32>'
|
||||
SERVICE_PASSWORD_NOBRACES: '<generated:SERVICE_PASSWORD_NOBRACES:32>'
|
||||
SERVICE_PASSWORD_WEB: '<generated:SERVICE_PASSWORD_WEB:32>'
|
||||
SERVICE_URL_ADMIN: 'https://7.admin.example.com'
|
||||
SERVICE_URL_API: 'https://7.www.api.example.com'
|
||||
SERVICE_URL_API_V2: 'https://7.api-v2.example.com'
|
||||
SERVICE_URL_BLOG: 'https://7.blog.example.com/blog:2368'
|
||||
SERVICE_URL_MY_APP: 'https://7.my-app.example.com'
|
||||
SERVICE_URL_ADMIN: 'https://admin.example.com'
|
||||
SERVICE_URL_API: 'https://www.api.example.com'
|
||||
SERVICE_URL_API_V2: 'https://api-v2.example.com'
|
||||
SERVICE_URL_BLOG: 'https://blog.example.com/blog:2368'
|
||||
SERVICE_URL_MY_APP: 'https://my-app.example.com'
|
||||
SERVICE_URL_MY_APP_80: null
|
||||
SERVICE_URL_WEB: 'https://7.web.example.com'
|
||||
SERVICE_URL_WEB_3000: null
|
||||
SERVICE_URL_WEB: 'https://web.example.com'
|
||||
SERVICE_URL_WEB_3000: 'http://web-referenceapplication0001.10.0.0.1.sslip.io:3000'
|
||||
SERVICE_USER_DB: '<generated:SERVICE_USER_DB:16>'
|
||||
SERVICE_USER_WEB: '<generated:SERVICE_USER_WEB:16>'
|
||||
WITH_DEFAULT: null
|
||||
@@ -2511,23 +2511,23 @@
|
||||
SERVICE_FQDN_ADMIN: referenceapplication0001.10.0.0.1.sslip.io
|
||||
SERVICE_FQDN_ADMIN_8080: null
|
||||
SERVICE_FQDN_API: referenceapplication0001.10.0.0.1.sslip.io/api
|
||||
SERVICE_FQDN_API_V2: 7.api-v2.example.com
|
||||
SERVICE_FQDN_BLOG: 7.blog.example.com
|
||||
SERVICE_FQDN_MY_APP: 7.my-app.example.com
|
||||
SERVICE_FQDN_WEB: 7.web.example.com
|
||||
SERVICE_FQDN_WEB_3000: null
|
||||
SERVICE_FQDN_API_V2: api-v2.example.com
|
||||
SERVICE_FQDN_BLOG: blog.example.com
|
||||
SERVICE_FQDN_MY_APP: my-app.example.com
|
||||
SERVICE_FQDN_WEB: web.example.com
|
||||
SERVICE_FQDN_WEB_3000: 'web-referenceapplication0001.10.0.0.1.sslip.io:3000'
|
||||
SERVICE_HEX_32_WEB: '<generated:SERVICE_HEX_32_WEB:32>'
|
||||
SERVICE_PASSWORD_DB: '<generated:SERVICE_PASSWORD_DB:32>'
|
||||
SERVICE_PASSWORD_NOBRACES: '<generated:SERVICE_PASSWORD_NOBRACES:32>'
|
||||
SERVICE_PASSWORD_WEB: '<generated:SERVICE_PASSWORD_WEB:32>'
|
||||
SERVICE_URL_ADMIN: 'https://7.admin.example.com'
|
||||
SERVICE_URL_API: 'https://7.www.api.example.com'
|
||||
SERVICE_URL_API_V2: 'https://7.api-v2.example.com'
|
||||
SERVICE_URL_BLOG: 'https://7.blog.example.com/blog:2368'
|
||||
SERVICE_URL_MY_APP: 'https://7.my-app.example.com'
|
||||
SERVICE_URL_ADMIN: 'https://admin.example.com'
|
||||
SERVICE_URL_API: 'https://www.api.example.com'
|
||||
SERVICE_URL_API_V2: 'https://api-v2.example.com'
|
||||
SERVICE_URL_BLOG: 'https://blog.example.com/blog:2368'
|
||||
SERVICE_URL_MY_APP: 'https://my-app.example.com'
|
||||
SERVICE_URL_MY_APP_80: null
|
||||
SERVICE_URL_WEB: 'https://7.web.example.com'
|
||||
SERVICE_URL_WEB_3000: null
|
||||
SERVICE_URL_WEB: 'https://web.example.com'
|
||||
SERVICE_URL_WEB_3000: 'http://web-referenceapplication0001.10.0.0.1.sslip.io:3000'
|
||||
SERVICE_USER_DB: '<generated:SERVICE_USER_DB:16>'
|
||||
SERVICE_USER_WEB: '<generated:SERVICE_USER_WEB:16>'
|
||||
WITH_DEFAULT: null
|
||||
|
||||
@@ -1530,26 +1530,26 @@
|
||||
required: true
|
||||
SELF_REF: null
|
||||
SERVICE_BASE64_64_WEB: '<generated:SERVICE_BASE64_64_WEB:64>'
|
||||
SERVICE_FQDN_ADMIN: 7.admin.example.com
|
||||
SERVICE_FQDN_ADMIN: referenceapplication0001.10.0.0.1.sslip.io
|
||||
SERVICE_FQDN_ADMIN_8080: null
|
||||
SERVICE_FQDN_API: 7.www.api.example.com
|
||||
SERVICE_FQDN_API_V2: 7.api-v2.example.com
|
||||
SERVICE_FQDN_BLOG: 7.blog.example.com
|
||||
SERVICE_FQDN_MY_APP: 7.my-app.example.com
|
||||
SERVICE_FQDN_WEB: 7.web.example.com
|
||||
SERVICE_FQDN_WEB_3000: null
|
||||
SERVICE_FQDN_API: referenceapplication0001.10.0.0.1.sslip.io/api
|
||||
SERVICE_FQDN_API_V2: api-v2.example.com
|
||||
SERVICE_FQDN_BLOG: blog.example.com
|
||||
SERVICE_FQDN_MY_APP: my-app.example.com
|
||||
SERVICE_FQDN_WEB: web.example.com
|
||||
SERVICE_FQDN_WEB_3000: 'web-referenceapplication0001.10.0.0.1.sslip.io:3000'
|
||||
SERVICE_HEX_32_WEB: '<generated:SERVICE_HEX_32_WEB:32>'
|
||||
SERVICE_PASSWORD_DB: '<generated:SERVICE_PASSWORD_DB:32>'
|
||||
SERVICE_PASSWORD_NOBRACES: '<generated:SERVICE_PASSWORD_NOBRACES:32>'
|
||||
SERVICE_PASSWORD_WEB: '<generated:SERVICE_PASSWORD_WEB:32>'
|
||||
SERVICE_URL_ADMIN: 'https://7.admin.example.com'
|
||||
SERVICE_URL_API: 'https://7.www.api.example.com'
|
||||
SERVICE_URL_API_V2: 'https://7.api-v2.example.com'
|
||||
SERVICE_URL_BLOG: 'https://7.blog.example.com/blog:2368'
|
||||
SERVICE_URL_MY_APP: 'https://7.my-app.example.com'
|
||||
SERVICE_URL_ADMIN: 'https://admin.example.com'
|
||||
SERVICE_URL_API: 'https://www.api.example.com'
|
||||
SERVICE_URL_API_V2: 'https://api-v2.example.com'
|
||||
SERVICE_URL_BLOG: 'https://blog.example.com/blog:2368'
|
||||
SERVICE_URL_MY_APP: 'https://my-app.example.com'
|
||||
SERVICE_URL_MY_APP_80: null
|
||||
SERVICE_URL_WEB: 'https://7.web.example.com'
|
||||
SERVICE_URL_WEB_3000: null
|
||||
SERVICE_URL_WEB: 'https://web.example.com'
|
||||
SERVICE_URL_WEB_3000: 'http://web-referenceapplication0001.10.0.0.1.sslip.io:3000'
|
||||
SERVICE_USER_DB: '<generated:SERVICE_USER_DB:16>'
|
||||
SERVICE_USER_WEB: '<generated:SERVICE_USER_WEB:16>'
|
||||
WITH_DEFAULT: null
|
||||
@@ -2331,23 +2331,23 @@
|
||||
SERVICE_FQDN_ADMIN: referenceapplication0001.10.0.0.1.sslip.io
|
||||
SERVICE_FQDN_ADMIN_8080: null
|
||||
SERVICE_FQDN_API: referenceapplication0001.10.0.0.1.sslip.io/api
|
||||
SERVICE_FQDN_API_V2: 7.api-v2.example.com
|
||||
SERVICE_FQDN_BLOG: 7.blog.example.com
|
||||
SERVICE_FQDN_MY_APP: 7.my-app.example.com
|
||||
SERVICE_FQDN_WEB: 7.web.example.com
|
||||
SERVICE_FQDN_WEB_3000: null
|
||||
SERVICE_FQDN_API_V2: api-v2.example.com
|
||||
SERVICE_FQDN_BLOG: blog.example.com
|
||||
SERVICE_FQDN_MY_APP: my-app.example.com
|
||||
SERVICE_FQDN_WEB: web.example.com
|
||||
SERVICE_FQDN_WEB_3000: 'web-referenceapplication0001.10.0.0.1.sslip.io:3000'
|
||||
SERVICE_HEX_32_WEB: '<generated:SERVICE_HEX_32_WEB:32>'
|
||||
SERVICE_PASSWORD_DB: '<generated:SERVICE_PASSWORD_DB:32>'
|
||||
SERVICE_PASSWORD_NOBRACES: '<generated:SERVICE_PASSWORD_NOBRACES:32>'
|
||||
SERVICE_PASSWORD_WEB: '<generated:SERVICE_PASSWORD_WEB:32>'
|
||||
SERVICE_URL_ADMIN: 'https://7.admin.example.com'
|
||||
SERVICE_URL_API: 'https://7.www.api.example.com'
|
||||
SERVICE_URL_API_V2: 'https://7.api-v2.example.com'
|
||||
SERVICE_URL_BLOG: 'https://7.blog.example.com/blog:2368'
|
||||
SERVICE_URL_MY_APP: 'https://7.my-app.example.com'
|
||||
SERVICE_URL_ADMIN: 'https://admin.example.com'
|
||||
SERVICE_URL_API: 'https://www.api.example.com'
|
||||
SERVICE_URL_API_V2: 'https://api-v2.example.com'
|
||||
SERVICE_URL_BLOG: 'https://blog.example.com/blog:2368'
|
||||
SERVICE_URL_MY_APP: 'https://my-app.example.com'
|
||||
SERVICE_URL_MY_APP_80: null
|
||||
SERVICE_URL_WEB: 'https://7.web.example.com'
|
||||
SERVICE_URL_WEB_3000: null
|
||||
SERVICE_URL_WEB: 'https://web.example.com'
|
||||
SERVICE_URL_WEB_3000: 'http://web-referenceapplication0001.10.0.0.1.sslip.io:3000'
|
||||
SERVICE_USER_DB: '<generated:SERVICE_USER_DB:16>'
|
||||
SERVICE_USER_WEB: '<generated:SERVICE_USER_WEB:16>'
|
||||
WITH_DEFAULT: null
|
||||
|
||||
@@ -406,3 +406,25 @@ it('describes added unlocked environment variables with their value', function (
|
||||
->and($change['new_display_value'])->toBe('new-secret')
|
||||
->and(json_encode($diff->toArray()))->toContain('new-secret');
|
||||
});
|
||||
|
||||
it('does not report Docker Compose preview volumes as pending production changes', function () {
|
||||
$application = snapshotTestApplication(['build_pack' => 'dockercompose']);
|
||||
$previewVolume = fn (): LocalPersistentVolume => LocalPersistentVolume::create([
|
||||
'name' => $application->uuid.'_data-pr-42',
|
||||
'mount_path' => '/app/data',
|
||||
'resource_id' => $application->id,
|
||||
'resource_type' => $application->getMorphClass(),
|
||||
]);
|
||||
|
||||
// A preview deployment adds its volume after the production deployment.
|
||||
markSnapshotTestApplicationDeployed($application);
|
||||
$volume = $previewVolume();
|
||||
expect($application->refresh()->pendingDeploymentConfigurationDiff()->isChanged())->toBeFalse();
|
||||
|
||||
// An older production snapshot contains the volume, and the preview cleanup removes it.
|
||||
$volume->delete();
|
||||
$previewVolume();
|
||||
markSnapshotTestApplicationDeployed($application);
|
||||
LocalPersistentVolume::query()->where('name', $application->uuid.'_data-pr-42')->delete();
|
||||
expect($application->refresh()->pendingDeploymentConfigurationDiff()->isChanged())->toBeFalse();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user