diff --git a/__tests__/ut/commands/build_test.ts b/__tests__/ut/commands/build_test.ts index 9ce1b78..6d862ef 100644 --- a/__tests__/ut/commands/build_test.ts +++ b/__tests__/ut/commands/build_test.ts @@ -1,4 +1,4 @@ -import BuilderFactory, { BuildType } from '../../../src/subCommands/build'; +import BuilderFactory, { BuildType, resolveEnvVariables } from '../../../src/subCommands/build'; import { ImageBuiltKitBuilder } from '../../../src/subCommands/build/impl/imageBuiltKitBuilder'; import { ImageDockerBuilder } from '../../../src/subCommands/build/impl/imageDockerBuilder'; import { ImageKanikoBuilder } from '../../../src/subCommands/build/impl/imageKanikoBuilder'; @@ -302,4 +302,43 @@ describe('BuilderFactory', () => { expect(builder2).toBe(mockBuilder2); }); }); + + describe('resolveEnvVariables', () => { + it('should replace env variables with single quotes', () => { + process.env.MY_VAR = 'hello'; + const result = resolveEnvVariables("value: ${env('MY_VAR')}"); + expect(result).toBe('value: hello'); + delete process.env.MY_VAR; + }); + + it('should replace env variables with double quotes', () => { + process.env.MY_VAR = 'world'; + const result = resolveEnvVariables('value: ${env("MY_VAR")}'); + expect(result).toBe('value: world'); + delete process.env.MY_VAR; + }); + + it('should replace multiple env variables', () => { + process.env.USERNAME = 'admin'; + process.env.PASSWORD = 'secret'; + const result = resolveEnvVariables( + "username: ${env('USERNAME')}\npassword: ${env('PASSWORD')}", + ); + expect(result).toBe('username: admin\npassword: secret'); + delete process.env.USERNAME; + delete process.env.PASSWORD; + }); + + it('should throw error when env variable is not found', () => { + delete process.env.NOT_EXIST; + expect(() => resolveEnvVariables("value: ${env('NOT_EXIST')}")).toThrow( + 'Environment variable not found: NOT_EXIST', + ); + }); + + it('should not modify content without env variables', () => { + const content = 'region: cn-hangzhou\nruntime: nodejs18'; + expect(resolveEnvVariables(content)).toBe(content); + }); + }); }); diff --git a/src/subCommands/build/index.ts b/src/subCommands/build/index.ts index 35913cb..a27856f 100644 --- a/src/subCommands/build/index.ts +++ b/src/subCommands/build/index.ts @@ -22,6 +22,17 @@ export enum BuildType { Default = 'DEFAULT', } +export function resolveEnvVariables(content: string): string { + return content.replace(/\$\{env\(['"](.+?)['"]\)\}/g, (match, envName: string) => { + const value = process.env[envName]; + if (value === undefined) { + logger.error(`Environment variable not found: ${envName}`); + throw new Error(`Environment variable not found: ${envName}`); + } + return value; + }); +} + export default class BuilderFactory { private inputs: IInputs; private debugInstance: boolean; @@ -73,7 +84,8 @@ export default class BuilderFactory { try { const buildYamlContent = fs.readFileSync(buildYamlPath, 'utf8'); - const buildConfig = yaml.load(buildYamlContent) as any; + const resolvedContent = resolveEnvVariables(buildYamlContent); + const buildConfig = yaml.load(resolvedContent) as any; // 从build.yaml中提取配置,支持多种格式 let config = buildConfig;