chore: small improvement

This commit is contained in:
David Buday 2024-11-10 17:00:38 +01:00
parent ebf207296b
commit 9d08eed7f6
2 changed files with 61 additions and 61 deletions

View file

@ -196,8 +196,8 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
$this->preserveRepository = $this->application->settings->is_preserve_repository_enabled;
$this->basedir = $this->application->generateBaseDir($this->deployment_uuid);
$this->workdir = "{$this->basedir}".rtrim($this->application->base_directory, '/');
$this->configuration_dir = application_configuration_dir()."/{$this->application->uuid}";
$this->workdir = "{$this->basedir}" . rtrim($this->application->base_directory, '/');
$this->configuration_dir = application_configuration_dir() . "/{$this->application->uuid}";
$this->is_debug_enabled = $this->application->settings->is_debug_enabled;
$this->container_name = generateApplicationContainerName($this->application, $this->pull_request_id);
@ -397,12 +397,12 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
if ($this->application->docker_use_custom_registry) {
$this->handleRegistryAuth();
}
$this->generate_image_names();
$this->prepare_builder_image();
$this->generate_compose_file();
$this->rolling_update();
// Logout if use custom registry
if ($this->application->docker_use_custom_registry) {
$this->application_deployment_queue->addLogEntry('Logging out from registry...');
@ -419,7 +419,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
'hidden' => true
]);
}
$this->application_deployment_queue->addLogEntry('Deployment error: ' . $e->getMessage(), 'stderr');
//$this->application_deployment_queue->addLogEntry('Deployment error: ' . $e->getMessage(), 'stderr');
throw $e;
}
}
@ -432,13 +432,13 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
if (data_get($this->application, 'docker_compose_custom_start_command')) {
$this->docker_compose_custom_start_command = $this->application->docker_compose_custom_start_command;
if (! str($this->docker_compose_custom_start_command)->contains('--project-directory')) {
$this->docker_compose_custom_start_command = str($this->docker_compose_custom_start_command)->replaceFirst('compose', 'compose --project-directory '.$this->workdir)->value();
$this->docker_compose_custom_start_command = str($this->docker_compose_custom_start_command)->replaceFirst('compose', 'compose --project-directory ' . $this->workdir)->value();
}
}
if (data_get($this->application, 'docker_compose_custom_build_command')) {
$this->docker_compose_custom_build_command = $this->application->docker_compose_custom_build_command;
if (! str($this->docker_compose_custom_build_command)->contains('--project-directory')) {
$this->docker_compose_custom_build_command = str($this->docker_compose_custom_build_command)->replaceFirst('compose', 'compose --project-directory '.$this->workdir)->value();
$this->docker_compose_custom_build_command = str($this->docker_compose_custom_build_command)->replaceFirst('compose', 'compose --project-directory ' . $this->workdir)->value();
}
}
if ($this->pull_request_id === 0) {
@ -452,7 +452,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
if ($this->preserveRepository) {
foreach ($this->application->fileStorages as $fileStorage) {
$path = $fileStorage->fs_path;
$saveName = 'file_stat_'.$fileStorage->id;
$saveName = 'file_stat_' . $fileStorage->id;
$realPathInGit = str($path)->replace($this->application->workdir(), $this->workdir)->value();
// check if the file is a directory or a file inside the repository
$this->execute_remote_command(
@ -947,12 +947,12 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
$real_value = $env->real_value;
} else {
if ($env->is_literal || $env->is_multiline) {
$real_value = '\''.$real_value.'\'';
$real_value = '\'' . $real_value . '\'';
} else {
$real_value = escapeEnvVariables($env->real_value);
}
}
$envs->push($env->key.'='.$real_value);
$envs->push($env->key . '=' . $real_value);
}
// Add PORT if not exists, use the first port as default
if ($this->build_pack !== 'dockercompose') {
@ -1006,12 +1006,12 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
$real_value = $env->real_value;
} else {
if ($env->is_literal || $env->is_multiline) {
$real_value = '\''.$real_value.'\'';
$real_value = '\'' . $real_value . '\'';
} else {
$real_value = escapeEnvVariables($env->real_value);
}
}
$envs->push($env->key.'='.$real_value);
$envs->push($env->key . '=' . $real_value);
}
// Add PORT if not exists, use the first port as default
if ($this->build_pack !== 'dockercompose') {
@ -1419,7 +1419,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
destination: $destination,
no_questions_asked: true,
);
$this->application_deployment_queue->addLogEntry("Deployment to {$server->name}. Logs: ".route('project.application.deployment.show', [
$this->application_deployment_queue->addLogEntry("Deployment to {$server->name}. Logs: " . route('project.application.deployment.show', [
'project_uuid' => data_get($this->application, 'environment.project.uuid'),
'application_uuid' => data_get($this->application, 'uuid'),
'deployment_uuid' => $deployment_uuid,
@ -1759,27 +1759,27 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
'CMD-SHELL',
$this->generate_healthcheck_commands(),
],
'interval' => $this->application->health_check_interval.'s',
'timeout' => $this->application->health_check_timeout.'s',
'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',
'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);
data_set($docker_compose, 'services.' . $this->container_name . '.cpuset', $this->application->limits_cpuset);
}
if ($this->server->isSwarm()) {
data_forget($docker_compose, 'services.'.$this->container_name.'.container_name');
data_forget($docker_compose, 'services.'.$this->container_name.'.expose');
data_forget($docker_compose, 'services.'.$this->container_name.'.restart');
data_forget($docker_compose, 'services.' . $this->container_name . '.container_name');
data_forget($docker_compose, 'services.' . $this->container_name . '.expose');
data_forget($docker_compose, 'services.' . $this->container_name . '.restart');
data_forget($docker_compose, 'services.'.$this->container_name.'.mem_limit');
data_forget($docker_compose, 'services.'.$this->container_name.'.memswap_limit');
data_forget($docker_compose, 'services.'.$this->container_name.'.mem_swappiness');
data_forget($docker_compose, 'services.'.$this->container_name.'.mem_reservation');
data_forget($docker_compose, 'services.'.$this->container_name.'.cpus');
data_forget($docker_compose, 'services.'.$this->container_name.'.cpuset');
data_forget($docker_compose, 'services.'.$this->container_name.'.cpu_shares');
data_forget($docker_compose, 'services.' . $this->container_name . '.mem_limit');
data_forget($docker_compose, 'services.' . $this->container_name . '.memswap_limit');
data_forget($docker_compose, 'services.' . $this->container_name . '.mem_swappiness');
data_forget($docker_compose, 'services.' . $this->container_name . '.mem_reservation');
data_forget($docker_compose, 'services.' . $this->container_name . '.cpus');
data_forget($docker_compose, 'services.' . $this->container_name . '.cpuset');
data_forget($docker_compose, 'services.' . $this->container_name . '.cpu_shares');
$docker_compose['services'][$this->container_name]['deploy'] = [
'mode' => 'replicated',
@ -1841,20 +1841,20 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
}
}
if ($this->application->isHealthcheckDisabled()) {
data_forget($docker_compose, 'services.'.$this->container_name.'.healthcheck');
data_forget($docker_compose, 'services.' . $this->container_name . '.healthcheck');
}
if (count($this->application->ports_mappings_array) > 0 && $this->pull_request_id === 0) {
$docker_compose['services'][$this->container_name]['ports'] = $this->application->ports_mappings_array;
}
if (count($persistent_storages) > 0) {
if (! data_get($docker_compose, 'services.'.$this->container_name.'.volumes')) {
if (! data_get($docker_compose, 'services.' . $this->container_name . '.volumes')) {
$docker_compose['services'][$this->container_name]['volumes'] = [];
}
$docker_compose['services'][$this->container_name]['volumes'] = array_merge($docker_compose['services'][$this->container_name]['volumes'], $persistent_storages);
}
if (count($persistent_file_volumes) > 0) {
if (! data_get($docker_compose, 'services.'.$this->container_name.'.volumes')) {
if (! data_get($docker_compose, 'services.' . $this->container_name . '.volumes')) {
$docker_compose['services'][$this->container_name]['volumes'] = [];
}
$docker_compose['services'][$this->container_name]['volumes'] = array_merge($docker_compose['services'][$this->container_name]['volumes'], $persistent_file_volumes->map(function ($item) {
@ -1922,9 +1922,9 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
$volume_name = $persistentStorage->name;
}
if ($this->pull_request_id !== 0) {
$volume_name = $volume_name.'-pr-'.$this->pull_request_id;
$volume_name = $volume_name . '-pr-' . $this->pull_request_id;
}
$local_persistent_volumes[] = $volume_name.':'.$persistentStorage->mount_path;
$local_persistent_volumes[] = $volume_name . ':' . $persistentStorage->mount_path;
}
return $local_persistent_volumes;
@ -1940,7 +1940,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
$name = $persistentStorage->name;
if ($this->pull_request_id !== 0) {
$name = $name.'-pr-'.$this->pull_request_id;
$name = $name . '-pr-' . $this->pull_request_id;
}
$local_persistent_volumes_names[$name] = [
@ -2248,7 +2248,7 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
);
}
} catch (\Exception $error) {
$this->application_deployment_queue->addLogEntry("Error stopping container $containerName: ".$error->getMessage(), 'stderr');
$this->application_deployment_queue->addLogEntry("Error stopping container $containerName: " . $error->getMessage(), 'stderr');
}
$this->remove_container($containerName);
@ -2271,7 +2271,7 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
$containers = getCurrentApplicationContainerStatus($this->server, $this->application->id, $this->pull_request_id);
if ($this->pull_request_id === 0) {
$containers = $containers->filter(function ($container) {
return data_get($container, 'Names') !== $this->container_name && data_get($container, 'Names') !== $this->container_name.'-pr-'.$this->pull_request_id;
return data_get($container, 'Names') !== $this->container_name && data_get($container, 'Names') !== $this->container_name . '-pr-' . $this->pull_request_id;
});
}
$containers->each(function ($container) {
@ -2375,8 +2375,8 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
foreach ($containers as $container) {
$containerName = data_get($container, 'Names');
if ($containers->count() == 1 || str_starts_with($containerName, $this->application->pre_deployment_command_container.'-'.$this->application->uuid)) {
$cmd = "sh -c '".str_replace("'", "'\''", $this->application->pre_deployment_command)."'";
if ($containers->count() == 1 || str_starts_with($containerName, $this->application->pre_deployment_command_container . '-' . $this->application->uuid)) {
$cmd = "sh -c '" . str_replace("'", "'\''", $this->application->pre_deployment_command) . "'";
$exec = "docker exec {$containerName} {$cmd}";
$this->execute_remote_command(
[
@ -2402,8 +2402,8 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
$containers = getCurrentApplicationContainerStatus($this->server, $this->application->id, $this->pull_request_id);
foreach ($containers as $container) {
$containerName = data_get($container, 'Names');
if ($containers->count() == 1 || str_starts_with($containerName, $this->application->post_deployment_command_container.'-'.$this->application->uuid)) {
$cmd = "sh -c '".str_replace("'", "'\''", $this->application->post_deployment_command)."'";
if ($containers->count() == 1 || str_starts_with($containerName, $this->application->post_deployment_command_container . '-' . $this->application->uuid)) {
$cmd = "sh -c '" . str_replace("'", "'\''", $this->application->post_deployment_command) . "'";
$exec = "docker exec {$containerName} {$cmd}";
try {
$this->execute_remote_command(

View file

@ -23,7 +23,7 @@ trait ExecuteRemoteCommand
} else {
$commandsText = collect($commands);
}
if ($this->server instanceof Server === false) {
if (! $this->server instanceof Server) {
throw new \RuntimeException('Server is not set or is not an instance of Server model');
}
$commandsText->each(function ($single_command) {
@ -36,9 +36,9 @@ trait ExecuteRemoteCommand
$ignore_errors = data_get($single_command, 'ignore_errors', false);
$append = data_get($single_command, 'append', true);
$this->save = data_get($single_command, 'save');
$secrets = data_get($single_command, 'secrets', []); // Secrets for interpolation and masking
if (count($secrets) > 0) {
$command = $this->interpolateCommand($command, $secrets);
$secrets = data_get($single_command, 'secrets', []);
if (!empty($secrets)) {
$command = $this->replaceSecrets($command, $secrets);
}
if ($this->server->isNonRoot()) {
if (str($command)->startsWith('docker exec')) {
@ -50,7 +50,7 @@ trait ExecuteRemoteCommand
$remote_command = SshMultiplexingHelper::generateSshCommand($this->server, $command);
$process = Process::timeout(3600)->idleTimeout(3600)->start($remote_command, function (string $type, string $output) use ($command, $secrets, $hidden, $customType, $append) {
$output = str($output)->trim();
if (count($secrets) > 0) {
if (!empty($secrets)) {
$output = $this->maskSecrets($output, $secrets);
$command = $this->maskSecrets($command, $secrets);
}
@ -68,7 +68,11 @@ trait ExecuteRemoteCommand
if (! $this->application_deployment_queue->logs) {
$new_log_entry['order'] = 1;
} else {
$previous_logs = json_decode($this->application_deployment_queue->logs, associative: true, flags: JSON_THROW_ON_ERROR);
$previous_logs = json_decode(
$this->application_deployment_queue->logs,
associative: true,
flags: JSON_THROW_ON_ERROR
);
$new_log_entry['order'] = count($previous_logs) + 1;
}
$previous_logs[] = $new_log_entry;
@ -102,27 +106,23 @@ trait ExecuteRemoteCommand
});
}
private function interpolateCommand(string $command, array $secrets): string
private function replaceSecrets(string $text, array $secrets): string
{
foreach ($secrets as $key => $value) {
// Define the placeholder format
$placeholder = "{{secrets.$key}}";
// Replace placeholder with actual value
$command = str_replace($placeholder, $value, $command);
}
return $command;
return preg_replace_callback(
'/\{\{secrets\.(\w+)\}\}/',
fn($match) => $secrets[$match[1]] ?? $match[0],
$text
);
}
private function maskSecrets(string $text, array $secrets): string
{
// Sort secrets by length descending to prevent partial masking
usort($secrets, function ($a, $b) {
return strlen($b) - strlen($a);
});
foreach ($secrets as $value) {
// Replace each secret value with '*****'
$text = str_replace($value, '*****', $text);
// Sort by length to prevent partial matches
$sortedSecrets = collect($secrets)->sortByDesc(fn($value) => strlen($value));
foreach ($sortedSecrets as $value) {
if (!empty($value)) {
$text = str_replace($value, '******', $text);
}
}
return $text;
}