add env variables to deployment

This commit is contained in:
Andras Bacsai
2023-05-05 09:02:50 +02:00
parent 1e98cddaa6
commit 23f58b8c13
5 changed files with 51 additions and 15 deletions

View File

@@ -33,6 +33,9 @@ class General extends Component
'application.git_repository' => 'required', 'application.git_repository' => 'required',
'application.git_branch' => 'required', 'application.git_branch' => 'required',
'application.git_commit_sha' => 'nullable', 'application.git_commit_sha' => 'nullable',
'application.install_command' => 'nullable',
'application.build_command' => 'nullable',
'application.start_command' => 'nullable',
'application.build_pack' => 'required', 'application.build_pack' => 'required',
'application.static_image' => 'required', 'application.static_image' => 'required',
'application.base_directory' => 'required', 'application.base_directory' => 'required',

View File

@@ -171,9 +171,6 @@ class DeployApplicationJob implements ShouldQueue
$this->execute_in_builder("rm -fr {$this->workdir}/.git") $this->execute_in_builder("rm -fr {$this->workdir}/.git")
], hideFromOutput: true); ], hideFromOutput: true);
// Generate docker-compose.yml
$this->generateComposeFile();
$this->executeNow([ $this->executeNow([
"echo -n 'Generating nixpacks configuration... '", "echo -n 'Generating nixpacks configuration... '",
]); ]);
@@ -183,14 +180,18 @@ class DeployApplicationJob implements ShouldQueue
$this->execute_in_builder("rm -f {$this->workdir}/.nixpacks/Dockerfile"), $this->execute_in_builder("rm -f {$this->workdir}/.nixpacks/Dockerfile"),
], isDebuggable: true); ], isDebuggable: true);
// Generate docker-compose.yml
$this->generateComposeFile();
$this->executeNow([ $this->executeNow([
"echo 'Done.'", "echo 'Done.'",
"echo -n 'Building image... '", "echo -n 'Building image... '",
]); ]);
$build_args = $this->generate_build_environment_variables();
if ($this->application->settings->is_static) { if ($this->application->settings->is_static) {
$this->executeNow([ $this->executeNow([
$this->execute_in_builder("docker build -f {$this->workdir}/Dockerfile --build-arg SOURCE_COMMIT={$this->git_commit} --progress plain -t {$this->application->uuid}:{$this->git_commit}-build {$this->workdir}"), $this->execute_in_builder("docker build -f {$this->workdir}/Dockerfile {$build_args} --progress plain -t {$this->application->uuid}:{$this->git_commit}-build {$this->workdir}"),
], isDebuggable: true); ], isDebuggable: true);
$dockerfile = "FROM {$this->application->static_image} $dockerfile = "FROM {$this->application->static_image}
@@ -201,11 +202,11 @@ COPY --from={$this->application->uuid}:{$this->git_commit}-build /app/{$this->ap
$this->executeNow([ $this->executeNow([
$this->execute_in_builder("echo '{$docker_file}' | base64 -d > {$this->workdir}/Dockerfile-prod"), $this->execute_in_builder("echo '{$docker_file}' | base64 -d > {$this->workdir}/Dockerfile-prod"),
$this->execute_in_builder("docker build -f {$this->workdir}/Dockerfile-prod --build-arg SOURCE_COMMIT={$this->git_commit} --progress plain -t {$this->application->uuid}:{$this->git_commit} {$this->workdir}"), $this->execute_in_builder("docker build -f {$this->workdir}/Dockerfile-prod {$build_args} --progress plain -t {$this->application->uuid}:{$this->git_commit} {$this->workdir}"),
], hideFromOutput: true); ], hideFromOutput: true);
} else { } else {
$this->executeNow([ $this->executeNow([
$this->execute_in_builder("docker build -f {$this->workdir}/Dockerfile --build-arg SOURCE_COMMIT={$this->git_commit} --progress plain -t {$this->application->uuid}:{$this->git_commit} {$this->workdir}"), $this->execute_in_builder("docker build -f {$this->workdir}/Dockerfile {$build_args} --progress plain -t {$this->application->uuid}:{$this->git_commit} {$this->workdir}"),
], isDebuggable: true); ], isDebuggable: true);
} }
@@ -217,9 +218,6 @@ COPY --from={$this->application->uuid}:{$this->git_commit}-build /app/{$this->ap
// Start application // Start application
$this->startByComposeFile(); $this->startByComposeFile();
// Saving docker-compose.yml
Storage::disk('deployments')->put(Str::kebab($this->application->name) . '/docker-compose.yml', $this->docker_compose);
} catch (\Exception $e) { } catch (\Exception $e) {
$this->executeNow([ $this->executeNow([
"echo '\nOops something is not okay, are you okay? 😢'", "echo '\nOops something is not okay, are you okay? 😢'",
@@ -227,6 +225,8 @@ COPY --from={$this->application->uuid}:{$this->git_commit}-build /app/{$this->ap
]); ]);
$this->fail($e->getMessage()); $this->fail($e->getMessage());
} finally { } finally {
// Saving docker-compose.yml
Storage::disk('deployments')->put(Str::kebab($this->application->name) . '/docker-compose.yml', $this->docker_compose);
$this->executeNow(["docker rm -f {$this->deployment_uuid} >/dev/null 2>&1"], hideFromOutput: true); $this->executeNow(["docker rm -f {$this->deployment_uuid} >/dev/null 2>&1"], hideFromOutput: true);
dispatch(new ContainerStatusJob($this->application_uuid)); dispatch(new ContainerStatusJob($this->application_uuid));
} }
@@ -236,12 +236,43 @@ COPY --from={$this->application->uuid}:{$this->git_commit}-build /app/{$this->ap
{ {
return "docker exec {$this->deployment_uuid} bash -c '{$command}'"; return "docker exec {$this->deployment_uuid} bash -c '{$command}'";
} }
private function generate_environment_variables($ports)
{
$environment_variables = collect();
foreach ($this->application->environment_variables as $env) {
$environment_variables->push("$env->key=$env->value");
}
// Add PORT if not exists, use the first port as default
if ($environment_variables->filter(fn ($env) => Str::of($env)->contains('PORT'))->isEmpty()) {
$environment_variables->push("PORT={$ports[0]}");
}
return $environment_variables->all();
}
private function generate_build_environment_variables()
{
$build_args = collect(["--build-arg SOURCE_COMMIT={$this->git_commit}"]);
$this->executeNow([
$this->execute_in_builder("cat {$this->workdir}/Dockerfile")
], propertyName: 'dockerfile', hideFromOutput: true);
$dockerfile = collect(Str::of($this->activity->properties->get('dockerfile'))->trim()->explode("\n"));
foreach ($this->application->build_environment_variables as $env) {
$build_args->push("--build-arg {$env->key}={$env->value}");
$dockerfile->splice(1, 0, "ARG {$env->key}={$env->value}");
}
$dockerfile_base64 = base64_encode($dockerfile->implode("\n"));
$this->executeNow([
$this->execute_in_builder("echo '{$dockerfile_base64}' | base64 -d > {$this->workdir}/Dockerfile")
], hideFromOutput: true);
return $build_args->implode(' ');
}
private function generate_docker_compose() private function generate_docker_compose()
{ {
$ports = $this->application->settings->is_static ? [80] : $this->application->ports_exposes_array;
$persistentStorages = $this->generate_local_persistent_volumes(); $persistentStorages = $this->generate_local_persistent_volumes();
$volume_names = $this->generate_local_persistent_volumes_only_volume_names(); $volume_names = $this->generate_local_persistent_volumes_only_volume_names();
$ports = $this->application->settings->is_static ? [80] : $this->application->ports_exposes_array; $environment_variables = $this->generate_environment_variables($ports);
$docker_compose = [ $docker_compose = [
'version' => '3.8', 'version' => '3.8',
'services' => [ 'services' => [
@@ -249,9 +280,7 @@ COPY --from={$this->application->uuid}:{$this->git_commit}-build /app/{$this->ap
'image' => "{$this->application->uuid}:$this->git_commit", 'image' => "{$this->application->uuid}:$this->git_commit",
'container_name' => $this->application->uuid, 'container_name' => $this->application->uuid,
'restart' => 'always', 'restart' => 'always',
'environment' => [ 'environment' => $environment_variables,
'PORT' => $ports[0]
],
'labels' => $this->set_labels_for_applications(), 'labels' => $this->set_labels_for_applications(),
'expose' => $ports, 'expose' => $ports,
'networks' => [ 'networks' => [

View File

@@ -78,6 +78,10 @@ class Application extends BaseModel
{ {
return $this->hasMany(EnvironmentVariable::class); return $this->hasMany(EnvironmentVariable::class);
} }
public function build_environment_variables(): HasMany
{
return $this->hasMany(EnvironmentVariable::class)->where('is_build_time', true);
}
public function environment() public function environment()
{ {
return $this->belongsTo(Environment::class); return $this->belongsTo(Environment::class);

View File

@@ -16,7 +16,7 @@ class EnvironmentVariable extends Model
]; ];
private function get_environment_variables(string $environment_variable): string|null private function get_environment_variables(string $environment_variable): string|null
{ {
$team_id = session('currentTeam')->id; // $team_id = session('currentTeam')->id;
if (str_contains(trim($environment_variable), '{{') && str_contains(trim($environment_variable), '}}')) { if (str_contains(trim($environment_variable), '{{') && str_contains(trim($environment_variable), '}}')) {
$environment_variable = preg_replace('/\s+/', '', $environment_variable); $environment_variable = preg_replace('/\s+/', '', $environment_variable);
$environment_variable = str_replace('{{', '', $environment_variable); $environment_variable = str_replace('{{', '', $environment_variable);

View File

@@ -2,7 +2,7 @@
'isWarning' => null, 'isWarning' => null,
'defaultClass' => 'text-white bg-neutral-800 hover:bg-violet-600 w-28', 'defaultClass' => 'text-white bg-neutral-800 hover:bg-violet-600 w-28',
'defaultWarningClass' => 'text-white bg-red-500 hover:bg-red-600 w-28', 'defaultWarningClass' => 'text-white bg-red-500 hover:bg-red-600 w-28',
'loadingClass' => 'text-black bg-green-500', 'loadingClass' => 'text-black bg-green-500 w-28',
'confirm' => null, 'confirm' => null,
'confirmAction' => null, 'confirmAction' => null,
]) ])