From c8d8a1de053187649cf7c0a61422517e85520bc1 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 20 Dec 2024 12:08:32 +0100 Subject: [PATCH] fix: omit collecting backend-common package if backend-defaults is included Signed-off-by: blam --- .../config-loader/src/schema/collect.test.ts | 55 +++++++++++++++++ packages/config-loader/src/schema/collect.ts | 61 ++++++++++++------- .../config-loader/src/schema/compile.test.ts | 16 +++++ packages/config-loader/src/schema/types.ts | 4 ++ 4 files changed, 115 insertions(+), 21 deletions(-) diff --git a/packages/config-loader/src/schema/collect.test.ts b/packages/config-loader/src/schema/collect.test.ts index 8c6d1c6b90..1e5c3c2bc5 100644 --- a/packages/config-loader/src/schema/collect.test.ts +++ b/packages/config-loader/src/schema/collect.test.ts @@ -93,6 +93,61 @@ describe('collectConfigSchemas', () => { ]); }); + it('should not include schemas for backend-common if theres a backend-defaults package', async () => { + mockDir.setContent({ + root: { + 'package.json': JSON.stringify({ + name: 'root', + configSchema: mockSchema, + dependencies: {}, + }), + node_modules: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + dependencies: { + b: '0.0.0', + }, + }), + }, + b: { + 'package.json': JSON.stringify({ + name: 'a', + dependencies: { + b: '0.0.0', + }, + }), + }, + '@backstage': { + 'backend-common': { + 'package.json': JSON.stringify({ + name: '@backstage/backend-common', + configSchema: { ...mockSchema, title: 'backend-common' }, + }), + }, + 'backend-defaults': { + 'package.json': JSON.stringify({ + name: '@backstage/backend-defaults', + configSchema: { ...mockSchema, title: 'backend-defaults' }, + }), + }, + }, + }, + }, + }); + + process.chdir(mockDir.path); + + await expect( + collectConfigSchemas([], [path.join('root', 'package.json')]), + ).resolves.toEqual([ + { + path: path.join('root', 'package.json'), + value: mockSchema, + }, + ]); + }); + it('should find schema in transitive dependencies and explicit path', async () => { mockDir.setContent({ root: { diff --git a/packages/config-loader/src/schema/collect.ts b/packages/config-loader/src/schema/collect.ts index 7120c12d90..bf0fb8dd05 100644 --- a/packages/config-loader/src/schema/collect.ts +++ b/packages/config-loader/src/schema/collect.ts @@ -45,7 +45,7 @@ export async function collectConfigSchemas( packagePaths: string[], ): Promise { const schemas = new Array(); - const tsSchemaPaths = new Array(); + const tsSchemaPaths = new Array<{ packageName: string; path: string }>(); const visitedPackageVersions = new Map>(); // pkgName: [versions...] const currentDir = await fs.realpath(process.cwd()); @@ -115,22 +115,25 @@ export async function collectConfigSchemas( ); } if (isDts) { - tsSchemaPaths.push( - relativePath( + tsSchemaPaths.push({ + path: relativePath( currentDir, resolvePath(dirname(pkgPath), pkg.configSchema), ), - ); + packageName: pkg.name, + }); } else { const path = resolvePath(dirname(pkgPath), pkg.configSchema); const value = await fs.readJson(path); schemas.push({ + packageName: pkg.name, value, path: relativePath(currentDir, path), }); } } else { schemas.push({ + packageName: pkg.name, value: pkg.configSchema, path: relativePath(currentDir, pkgPath), }); @@ -151,14 +154,27 @@ export async function collectConfigSchemas( const tsSchemas = await compileTsSchemas(tsSchemaPaths); - return schemas.concat(tsSchemas); + return schemas + .concat(tsSchemas) + .filter( + ({ packageName }, _, original) => + true || + !( + packageName === '@backstage/backend-common' && + original.some( + ({ packageName: p }) => p === '@backstage/backend-defaults', + ) + ), + ); } // This handles the support of TypeScript .d.ts config schema declarations. // We collect all typescript schema definition and compile them all in one go. // This is much faster than compiling them separately. -async function compileTsSchemas(paths: string[]) { - if (paths.length === 0) { +async function compileTsSchemas( + entries: { path: string; packageName: string }[], +) { + if (entries.length === 0) { return []; } @@ -168,20 +184,23 @@ async function compileTsSchemas(paths: string[]) { 'typescript-json-schema' ); - const program = getProgramFromFiles(paths, { - incremental: false, - isolatedModules: true, - lib: ['ES5'], // Skipping most libs speeds processing up a lot, we just need the primitive types anyway - noEmit: true, - noResolve: true, - skipLibCheck: true, // Skipping lib checks speeds things up - skipDefaultLibCheck: true, - strict: true, - typeRoots: [], // Do not include any additional types - types: [], - }); + const program = getProgramFromFiles( + entries.map(({ path }) => path), + { + incremental: false, + isolatedModules: true, + lib: ['ES5'], // Skipping most libs speeds processing up a lot, we just need the primitive types anyway + noEmit: true, + noResolve: true, + skipLibCheck: true, // Skipping lib checks speeds things up + skipDefaultLibCheck: true, + strict: true, + typeRoots: [], // Do not include any additional types + types: [], + }, + ); - const tsSchemas = paths.map(path => { + const tsSchemas = entries.map(({ path, packageName }) => { let value; try { const generator = buildGenerator( @@ -228,7 +247,7 @@ async function compileTsSchemas(paths: string[]) { if (!value) { throw new Error(`Invalid schema in ${path}, missing Config export`); } - return { path, value }; + return { path, value, packageName }; }); return tsSchemas; diff --git a/packages/config-loader/src/schema/compile.test.ts b/packages/config-loader/src/schema/compile.test.ts index ff0a9543aa..b39d2537d1 100644 --- a/packages/config-loader/src/schema/compile.test.ts +++ b/packages/config-loader/src/schema/compile.test.ts @@ -21,10 +21,12 @@ describe('compileConfigSchemas', () => { const validate = compileConfigSchemas([ { path: 'a', + packageName: 'a', value: { type: 'object', properties: { a: { type: 'string' } } }, }, { path: 'b', + packageName: 'b', value: { type: 'object', properties: { b: { type: 'number' } } }, }, ]); @@ -64,6 +66,7 @@ describe('compileConfigSchemas', () => { const validate = compileConfigSchemas([ { path: 'a1', + packageName: 'a1', value: { type: 'object', properties: { @@ -80,6 +83,7 @@ describe('compileConfigSchemas', () => { }, { path: 'a2', + packageName: 'a2', value: { type: 'object', properties: { @@ -126,6 +130,7 @@ describe('compileConfigSchemas', () => { compileConfigSchemas([ { path: 'a1', + packageName: 'a1', value: { type: 'object', properties: { a: { type: 'string', visibility: 'frontend' } }, @@ -133,6 +138,7 @@ describe('compileConfigSchemas', () => { }, { path: 'a2', + packageName: 'a2', value: { type: 'object', properties: { a: { type: 'string', visibility: 'secret' } }, @@ -148,6 +154,7 @@ describe('compileConfigSchemas', () => { const validate = compileConfigSchemas([ { path: 'a1', + packageName: 'a1', value: { type: 'object', properties: { @@ -179,6 +186,7 @@ describe('compileConfigSchemas', () => { const validate = compileConfigSchemas([ { path: 'a1', + packageName: 'a1', value: { type: 'object', properties: { @@ -242,6 +250,7 @@ describe('deepVisibility', () => { const validate = compileConfigSchemas([ { path: 'a1', + packageName: 'a1', value: { type: 'object', properties: { @@ -257,6 +266,7 @@ describe('deepVisibility', () => { }, { path: 'a2', + packageName: 'a2', value: { type: 'object', deepVisibility: 'secret', @@ -305,6 +315,7 @@ describe('deepVisibility', () => { compileConfigSchemas([ { path: 'a1', + packageName: 'a1', value: { type: 'object', properties: { @@ -320,6 +331,7 @@ describe('deepVisibility', () => { }, { path: 'a2', + packageName: 'a2', value: { type: 'object', deepVisibility: 'secret', @@ -346,6 +358,7 @@ describe('deepVisibility', () => { compileConfigSchemas([ { path: 'a2', + packageName: 'a2', value: { type: 'object', deepVisibility: 'secret', @@ -376,6 +389,7 @@ describe('deepVisibility', () => { compileConfigSchemas([ { path: 'a2', + packageName: 'a2', value: { type: 'object', properties: { @@ -398,6 +412,7 @@ describe('deepVisibility', () => { compileConfigSchemas([ { path: 'a1', + packageName: 'a1', value: { type: 'object', properties: { @@ -418,6 +433,7 @@ describe('deepVisibility', () => { }, { path: 'a2', + packageName: 'a2', value: { type: 'object', deepVisibility: 'secret', diff --git a/packages/config-loader/src/schema/types.ts b/packages/config-loader/src/schema/types.ts index 8f679c93fc..4ba65245da 100644 --- a/packages/config-loader/src/schema/types.ts +++ b/packages/config-loader/src/schema/types.ts @@ -29,6 +29,10 @@ export type ConfigSchemaPackageEntry = { * The relative path that the configuration schema was discovered at. */ path: string; + /** + * The package name for the package this belongs to + */ + packageName: string; }; /**