From 63ba33261b2afa60c87060f2d3b5096e49b871e7 Mon Sep 17 00:00:00 2001 From: vaguul <88252044+vaguul@users.noreply.github.com> Date: Thu, 4 Jun 2026 17:51:17 -0600 Subject: [PATCH 1/3] fix(api): allow source commit build setting --- .../Api/ApplicationsController.php | 9 ++- .../ApplicationSourceCommitSettingApiTest.php | 81 +++++++++++++++++++ 2 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 tests/Feature/Api/ApplicationSourceCommitSettingApiTest.php diff --git a/app/Http/Controllers/Api/ApplicationsController.php b/app/Http/Controllers/Api/ApplicationsController.php index 5e5405a7a..ad8d2ed97 100644 --- a/app/Http/Controllers/Api/ApplicationsController.php +++ b/app/Http/Controllers/Api/ApplicationsController.php @@ -2365,7 +2365,7 @@ public function update_by_uuid(Request $request) $this->authorize('update', $application); $server = $application->destination->server; - $allowedFields = ['name', 'description', 'is_static', 'is_spa', 'is_auto_deploy_enabled', 'is_force_https_enabled', 'domains', 'git_repository', 'git_branch', 'git_commit_sha', 'docker_registry_image_name', 'docker_registry_image_tag', 'build_pack', 'static_image', 'install_command', 'build_command', 'start_command', 'ports_exposes', 'ports_mappings', 'custom_network_aliases', 'base_directory', 'publish_directory', 'health_check_enabled', 'health_check_type', 'health_check_command', 'health_check_path', 'health_check_port', 'health_check_host', 'health_check_method', 'health_check_return_code', 'health_check_scheme', 'health_check_response_text', 'health_check_interval', 'health_check_timeout', 'health_check_retries', 'health_check_start_period', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'custom_labels', 'custom_docker_run_options', 'post_deployment_command', 'post_deployment_command_container', 'pre_deployment_command', 'pre_deployment_command_container', 'watch_paths', 'manual_webhook_secret_github', 'manual_webhook_secret_gitlab', 'manual_webhook_secret_bitbucket', 'manual_webhook_secret_gitea', 'dockerfile_location', 'dockerfile_target_build', 'docker_compose_location', 'docker_compose_custom_start_command', 'docker_compose_custom_build_command', 'docker_compose_domains', 'redirect', 'instant_deploy', 'use_build_server', 'custom_nginx_configuration', 'is_http_basic_auth_enabled', 'http_basic_auth_username', 'http_basic_auth_password', 'connect_to_docker_network', 'force_domain_override', 'is_container_label_escape_enabled', 'is_preserve_repository_enabled']; + $allowedFields = ['name', 'description', 'is_static', 'is_spa', 'is_auto_deploy_enabled', 'is_force_https_enabled', 'domains', 'git_repository', 'git_branch', 'git_commit_sha', 'docker_registry_image_name', 'docker_registry_image_tag', 'build_pack', 'static_image', 'install_command', 'build_command', 'start_command', 'ports_exposes', 'ports_mappings', 'custom_network_aliases', 'base_directory', 'publish_directory', 'health_check_enabled', 'health_check_type', 'health_check_command', 'health_check_path', 'health_check_port', 'health_check_host', 'health_check_method', 'health_check_return_code', 'health_check_scheme', 'health_check_response_text', 'health_check_interval', 'health_check_timeout', 'health_check_retries', 'health_check_start_period', 'limits_memory', 'limits_memory_swap', 'limits_memory_swappiness', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset', 'limits_cpu_shares', 'custom_labels', 'custom_docker_run_options', 'post_deployment_command', 'post_deployment_command_container', 'pre_deployment_command', 'pre_deployment_command_container', 'watch_paths', 'manual_webhook_secret_github', 'manual_webhook_secret_gitlab', 'manual_webhook_secret_bitbucket', 'manual_webhook_secret_gitea', 'dockerfile_location', 'dockerfile_target_build', 'docker_compose_location', 'docker_compose_custom_start_command', 'docker_compose_custom_build_command', 'docker_compose_domains', 'redirect', 'instant_deploy', 'use_build_server', 'custom_nginx_configuration', 'is_http_basic_auth_enabled', 'http_basic_auth_username', 'http_basic_auth_password', 'connect_to_docker_network', 'force_domain_override', 'is_container_label_escape_enabled', 'is_preserve_repository_enabled', 'include_source_commit_in_build']; $validationRules = [ 'name' => 'string|max:255', @@ -2380,6 +2380,7 @@ public function update_by_uuid(Request $request) 'is_http_basic_auth_enabled' => 'boolean|nullable', 'http_basic_auth_username' => 'string', 'http_basic_auth_password' => 'string', + 'include_source_commit_in_build' => 'boolean', ]; $validationRules = array_merge(sharedDataApplications(), $validationRules); $validationMessages = [ @@ -2616,6 +2617,7 @@ public function update_by_uuid(Request $request) $useBuildServer = $request->use_build_server; $isContainerLabelEscapeEnabled = $request->boolean('is_container_label_escape_enabled'); $isPreserveRepositoryEnabled = $request->boolean('is_preserve_repository_enabled'); + $includeSourceCommitInBuild = $request->boolean('include_source_commit_in_build'); if (isset($useBuildServer)) { $application->settings->is_build_server_enabled = $useBuildServer; $application->settings->save(); @@ -2654,6 +2656,11 @@ public function update_by_uuid(Request $request) $application->settings->is_preserve_repository_enabled = $isPreserveRepositoryEnabled; $application->settings->save(); } + if ($request->has('include_source_commit_in_build')) { + $application->settings->include_source_commit_in_build = $includeSourceCommitInBuild; + $application->settings->save(); + $request->offsetUnset('include_source_commit_in_build'); + } removeUnnecessaryFieldsFromRequest($request); $data = $request->only($allowedFields); diff --git a/tests/Feature/Api/ApplicationSourceCommitSettingApiTest.php b/tests/Feature/Api/ApplicationSourceCommitSettingApiTest.php new file mode 100644 index 000000000..650be6d2e --- /dev/null +++ b/tests/Feature/Api/ApplicationSourceCommitSettingApiTest.php @@ -0,0 +1,81 @@ + InstanceSettings::firstOrCreate(['id' => 0])); + + $this->team = Team::factory()->create(); + $this->user = User::factory()->create(); + $this->team->members()->attach($this->user->id, ['role' => 'owner']); + session(['currentTeam' => $this->team]); + + $plainTextToken = Str::random(40); + $token = $this->user->tokens()->create([ + 'name' => 'source-commit-api-test-'.Str::random(6), + 'token' => hash('sha256', $plainTextToken), + 'abilities' => ['*'], + 'team_id' => $this->team->id, + ]); + $this->bearerToken = $token->getKey().'|'.$plainTextToken; + + $this->server = Server::factory()->create(['team_id' => $this->team->id]); + $this->destination = StandaloneDocker::where('server_id', $this->server->id)->first(); + $this->project = Project::factory()->create(['team_id' => $this->team->id]); + $this->environment = Environment::factory()->create(['project_id' => $this->project->id]); + $this->application = Application::factory()->create([ + 'environment_id' => $this->environment->id, + 'destination_id' => $this->destination->id, + 'destination_type' => $this->destination->getMorphClass(), + ]); +}); + +function sourceCommitSettingApiHeaders(string $bearerToken): array +{ + return [ + 'Authorization' => 'Bearer '.$bearerToken, + 'Content-Type' => 'application/json', + ]; +} + +describe('PATCH /api/v1/applications/{uuid} include_source_commit_in_build', function () { + test('updates the application setting through the API', function () { + expect((bool) $this->application->settings->include_source_commit_in_build)->toBeFalse(); + + $this->withHeaders(sourceCommitSettingApiHeaders($this->bearerToken)) + ->patchJson("/api/v1/applications/{$this->application->uuid}", [ + 'include_source_commit_in_build' => true, + ]) + ->assertOk(); + + expect((bool) $this->application->fresh()->settings->include_source_commit_in_build)->toBeTrue(); + + $this->withHeaders(sourceCommitSettingApiHeaders($this->bearerToken)) + ->patchJson("/api/v1/applications/{$this->application->uuid}", [ + 'include_source_commit_in_build' => false, + ]) + ->assertOk(); + + expect((bool) $this->application->fresh()->settings->include_source_commit_in_build)->toBeFalse(); + }); + + test('rejects non boolean values', function () { + $this->withHeaders(sourceCommitSettingApiHeaders($this->bearerToken)) + ->patchJson("/api/v1/applications/{$this->application->uuid}", [ + 'include_source_commit_in_build' => 'not-a-boolean', + ]) + ->assertUnprocessable() + ->assertJsonValidationErrors('include_source_commit_in_build'); + }); +}); From 6baabf9eda5c9beca8e481265672950867f61ba8 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Tue, 7 Jul 2026 12:08:07 +0200 Subject: [PATCH 2/3] fix(api): document source commit build option --- app/Http/Controllers/Api/ApplicationsController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Http/Controllers/Api/ApplicationsController.php b/app/Http/Controllers/Api/ApplicationsController.php index ad8d2ed97..cd2d7fce5 100644 --- a/app/Http/Controllers/Api/ApplicationsController.php +++ b/app/Http/Controllers/Api/ApplicationsController.php @@ -2280,6 +2280,7 @@ public function delete_by_uuid(Request $request) 'force_domain_override' => ['type' => 'boolean', 'description' => 'Force domain usage even if conflicts are detected. Default is false.'], 'is_container_label_escape_enabled' => ['type' => 'boolean', 'default' => true, 'description' => 'Escape special characters in labels. By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$. If you want to use env variables inside the labels, turn this off.'], 'is_preserve_repository_enabled' => ['type' => 'boolean', 'description' => 'Preserve git repository during application update. If false, the existing repository will be removed and replaced with the new one. If true, the existing repository will be kept and the new one will be ignored. Default is false.'], + 'include_source_commit_in_build' => ['type' => 'boolean', 'description' => 'Include source commit information in the build. Default is false.'], ], ) ), From 59b158381c3036ae01b1ea2ac0ed2b0ba94b2464 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Tue, 7 Jul 2026 12:12:20 +0200 Subject: [PATCH 3/3] fix(api): preserve source commit flag until cleanup --- app/Http/Controllers/Api/ApplicationsController.php | 1 - bootstrap/helpers/api.php | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/Api/ApplicationsController.php b/app/Http/Controllers/Api/ApplicationsController.php index cd2d7fce5..9dc3c7661 100644 --- a/app/Http/Controllers/Api/ApplicationsController.php +++ b/app/Http/Controllers/Api/ApplicationsController.php @@ -2660,7 +2660,6 @@ public function update_by_uuid(Request $request) if ($request->has('include_source_commit_in_build')) { $application->settings->include_source_commit_in_build = $includeSourceCommitInBuild; $application->settings->save(); - $request->offsetUnset('include_source_commit_in_build'); } removeUnnecessaryFieldsFromRequest($request); diff --git a/bootstrap/helpers/api.php b/bootstrap/helpers/api.php index 6a288a064..ab3b8f9d6 100644 --- a/bootstrap/helpers/api.php +++ b/bootstrap/helpers/api.php @@ -203,5 +203,6 @@ function removeUnnecessaryFieldsFromRequest(Request $request) $request->offsetUnset('autogenerate_domain'); $request->offsetUnset('is_container_label_escape_enabled'); $request->offsetUnset('is_preserve_repository_enabled'); + $request->offsetUnset('include_source_commit_in_build'); $request->offsetUnset('docker_compose_raw'); }