Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v4.0.0-beta.271 #2097

Merged
merged 24 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c4dfd99
init commit
iamEvanYT Apr 14, 2024
93acd4f
Merge branch 'coollabsio:main' into mongodb-restore
iamEvanYT Apr 25, 2024
23de13b
mac dev docker-compose
iamEvanYT Apr 25, 2024
3582cb3
fix mongodb imports
iamEvanYT Apr 25, 2024
8551e6e
opps... wrong commit
iamEvanYT Apr 25, 2024
e4aa3d3
Merge branch 'next' into mongodb-restore
iamEvanYT Apr 26, 2024
ae12222
Update version to 4.0.0-beta.271
andrasbacsai Apr 29, 2024
bb6c9cf
fix: backups
andrasbacsai Apr 29, 2024
3df80f2
fix: autoupdate
andrasbacsai Apr 29, 2024
94ad56f
Add generate_unique_uuid parameter to fqdnLabelsForTraefik function
andrasbacsai Apr 29, 2024
bbbeace
Update popup-small.blade.php and configuration-checker.blade.php
andrasbacsai Apr 29, 2024
360f5db
add private key description
andrasbacsai Apr 29, 2024
6bb05a6
refactor backup download
andrasbacsai Apr 29, 2024
c36636b
Add dispatch('refreshEnvs') to loadComposeFile method
andrasbacsai Apr 29, 2024
11baa97
Refactor services.php file to improve variable replacement logic
andrasbacsai Apr 29, 2024
2644efd
Update input.blade.php and health-checks.blade.php
andrasbacsai Apr 29, 2024
d400ac5
disable hc by default for some build packs
andrasbacsai Apr 29, 2024
0c51684
Update health check validation rules in HealthChecks.php
andrasbacsai Apr 29, 2024
05c6d67
fix: respect start period and chekc interval for hc
andrasbacsai Apr 29, 2024
16278f3
fix: parse HEALTHCHECK from dockerfile
andrasbacsai Apr 29, 2024
57d67bc
Fix repository URL handling in PublicGitRepository.php and public-git…
andrasbacsai Apr 29, 2024
4af7661
Fix repository URL handling in PublicGitRepository.php
andrasbacsai Apr 30, 2024
080db4d
Remove dispatch('configurationChanged') from check_status method in H…
andrasbacsai Apr 30, 2024
a966a50
Merge pull request #2071 from iamEvanYT/mongodb-restore
andrasbacsai Apr 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/Console/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ private function check_resources($schedule)
}
private function instance_auto_update($schedule)
{
if (isDev()) {
if (isDev() || isCloud()) {
return;
}
$settings = InstanceSettings::get();
Expand Down
55 changes: 32 additions & 23 deletions app/Jobs/ApplicationDeploymentJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
private ?string $buildTarget = null;
private Collection $saved_outputs;
private ?string $full_healthcheck_url = null;
private bool $custom_healthcheck_found = false;

private string $serverUser = 'root';
private string $serverUserHomeDir = '/root';
Expand Down Expand Up @@ -903,17 +902,26 @@ private function health_check()
if ($this->server->isSwarm()) {
// Implement healthcheck for swarm
} else {
if ($this->application->isHealthcheckDisabled() && $this->custom_healthcheck_found === false) {
if ($this->application->isHealthcheckDisabled() && $this->application->custom_healthcheck_found === false) {
$this->newVersionIsHealthy = true;
return;
}
if ($this->application->custom_healthcheck_found) {
$this->application_deployment_queue->addLogEntry("Custom healthcheck found, skipping default healthcheck.");
}
// ray('New container name: ', $this->container_name);
if ($this->container_name) {
$counter = 1;
$this->application_deployment_queue->addLogEntry("Waiting for healthcheck to pass on the new container.");
if ($this->full_healthcheck_url) {
$this->application_deployment_queue->addLogEntry("Healthcheck URL (inside the container): {$this->full_healthcheck_url}");
}
$this->application_deployment_queue->addLogEntry("Waiting for the start period ({$this->application->health_check_start_period} seconds) before starting healthcheck.");
$sleeptime = 0;
while ($sleeptime < $this->application->health_check_start_period) {
Sleep::for(1)->seconds();
$sleeptime++;
}
while ($counter <= $this->application->health_check_retries) {
$this->execute_remote_command(
[
Expand All @@ -936,7 +944,11 @@ private function health_check()
break;
}
$counter++;
Sleep::for($this->application->health_check_interval)->seconds();
$sleeptime = 0;
while ($sleeptime < $this->application->health_check_interval) {
Sleep::for(1)->seconds();
$sleeptime++;
}
}
}
}
Expand Down Expand Up @@ -1262,16 +1274,14 @@ private function generate_compose_file()
return escapeDollarSign($value);
});
$labels = $labels->merge(defaultLabels($this->application->id, $this->application->uuid, $this->pull_request_id))->toArray();

// Check for custom HEALTHCHECK
$this->custom_healthcheck_found = false;
if ($this->application->build_pack === 'dockerfile' || $this->application->dockerfile) {
$this->execute_remote_command([
executeInDocker($this->deployment_uuid, "cat {$this->workdir}{$this->dockerfile_location}"), "hidden" => true, "save" => 'dockerfile_from_repo', "ignore_errors" => true
]);
$dockerfile = collect(Str::of($this->saved_outputs->get('dockerfile_from_repo'))->trim()->explode("\n"));
if (str($dockerfile)->contains('HEALTHCHECK')) {
$this->custom_healthcheck_found = true;
}
$this->application->parseHealthcheckFromDockerfile($dockerfile);
}
$docker_compose = [
'version' => '3.8',
Expand Down Expand Up @@ -1317,18 +1327,17 @@ private function generate_compose_file()
if (!is_null($this->env_filename)) {
$docker_compose['services'][$this->container_name]['env_file'] = [$this->env_filename];
}
if (!$this->custom_healthcheck_found) {
$docker_compose['services'][$this->container_name]['healthcheck'] = [
'test' => [
'CMD-SHELL',
$this->generate_healthcheck_commands()
],
'interval' => $this->application->health_check_interval . 's',
'timeout' => $this->application->health_check_timeout . 's',
'retries' => $this->application->health_check_retries,
'start_period' => $this->application->health_check_start_period . 's'
];
}
$docker_compose['services'][$this->container_name]['healthcheck'] = [
'test' => [
'CMD-SHELL',
$this->generate_healthcheck_commands()
],
'interval' => $this->application->health_check_interval . 's',
'timeout' => $this->application->health_check_timeout . 's',
'retries' => $this->application->health_check_retries,
'start_period' => $this->application->health_check_start_period . 's'
];

if (!is_null($this->application->limits_cpuset)) {
data_set($docker_compose, 'services.' . $this->container_name . '.cpuset', $this->application->limits_cpuset);
}
Expand Down Expand Up @@ -1595,10 +1604,10 @@ private function generate_local_persistent_volumes_only_volume_names()

private function generate_healthcheck_commands()
{
if ($this->application->dockerfile || $this->application->build_pack === 'dockerfile' || $this->application->build_pack === 'dockerimage') {
// TODO: disabled HC because there are several ways to hc a simple docker image, hard to figure out a good way. Like some docker images (pocketbase) does not have curl.
return 'exit 0';
}
// if ($this->application->dockerfile || $this->application->build_pack === 'dockerfile' || $this->application->build_pack === 'dockerimage') {
// // TODO: disabled HC because there are several ways to hc a simple docker image, hard to figure out a good way. Like some docker images (pocketbase) does not have curl.
// return 'exit 0';
// }
if (!$this->application->health_check_port) {
$health_check_port = $this->application->ports_exposes_array[0];
} else {
Expand Down
5 changes: 2 additions & 3 deletions app/Jobs/DatabaseBackupJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ public function handle(): void
if ($this->backup->save_s3) {
$this->upload_to_s3();
}
$this->team?->notify(new BackupSuccess($this->backup, $this->database));
$this->team?->notify(new BackupSuccess($this->backup, $this->database, $database));
$this->backup_log->update([
'status' => 'success',
'message' => $this->backup_output,
Expand All @@ -305,8 +305,7 @@ public function handle(): void
]);
}
send_internal_notification('DatabaseBackupJob failed with: ' . $e->getMessage());
$this->team?->notify(new BackupFailed($this->backup, $this->database, $this->backup_output));
throw $e;
$this->team?->notify(new BackupFailed($this->backup, $this->database, $this->backup_output, $database));
}
}
} catch (\Throwable $e) {
Expand Down
3 changes: 2 additions & 1 deletion app/Jobs/InstanceAutoUpdateJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ class InstanceAutoUpdateJob implements ShouldQueue, ShouldBeUnique, ShouldBeEncr
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

public $timeout = 120;
public $timeout = 600;
public $tries = 1;

public function __construct(private bool $force = false)
{
Expand Down
2 changes: 1 addition & 1 deletion app/Jobs/SendMessageToTelegramJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public function handle(): void
}
}
$payload = [
'parse_mode' => 'markdown',
// 'parse_mode' => 'markdown',
'reply_markup' => json_encode([
'inline_keyboard' => [
[...$inlineButtons],
Expand Down
1 change: 1 addition & 0 deletions app/Livewire/Project/Application/General.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ public function loadComposeFile($isInit = false)
$this->dispatch('success', 'Docker compose file loaded.');
$this->dispatch('compose_loaded');
$this->dispatch('refresh_storages');
$this->dispatch('refreshEnvs');
} catch (\Throwable $e) {
$this->application->docker_compose_location = $this->initialDockerComposeLocation;
$this->application->docker_compose_pr_location = $this->initialDockerComposePrLocation;
Expand Down
3 changes: 2 additions & 1 deletion app/Livewire/Project/Application/Heading.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ public function check_status($showNotification = false)
}

if ($showNotification) $this->dispatch('success', "Success", "Application status updated.");
$this->dispatch('configurationChanged');
// Removed because it caused flickering
// $this->dispatch('configurationChanged');
}

public function force_deploy_without_cache()
Expand Down
5 changes: 0 additions & 5 deletions app/Livewire/Project/Database/Backup/Execution.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,6 @@ public function mount()
$this->executions = $executions;
$this->s3s = currentTeam()->s3s;
}
public function cleanupFailed()
{
$this->backup->executions()->where('status', 'failed')->delete();
$this->dispatch('refreshBackupExecutions');
}
public function render()
{
return view('livewire.project.database.backup.execution');
Expand Down
8 changes: 5 additions & 3 deletions app/Livewire/Project/Database/BackupExecutions.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

namespace App\Livewire\Project\Database;

use Illuminate\Support\Facades\Storage;
use Livewire\Component;
use Symfony\Component\HttpFoundation\StreamedResponse;

class BackupExecutions extends Component
{
Expand All @@ -16,11 +14,15 @@ public function getListeners()
$userId = auth()->user()->id;
return [
"echo-private:team.{$userId},BackupCreated" => 'refreshBackupExecutions',
"refreshBackupExecutions",
"deleteBackup"
];
}

public function cleanupFailed()
{
$this->backup->executions()->where('status', 'failed')->delete();
$this->refreshBackupExecutions();
}
public function deleteBackup($exeuctionId)
{
$execution = $this->backup->executions()->where('id', $exeuctionId)->first();
Expand Down
8 changes: 6 additions & 2 deletions app/Livewire/Project/Database/Import.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class Import extends Component
public string $postgresqlRestoreCommand = 'pg_restore -U $POSTGRES_USER -d $POSTGRES_DB';
public string $mysqlRestoreCommand = 'mysql -u $MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE';
public string $mariadbRestoreCommand = 'mariadb -u $MARIADB_USER -p$MARIADB_PASSWORD $MARIADB_DATABASE';
public string $mongodbRestoreCommand = 'mongorestore --authenticationDatabase=admin --username $MONGO_INITDB_ROOT_USERNAME --password $MONGO_INITDB_ROOT_PASSWORD --uri mongodb://localhost:27017 --gzip --archive=';

public function getListeners()
{
Expand Down Expand Up @@ -62,8 +63,7 @@ public function getContainers()
$this->resource->getMorphClass() == 'App\Models\StandaloneRedis' ||
$this->resource->getMorphClass() == 'App\Models\StandaloneKeydb' ||
$this->resource->getMorphClass() == 'App\Models\StandaloneDragonfly' ||
$this->resource->getMorphClass() == 'App\Models\StandaloneClickhouse' ||
$this->resource->getMorphClass() == 'App\Models\StandaloneMongodb'
$this->resource->getMorphClass() == 'App\Models\StandaloneClickhouse'
) {
$this->unsupported = true;
}
Expand Down Expand Up @@ -101,6 +101,10 @@ public function runImport()
$this->importCommands[] = "docker exec {$this->container} sh -c '{$this->postgresqlRestoreCommand} {$tmpPath}'";
$this->importCommands[] = "rm {$tmpPath}";
break;
case 'App\Models\StandaloneMongodb':
$this->importCommands[] = "docker exec {$this->container} sh -c '{$this->mongodbRestoreCommand}{$tmpPath}'";
$this->importCommands[] = "rm {$tmpPath}";
break;
}

$this->importCommands[] = "docker exec {$this->container} sh -c 'rm {$tmpPath}'";
Expand Down
14 changes: 11 additions & 3 deletions app/Livewire/Project/New/PublicGitRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,17 @@ public function load_branch()
$repository = str($this->repository_url)->after(':')->before('.git');
$this->repository_url = 'https://' . str($github_instance) . '/' . $repository;
}
if (
(str($this->repository_url)->startsWith('https://') ||
str($this->repository_url)->startsWith('http://')) &&
!str($this->repository_url)->endsWith('.git') &&
!str($this->repository_url)->contains('github.com')
) {
$this->repository_url = $this->repository_url . '.git';
}
if (str($this->repository_url)->contains('github.com')) {
$this->repository_url = str($this->repository_url)->before('.git')->value();
}
} catch (\Throwable $e) {
return handleError($e, $this);
}
Expand Down Expand Up @@ -170,7 +181,6 @@ public function submit()
'name' => generate_random_name(),
'git_repository' => $this->git_repository,
'git_branch' => $this->git_branch,
'build_pack' => 'nixpacks',
'ports_exposes' => $this->port,
'publish_directory' => $this->publish_directory,
'environment_id' => $environment->id,
Expand All @@ -183,7 +193,6 @@ public function submit()
'name' => generate_application_name($this->git_repository, $this->git_branch),
'git_repository' => $this->git_repository,
'git_branch' => $this->git_branch,
'build_pack' => 'nixpacks',
'ports_exposes' => $this->port,
'publish_directory' => $this->publish_directory,
'environment_id' => $environment->id,
Expand All @@ -195,7 +204,6 @@ public function submit()
];
}


