Ignore stale extension config errors based on flag

Signed-off-by: Musaab Elfaqih <musaabe@spotify.com>
This commit is contained in:
Musaab Elfaqih
2025-04-24 17:22:08 +02:00
parent 19f2aa04a8
commit 679207e918
3 changed files with 9 additions and 30 deletions
@@ -16,7 +16,6 @@
import { Config } from '@backstage/config';
import { JsonValue } from '@backstage/types';
import { FrontendFeature } from '../wiring';
export interface ExtensionParameters {
id: string;
@@ -27,34 +26,12 @@ export interface ExtensionParameters {
const knownExtensionParameters = ['attachTo', 'disabled', 'config'];
/**
* Returns a filtered list of extensions based on what is discovered in the
* provided features.
*/
export const filterExtensionsByFeatures = (
extensions: ExtensionParameters[],
features: FrontendFeature[],
): ExtensionParameters[] => {
// Get a list of all extension IDs discovered in the provided features.
const discoveredExtensionIds = features.flatMap(feature =>
('extensions' in feature && Array.isArray(feature.extensions)
? feature.extensions
: []
).map((extension: { id: string }) => extension.id),
);
return extensions.filter(extension =>
discoveredExtensionIds.includes(extension.id),
);
};
// Since we'll never merge arrays in config the config reader context
// isn't too much of a help. Fall back to manual config reading logic
// as the Config interface makes it quite hard for us otherwise.
/** @internal */
export function readAppExtensionsConfig(
rootConfig: Config,
features: FrontendFeature[] = [],
): ExtensionParameters[] {
const arr = rootConfig.getOptional('app.extensions');
if (!Array.isArray(arr)) {
@@ -66,11 +43,8 @@ export function readAppExtensionsConfig(
return [];
}
return filterExtensionsByFeatures(
arr.map((arrayEntry, arrayIndex) =>
expandShorthandExtensionParameters(arrayEntry, arrayIndex),
),
features,
return arr.map((arrayEntry, arrayIndex) =>
expandShorthandExtensionParameters(arrayEntry, arrayIndex),
);
}
@@ -33,12 +33,14 @@ export function resolveAppNodeSpecs(options: {
builtinExtensions?: Extension<any, any>[];
parameters?: Array<ExtensionParameters>;
forbidden?: Set<string>;
ignoreStaleExtensionConfig?: boolean;
}): AppNodeSpec[] {
const {
builtinExtensions = [],
parameters = [],
forbidden = new Set(),
features = [],
ignoreStaleExtensionConfig = false,
} = options;
const plugins = features.filter(OpaqueFrontendPlugin.isType);
@@ -202,7 +204,7 @@ export function resolveAppNodeSpecs(options: {
existing.params.disabled = Boolean(overrideParam.disabled);
}
order.set(extensionId, existing);
} else {
} else if (!ignoreStaleExtensionConfig) {
throw new Error(`Extension ${extensionId} does not exist`);
}
}
@@ -219,8 +219,11 @@ export function createSpecializedApp(options?: {
builtinExtensions: [
resolveExtensionDefinition(Root, { namespace: 'root' }),
],
parameters: readAppExtensionsConfig(config, features),
parameters: readAppExtensionsConfig(config),
forbidden: new Set(['root']),
ignoreStaleExtensionConfig: config.getOptionalBoolean(
'app.ignoreStaleExtensionConfig',
),
}),
);