From b763a6b6d26d868fff26df776d1175fe33846fc9 Mon Sep 17 00:00:00 2001 From: Vigneshraj Sekar Babu Date: Tue, 18 Aug 2026 16:17:08 -0700 Subject: [PATCH 1/2] fix: honor per-service defaultUUID for fallback public URL and hostnames getPublicUrl() and the internal hostname/grpc host fallback in DeployableService always used the global default UUID, ignoring a service's own defaultUUID override in lifecycle.yaml. Both now resolve through getUUID(), which already respected the per-service value. Adds unit test coverage for the override. --- src/server/models/yaml/YamlService.ts | 9 ++--- .../models/yaml/tests/YamlService.test.ts | 26 +++++++++++++ .../services/__tests__/deployable.test.ts | 37 +++++++++++++++++++ src/server/services/deployable.ts | 4 +- 4 files changed, 68 insertions(+), 8 deletions(-) diff --git a/src/server/models/yaml/YamlService.ts b/src/server/models/yaml/YamlService.ts index 365ed0d..93fc982 100644 --- a/src/server/models/yaml/YamlService.ts +++ b/src/server/models/yaml/YamlService.ts @@ -885,12 +885,9 @@ export const getDockerBuildPipelineId = (service) => service?.helm?.docker?.pipelineId || service?.github?.docker?.pipelineId; export async function getPublicUrl(service: Service, build: Build): Promise { - const { lifecycleDefaults, domainDefaults } = await GlobalConfigService.getInstance().getAllConfigs(); - let host = lifecycleDefaults.defaultUUID; - let { http: httpDomain, grpc: grpcDomain } = domainDefaults; - if (build?.enabledFeatures.includes(FeatureFlags.NO_DEFAULT_ENV_RESOLVE)) { - host = NO_DEFAULT_ENV_UUID; - } + const { domainDefaults } = await GlobalConfigService.getInstance().getAllConfigs(); + const host = await getUUID(service, build); + const { http: httpDomain, grpc: grpcDomain } = domainDefaults; if (DeployTypes.HELM === getDeployType(service)) { const helmService = (service as unknown as HelmService).helm; diff --git a/src/server/models/yaml/tests/YamlService.test.ts b/src/server/models/yaml/tests/YamlService.test.ts index 52c3092..6025c45 100644 --- a/src/server/models/yaml/tests/YamlService.test.ts +++ b/src/server/models/yaml/tests/YamlService.test.ts @@ -19,6 +19,7 @@ mockRedisClient(); import { YamlConfigParser } from 'server/lib/yamlConfigParser'; import { YamlConfigValidator } from 'server/lib/yamlConfigValidator'; +import { Build } from 'server/models'; import { DeployTypes } from 'shared/constants'; import * as YamlService from '../index'; @@ -587,6 +588,31 @@ services: }); }); + describe('getPublicUrl', () => { + beforeEach(() => { + mockGetAllConfigs.mockResolvedValue({ + lifecycleDefaults: { defaultUUID: 'dev-0' }, + domainDefaults: { http: 'lifecycle.example.com', grpc: 'lifecycle-grpc.example.com' }, + }); + }); + + test('falls back to the global default UUID when the service has none configured', async () => { + const service: YamlService.Service = { name: 'my-service' } as YamlService.Service; + const build = { enabledFeatures: [] } as unknown as Build; + + await expect(YamlService.getPublicUrl(service, build)).resolves.toEqual('my-service-dev-0.lifecycle.example.com'); + }); + + test('uses the service-level defaultUUID override when configured', async () => { + const service: YamlService.Service = { name: 'my-service', defaultUUID: 'sandbox' } as YamlService.Service; + const build = { enabledFeatures: [] } as unknown as Build; + + await expect(YamlService.getPublicUrl(service, build)).resolves.toEqual( + 'my-service-sandbox.lifecycle.example.com' + ); + }); + }); + describe('getEnvironmentVariables', () => { test('GithubService', () => { const parser = new YamlConfigParser(); diff --git a/src/server/services/__tests__/deployable.test.ts b/src/server/services/__tests__/deployable.test.ts index 2b4bf32..32947e7 100644 --- a/src/server/services/__tests__/deployable.test.ts +++ b/src/server/services/__tests__/deployable.test.ts @@ -52,6 +52,7 @@ jest.mock('server/lib/github', () => ({ })); import * as YamlService from 'server/models/yaml'; +import { Build } from 'server/models'; import DeployableService, { DeployableAttributes } from '../deployable'; const lifecycleDefaults = { @@ -260,6 +261,42 @@ describe('Deployable Service', () => { }); }); + test('service-level defaultUUID overrides the global default for hostname/URL fallbacks', async () => { + const githubService: YamlService.GithubService = { + name: 'github-app', + defaultUUID: 'sandbox', + github: { + repository: 'example-org/example-service', + branchName: 'unit-test', + docker: { + defaultTag: 'main', + app: { + dockerfilePath: 'app1/app.Dockerfile', + }, + }, + }, + }; + + const build = { enabledFeatures: [] } as unknown as Build; + + // @ts-ignore + const result: DeployableAttributes = await deployableService.generateAttributesFromYamlConfig( + 100, + 'unit-test-12345', + 1234567890, + 'unit-test', + githubService, + false, + '', + build + ); + + expect(result.defaultUUID).toEqual('sandbox'); + expect(result.defaultInternalHostname).toEqual('github-app-sandbox'); + expect(result.defaultPublicUrl).toEqual(`github-app-sandbox.${domainDefaults.http}`); + expect(result.defaultGrpcHost).toEqual(`github-app-sandbox.${domainDefaults.grpc}`); + }); + test('Generate config should have httpGet port and path', async () => { const githubService: YamlService.GithubService = { name: 'github-app', diff --git a/src/server/services/deployable.ts b/src/server/services/deployable.ts index bfc9d06..1b7f7e7 100644 --- a/src/server/services/deployable.ts +++ b/src/server/services/deployable.ts @@ -199,7 +199,7 @@ export default class DeployableService extends BaseService { const { serviceDefaults, lifecycleDefaults, domainDefaults, buildDefaults } = await GlobalConfigService.getInstance().getAllConfigs(); //TODO check and throw error here? - const defaultUUID = lifecycleDefaults.defaultUUID; + const defaultUUID = await YamlService.getUUID(service, build); const dockerBuildPipelineName = YamlService.getDockerBuildPipelineId(service) || lifecycleDefaults.buildPipeline; @@ -262,7 +262,7 @@ export default class DeployableService extends BaseService { deployment?.network?.grpc?.defaultHost ?? `${service.name}-${defaultUUID}.${domainDefaults.grpc}`, ingressAnnotations: deployment?.network?.ingressAnnotations ?? {}, - defaultUUID: await YamlService.getUUID(service, build), + defaultUUID, serviceDisksYaml: deployment?.serviceDisks ? JSON.stringify(deployment.serviceDisks) : null, nodeSelector: deployment?.node_selector ?? null, From 563a5d6c7eb5888510026b6e436bbb0d578f65ce Mon Sep 17 00:00:00 2001 From: Vigneshraj Sekar Babu Date: Tue, 18 Aug 2026 22:03:22 -0700 Subject: [PATCH 2/2] test: cover NO_DEFAULT_ENV_RESOLVE precedence for defaultUUID resolution Adds coverage for the case where the NO_DEFAULT_ENV_RESOLVE feature flag takes priority over a service-level defaultUUID override, for both getPublicUrl() and the deployable hostname/URL fallbacks. --- .../models/yaml/tests/YamlService.test.ts | 11 +++++- .../services/__tests__/deployable.test.ts | 37 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/server/models/yaml/tests/YamlService.test.ts b/src/server/models/yaml/tests/YamlService.test.ts index 6025c45..5b1d9e3 100644 --- a/src/server/models/yaml/tests/YamlService.test.ts +++ b/src/server/models/yaml/tests/YamlService.test.ts @@ -20,7 +20,7 @@ mockRedisClient(); import { YamlConfigParser } from 'server/lib/yamlConfigParser'; import { YamlConfigValidator } from 'server/lib/yamlConfigValidator'; import { Build } from 'server/models'; -import { DeployTypes } from 'shared/constants'; +import { DeployTypes, FeatureFlags, NO_DEFAULT_ENV_UUID } from 'shared/constants'; import * as YamlService from '../index'; const mockGetAllConfigs = jest.fn(); @@ -611,6 +611,15 @@ services: 'my-service-sandbox.lifecycle.example.com' ); }); + + test('NO_DEFAULT_ENV_RESOLVE takes priority over a service-level defaultUUID override', async () => { + const service: YamlService.Service = { name: 'my-service', defaultUUID: 'sandbox' } as YamlService.Service; + const build = { enabledFeatures: [FeatureFlags.NO_DEFAULT_ENV_RESOLVE] } as unknown as Build; + + await expect(YamlService.getPublicUrl(service, build)).resolves.toEqual( + `my-service-${NO_DEFAULT_ENV_UUID}.lifecycle.example.com` + ); + }); }); describe('getEnvironmentVariables', () => { diff --git a/src/server/services/__tests__/deployable.test.ts b/src/server/services/__tests__/deployable.test.ts index 32947e7..256f973 100644 --- a/src/server/services/__tests__/deployable.test.ts +++ b/src/server/services/__tests__/deployable.test.ts @@ -53,6 +53,7 @@ jest.mock('server/lib/github', () => ({ import * as YamlService from 'server/models/yaml'; import { Build } from 'server/models'; +import { FeatureFlags, NO_DEFAULT_ENV_UUID } from 'shared/constants'; import DeployableService, { DeployableAttributes } from '../deployable'; const lifecycleDefaults = { @@ -297,6 +298,42 @@ describe('Deployable Service', () => { expect(result.defaultGrpcHost).toEqual(`github-app-sandbox.${domainDefaults.grpc}`); }); + test('NO_DEFAULT_ENV_RESOLVE takes priority over a service-level defaultUUID override', async () => { + const githubService: YamlService.GithubService = { + name: 'github-app', + defaultUUID: 'sandbox', + github: { + repository: 'example-org/example-service', + branchName: 'unit-test', + docker: { + defaultTag: 'main', + app: { + dockerfilePath: 'app1/app.Dockerfile', + }, + }, + }, + }; + + const build = { enabledFeatures: [FeatureFlags.NO_DEFAULT_ENV_RESOLVE] } as unknown as Build; + + // @ts-ignore + const result: DeployableAttributes = await deployableService.generateAttributesFromYamlConfig( + 100, + 'unit-test-12345', + 1234567890, + 'unit-test', + githubService, + false, + '', + build + ); + + expect(result.defaultUUID).toEqual(NO_DEFAULT_ENV_UUID); + expect(result.defaultInternalHostname).toEqual(`github-app-${NO_DEFAULT_ENV_UUID}`); + expect(result.defaultPublicUrl).toEqual(`github-app-${NO_DEFAULT_ENV_UUID}.${domainDefaults.http}`); + expect(result.defaultGrpcHost).toEqual(`github-app-${NO_DEFAULT_ENV_UUID}.${domainDefaults.grpc}`); + }); + test('Generate config should have httpGet port and path', async () => { const githubService: YamlService.GithubService = { name: 'github-app',