$application = Application::create($application_init);

$application->settings->is_static = $this->is_static;
Expand Down
2 changes: 2 additions & 0 deletions app/Livewire/Project/New/SimpleDockerfile.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ public function submit()
'fqdn' => $fqdn
]);

$application->parseHealthcheckFromDockerfile(dockerfile: collect(str($this->dockerfile)->trim()->explode("\n")), isInit: true);

return redirect()->route('project.application.configuration', [
'application_uuid' => $application->uuid,
'environment_name' => $environment->name,
Expand Down
9 changes: 4 additions & 5 deletions app/Livewire/Project/Shared/HealthChecks.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,17 @@ class HealthChecks extends Component
'resource.health_check_return_code' => 'integer',
'resource.health_check_scheme' => 'string',
'resource.health_check_response_text' => 'nullable|string',
'resource.health_check_interval' => 'integer',
'resource.health_check_timeout' => 'integer',
'resource.health_check_retries' => 'integer',
'resource.health_check_interval' => 'integer|min:1',
'resource.health_check_timeout' => 'integer|min:1',
'resource.health_check_retries' => 'integer|min:1',
'resource.health_check_start_period' => 'integer',
'resource.custom_healthcheck_found' => 'boolean',

];
public function instantSave()
{
$this->resource->save();
$this->dispatch('success', 'Health check updated.');


}
public function submit()
{
Expand Down
47 changes: 47 additions & 0 deletions app/Models/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -963,4 +963,51 @@ public function getFilesFromServer(bool $isInit = false)
{
getFilesystemVolumesFromServer($this, $isInit);
}

public function parseHealthcheckFromDockerfile($dockerfile, bool $isInit = false) {
if (str($dockerfile)->contains('HEALTHCHECK') && ($this->isHealthcheckDisabled() || $isInit)) {
$healthcheckCommand = null;
$lines = $dockerfile->toArray();
foreach ($lines as $line) {
$trimmedLine = trim($line);
if (str_starts_with($trimmedLine, 'HEALTHCHECK')) {
$healthcheckCommand .= trim($trimmedLine, '\\ ');
continue;
}
if (isset($healthcheckCommand) && str_contains($trimmedLine, '\\')) {
$healthcheckCommand .= ' ' . trim($trimmedLine, '\\ ');
}
if (isset($healthcheckCommand) && !str_contains($trimmedLine, '\\') && !empty($healthcheckCommand)) {
$healthcheckCommand .= ' ' . $trimmedLine;
break;
}
}
if (str($healthcheckCommand)->isNotEmpty()) {
$interval = str($healthcheckCommand)->match('/--interval=(\d+)/');
$timeout = str($healthcheckCommand)->match('/--timeout=(\d+)/');
$start_period = str($healthcheckCommand)->match('/--start-period=(\d+)/');
$start_interval = str($healthcheckCommand)->match('/--start-interval=(\d+)/');
$retries = str($healthcheckCommand)->match('/--retries=(\d+)/');
if ($interval->isNotEmpty()) {
$this->health_check_interval = $interval->toInteger();
}
if ($timeout->isNotEmpty()) {
$this->health_check_timeout = $timeout->toInteger();
}
if ($start_period->isNotEmpty()) {
$this->health_check_start_period = $start_period->toInteger();
}
// if ($start_interval) {
// $this->health_check_start_interval = $start_interval->value();
// }
if ($retries->isNotEmpty()) {
$this->health_check_retries = $retries->toInteger();
}
if ($interval || $timeout || $start_period || $start_interval || $retries) {
$this->custom_healthcheck_found = true;
$this->save();
}
}
}
}
}
3 changes: 0 additions & 3 deletions app/Models/StandaloneClickhouse.php
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,4 @@ public function scheduledBackups()
{
return $this->morphMany(ScheduledDatabaseBackup::class, 'database');
}
public function database_name() {
return $this->clickhouse_db;
}
}
3 changes: 0 additions & 3 deletions app/Models/StandaloneDragonfly.php
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,4 @@ public function scheduledBackups()
{
return $this->morphMany(ScheduledDatabaseBackup::class, 'database');
}
public function database_name() {
return '0';
}
}
3 changes: 0 additions & 3 deletions app/Models/StandaloneKeydb.php
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,4 @@ public function scheduledBackups()
{
return $this->morphMany(ScheduledDatabaseBackup::class, 'database');
}
public function database_name() {
return '0';
}
}