Clean up stale Coolify API routes

This commit is contained in:
Jeppe Bundgaard
2026-06-08 18:02:08 +02:00
parent ef8d97c821
commit a3ea5fee83
3 changed files with 97 additions and 1 deletions
@@ -159,6 +159,11 @@ class coolify_api_client
return $this->request('GET', '/applications/' . rawurlencode($uuid) . '/restart');
}
public function stopApplication(string $uuid): array
{
return $this->request('GET', '/applications/' . rawurlencode($uuid) . '/stop');
}
public function deleteService(string $uuid): array
{
return $this->request('DELETE', '/services/' . rawurlencode($uuid));
+70 -1
View File
@@ -1435,6 +1435,7 @@ class release_manager
}
$expectedCommit = self::normalizeCommitSha((string)($gateInput['expected_commit'] ?? ''));
$enforceExpectedCommit = $expectedCommit !== '' && !$this->releaseGateAutoSyncRequested($gateInput);
$checked = [];
try {
foreach ($gateInput['api_ping_paths'] as $path) {
@@ -1444,7 +1445,7 @@ class release_manager
throw new RuntimeException(sprintf('%s returned success=false.', $path));
}
$actualCommit = $this->releaseGateApiPayloadCommitSha($payload);
if ($expectedCommit !== '' && !$this->releaseGateCommitMatches($actualCommit, $expectedCommit)) {
if ($enforceExpectedCommit && !$this->releaseGateCommitMatches($actualCommit, $expectedCommit)) {
throw new RuntimeException(sprintf(
'%s returned commit %s, expected %s.',
$path,
@@ -6257,6 +6258,7 @@ class release_manager
}
$deployment = $client->deployResource($serviceUuid, $this->releaseCoolifyForceRebuild($context));
$previousApplications = $this->stopCoolifyPreviousApplications($client, $context, $serviceUuid);
return [
'service_uuid' => $serviceUuid,
'resource_type' => $resourceType,
@@ -6266,9 +6268,76 @@ class release_manager
'updated' => self::redactPayload($update ?? []),
'runtime_env' => $runtimeEnvUpdate,
'deployment' => self::redactPayload($deployment),
'previous_applications' => self::redactPayload($previousApplications),
];
}
private function stopCoolifyPreviousApplications(coolify_api_client $client, array $context, string $activeUuid): array
{
$stopped = [];
foreach ($this->releaseCoolifyPreviousApplicationUuids($context, $activeUuid) as $uuid) {
try {
$stopped[] = [
'uuid' => $uuid,
'status' => 'stop_requested',
'result' => $client->stopApplication($uuid),
];
} catch (Throwable $throwable) {
$stopped[] = [
'uuid' => $uuid,
'status' => 'warning',
'error' => $throwable->getMessage(),
];
}
}
return $stopped;
}
private function releaseCoolifyPreviousApplicationUuids(array $context, string $activeUuid): array
{
$values = [];
foreach ([
'coolify_previous_application_uuid',
'coolify_previous_artifact_app_uuid',
'coolify_previous_artifact_application_uuid',
'previous_application_uuid',
'previous_app_uuid',
] as $key) {
if (is_scalar($context[$key] ?? null)) {
$values[] = (string)$context[$key];
}
}
foreach ([
'coolify_previous_application_uuids',
'coolify_previous_artifact_app_uuids',
'previous_application_uuids',
'previous_app_uuids',
] as $key) {
if (!is_array($context[$key] ?? null)) {
continue;
}
foreach ($context[$key] as $value) {
if (is_scalar($value)) {
$values[] = (string)$value;
}
}
}
$activeUuid = trim($activeUuid);
$uuids = [];
foreach ($values as $value) {
$uuid = trim((string)$value);
if ($uuid === '' || $uuid === $activeUuid || in_array($uuid, $uuids, true)) {
continue;
}
$uuids[] = $uuid;
}
return $uuids;
}
private function updateCoolifyReleaseRuntimeEnv(coolify_api_client $client, string $resourceUuid, string $resourceType, array $target, array $context): ?array
{
$env = $this->releaseCoolifyRuntimeEnv($target, $context);
@@ -1010,6 +1010,7 @@ it('defines release manager schema, routes, permissions, and system-status integ
expect($manager)->toContain('createService');
expect($manager)->toContain('updateService');
expect(file_get_contents(app_path('classes/coolify_api_client.php')))->toContain('updateApplicationEnvsBulk');
expect(file_get_contents(app_path('classes/coolify_api_client.php')))->toContain('stopApplication');
expect($manager)->toContain('channel_presets');
expect($manager)->toContain('target_presets');
@@ -1400,6 +1401,27 @@ it('resolves release deployment endpoints from manual overrides, URLs, health ch
]))->toBe('https://gateway.example.test/beta/frontend');
});
it('collects previous Coolify application UUIDs for stale route cleanup', function (): void {
$manager = new release_manager();
$previousApplications = new ReflectionMethod(release_manager::class, 'releaseCoolifyPreviousApplicationUuids');
$previousApplications->setAccessible(true);
expect($previousApplications->invoke($manager, [
'coolify_previous_artifact_app_uuid' => 'old-artifact-app',
'coolify_previous_application_uuid' => 'old-application',
'coolify_previous_application_uuids' => [
'old-application',
'active-application',
'other-old-application',
'',
],
], 'active-application'))->toBe([
'old-application',
'old-artifact-app',
'other-old-application',
]);
});
it('redacts GitHub access metadata from public release versions', function (): void {
$manager = new release_manager();
$publicVersion = new ReflectionMethod(release_manager::class, 'publicVersion');