coolify/app/Console/Commands/SyncBunny.php

222 lines
9.4 KiB
PHP
Raw Normal View History

2023-04-28 11:50:27 +00:00
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Http\Client\PendingRequest;
use Illuminate\Http\Client\Pool;
use Illuminate\Support\Facades\Http;
2023-04-28 11:50:27 +00:00
2023-09-27 19:51:06 +00:00
use function Laravel\Prompts\confirm;
2023-04-28 13:22:36 +00:00
class SyncBunny extends Command
2023-04-28 11:50:27 +00:00
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'sync:bunny {--templates} {--release} {--github-releases} {--nightly}';
2023-04-28 11:50:27 +00:00
/**
* The console command description.
*
* @var string
*/
2023-04-28 13:22:36 +00:00
protected $description = 'Sync files to BunnyCDN';
2023-04-28 11:50:27 +00:00
/**
* Fetch GitHub releases and sync to CDN
*/
private function syncGitHubReleases($parent_dir, $bunny_cdn_storage_name, $bunny_cdn_path, $bunny_cdn)
{
$this->info('Fetching releases from GitHub...');
try {
$response = Http::timeout(30)
->get('https://api.github.com/repos/coollabsio/coolify/releases', [
'per_page' => 30, // Fetch more releases for better changelog
]);
if ($response->successful()) {
$releases = $response->json();
// Save releases to a temporary file
$releases_file = "$parent_dir/releases.json";
file_put_contents($releases_file, json_encode($releases, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
// Upload to CDN
Http::pool(fn (Pool $pool) => [
$pool->storage(fileName: $releases_file)->put("/$bunny_cdn_storage_name/$bunny_cdn_path/releases.json"),
$pool->purge("$bunny_cdn/coolify/releases.json"),
]);
// Clean up temporary file
unlink($releases_file);
$this->info('releases.json uploaded & purged...');
$this->info('Total releases synced: '.count($releases));
return true;
} else {
$this->error('Failed to fetch releases from GitHub: '.$response->status());
return false;
}
} catch (\Throwable $e) {
$this->error('Error fetching releases: '.$e->getMessage());
return false;
}
}
2023-04-28 11:50:27 +00:00
/**
* Execute the console command.
*/
public function handle()
{
2023-09-28 09:54:20 +00:00
$that = $this;
2023-10-24 09:08:15 +00:00
$only_template = $this->option('templates');
$only_version = $this->option('release');
$only_github_releases = $this->option('github-releases');
$nightly = $this->option('nightly');
2024-06-10 20:43:34 +00:00
$bunny_cdn = 'https://cdn.coollabs.io';
$bunny_cdn_path = 'coolify';
$bunny_cdn_storage_name = 'coolcdn';
2023-04-28 11:50:27 +00:00
2024-06-10 20:43:34 +00:00
$parent_dir = realpath(dirname(__FILE__).'/../../..');
2023-04-28 11:50:27 +00:00
2024-06-10 20:43:34 +00:00
$compose_file = 'docker-compose.yml';
$compose_file_prod = 'docker-compose.prod.yml';
$install_script = 'install.sh';
$upgrade_script = 'upgrade.sh';
$production_env = '.env.production';
$service_template = config('constants.services.file_name');
2024-06-10 20:43:34 +00:00
$versions = 'versions.json';
2023-05-11 13:28:34 +00:00
$compose_file_location = "$parent_dir/$compose_file";
$compose_file_prod_location = "$parent_dir/$compose_file_prod";
$install_script_location = "$parent_dir/scripts/install.sh";
$upgrade_script_location = "$parent_dir/scripts/upgrade.sh";
$production_env_location = "$parent_dir/.env.production";
$versions_location = "$parent_dir/$versions";
PendingRequest::macro('storage', function ($fileName) use ($that) {
2023-04-28 11:50:27 +00:00
$headers = [
2024-11-12 14:53:05 +00:00
'AccessKey' => config('constants.bunny.storage_api_key'),
2023-04-28 11:50:27 +00:00
'Accept' => 'application/json',
2024-06-10 20:43:34 +00:00
'Content-Type' => 'application/octet-stream',
2023-04-28 11:50:27 +00:00
];
2024-06-10 20:43:34 +00:00
$fileStream = fopen($fileName, 'r');
2023-09-28 20:42:10 +00:00
$file = fread($fileStream, filesize($fileName));
2024-06-10 20:43:34 +00:00
$that->info('Uploading: '.$fileName);
2023-04-28 11:50:27 +00:00
return PendingRequest::baseUrl('https://storage.bunnycdn.com')->withHeaders($headers)->withBody($file)->throw();
});
2023-09-28 09:54:20 +00:00
PendingRequest::macro('purge', function ($url) use ($that) {
2023-05-10 07:56:12 +00:00
$headers = [
2024-11-12 14:53:05 +00:00
'AccessKey' => config('constants.bunny.api_key'),
2023-05-10 07:56:12 +00:00
'Accept' => 'application/json',
];
2024-06-10 20:43:34 +00:00
$that->info('Purging: '.$url);
2023-06-06 07:22:48 +00:00
return PendingRequest::withHeaders($headers)->get('https://api.bunny.net/purge', [
2024-06-10 20:43:34 +00:00
'url' => $url,
'async' => false,
2023-06-06 07:22:48 +00:00
]);
2023-05-10 07:56:12 +00:00
});
2023-04-28 11:50:27 +00:00
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";
$upgrade_script_location = "$parent_dir/other/nightly/$upgrade_script";
$install_script_location = "$parent_dir/other/nightly/$install_script";
$versions_location = "$parent_dir/other/nightly/$versions";
}
if (! $only_template && ! $only_version && ! $only_github_releases) {
if ($nightly) {
$this->info('About to sync files NIGHTLY (docker-compose.prod.yaml, upgrade.sh, install.sh, etc) to BunnyCDN.');
} else {
$this->info('About to sync files PRODUCTION (docker-compose.yml, docker-compose.prod.yml, upgrade.sh, install.sh, etc) to BunnyCDN.');
}
$confirmed = confirm('Are you sure you want to sync?');
if (! $confirmed) {
return;
}
2023-11-24 14:48:23 +00:00
}
if ($only_template) {
$this->info('About to sync '.config('constants.services.file_name').' to BunnyCDN.');
2024-06-10 20:43:34 +00:00
$confirmed = confirm('Are you sure you want to sync?');
if (! $confirmed) {
return;
}
2023-09-27 19:51:06 +00:00
Http::pool(fn (Pool $pool) => [
2023-09-28 20:42:10 +00:00
$pool->storage(fileName: "$parent_dir/templates/$service_template")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$service_template"),
2023-09-27 19:51:06 +00:00
$pool->purge("$bunny_cdn/$bunny_cdn_path/$service_template"),
]);
$this->info('Service template uploaded & purged...');
2024-06-10 20:43:34 +00:00
2023-09-27 19:51:06 +00:00
return;
2024-06-10 20:43:34 +00:00
} elseif ($only_version) {
if ($nightly) {
$this->info('About to sync NIGHLTY versions.json to BunnyCDN.');
} else {
$this->info('About to sync PRODUCTION versions.json to BunnyCDN.');
}
$file = file_get_contents($versions_location);
$json = json_decode($file, true);
$actual_version = data_get($json, 'coolify.v4.version');
$confirmed = confirm("Are you sure you want to sync to {$actual_version}?");
2024-06-10 20:43:34 +00:00
if (! $confirmed) {
return;
}
// First sync GitHub releases
$this->info('Syncing GitHub releases first...');
$this->syncGitHubReleases($parent_dir, $bunny_cdn_storage_name, $bunny_cdn_path, $bunny_cdn);
// Then sync versions.json
Http::pool(fn (Pool $pool) => [
$pool->storage(fileName: $versions_location)->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$versions"),
$pool->purge("$bunny_cdn/$bunny_cdn_path/$versions"),
]);
$this->info('versions.json uploaded & purged...');
2024-06-10 20:43:34 +00:00
return;
} elseif ($only_github_releases) {
$this->info('About to sync GitHub releases to BunnyCDN.');
$confirmed = confirm('Are you sure you want to sync GitHub releases?');
if (! $confirmed) {
return;
}
// Use the reusable function
$this->syncGitHubReleases($parent_dir, $bunny_cdn_storage_name, $bunny_cdn_path, $bunny_cdn);
return;
}
2023-09-27 19:51:06 +00:00
2023-08-11 18:48:52 +00:00
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: "$install_script_location")->put("/$bunny_cdn_storage_name/$bunny_cdn_path/$install_script"),
2023-06-06 07:22:48 +00:00
]);
2023-08-11 18:48:52 +00:00
Http::pool(fn (Pool $pool) => [
2023-06-06 07:22:48 +00:00
$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/$install_script"),
2023-04-28 11:50:27 +00:00
]);
2024-06-10 20:43:34 +00:00
$this->info('All files uploaded & purged...');
2023-09-11 15:36:30 +00:00
} catch (\Throwable $e) {
2024-06-10 20:43:34 +00:00
$this->error('Error: '.$e->getMessage());
2023-04-28 11:50:27 +00:00
}
}
}