refactor(railpack): extract static image build, fix port logic, bump to v0.22.0
Extract build_railpack_static_image() into its own method, prevent port override when is_static is set, bump Railpack to 0.22.0, and improve test setup with beforeEach and correct polymorphic env var fields.
This commit is contained in:
parent
793077d74f
commit
cddbaf581f
7 changed files with 93 additions and 62 deletions
|
|
@ -483,7 +483,7 @@ private function decide_what_to_do()
|
|||
} elseif ($this->application->build_pack === 'railpack') {
|
||||
$this->deploy_railpack_buildpack();
|
||||
} else {
|
||||
throw new \RuntimeException("Unsupported build pack: {$this->application->build_pack}");
|
||||
throw new DeploymentException("Unsupported build pack: {$this->application->build_pack}");
|
||||
}
|
||||
$this->post_deployment();
|
||||
}
|
||||
|
|
@ -2517,35 +2517,40 @@ private function build_railpack_image(): void
|
|||
|
||||
// Step 3: If static, copy built assets into nginx image
|
||||
if ($this->application->settings->is_static) {
|
||||
$publishDir = trim($this->application->publish_directory, '/');
|
||||
$publishDir = $publishDir ? "/{$publishDir}" : '';
|
||||
$dockerfile = base64_encode("FROM {$this->application->static_image}
|
||||
$this->build_railpack_static_image();
|
||||
}
|
||||
}
|
||||
|
||||
private function build_railpack_static_image(): void
|
||||
{
|
||||
$publishDir = trim($this->application->publish_directory, '/');
|
||||
$publishDir = $publishDir ? "/{$publishDir}" : '';
|
||||
$dockerfile = base64_encode("FROM {$this->application->static_image}
|
||||
WORKDIR /usr/share/nginx/html/
|
||||
LABEL coolify.deploymentId={$this->deployment_uuid}
|
||||
COPY --from={$this->build_image_name} /app{$publishDir} .
|
||||
COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
|
||||
|
||||
if (str($this->application->custom_nginx_configuration)->isNotEmpty()) {
|
||||
$nginx_config = base64_encode($this->application->custom_nginx_configuration);
|
||||
} else {
|
||||
$nginx_config = $this->application->settings->is_spa
|
||||
? base64_encode(defaultNginxConfiguration('spa'))
|
||||
: base64_encode(defaultNginxConfiguration());
|
||||
}
|
||||
|
||||
$static_build = $this->dockerBuildkitSupported
|
||||
? "DOCKER_BUILDKIT=1 docker build {$this->addHosts} --network host -f {$this->workdir}/Dockerfile --progress plain -t {$this->production_image_name} {$this->workdir}"
|
||||
: "docker build {$this->addHosts} --network host -f {$this->workdir}/Dockerfile -t {$this->production_image_name} {$this->workdir}";
|
||||
|
||||
$base64_static_build = base64_encode($static_build);
|
||||
$this->execute_remote_command(
|
||||
[executeInDocker($this->deployment_uuid, "echo '{$dockerfile}' | base64 -d | tee {$this->workdir}/Dockerfile > /dev/null")],
|
||||
[executeInDocker($this->deployment_uuid, "echo '{$nginx_config}' | base64 -d | tee {$this->workdir}/nginx.conf > /dev/null")],
|
||||
[executeInDocker($this->deployment_uuid, "echo '{$base64_static_build}' | base64 -d | tee ".self::BUILD_SCRIPT_PATH.' > /dev/null'), 'hidden' => true],
|
||||
[executeInDocker($this->deployment_uuid, 'cat '.self::BUILD_SCRIPT_PATH), 'hidden' => true],
|
||||
[executeInDocker($this->deployment_uuid, 'bash '.self::BUILD_SCRIPT_PATH), 'hidden' => true],
|
||||
);
|
||||
if (str($this->application->custom_nginx_configuration)->isNotEmpty()) {
|
||||
$nginx_config = base64_encode($this->application->custom_nginx_configuration);
|
||||
} else {
|
||||
$nginx_config = $this->application->settings->is_spa
|
||||
? base64_encode(defaultNginxConfiguration('spa'))
|
||||
: base64_encode(defaultNginxConfiguration());
|
||||
}
|
||||
|
||||
$static_build = $this->dockerBuildkitSupported
|
||||
? "DOCKER_BUILDKIT=1 docker build {$this->addHosts} --network host -f {$this->workdir}/Dockerfile --progress plain -t {$this->production_image_name} {$this->workdir}"
|
||||
: "docker build {$this->addHosts} --network host -f {$this->workdir}/Dockerfile -t {$this->production_image_name} {$this->workdir}";
|
||||
|
||||
$base64_static_build = base64_encode($static_build);
|
||||
$this->execute_remote_command(
|
||||
[executeInDocker($this->deployment_uuid, "echo '{$dockerfile}' | base64 -d | tee {$this->workdir}/Dockerfile > /dev/null")],
|
||||
[executeInDocker($this->deployment_uuid, "echo '{$nginx_config}' | base64 -d | tee {$this->workdir}/nginx.conf > /dev/null")],
|
||||
[executeInDocker($this->deployment_uuid, "echo '{$base64_static_build}' | base64 -d | tee ".self::BUILD_SCRIPT_PATH.' > /dev/null'), 'hidden' => true],
|
||||
[executeInDocker($this->deployment_uuid, 'cat '.self::BUILD_SCRIPT_PATH), 'hidden' => true],
|
||||
[executeInDocker($this->deployment_uuid, 'bash '.self::BUILD_SCRIPT_PATH), 'hidden' => true],
|
||||
);
|
||||
}
|
||||
|
||||
private function generate_coolify_env_variables(bool $forBuildTime = false): Collection
|
||||
|
|
|
|||
|
|
@ -84,7 +84,9 @@ public function updatedBuildPack()
|
|||
{
|
||||
if ($this->build_pack === 'nixpacks' || $this->build_pack === 'railpack') {
|
||||
$this->show_is_static = true;
|
||||
$this->port = 3000;
|
||||
if (! $this->is_static) {
|
||||
$this->port = 3000;
|
||||
}
|
||||
} elseif ($this->build_pack === 'static') {
|
||||
$this->show_is_static = false;
|
||||
$this->is_static = false;
|
||||
|
|
|
|||
|
|
@ -97,7 +97,9 @@ public function updatedBuildPack()
|
|||
{
|
||||
if ($this->build_pack === 'nixpacks' || $this->build_pack === 'railpack') {
|
||||
$this->show_is_static = true;
|
||||
$this->port = 3000;
|
||||
if (! $this->is_static) {
|
||||
$this->port = 3000;
|
||||
}
|
||||
} elseif ($this->build_pack === 'static') {
|
||||
$this->show_is_static = false;
|
||||
$this->is_static = false;
|
||||
|
|
|
|||
|
|
@ -101,7 +101,9 @@ public function updatedBuildPack()
|
|||
{
|
||||
if ($this->build_pack === 'nixpacks' || $this->build_pack === 'railpack') {
|
||||
$this->show_is_static = true;
|
||||
$this->port = 3000;
|
||||
if (! $this->isStatic) {
|
||||
$this->port = 3000;
|
||||
}
|
||||
} elseif ($this->build_pack === 'static') {
|
||||
$this->show_is_static = false;
|
||||
$this->isStatic = false;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ ARG PACK_VERSION=0.38.2
|
|||
# https://github.com/railwayapp/nixpacks/releases
|
||||
ARG NIXPACKS_VERSION=1.41.0
|
||||
# https://github.com/railwayapp/railpack/releases
|
||||
ARG RAILPACK_VERSION=0.21.0
|
||||
ARG RAILPACK_VERSION=0.22.0
|
||||
# https://github.com/jdx/mise/releases — must match railpack's pinned version (https://raw.githubusercontent.com/railwayapp/railpack/refs/heads/main/core/mise/version.txt)
|
||||
ARG MISE_VERSION=2026.3.12
|
||||
# https://github.com/minio/mc/releases
|
||||
|
|
|
|||
|
|
@ -78,26 +78,29 @@
|
|||
|
||||
// Add environment variables that should be deleted
|
||||
EnvironmentVariable::create([
|
||||
'application_id' => $application->id,
|
||||
'resourceable_type' => Application::class,
|
||||
'resourceable_id' => $application->id,
|
||||
'key' => 'SERVICE_FQDN_APP',
|
||||
'value' => 'app.example.com',
|
||||
'is_build_time' => false,
|
||||
'is_buildtime' => false,
|
||||
'is_preview' => false,
|
||||
]);
|
||||
|
||||
EnvironmentVariable::create([
|
||||
'application_id' => $application->id,
|
||||
'resourceable_type' => Application::class,
|
||||
'resourceable_id' => $application->id,
|
||||
'key' => 'SERVICE_URL_APP',
|
||||
'value' => 'http://app.example.com',
|
||||
'is_build_time' => false,
|
||||
'is_buildtime' => false,
|
||||
'is_preview' => false,
|
||||
]);
|
||||
|
||||
EnvironmentVariable::create([
|
||||
'application_id' => $application->id,
|
||||
'resourceable_type' => Application::class,
|
||||
'resourceable_id' => $application->id,
|
||||
'key' => 'REGULAR_VAR',
|
||||
'value' => 'should_remain',
|
||||
'is_build_time' => false,
|
||||
'is_buildtime' => false,
|
||||
'is_preview' => false,
|
||||
]);
|
||||
|
||||
|
|
@ -154,6 +157,34 @@
|
|||
'docker_compose_raw' => 'version: "3.8"\nservices:\n app:\n image: nginx',
|
||||
]);
|
||||
|
||||
// Add environment variables that should be deleted
|
||||
EnvironmentVariable::create([
|
||||
'resourceable_type' => Application::class,
|
||||
'resourceable_id' => $application->id,
|
||||
'key' => 'SERVICE_FQDN_APP',
|
||||
'value' => 'app.example.com',
|
||||
'is_buildtime' => false,
|
||||
'is_preview' => false,
|
||||
]);
|
||||
|
||||
EnvironmentVariable::create([
|
||||
'resourceable_type' => Application::class,
|
||||
'resourceable_id' => $application->id,
|
||||
'key' => 'SERVICE_URL_APP',
|
||||
'value' => 'http://app.example.com',
|
||||
'is_buildtime' => false,
|
||||
'is_preview' => false,
|
||||
]);
|
||||
|
||||
EnvironmentVariable::create([
|
||||
'resourceable_type' => Application::class,
|
||||
'resourceable_id' => $application->id,
|
||||
'key' => 'REGULAR_VAR',
|
||||
'value' => 'should_remain',
|
||||
'is_buildtime' => false,
|
||||
'is_preview' => false,
|
||||
]);
|
||||
|
||||
$application->build_pack = 'railpack';
|
||||
$application->save();
|
||||
$application->refresh();
|
||||
|
|
@ -161,6 +192,13 @@
|
|||
expect($application->build_pack)->toBe('railpack');
|
||||
expect($application->docker_compose_domains)->toBeNull();
|
||||
expect($application->docker_compose_raw)->toBeNull();
|
||||
|
||||
// Verify SERVICE_FQDN_* and SERVICE_URL_* were deleted
|
||||
expect($application->environment_variables()->where('key', 'SERVICE_FQDN_APP')->count())->toBe(0);
|
||||
expect($application->environment_variables()->where('key', 'SERVICE_URL_APP')->count())->toBe(0);
|
||||
|
||||
// Verify regular variables remain
|
||||
expect($application->environment_variables()->where('key', 'REGULAR_VAR')->count())->toBe(1);
|
||||
});
|
||||
|
||||
test('model does not clear dockerfile fields when switching to dockerfile', function () {
|
||||
|
|
|
|||
|
|
@ -10,13 +10,15 @@
|
|||
uses(RefreshDatabase::class);
|
||||
|
||||
describe('Application Railpack Support', function () {
|
||||
test('could_set_build_commands returns true for railpack', function () {
|
||||
beforeEach(function () {
|
||||
$team = Team::factory()->create();
|
||||
$project = Project::factory()->create(['team_id' => $team->id]);
|
||||
$environment = Environment::factory()->create(['project_id' => $project->id]);
|
||||
$this->environment = Environment::factory()->create(['project_id' => $project->id]);
|
||||
});
|
||||
|
||||
test('could_set_build_commands returns true for railpack', function () {
|
||||
$application = Application::factory()->create([
|
||||
'environment_id' => $environment->id,
|
||||
'environment_id' => $this->environment->id,
|
||||
'build_pack' => 'railpack',
|
||||
]);
|
||||
|
||||
|
|
@ -24,12 +26,8 @@
|
|||
});
|
||||
|
||||
test('could_set_build_commands returns true for nixpacks', function () {
|
||||
$team = Team::factory()->create();
|
||||
$project = Project::factory()->create(['team_id' => $team->id]);
|
||||
$environment = Environment::factory()->create(['project_id' => $project->id]);
|
||||
|
||||
$application = Application::factory()->create([
|
||||
'environment_id' => $environment->id,
|
||||
'environment_id' => $this->environment->id,
|
||||
'build_pack' => 'nixpacks',
|
||||
]);
|
||||
|
||||
|
|
@ -37,12 +35,8 @@
|
|||
});
|
||||
|
||||
test('could_set_build_commands returns false for dockerfile', function () {
|
||||
$team = Team::factory()->create();
|
||||
$project = Project::factory()->create(['team_id' => $team->id]);
|
||||
$environment = Environment::factory()->create(['project_id' => $project->id]);
|
||||
|
||||
$application = Application::factory()->create([
|
||||
'environment_id' => $environment->id,
|
||||
'environment_id' => $this->environment->id,
|
||||
'build_pack' => 'dockerfile',
|
||||
]);
|
||||
|
||||
|
|
@ -50,12 +44,8 @@
|
|||
});
|
||||
|
||||
test('railpack_environment_variables returns only RAILPACK_ prefixed vars', function () {
|
||||
$team = Team::factory()->create();
|
||||
$project = Project::factory()->create(['team_id' => $team->id]);
|
||||
$environment = Environment::factory()->create(['project_id' => $project->id]);
|
||||
|
||||
$application = Application::factory()->create([
|
||||
'environment_id' => $environment->id,
|
||||
'environment_id' => $this->environment->id,
|
||||
'build_pack' => 'railpack',
|
||||
]);
|
||||
|
||||
|
|
@ -92,12 +82,8 @@
|
|||
});
|
||||
|
||||
test('runtime_environment_variables excludes RAILPACK_ and NIXPACKS_ prefixed vars', function () {
|
||||
$team = Team::factory()->create();
|
||||
$project = Project::factory()->create(['team_id' => $team->id]);
|
||||
$environment = Environment::factory()->create(['project_id' => $project->id]);
|
||||
|
||||
$application = Application::factory()->create([
|
||||
'environment_id' => $environment->id,
|
||||
'environment_id' => $this->environment->id,
|
||||
'build_pack' => 'railpack',
|
||||
]);
|
||||
|
||||
|
|
@ -134,12 +120,8 @@
|
|||
});
|
||||
|
||||
test('railpack_environment_variables_preview returns only RAILPACK_ prefixed preview vars', function () {
|
||||
$team = Team::factory()->create();
|
||||
$project = Project::factory()->create(['team_id' => $team->id]);
|
||||
$environment = Environment::factory()->create(['project_id' => $project->id]);
|
||||
|
||||
$application = Application::factory()->create([
|
||||
'environment_id' => $environment->id,
|
||||
'environment_id' => $this->environment->id,
|
||||
'build_pack' => 'railpack',
|
||||
]);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue