chore(cdn): remove BunnyCDN sync and rename sync:bunny to sync:cdn

CDN files are synced through the coollabs-cdn GitHub repository only.
Remove the --bunny direct upload path, the BUNNY_API_KEY and
BUNNY_STORAGE_API_KEY settings, and rename the command to sync:cdn.
This commit is contained in:
Andras Bacsai committed 2026-10-02 11:36:04 +02:00
1 parent 99b2bce9ee
commit a14ef2d4ee
5 files changed
+64 -264

No files matched your search

-4
View File
@@ -45,7 +45,3 @@ VITE_PORT=5173
DUSK_DRIVER_URL=http://selenium:4444
# Special Keys for Andras
# For cache purging
BUNNY_API_KEY=
# For asset uploads
BUNNY_STORAGE_API_KEY=
@@ -3,30 +3,27 @@
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Http\Client\PendingRequest;
use Illuminate\Http\Client\Pool;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Http;
use function Laravel\Prompts\confirm;
use function Laravel\Prompts\multiselect;
use function Laravel\Prompts\select;
class SyncBunny extends Command
class SyncCdn extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'sync:bunny {--bunny}';
protected $signature = 'sync:cdn';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Sync files to BunnyCDN';
protected $description = 'Sync CDN files to the coollabs-cdn GitHub repository';
protected function removeTemporaryDirectory(string $tmpDir): void
{
@@ -246,8 +243,6 @@ class SyncBunny extends Command
*/
public function handle()
{
$that = $this;
$only_bunny = $this->option('bunny');
$nightly = select(
label: 'Which environment would you like to sync?',
options: [
@@ -256,9 +251,6 @@ class SyncBunny extends Command
],
default: 'production',
) === 'nightly';
$bunny_cdn = 'https://cdn.coollabs.io';
$bunny_cdn_path = 'coolify';
$bunny_cdn_storage_name = 'coolcdn';
$parent_dir = realpath(dirname(__FILE__).'/../../..');
@@ -280,34 +272,8 @@ class SyncBunny extends Command
$service_template_location = "$parent_dir/templates/$service_template";
$versions_location = "$parent_dir/$versions";
PendingRequest::macro('storage', function ($fileName) use ($that) {
$headers = [
'AccessKey' => config('constants.bunny.storage_api_key'),
'Accept' => 'application/json',
'Content-Type' => 'application/octet-stream',
];
$fileStream = fopen($fileName, 'r');
$file = fread($fileStream, filesize($fileName));
$that->info('Uploading: '.$fileName);
return PendingRequest::baseUrl('https://storage.bunnycdn.com')->withHeaders($headers)->withBody($file)->throw();
});
PendingRequest::macro('purge', function ($url) use ($that) {
$headers = [
'AccessKey' => config('constants.bunny.api_key'),
'Accept' => 'application/json',
];
$that->info('Purging: '.$url);
return PendingRequest::withHeaders($headers)->get('https://api.bunny.net/purge', [
'url' => $url,
'async' => false,
]);
});
try {
if ($nightly) {
$bunny_cdn_path = 'coolify-nightly';
$compose_file_location = "$parent_dir/other/nightly/$compose_file";
$compose_file_prod_location = "$parent_dir/other/nightly/$compose_file_prod";
$production_env_location = "$parent_dir/other/nightly/$production_env";
@@ -316,150 +282,54 @@ class SyncBunny extends Command
$install_script_location = "$parent_dir/other/nightly/$install_script";
$versions_location = "$parent_dir/other/nightly/$versions";
}
if ($only_bunny) {
$envLabel = $nightly ? 'NIGHTLY' : 'PRODUCTION';
$this->info("About to sync $envLabel files to BunnyCDN.");
$this->newLine();
$envLabel = $nightly ? 'NIGHTLY' : 'PRODUCTION';
$this->info("About to sync $envLabel releases, versions, compose, and environment files to GitHub repository.");
// BunnyCDN file mapping (local file => CDN URL path)
$bunnyFileMapping = [
$compose_file_location => "$bunny_cdn/$bunny_cdn_path/$compose_file",
$compose_file_prod_location => "$bunny_cdn/$bunny_cdn_path/$compose_file_prod",
$production_env_location => "$bunny_cdn/$bunny_cdn_path/$production_env",
$upgrade_script_location => "$bunny_cdn/$bunny_cdn_path/$upgrade_script",
$upgrade_postgres_script_location => "$bunny_cdn/$bunny_cdn_path/$upgrade_postgres_script",
$install_script_location => "$bunny_cdn/$bunny_cdn_path/$install_script",
if ($nightly) {
$files = [
$versions_location => 'json/coolify/nightly/versions.json',
$compose_file_location => 'json/coolify/nightly/docker-compose.yml',
$compose_file_prod_location => 'json/coolify/nightly/docker-compose.prod.yml',
$production_env_location => 'json/coolify/nightly/.env.production',
$install_script_location => 'json/coolify/nightly/install.sh',
$upgrade_script_location => 'json/coolify/nightly/upgrade.sh',
$upgrade_postgres_script_location => 'json/coolify/nightly/upgrade-postgres.sh',
$service_template_location => 'json/coolify/nightly/service-templates-latest.json',
];
} else {
$files = [
$versions_location => 'json/coolify/versions.json',
$compose_file_location => 'json/coolify/docker-compose.yml',
$compose_file_prod_location => 'json/coolify/docker-compose.prod.yml',
$production_env_location => 'json/coolify/.env.production',
$install_script_location => 'json/coolify/install.sh',
$upgrade_script_location => 'json/coolify/upgrade.sh',
$upgrade_postgres_script_location => 'json/coolify/upgrade-postgres.sh',
$service_template_location => 'json/coolify/service-templates-latest.json',
];
$diffTmpDir = sys_get_temp_dir().'/coollabs-cdn-diff-'.time();
@mkdir($diffTmpDir, 0755, true);
$hasChanges = false;
// Diff against BunnyCDN
$this->info('Fetching files from BunnyCDN to compare...');
foreach ($bunnyFileMapping as $localFile => $cdnUrl) {
if (! file_exists($localFile)) {
$this->warn('Local file not found: '.$localFile);
continue;
}
$fileName = basename($cdnUrl);
$remoteTmp = "$diffTmpDir/bunny-$fileName";
try {
$response = Http::timeout(10)->get($cdnUrl);
if ($response->successful()) {
file_put_contents($remoteTmp, $response->body());
$diffOutput = [];
exec('diff -u '.escapeshellarg($remoteTmp).' '.escapeshellarg($localFile).' 2>&1', $diffOutput, $diffCode);
if ($diffCode !== 0) {
$hasChanges = true;
$this->newLine();
$this->info("--- BunnyCDN: $bunny_cdn_path/$fileName");
$this->info("+++ Local: $fileName");
foreach ($diffOutput as $line) {
if (str_starts_with($line, '---') || str_starts_with($line, '+++')) {
continue;
}
$this->line($line);
}
}
} else {
$this->info("NEW on BunnyCDN: $bunny_cdn_path/$fileName (HTTP {$response->status()})");
$hasChanges = true;
}
} catch (\Throwable $e) {
$this->warn("Could not fetch $cdnUrl: {$e->getMessage()}");
}
}
$this->removeTemporaryDirectory($diffTmpDir);
if (! $hasChanges) {
$this->newLine();
$this->info('No differences found. All files are already up to date.');
return;
}
$this->newLine();
$confirmed = confirm('Are you sure you want to sync?');
if (! $confirmed) {
return;
}
}
if (! $only_bunny) {
$envLabel = $nightly ? 'NIGHTLY' : 'PRODUCTION';
$this->info("About to sync $envLabel releases, versions, compose, and environment files to GitHub repository.");
if ($nightly) {
$files = [
$versions_location => 'json/coolify/nightly/versions.json',
$compose_file_location => 'json/coolify/nightly/docker-compose.yml',
$compose_file_prod_location => 'json/coolify/nightly/docker-compose.prod.yml',
$production_env_location => 'json/coolify/nightly/.env.production',
$install_script_location => 'json/coolify/nightly/install.sh',
$upgrade_script_location => 'json/coolify/nightly/upgrade.sh',
$upgrade_postgres_script_location => 'json/coolify/nightly/upgrade-postgres.sh',
$service_template_location => 'json/coolify/nightly/service-templates-latest.json',
];
} else {
$files = [
$versions_location => 'json/coolify/versions.json',
$compose_file_location => 'json/coolify/docker-compose.yml',
$compose_file_prod_location => 'json/coolify/docker-compose.prod.yml',
$production_env_location => 'json/coolify/.env.production',
$install_script_location => 'json/coolify/install.sh',
$upgrade_script_location => 'json/coolify/upgrade.sh',
$upgrade_postgres_script_location => 'json/coolify/upgrade-postgres.sh',
$service_template_location => 'json/coolify/service-templates-latest.json',
];
}
$releasesTarget = $nightly ? 'json/coolify/nightly/releases.json' : 'json/coolify/releases.json';
$options = [$releasesTarget, ...array_values($files)];
$selectedFiles = multiselect(
label: 'Which files would you like to sync?',
options: $options,
default: $options,
required: true,
scroll: count($options),
);
$includeReleases = in_array($releasesTarget, $selectedFiles, true);
$files = array_filter(
$files,
fn (string $targetPath) => in_array($targetPath, $selectedFiles, true),
);
if ($includeReleases) {
$this->syncReleasesToGitHubRepo($files, $nightly);
} else {
$this->syncFilesToGitHubRepo($files, $nightly);
}
return;
}
Http::pool(fn (Pool $pool) => [
$pool->storage(fileName: "$compose_file_location")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$compose_file"),
$pool->storage(fileName: "$compose_file_prod_location")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$compose_file_prod"),
$pool->storage(fileName: "$production_env_location")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$production_env"),
$pool->storage(fileName: "$upgrade_script_location")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$upgrade_script"),
$pool->storage(fileName: "$upgrade_postgres_script_location")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$upgrade_postgres_script"),
$pool->storage(fileName: "$install_script_location")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$install_script"),
]);
Http::pool(fn (Pool $pool) => [
$pool->purge("$bunny_cdn/$bunny_cdn_path/$compose_file"),
$pool->purge("$bunny_cdn/$bunny_cdn_path/$compose_file_prod"),
$pool->purge("$bunny_cdn/$bunny_cdn_path/$production_env"),
$pool->purge("$bunny_cdn/$bunny_cdn_path/$upgrade_script"),
$pool->purge("$bunny_cdn/$bunny_cdn_path/$upgrade_postgres_script"),
$pool->purge("$bunny_cdn/$bunny_cdn_path/$install_script"),
]);
$this->info('All files uploaded & purged to BunnyCDN.');
$releasesTarget = $nightly ? 'json/coolify/nightly/releases.json' : 'json/coolify/releases.json';
$options = [$releasesTarget, ...array_values($files)];
$selectedFiles = multiselect(
label: 'Which files would you like to sync?',
options: $options,
default: $options,
required: true,
scroll: count($options),
);
$includeReleases = in_array($releasesTarget, $selectedFiles, true);
$files = array_filter(
$files,
fn (string $targetPath) => in_array($targetPath, $selectedFiles, true),
);
if ($includeReleases) {
$this->syncReleasesToGitHubRepo($files, $nightly);
} else {
$this->syncFilesToGitHubRepo($files, $nightly);
}
} catch (\Throwable $e) {
$this->error('Error: '.$e->getMessage());
}
-5
View File
@@ -136,11 +136,6 @@ return [
'dev_webhook' => env('SERVEO_URL'),
],
'bunny' => [
'storage_api_key' => env('BUNNY_STORAGE_API_KEY'),
'api_key' => env('BUNNY_API_KEY'),
],
'server_checks' => [
// Notification delay configuration for parallel server checks
// Used for Traefik version checks and other future server check jobs
+2 -2
View File
@@ -27,8 +27,8 @@ function test {
docker compose -f docker-compose.yml -f docker-compose.dev.yml exec -T coolify php artisan test --testsuite=Feature -p
}
function sync:bunny {
php artisan sync:bunny --env=secrets
function sync:cdn {
php artisan sync:cdn --env=secrets
}
function db:reset {
@@ -1,19 +1,19 @@
<?php
use App\Console\Commands\SyncBunny;
use App\Console\Commands\SyncCdn;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Http;
function createFakeSyncBunnyBinary(string $binDir, string $name, string $contents): void
function createFakeSyncCdnBinary(string $binDir, string $name, string $contents): void
{
file_put_contents("{$binDir}/{$name}", $contents);
chmod("{$binDir}/{$name}", 0755);
}
it('only exposes the BunnyCDN legacy sync option', function () {
$definition = Artisan::all()['sync:bunny']->getDefinition();
it('does not expose the removed sync options', function () {
$definition = Artisan::all()['sync:cdn']->getDefinition();
expect($definition->hasOption('bunny'))->toBeTrue()
expect($definition->hasOption('bunny'))->toBeFalse()
->and($definition->hasOption('github-releases'))->toBeFalse()
->and($definition->hasOption('release'))->toBeFalse()
->and($definition->hasOption('nightly'))->toBeFalse()
@@ -26,7 +26,7 @@ it('loads service templates from the Coollabs CDN', function () {
});
it('only removes validated Coolify CDN temporary directories', function () {
$command = new class extends SyncBunny
$command = new class extends SyncCdn
{
public function removeDirectory(string $path): void
{
@@ -49,89 +49,28 @@ it('only removes validated Coolify CDN temporary directories', function () {
rmdir($invalidDirectory);
});
it('syncs full files to BunnyCDN only when explicitly requested', function () {
Http::fake([
'https://cdn.coollabs.io/coolify/*' => Http::response('', 404),
'https://storage.bunnycdn.com/*' => Http::response([], 201),
'https://api.bunny.net/purge*' => Http::response([], 200),
]);
$binDir = sys_get_temp_dir().'/sync-bunny-bin-'.uniqid();
$logFile = sys_get_temp_dir().'/sync-bunny-'.uniqid().'.log';
mkdir($binDir, 0755, true);
createFakeSyncBunnyBinary($binDir, 'gh', <<<'SH'
#!/bin/sh
printf 'gh %s\n' "$*" >> "$SYNC_BUNNY_TEST_LOG"
if [ "$1" = "repo" ] && [ "$2" = "clone" ]; then
mkdir -p "$4/scripts"
fi
exit 0
SH);
createFakeSyncBunnyBinary($binDir, 'git', <<<'SH'
#!/bin/sh
printf 'git %s\n' "$*" >> "$SYNC_BUNNY_TEST_LOG"
if [ "$1" = "status" ]; then
printf 'M scripts/upgrade-postgres.sh\n'
fi
exit 0
SH);
$originalPath = getenv('PATH') ?: '';
putenv("PATH={$binDir}:{$originalPath}");
putenv("SYNC_BUNNY_TEST_LOG={$logFile}");
try {
$this->artisan('sync:bunny --bunny')
->expectsChoice('Which environment would you like to sync?', 'production', [
'production' => 'Production',
'nightly' => 'Nightly',
])
->expectsConfirmation('Are you sure you want to sync?', 'yes')
->assertExitCode(0);
} finally {
putenv("PATH={$originalPath}");
putenv('SYNC_BUNNY_TEST_LOG');
}
$log = file_exists($logFile) ? file_get_contents($logFile) : '';
expect($log)
->not->toContain('gh repo clone')
->not->toContain('gh pr create')
->not->toContain('coollabsio/coolify-cdn');
Http::assertSent(fn ($request) => $request->method() === 'PUT'
&& $request->url() === 'https://storage.bunnycdn.com/coolcdn/coolify/upgrade-postgres.sh');
Http::assertSent(fn ($request) => str_starts_with($request->url(), 'https://api.bunny.net/purge')
&& $request['url'] === 'https://cdn.coollabs.io/coolify/upgrade-postgres.sh');
});
it('selects the environment and release files to sync to GitHub', function (string $targetDirectory, string $environment, array $selectedBasenames) {
Http::fake([
'api.github.com/repos/coollabsio/coolify/releases*' => Http::response([], 200),
]);
$binDir = sys_get_temp_dir().'/sync-bunny-bin-'.uniqid();
$logFile = sys_get_temp_dir().'/sync-bunny-'.uniqid().'.log';
$binDir = sys_get_temp_dir().'/sync-cdn-bin-'.uniqid();
$logFile = sys_get_temp_dir().'/sync-cdn-'.uniqid().'.log';
mkdir($binDir, 0755, true);
createFakeSyncBunnyBinary($binDir, 'gh', <<<'SH'
createFakeSyncCdnBinary($binDir, 'gh', <<<'SH'
#!/bin/sh
printf 'gh %s\n' "$*" >> "$SYNC_BUNNY_TEST_LOG"
printf 'gh %s\n' "$*" >> "$SYNC_CDN_TEST_LOG"
if [ "$1" = "repo" ] && [ "$2" = "clone" ]; then
mkdir -p "$4"
fi
exit 0
SH);
createFakeSyncBunnyBinary($binDir, 'git', <<<'SH'
createFakeSyncCdnBinary($binDir, 'git', <<<'SH'
#!/bin/sh
printf 'git %s\n' "$*" >> "$SYNC_BUNNY_TEST_LOG"
printf 'git %s\n' "$*" >> "$SYNC_CDN_TEST_LOG"
if [ "$1" = "status" ]; then
printf 'M json/releases.json\n'
fi
@@ -147,7 +86,7 @@ SH);
$originalPath = getenv('PATH') ?: '';
putenv("PATH={$binDir}:{$originalPath}");
putenv("SYNC_BUNNY_TEST_LOG={$logFile}");
putenv("SYNC_CDN_TEST_LOG={$logFile}");
$allBasenames = [
'releases.json',
@@ -164,7 +103,7 @@ SH);
$selectedTargets = array_map(fn (string $file) => "$targetDirectory/$file", $selectedBasenames);
try {
$this->artisan('sync:bunny')
$this->artisan('sync:cdn')
->expectsChoice('Which environment would you like to sync?', $environment, [
'production' => 'Production',
'nightly' => 'Nightly',
@@ -173,7 +112,7 @@ SH);
->assertExitCode(0);
} finally {
putenv("PATH={$originalPath}");
putenv('SYNC_BUNNY_TEST_LOG');
putenv('SYNC_CDN_TEST_LOG');
}
$log = file_get_contents($logFile);