Merge pull request #30722 from drodil/env_config_files

feat(config): allow specifying env specific config files
This commit is contained in:
Patrik Oldsberg
2025-09-08 09:11:38 +02:00
committed by GitHub
4 changed files with 64 additions and 4 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/config-loader': patch
---
Allow using `BACKSTAGE_ENV` for loading environment specific config files
+18 -4
View File
@@ -16,10 +16,24 @@ 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 <path>` 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_ENV`
environment variable, which will load `app-config.<BACKSTAGE_ENV>.yaml`.
Loading order of these files is as follows:
1. `app-config.yaml`
2. `app-config.<BACKSTAGE_ENV>.yaml`
3. `app-config.local.yaml`
4. `app-config.<BACKSTAGE_ENV>.local.yaml`
Other sets of files can by loaded by passing `--config <path>` 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
@@ -89,6 +89,19 @@ describe('ConfigSources', () => {
{ name: 'FileConfigSource', path: `${root}app-config.yaml` },
{ name: 'FileConfigSource', path: `${root}app-config.local.yaml` },
]);
process.env = Object.assign(process.env, { BACKSTAGE_ENV: '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` },
{ name: 'FileConfigSource', path: `${root}app-config.test.local.yaml` },
]);
fsSpy.mockRestore();
expect(
@@ -182,6 +182,14 @@ 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_ENV}.yaml`,
);
const envLocalPath = resolvePath(
rootDir,
`app-config.${process.env.BACKSTAGE_ENV}.local.yaml`,
);
const alwaysIncludeDefaultConfigSource =
!options.allowMissingDefaultConfig;
@@ -195,6 +203,16 @@ export class ConfigSources {
);
}
if (process.env.BACKSTAGE_ENV && fs.pathExistsSync(envPath)) {
argSources.push(
FileConfigSource.create({
watch: options.watch,
path: envPath,
substitutionFunc: options.substitutionFunc,
}),
);
}
if (fs.pathExistsSync(localPath)) {
argSources.push(
FileConfigSource.create({
@@ -204,6 +222,16 @@ export class ConfigSources {
}),
);
}
if (process.env.BACKSTAGE_ENV && fs.pathExistsSync(envLocalPath)) {
argSources.push(
FileConfigSource.create({
watch: options.watch,
path: envLocalPath,
substitutionFunc: options.substitutionFunc,
}),
);
}
}
return this.merge(argSources);