diff --git a/app/Models/Application.php b/app/Models/Application.php
index 97b257752..fd7f486b9 100644
--- a/app/Models/Application.php
+++ b/app/Models/Application.php
@@ -1188,17 +1188,20 @@ class Application extends BaseModel
$currentSnapshot = $this->deploymentConfigurationSnapshot();
$lastDeployment = $this->get_last_successful_deployment();
- if ($lastDeployment?->configuration_snapshot) {
- return app(ConfigurationDiffer::class)->diff($lastDeployment->configuration_snapshot, $currentSnapshot);
+ $previousSnapshot = $lastDeployment?->configuration_snapshot;
+
+ if (! $previousSnapshot) {
+ $oldConfigHash = data_get($this, 'config_hash');
+ $hasLegacyChange = $oldConfigHash === null || $oldConfigHash !== $this->legacyConfigurationHash();
+
+ if (! $hasLegacyChange) {
+ return ConfigurationDiff::unchanged();
+ }
+
+ $previousSnapshot = [];
}
- $oldConfigHash = data_get($this, 'config_hash');
-
- if ($oldConfigHash === null) {
- return ConfigurationDiff::legacy(true);
- }
-
- return ConfigurationDiff::legacy($oldConfigHash !== $this->legacyConfigurationHash());
+ return app(ConfigurationDiffer::class)->diff($previousSnapshot, $currentSnapshot);
}
public function hasPendingDeploymentConfigurationChanges(): bool
diff --git a/app/Services/DeploymentConfiguration/ApplicationConfigurationSnapshot.php b/app/Services/DeploymentConfiguration/ApplicationConfigurationSnapshot.php
index 676b22b6c..8369f9a90 100644
--- a/app/Services/DeploymentConfiguration/ApplicationConfigurationSnapshot.php
+++ b/app/Services/DeploymentConfiguration/ApplicationConfigurationSnapshot.php
@@ -306,7 +306,7 @@ class ApplicationConfigurationSnapshot
private function displayValue(mixed $value): string
{
if ($value === null) {
- return 'Not set';
+ return '-';
}
if (is_bool($value)) {
@@ -323,7 +323,7 @@ class ApplicationConfigurationSnapshot
private function summarizeText(?string $value): string
{
if (blank($value)) {
- return 'Not set';
+ return '-';
}
$value = trim((string) $value);
diff --git a/app/Services/DeploymentConfiguration/ConfigurationDiffer.php b/app/Services/DeploymentConfiguration/ConfigurationDiffer.php
index 27e8d4c3f..b101b9d5b 100644
--- a/app/Services/DeploymentConfiguration/ConfigurationDiffer.php
+++ b/app/Services/DeploymentConfiguration/ConfigurationDiffer.php
@@ -37,8 +37,8 @@ class ConfigurationDiffer
'impact' => data_get($item, 'impact', 'redeploy'),
'sensitive' => $sensitive,
'display_summary' => $displaySummary,
- 'old_display_value' => $sensitive ? ($previous === null ? 'Not set' : 'Set') : data_get($previous, 'display_value', 'Not set'),
- 'new_display_value' => $sensitive ? ($current === null ? 'Removed' : 'Set') : data_get($current, 'display_value', 'Not set'),
+ 'old_display_value' => $sensitive ? ($previous === null ? '-' : '••••••••') : data_get($previous, 'display_value', '-'),
+ 'new_display_value' => $sensitive ? ($current === null ? '-' : '••••••••') : data_get($current, 'display_value', '-'),
];
}
diff --git a/resources/views/components/deployment/configuration-diff.blade.php b/resources/views/components/deployment/configuration-diff.blade.php
index ffc0cd34a..f01481057 100644
--- a/resources/views/components/deployment/configuration-diff.blade.php
+++ b/resources/views/components/deployment/configuration-diff.blade.php
@@ -4,9 +4,9 @@
])
@php
- $changes = data_get($diff, 'changes', []);
- $count = data_get($diff, 'count', count($changes));
- $requiresBuild = data_get($diff, 'requires_build', false);
+ $changes = collect(data_get($diff, 'changes', []))->filter(fn ($change) => data_get($change, 'key') !== 'domains.custom_labels')->values()->all();
+ $count = count($changes);
+ $requiresBuild = collect($changes)->contains(fn ($change) => data_get($change, 'impact') === 'build');
@endphp
@if ($count > 0)
@@ -21,45 +21,39 @@
'bg-red-100 text-red-700 dark:bg-red-500/20 dark:text-red-300' => $requiresBuild,
'bg-blue-100 text-blue-700 dark:bg-blue-500/20 dark:text-blue-300' => ! $requiresBuild,
])>
- {{ $requiresBuild ? 'Rebuild' : 'Redeploy' }}
+ {{ $requiresBuild ? 'Rebuild required' : 'Redeploy required' }}
@unless ($compact)
-
+
@foreach (collect($changes)->groupBy('section_label') as $sectionLabel => $sectionChanges)
{{ $sectionLabel }}
-
-
-
-
Field
-
Type
-
From
-
-
To
-
-
- @foreach ($sectionChanges as $change)
-
-
- {{ data_get($change, 'label') }}
-
-
- {{ data_get($change, 'type') }}
-
-
- {{ data_get($change, 'old_display_value') }}
-
-
→
-
- {{ data_get($change, 'new_display_value') }}
-
+
+
+
+ @foreach ($sectionChanges as $change)
+
+
+ {{ data_get($change, 'label') }}
- @endforeach
-
+
+ {{ data_get($change, 'old_display_value') }}
+
+
→
+
+ {{ data_get($change, 'new_display_value') }}
+
+
+ @endforeach
diff --git a/tests/Feature/ApplicationConfigurationChangedTest.php b/tests/Feature/ApplicationConfigurationChangedTest.php
index f862f840d..b91e9f289 100644
--- a/tests/Feature/ApplicationConfigurationChangedTest.php
+++ b/tests/Feature/ApplicationConfigurationChangedTest.php
@@ -80,11 +80,11 @@ it('checks legacy preview deployment configuration hash using preview environmen
$diff = $application->pendingDeploymentConfigurationDiff();
- expect($diff->isLegacyFallback())->toBeTrue()
- ->and($diff->isChanged())->toBeTrue();
+ expect($diff->isChanged())->toBeTrue()
+ ->and($diff->count())->toBeGreaterThan(0);
});
-it('falls back to legacy configuration hash when no deployment snapshot exists', function () {
+it('falls back to real diff against empty snapshot when no deployment snapshot exists', function () {
$application = configurationChangedTestApplication();
$application->isConfigurationChanged(save: true);
@@ -92,6 +92,10 @@ it('falls back to legacy configuration hash when no deployment snapshot exists',
$application->update(['build_command' => 'pnpm build']);
- expect($application->refresh()->pendingDeploymentConfigurationDiff()->isLegacyFallback())->toBeTrue()
- ->and($application->pendingDeploymentConfigurationDiff()->isChanged())->toBeTrue();
+ $diff = $application->refresh()->pendingDeploymentConfigurationDiff();
+
+ expect($diff->isChanged())->toBeTrue()
+ ->and($diff->isLegacyFallback())->toBeFalse()
+ ->and($diff->count())->toBeGreaterThan(0)
+ ->and(collect($diff->changes())->pluck('label')->toArray())->toContain('Build command');
});
diff --git a/tests/Feature/Livewire/ConfigurationCheckerTest.php b/tests/Feature/Livewire/ConfigurationCheckerTest.php
index edf8c5044..d9e6729c8 100644
--- a/tests/Feature/Livewire/ConfigurationCheckerTest.php
+++ b/tests/Feature/Livewire/ConfigurationCheckerTest.php
@@ -126,8 +126,7 @@ it('does not render environment variable secret values', function () {
Livewire::test(ConfigurationChecker::class, ['resource' => $application->refresh()])
->assertSee('API_TOKEN')
- ->assertSee('changed')
- ->assertSee('Set')
+ ->assertSee('••••••••')
->assertDontSee('Hidden')
->assertDontSee('old-secret')
->assertDontSee('new-secret');
@@ -150,9 +149,9 @@ it('renders added environment variables as set without exposing secret values',
Livewire::test(ConfigurationChecker::class, ['resource' => $application->refresh()])
->assertSee('API_TOKEN')
->assertSee('From')
- ->assertSee('Not set')
+ ->assertSee('-')
->assertSee('To')
- ->assertSee('Set')
+ ->assertSee('••••••••')
->assertDontSee('Hidden')
->assertDontSee('new-secret');
});
diff --git a/tests/Unit/DeploymentConfiguration/ApplicationConfigurationSnapshotTest.php b/tests/Unit/DeploymentConfiguration/ApplicationConfigurationSnapshotTest.php
index 2106697b2..20b7c0adc 100644
--- a/tests/Unit/DeploymentConfiguration/ApplicationConfigurationSnapshotTest.php
+++ b/tests/Unit/DeploymentConfiguration/ApplicationConfigurationSnapshotTest.php
@@ -93,8 +93,8 @@ it('detects environment variable value changes without exposing secret values',
expect($change)->not->toBeNull()
->and($change['display_summary'])->toBe('Changed')
- ->and($change['old_display_value'])->toBe('Set')
- ->and($change['new_display_value'])->toBe('Set')
+ ->and($change['old_display_value'])->toBe('••••••••')
+ ->and($change['new_display_value'])->toBe('••••••••')
->and(json_encode($diff->toArray()))->not->toContain('old-secret')->not->toContain('new-secret');
});
@@ -117,7 +117,7 @@ it('describes added environment variables as set without exposing secret values'
expect($change)->not->toBeNull()
->and($change['display_summary'])->toBeNull()
- ->and($change['old_display_value'])->toBe('Not set')
- ->and($change['new_display_value'])->toBe('Set')
+ ->and($change['old_display_value'])->toBe('-')
+ ->and($change['new_display_value'])->toBe('••••••••')
->and(json_encode($diff->toArray()))->not->toContain('new-secret');
});