diff --git a/.changeset/real-ants-perform.md b/.changeset/real-ants-perform.md new file mode 100644 index 0000000000..8c06e78dc6 --- /dev/null +++ b/.changeset/real-ants-perform.md @@ -0,0 +1,5 @@ +--- +'@backstage/config': patch +--- + +Only warn once per key when trying to read visibility-filtered values diff --git a/packages/config/src/reader.test.ts b/packages/config/src/reader.test.ts index 2f846fe159..7f3513abf6 100644 --- a/packages/config/src/reader.test.ts +++ b/packages/config/src/reader.test.ts @@ -195,7 +195,7 @@ describe('ConfigReader', () => { { data: DATA, context: CTX, - filteredKeys: ['a', 'b[0]'], + filteredKeys: ['a', 'a2', 'b[0]'], }, ]); @@ -204,13 +204,13 @@ describe('ConfigReader', () => { "Failed to read configuration value at 'a' as it is not visible. See https://backstage.io/docs/conf/defining#visibility for instructions on how to make it visible.", ], }); - expect(withLogCollector(() => config.getOptionalString('a'))).toMatchObject( - { - warn: [ - "Failed to read configuration value at 'a' as it is not visible. See https://backstage.io/docs/conf/defining#visibility for instructions on how to make it visible.", - ], - }, - ); + expect( + withLogCollector(() => config.getOptionalString('a2')), + ).toMatchObject({ + warn: [ + "Failed to read configuration value at 'a2' as it is not visible. See https://backstage.io/docs/conf/defining#visibility for instructions on how to make it visible.", + ], + }); expect( withLogCollector(() => config.getOptionalConfigArray('b')), ).toMatchObject({ @@ -222,6 +222,30 @@ describe('ConfigReader', () => { (process.env as any).NODE_ENV = oldEnv; }); + it('only warns once when accessing filtered keys in development mode', () => { + const oldEnv = process.env.NODE_ENV; + (process.env as any).NODE_ENV = 'development'; + + const config = ConfigReader.fromConfigs([ + { + data: DATA, + context: CTX, + filteredKeys: ['a'], + }, + ]); + + expect(withLogCollector(() => config.getOptional('a'))).toMatchObject({ + warn: [ + "Failed to read configuration value at 'a' as it is not visible. See https://backstage.io/docs/conf/defining#visibility for instructions on how to make it visible.", + ], + }); + expect(withLogCollector(() => config.getOptional('a'))).toMatchObject({ + warn: [], + }); + + (process.env as any).NODE_ENV = oldEnv; + }); + it('should not warn when accessing filtered keys outside of development mode', () => { const config = ConfigReader.fromConfigs([ { diff --git a/packages/config/src/reader.ts b/packages/config/src/reader.ts index d93706c12e..c6f69e5b29 100644 --- a/packages/config/src/reader.ts +++ b/packages/config/src/reader.ts @@ -63,6 +63,7 @@ export class ConfigReader implements Config { * the frontend in development mode. */ private filteredKeys?: string[]; + private notifiedFilteredKeys = new Set(); static fromConfigs(configs: AppConfig[]): ConfigReader { if (configs.length === 0) { @@ -118,7 +119,11 @@ export class ConfigReader implements Config { if (process.env.NODE_ENV === 'development') { if (fallbackValue === undefined && key) { const fullKey = this.fullKey(key); - if (this.filteredKeys?.includes(fullKey)) { + if ( + this.filteredKeys?.includes(fullKey) && + !this.notifiedFilteredKeys.has(fullKey) + ) { + this.notifiedFilteredKeys.add(fullKey); // eslint-disable-next-line no-console console.warn( `Failed to read configuration value at '${fullKey}' as it is not visible. ` + @@ -190,7 +195,11 @@ export class ConfigReader implements Config { if (!configs) { if (process.env.NODE_ENV === 'development') { const fullKey = this.fullKey(key); - if (this.filteredKeys?.some(k => k.startsWith(fullKey))) { + if ( + this.filteredKeys?.some(k => k.startsWith(fullKey)) && + !this.notifiedFilteredKeys.has(key) + ) { + this.notifiedFilteredKeys.add(key); // eslint-disable-next-line no-console console.warn( `Failed to read configuration array at '${key}' as it does not have any visible elements. ` + @@ -310,7 +319,11 @@ export class ConfigReader implements Config { if (value === undefined) { if (process.env.NODE_ENV === 'development') { const fullKey = this.fullKey(key); - if (this.filteredKeys?.includes(fullKey)) { + if ( + this.filteredKeys?.includes(fullKey) && + !this.notifiedFilteredKeys.has(fullKey) + ) { + this.notifiedFilteredKeys.add(fullKey); // eslint-disable-next-line no-console console.warn( `Failed to read configuration value at '${fullKey}' as it is not visible. ` +