fix(applications): refresh pending configuration changes
Dispatch configuration change events after saving application source and advanced settings, and refresh the configuration checker before showing redeploy diffs.
This commit is contained in:
parent
f8849aba73
commit
0ecd488d6a
7 changed files with 95 additions and 6 deletions
|
|
@ -219,6 +219,7 @@ public function submit()
|
||||||
}
|
}
|
||||||
$this->syncData(true);
|
$this->syncData(true);
|
||||||
$this->dispatch('success', 'Settings saved.');
|
$this->dispatch('success', 'Settings saved.');
|
||||||
|
$this->dispatch('configurationChanged');
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return handleError($e, $this);
|
return handleError($e, $this);
|
||||||
}
|
}
|
||||||
|
|
@ -237,6 +238,7 @@ public function saveCustomName()
|
||||||
if (is_null($this->customInternalName)) {
|
if (is_null($this->customInternalName)) {
|
||||||
$this->syncData(true);
|
$this->syncData(true);
|
||||||
$this->dispatch('success', 'Custom name saved.');
|
$this->dispatch('success', 'Custom name saved.');
|
||||||
|
$this->dispatch('configurationChanged');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -256,6 +258,7 @@ public function saveCustomName()
|
||||||
}
|
}
|
||||||
$this->syncData(true);
|
$this->syncData(true);
|
||||||
$this->dispatch('success', 'Custom name saved.');
|
$this->dispatch('success', 'Custom name saved.');
|
||||||
|
$this->dispatch('configurationChanged');
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return handleError($e, $this);
|
return handleError($e, $this);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,7 @@ public function setPrivateKey(int $privateKeyId)
|
||||||
$this->application->refresh();
|
$this->application->refresh();
|
||||||
$this->privateKeyName = $this->application->private_key->name;
|
$this->privateKeyName = $this->application->private_key->name;
|
||||||
$this->dispatch('success', 'Private key updated!');
|
$this->dispatch('success', 'Private key updated!');
|
||||||
|
$this->dispatch('configurationChanged');
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return handleError($e, $this);
|
return handleError($e, $this);
|
||||||
}
|
}
|
||||||
|
|
@ -124,6 +125,7 @@ public function submit()
|
||||||
}
|
}
|
||||||
$this->syncData(true);
|
$this->syncData(true);
|
||||||
$this->dispatch('success', 'Application source updated!');
|
$this->dispatch('success', 'Application source updated!');
|
||||||
|
$this->dispatch('configurationChanged');
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return handleError($e, $this);
|
return handleError($e, $this);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
use App\Models\StandaloneMysql;
|
use App\Models\StandaloneMysql;
|
||||||
use App\Models\StandalonePostgresql;
|
use App\Models\StandalonePostgresql;
|
||||||
use App\Models\StandaloneRedis;
|
use App\Models\StandaloneRedis;
|
||||||
|
use Illuminate\Contracts\View\View;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class ConfigurationChecker extends Component
|
class ConfigurationChecker extends Component
|
||||||
|
|
@ -24,7 +25,7 @@ class ConfigurationChecker extends Component
|
||||||
|
|
||||||
public Application|Service|StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse $resource;
|
public Application|Service|StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse $resource;
|
||||||
|
|
||||||
public function getListeners()
|
public function getListeners(): array
|
||||||
{
|
{
|
||||||
$teamId = auth()->user()->currentTeam()->id;
|
$teamId = auth()->user()->currentTeam()->id;
|
||||||
|
|
||||||
|
|
@ -34,18 +35,25 @@ public function getListeners()
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function mount()
|
public function mount(): void
|
||||||
{
|
{
|
||||||
$this->configurationChanged();
|
$this->configurationChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render()
|
public function render(): View
|
||||||
{
|
{
|
||||||
return view('livewire.project.shared.configuration-checker');
|
return view('livewire.project.shared.configuration-checker');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function configurationChanged()
|
public function refreshConfigurationChanges(): void
|
||||||
{
|
{
|
||||||
|
$this->configurationChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function configurationChanged(): void
|
||||||
|
{
|
||||||
|
$this->resource->refresh();
|
||||||
|
|
||||||
if ($this->resource instanceof Application) {
|
if ($this->resource instanceof Application) {
|
||||||
$diff = $this->resource->pendingDeploymentConfigurationDiff();
|
$diff = $this->resource->pendingDeploymentConfigurationDiff();
|
||||||
$this->isConfigurationChanged = $diff->isChanged();
|
$this->isConfigurationChanged = $diff->isChanged();
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,8 @@
|
||||||
Please redeploy to apply the new configuration.
|
Please redeploy to apply the new configuration.
|
||||||
@endif
|
@endif
|
||||||
<button type="button" class="ml-1 font-semibold underline text-coollabs dark:text-warning"
|
<button type="button" class="ml-1 font-semibold underline text-coollabs dark:text-warning"
|
||||||
@click="configurationDiffModalOpen = true">
|
x-on:click="$wire.refreshConfigurationChanges().then(() => configurationDiffModalOpen = true)"
|
||||||
|
wire:loading.attr="disabled" wire:target="refreshConfigurationChanges">
|
||||||
View changes
|
View changes
|
||||||
</button>
|
</button>
|
||||||
@else
|
@else
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,23 @@
|
||||||
$this->environment = Environment::factory()->create(['project_id' => $this->project->id]);
|
$this->environment = Environment::factory()->create(['project_id' => $this->project->id]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function applicationSourceValidPrivateKey(): string
|
||||||
|
{
|
||||||
|
return '-----BEGIN OPENSSH PRIVATE KEY-----
|
||||||
|
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||||
|
QyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevAAAAJi/QySHv0Mk
|
||||||
|
hwAAAAtzc2gtZWQyNTUxOQAAACBbhpqHhqv6aI67Mj9abM3DVbmcfYhZAhC7ca4d9UCevA
|
||||||
|
AAAECBQw4jg1WRT2IGHMncCiZhURCts2s24HoDS0thHnnRKVuGmoeGq/pojrsyP1pszcNV
|
||||||
|
uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
|
||||||
|
-----END OPENSSH PRIVATE KEY-----';
|
||||||
|
}
|
||||||
|
|
||||||
describe('Application Source with localhost key (id=0)', function () {
|
describe('Application Source with localhost key (id=0)', function () {
|
||||||
test('renders deploy key section when private_key_id is 0', function () {
|
test('renders deploy key section when private_key_id is 0', function () {
|
||||||
$privateKey = PrivateKey::create([
|
$privateKey = PrivateKey::create([
|
||||||
'id' => 0,
|
'id' => 0,
|
||||||
'name' => 'localhost',
|
'name' => 'localhost',
|
||||||
'private_key' => 'test-key-content',
|
'private_key' => applicationSourceValidPrivateKey(),
|
||||||
'team_id' => $this->team->id,
|
'team_id' => $this->team->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -56,4 +67,19 @@
|
||||||
->assertDontSee('Deploy Key')
|
->assertDontSee('Deploy Key')
|
||||||
->assertSee('No source connected');
|
->assertSee('No source connected');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('dispatches configuration changed when source settings are saved', function () {
|
||||||
|
$application = Application::factory()->create([
|
||||||
|
'environment_id' => $this->environment->id,
|
||||||
|
'git_repository' => 'coollabsio/coolify',
|
||||||
|
'git_branch' => 'main',
|
||||||
|
'git_commit_sha' => 'HEAD',
|
||||||
|
]);
|
||||||
|
|
||||||
|
Livewire::test(Source::class, ['application' => $application])
|
||||||
|
->set('gitBranch', 'next')
|
||||||
|
->call('submit')
|
||||||
|
->assertHasNoErrors()
|
||||||
|
->assertDispatched('configurationChanged');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,45 @@ function markConfigurationCheckerApplicationDeployed(Application $application):
|
||||||
->assertSee('A rebuild is required.');
|
->assertSee('A rebuild is required.');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('refreshes configuration changes when the event is received', function () {
|
||||||
|
$application = configurationCheckerApplication($this->environment);
|
||||||
|
markConfigurationCheckerApplicationDeployed($application);
|
||||||
|
|
||||||
|
$component = Livewire::test(ConfigurationChecker::class, ['resource' => $application->refresh()])
|
||||||
|
->assertSet('isConfigurationChanged', false)
|
||||||
|
->assertDontSee('The latest configuration has not been applied');
|
||||||
|
|
||||||
|
$application->update(['build_command' => 'pnpm build']);
|
||||||
|
|
||||||
|
$component
|
||||||
|
->dispatch('configurationChanged')
|
||||||
|
->assertSet('isConfigurationChanged', true)
|
||||||
|
->assertSee('The latest configuration has not been applied')
|
||||||
|
->assertSee('Build command');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('refreshes stale modal configuration diff before opening changes', function () {
|
||||||
|
$application = configurationCheckerApplication($this->environment);
|
||||||
|
markConfigurationCheckerApplicationDeployed($application);
|
||||||
|
|
||||||
|
$application->update(['build_command' => 'pnpm build']);
|
||||||
|
|
||||||
|
$component = Livewire::test(ConfigurationChecker::class, ['resource' => $application->refresh()])
|
||||||
|
->assertSee('Build command')
|
||||||
|
->assertDontSee('Start command');
|
||||||
|
|
||||||
|
$application->update([
|
||||||
|
'build_command' => 'npm run build',
|
||||||
|
'start_command' => 'node server.js',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$component
|
||||||
|
->call('refreshConfigurationChanges')
|
||||||
|
->assertSet('isConfigurationChanged', true)
|
||||||
|
->assertSee('Start command')
|
||||||
|
->assertDontSee('Build command');
|
||||||
|
});
|
||||||
|
|
||||||
it('does not render environment variable secret values', function () {
|
it('does not render environment variable secret values', function () {
|
||||||
$application = configurationCheckerApplication($this->environment);
|
$application = configurationCheckerApplication($this->environment);
|
||||||
EnvironmentVariable::create([
|
EnvironmentVariable::create([
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,16 @@ function createApplicationForAdvancedStopGracePeriodTest(): Application
|
||||||
expect($application->settings()->first()->stop_grace_period)->toBe(300);
|
expect($application->settings()->first()->stop_grace_period)->toBe(300);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('dispatches configuration changed when advanced settings are saved', function () {
|
||||||
|
$application = createApplicationForAdvancedStopGracePeriodTest();
|
||||||
|
|
||||||
|
Livewire::test(Advanced::class, ['application' => $application])
|
||||||
|
->set('includeSourceCommitInBuild', true)
|
||||||
|
->call('submit')
|
||||||
|
->assertHasNoErrors()
|
||||||
|
->assertDispatched('configurationChanged');
|
||||||
|
});
|
||||||
|
|
||||||
it('clears the stop grace period when submitted empty', function () {
|
it('clears the stop grace period when submitted empty', function () {
|
||||||
$application = createApplicationForAdvancedStopGracePeriodTest();
|
$application = createApplicationForAdvancedStopGracePeriodTest();
|
||||||
$application->settings->update(['stop_grace_period' => 300]);
|
$application->settings->update(['stop_grace_period' => 300]);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue