From a73f4958401c2f6e6a46331b53dea6403e28a9e1 Mon Sep 17 00:00:00 2001 From: Hellgren Heikki Date: Fri, 1 Aug 2025 15:45:22 +0300 Subject: [PATCH 1/3] feat(config): allow specifying env specific config files this change allows to specify loading of environment specific config files based on `BACKSTAGE_ENVIRONMENT` environment variable. relates to #30716 Signed-off-by: Hellgren Heikki --- .changeset/better-eagles-tickle.md | 5 +++++ docs/conf/index.md | 21 +++++++++++++++---- .../src/sources/ConfigSources.test.ts | 12 +++++++++++ .../src/sources/ConfigSources.ts | 14 +++++++++++++ 4 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 .changeset/better-eagles-tickle.md diff --git a/.changeset/better-eagles-tickle.md b/.changeset/better-eagles-tickle.md new file mode 100644 index 0000000000..b199ae21d7 --- /dev/null +++ b/.changeset/better-eagles-tickle.md @@ -0,0 +1,5 @@ +--- +'@backstage/config-loader': patch +--- + +Allow using `BACKSTAGE_ENVIRONMENT` for loading environment specific config files diff --git a/docs/conf/index.md b/docs/conf/index.md index 659ffccfe3..7c5be174e5 100644 --- a/docs/conf/index.md +++ b/docs/conf/index.md @@ -16,10 +16,23 @@ allowing for customization. ## Supplying Configuration Configuration is stored in YAML files where the defaults are `app-config.yaml` -and `app-config.local.yaml` for local overrides. Other sets of files can by -loaded by passing `--config ` flags. The configuration files themselves -contain plain YAML, but with support for loading in data and secrets from -various sources using for example `$env` and `$file` keys. +and `app-config.local.yaml` for local overrides. Additionally, it is possible +to define environment based configuration files with `BACKSTAGE_ENVIRONMENT` +environment variable, which will load `app-config..yaml`. + +Loading order of these files is as follows: + +1. `app-config.yaml` +2. `app-config..yaml` +3. `app-config.local.yaml` + +Other sets of files can by loaded by passing `--config ` flags. +Read more about the configuration loading order in the +[Configuration Files](./writing.md#configuration-files) section. + +The configuration files themselves contain plain YAML, but with support for +loading in data and secrets from various sources using for example +`$env` and `$file` keys. It is also possible to supply configuration through environment variables, for example `APP_CONFIG_app_baseUrl=https://staging.example.com`. However these diff --git a/packages/config-loader/src/sources/ConfigSources.test.ts b/packages/config-loader/src/sources/ConfigSources.test.ts index e19ac1d51f..9b2932e439 100644 --- a/packages/config-loader/src/sources/ConfigSources.test.ts +++ b/packages/config-loader/src/sources/ConfigSources.test.ts @@ -89,6 +89,18 @@ describe('ConfigSources', () => { { name: 'FileConfigSource', path: `${root}app-config.yaml` }, { name: 'FileConfigSource', path: `${root}app-config.local.yaml` }, ]); + + process.env = Object.assign(process.env, { BACKSTAGE_ENVIRONMENT: 'test' }); + expect( + mergeSources( + ConfigSources.defaultForTargets({ rootDir: '/', targets: [] }), + ), + ).toEqual([ + { name: 'FileConfigSource', path: `${root}app-config.yaml` }, + { name: 'FileConfigSource', path: `${root}app-config.test.yaml` }, + { name: 'FileConfigSource', path: `${root}app-config.local.yaml` }, + ]); + fsSpy.mockRestore(); expect( diff --git a/packages/config-loader/src/sources/ConfigSources.ts b/packages/config-loader/src/sources/ConfigSources.ts index 37c1c6b087..0d958bb81d 100644 --- a/packages/config-loader/src/sources/ConfigSources.ts +++ b/packages/config-loader/src/sources/ConfigSources.ts @@ -182,6 +182,10 @@ export class ConfigSources { if (argSources.length === 0) { const defaultPath = resolvePath(rootDir, 'app-config.yaml'); const localPath = resolvePath(rootDir, 'app-config.local.yaml'); + const envPath = resolvePath( + rootDir, + `app-config.${process.env.BACKSTAGE_ENVIRONMENT}.yaml`, + ); const alwaysIncludeDefaultConfigSource = !options.allowMissingDefaultConfig; @@ -195,6 +199,16 @@ export class ConfigSources { ); } + if (process.env.BACKSTAGE_ENVIRONMENT && fs.pathExistsSync(envPath)) { + argSources.push( + FileConfigSource.create({ + watch: options.watch, + path: envPath, + substitutionFunc: options.substitutionFunc, + }), + ); + } + if (fs.pathExistsSync(localPath)) { argSources.push( FileConfigSource.create({ From b321dd90406223c4b8a05f462bab9b02c560c3fd Mon Sep 17 00:00:00 2001 From: Hellgren Heikki Date: Mon, 11 Aug 2025 14:46:51 +0300 Subject: [PATCH 2/3] feat: add support for local env specific config files Signed-off-by: Hellgren Heikki --- docs/conf/index.md | 1 + .../src/sources/ConfigSources.test.ts | 1 + .../config-loader/src/sources/ConfigSources.ts | 17 +++++++++++++++++ 3 files changed, 19 insertions(+) diff --git a/docs/conf/index.md b/docs/conf/index.md index 7c5be174e5..0b2240e2de 100644 --- a/docs/conf/index.md +++ b/docs/conf/index.md @@ -25,6 +25,7 @@ Loading order of these files is as follows: 1. `app-config.yaml` 2. `app-config..yaml` 3. `app-config.local.yaml` +4. `app-config..local.yaml` Other sets of files can by loaded by passing `--config ` flags. Read more about the configuration loading order in the diff --git a/packages/config-loader/src/sources/ConfigSources.test.ts b/packages/config-loader/src/sources/ConfigSources.test.ts index 9b2932e439..da56f5ccf9 100644 --- a/packages/config-loader/src/sources/ConfigSources.test.ts +++ b/packages/config-loader/src/sources/ConfigSources.test.ts @@ -99,6 +99,7 @@ describe('ConfigSources', () => { { name: 'FileConfigSource', path: `${root}app-config.yaml` }, { name: 'FileConfigSource', path: `${root}app-config.test.yaml` }, { name: 'FileConfigSource', path: `${root}app-config.local.yaml` }, + { name: 'FileConfigSource', path: `${root}app-config.test.local.yaml` }, ]); fsSpy.mockRestore(); diff --git a/packages/config-loader/src/sources/ConfigSources.ts b/packages/config-loader/src/sources/ConfigSources.ts index 0d958bb81d..1dacdc4752 100644 --- a/packages/config-loader/src/sources/ConfigSources.ts +++ b/packages/config-loader/src/sources/ConfigSources.ts @@ -186,6 +186,10 @@ export class ConfigSources { rootDir, `app-config.${process.env.BACKSTAGE_ENVIRONMENT}.yaml`, ); + const envLocalPath = resolvePath( + rootDir, + `app-config.${process.env.BACKSTAGE_ENVIRONMENT}.local.yaml`, + ); const alwaysIncludeDefaultConfigSource = !options.allowMissingDefaultConfig; @@ -218,6 +222,19 @@ export class ConfigSources { }), ); } + + if ( + process.env.BACKSTAGE_ENVIRONMENT && + fs.pathExistsSync(envLocalPath) + ) { + argSources.push( + FileConfigSource.create({ + watch: options.watch, + path: envLocalPath, + substitutionFunc: options.substitutionFunc, + }), + ); + } } return this.merge(argSources); From 5798d2566f2d6898863568793de556cbc58c3e2d Mon Sep 17 00:00:00 2001 From: Hellgren Heikki Date: Mon, 8 Sep 2025 08:47:51 +0300 Subject: [PATCH 3/3] chore: change to BACKSTAGE_ENV as per review Signed-off-by: Hellgren Heikki --- .changeset/better-eagles-tickle.md | 2 +- docs/conf/index.md | 8 ++++---- .../config-loader/src/sources/ConfigSources.test.ts | 2 +- packages/config-loader/src/sources/ConfigSources.ts | 11 ++++------- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/.changeset/better-eagles-tickle.md b/.changeset/better-eagles-tickle.md index b199ae21d7..418f0bcae0 100644 --- a/.changeset/better-eagles-tickle.md +++ b/.changeset/better-eagles-tickle.md @@ -2,4 +2,4 @@ '@backstage/config-loader': patch --- -Allow using `BACKSTAGE_ENVIRONMENT` for loading environment specific config files +Allow using `BACKSTAGE_ENV` for loading environment specific config files diff --git a/docs/conf/index.md b/docs/conf/index.md index 0b2240e2de..029c5b88fd 100644 --- a/docs/conf/index.md +++ b/docs/conf/index.md @@ -17,15 +17,15 @@ allowing for customization. Configuration is stored in YAML files where the defaults are `app-config.yaml` and `app-config.local.yaml` for local overrides. Additionally, it is possible -to define environment based configuration files with `BACKSTAGE_ENVIRONMENT` -environment variable, which will load `app-config..yaml`. +to define environment based configuration files with `BACKSTAGE_ENV` +environment variable, which will load `app-config..yaml`. Loading order of these files is as follows: 1. `app-config.yaml` -2. `app-config..yaml` +2. `app-config..yaml` 3. `app-config.local.yaml` -4. `app-config..local.yaml` +4. `app-config..local.yaml` Other sets of files can by loaded by passing `--config ` flags. Read more about the configuration loading order in the diff --git a/packages/config-loader/src/sources/ConfigSources.test.ts b/packages/config-loader/src/sources/ConfigSources.test.ts index da56f5ccf9..a6b0648889 100644 --- a/packages/config-loader/src/sources/ConfigSources.test.ts +++ b/packages/config-loader/src/sources/ConfigSources.test.ts @@ -90,7 +90,7 @@ describe('ConfigSources', () => { { name: 'FileConfigSource', path: `${root}app-config.local.yaml` }, ]); - process.env = Object.assign(process.env, { BACKSTAGE_ENVIRONMENT: 'test' }); + process.env = Object.assign(process.env, { BACKSTAGE_ENV: 'test' }); expect( mergeSources( ConfigSources.defaultForTargets({ rootDir: '/', targets: [] }), diff --git a/packages/config-loader/src/sources/ConfigSources.ts b/packages/config-loader/src/sources/ConfigSources.ts index 1dacdc4752..18d0443986 100644 --- a/packages/config-loader/src/sources/ConfigSources.ts +++ b/packages/config-loader/src/sources/ConfigSources.ts @@ -184,11 +184,11 @@ export class ConfigSources { const localPath = resolvePath(rootDir, 'app-config.local.yaml'); const envPath = resolvePath( rootDir, - `app-config.${process.env.BACKSTAGE_ENVIRONMENT}.yaml`, + `app-config.${process.env.BACKSTAGE_ENV}.yaml`, ); const envLocalPath = resolvePath( rootDir, - `app-config.${process.env.BACKSTAGE_ENVIRONMENT}.local.yaml`, + `app-config.${process.env.BACKSTAGE_ENV}.local.yaml`, ); const alwaysIncludeDefaultConfigSource = !options.allowMissingDefaultConfig; @@ -203,7 +203,7 @@ export class ConfigSources { ); } - if (process.env.BACKSTAGE_ENVIRONMENT && fs.pathExistsSync(envPath)) { + if (process.env.BACKSTAGE_ENV && fs.pathExistsSync(envPath)) { argSources.push( FileConfigSource.create({ watch: options.watch, @@ -223,10 +223,7 @@ export class ConfigSources { ); } - if ( - process.env.BACKSTAGE_ENVIRONMENT && - fs.pathExistsSync(envLocalPath) - ) { + if (process.env.BACKSTAGE_ENV && fs.pathExistsSync(envLocalPath)) { argSources.push( FileConfigSource.create({ watch: options.watch,