diff --git a/packages/cli-kit/src/public/node/context/local.test.ts b/packages/cli-kit/src/public/node/context/local.test.ts index abe71bb52b7..9c98d9f73b4 100644 --- a/packages/cli-kit/src/public/node/context/local.test.ts +++ b/packages/cli-kit/src/public/node/context/local.test.ts @@ -7,6 +7,7 @@ import { isUnitTest, analyticsDisabled, cloudEnvironment, + _resetCloudEnvironmentCache, macAddress, getThemeKitAccessDomain, opentelemetryDomain, @@ -217,6 +218,10 @@ describe('macAddress', () => { }) describe('cloudEnvironment', () => { + afterEach(() => { + _resetCloudEnvironmentCache() + }) + test('when codespace environmentreturns correct cloud platform', () => { // Given const env = {CODESPACES: '1'} @@ -249,6 +254,51 @@ describe('cloudEnvironment', () => { // Then expect(got.platform).toBe('localhost') }) + + test('memoizes the result when using process.env', () => { + // Given + const originalEnv = process.env + const mockEnv = {...process.env, CODESPACES: '1'} + try { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ;(process as any).env = mockEnv + + // When + const got1 = cloudEnvironment() + const got2 = cloudEnvironment() + + // Then + expect(got1.platform).toBe('codespaces') + expect(got1).toBe(got2) + + // And resetting the cache + _resetCloudEnvironmentCache() + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ;(process as any).env = {...process.env, GITPOD_WORKSPACE_URL: 'http://custom.gitpod.io'} + delete (process.env as any).CODESPACES + + const got3 = cloudEnvironment() + expect(got3.platform).toBe('gitpod') + } finally { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ;(process as any).env = originalEnv + } + }) + + test('does not memoize when a custom environment is provided', () => { + // Given + const env1 = {CODESPACES: '1'} + const env2 = {GITPOD_WORKSPACE_URL: 'http://custom.gitpod.io'} + + // When + const got1 = cloudEnvironment(env1) + const got2 = cloudEnvironment(env2) + + // Then + expect(got1.platform).toBe('codespaces') + expect(got2.platform).toBe('gitpod') + expect(got1).not.toBe(got2) + }) }) describe('ciPlatform', () => { diff --git a/packages/cli-kit/src/public/node/context/local.ts b/packages/cli-kit/src/public/node/context/local.ts index ad816399db9..adbdc91261f 100644 --- a/packages/cli-kit/src/public/node/context/local.ts +++ b/packages/cli-kit/src/public/node/context/local.ts @@ -44,6 +44,16 @@ let memoizedIsVerbose: boolean | undefined */ let memoizedIsUnitTest: boolean | undefined +/** + * Memoized value for the cloud environment check. + */ +let memoizedCloudEnvironment: + | { + platform: 'codespaces' | 'gitpod' | 'cloudShell' | 'localhost' + editor: boolean + } + | undefined + /** * Returns true if the CLI is running in debug mode. * @@ -219,16 +229,30 @@ export function cloudEnvironment(env: NodeJS.ProcessEnv = process.env): { platform: 'codespaces' | 'gitpod' | 'cloudShell' | 'localhost' editor: boolean } { - if (isSet(env[environmentVariables.codespaces])) { - return {platform: 'codespaces', editor: true} + if (env === process.env && memoizedCloudEnvironment) { + return memoizedCloudEnvironment + } + + let result: { + platform: 'codespaces' | 'gitpod' | 'cloudShell' | 'localhost' + editor: boolean } - if (isSet(env[environmentVariables.gitpod])) { - return {platform: 'gitpod', editor: true} + + if (isSet(env[environmentVariables.codespaces])) { + result = {platform: 'codespaces', editor: true} + } else if (isSet(env[environmentVariables.gitpod])) { + result = {platform: 'gitpod', editor: true} + } else if (isSet(env[environmentVariables.cloudShell])) { + result = {platform: 'cloudShell', editor: true} + } else { + result = {platform: 'localhost', editor: false} } - if (isSet(env[environmentVariables.cloudShell])) { - return {platform: 'cloudShell', editor: true} + + if (env === process.env) { + memoizedCloudEnvironment = result } - return {platform: 'localhost', editor: false} + + return result } /** @@ -326,3 +350,10 @@ export function opentelemetryDomain(env = process.env): string { } export type CIMetadata = Metadata + +/** + * Resets the cloud environment cache. + */ +export function _resetCloudEnvironmentCache(): void { + memoizedCloudEnvironment = undefined +}