diff --git a/services/nginx/app/classes/release_manager.php b/services/nginx/app/classes/release_manager.php index 64947855..8f129933 100644 --- a/services/nginx/app/classes/release_manager.php +++ b/services/nginx/app/classes/release_manager.php @@ -1021,6 +1021,7 @@ class release_manager 'channel_slug' => $channelSlug, 'route_slug' => $routeSlug, 'app' => $app, + 'apps' => $this->releaseTestAppsFromInput($input), 'repository' => $repository, 'branch' => $branch, 'auto_sync' => $this->toBool($input['auto_sync'] ?? false), @@ -4802,22 +4803,22 @@ class release_manager throw new RuntimeException('Beta release channel uses production services and does not promote separate release bundles.'); } $this->assertBetaProductionDataPolicy($channel, $serviceSet); + $frontendVersionId = $this->nullablePositiveInt($bundle['frontend_version_id'] ?? null); + $apiVersionId = $this->nullablePositiveInt($bundle['api_version_id'] ?? null); $this->assertReleaseGatePassedForPromotion( $channelId, (string)($bundle['frontend_commit_sha'] ?? ''), null, 'frontend' ); - if (trim((string)($bundle['api_commit_sha'] ?? '')) !== '') { + if ($apiVersionId !== null) { $this->assertReleaseGatePassedForPromotion( $channelId, - (string)$bundle['api_commit_sha'], + (string)($bundle['api_commit_sha'] ?? ''), null, 'api' ); } - $frontendVersionId = $this->nullablePositiveInt($bundle['frontend_version_id'] ?? null); - $apiVersionId = $this->nullablePositiveInt($bundle['api_version_id'] ?? null); $deploymentId = $this->nullablePositiveInt($bundle['api_deployment_id'] ?? null) ?? $this->nullablePositiveInt($bundle['frontend_deployment_id'] ?? null); diff --git a/services/nginx/app/tests/Unit/ReleaseManager/ReleaseManagerTest.php b/services/nginx/app/tests/Unit/ReleaseManager/ReleaseManagerTest.php index 92b695c1..5083d149 100644 --- a/services/nginx/app/tests/Unit/ReleaseManager/ReleaseManagerTest.php +++ b/services/nginx/app/tests/Unit/ReleaseManager/ReleaseManagerTest.php @@ -83,6 +83,7 @@ it('normalizes app-specific release gate auto-sync metadata', function (): void 'channel_slug' => 'stable', 'route_slug' => 'master', 'app' => 'api', + 'apps' => ['api'], 'repository' => 'copenhagentruckwash/api', 'branch' => 'master', 'expected_commit' => 'd52ceb85138740c45f20cda9b7ed9b7a21f0d4e8', @@ -90,6 +91,11 @@ it('normalizes app-specific release gate auto-sync metadata', function (): void 'auto_sync' => true, ]); + $fullStackGate = $normalizeGate->invoke($manager, [ + 'channel_slug' => 'stable', + ], ['slug' => 'stable']); + + expect($fullStackGate['apps'])->toBe(['frontend', 'api']); expect($appMatches->invoke($manager, ['app' => 'api'], 'api'))->toBeTrue(); expect($appMatches->invoke($manager, ['apps' => ['frontend', 'api']], 'api'))->toBeTrue(); expect($appMatches->invoke($manager, [], 'frontend'))->toBeTrue(); @@ -899,6 +905,7 @@ it('defines release manager schema, routes, permissions, and system-status integ expect($manager)->toContain('createBundle'); expect($manager)->toContain('deployBundle'); expect($manager)->toContain('promoteBundle'); + expect($manager)->toContain('if ($apiVersionId !== null)'); expect($manager)->toContain('setChannelBundle'); expect($manager)->toContain('searchAssignmentSubjects'); expect($manager)->toContain('publicAssignmentSubjectSuggestion'); @@ -975,6 +982,7 @@ it('defines release manager schema, routes, permissions, and system-status integ expect($manager)->toContain('channelSlugForRoute'); expect($manager)->toContain('syncChannel'); expect($manager)->toContain('runReleaseTest'); + expect($manager)->toContain("'apps' => \$this->releaseTestAppsFromInput(\$input)"); expect($manager)->toContain('releaseTestAppsFromInput'); expect($manager)->toContain('release_operation_runs'); expect($manager)->toContain('active_channel_app_key');