Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,8 @@ export function defaultValues(
baseDefaults.jobConfigs.advisor.advisors,
config: mergePluginConfigs(
ortRun?.jobConfigs?.advisor?.config,
advisorPluginDefaultValues
advisorPluginDefaultValues,
advisorPlugins
),
keepAliveWorker:
(ortRun.jobConfigs.advisor?.keepAliveWorker && isSuperuser) ||
Expand All @@ -265,7 +266,8 @@ export function defaultValues(
),
config: mergePluginConfigs(
ortRun.jobConfigs.scanner?.config,
scannerPluginDefaultValues
scannerPluginDefaultValues,
scannerPlugins
),
},
evaluator: {
Expand Down Expand Up @@ -388,4 +390,163 @@ if (import.meta.vitest) {
},
});
});

it('applies fixed plugin option precedence for advisor and scanner reruns', () => {
const ortRun = {
revision: 'main',
path: '',
jobConfigs: {
advisor: {
advisors: ['OSV'],
config: {
OSV: {
options: {
url: 'https://rerun.example/advisor',
fixedNoDefault: 'legacy-advisor-fixed',
token: 'legacy-advisor-token',
},
secrets: {
fixedSecret: 'legacy-advisor-secret',
},
},
},
},
scanner: {
scanners: ['SCANOSS'],
config: {
SCANOSS: {
options: {
url: 'https://rerun.example/scanner',
fixedNoDefault: 'legacy-scanner-fixed',
token: 'legacy-scanner-token',
},
secrets: {
fixedSecret: 'legacy-scanner-secret',
},
},
},
},
},
labels: {},
} as unknown as OrtRun;

const advisorPlugins: PreconfiguredPluginDescriptor[] = [
{
id: 'OSV',
type: 'ADVISOR',
displayName: 'OSV',
summary: 'OSV advisor.',
description: 'OSV advisor.',
options: [
{
name: 'url',
description: 'Base URL.',
type: 'STRING',
defaultValue: 'https://default.example/advisor',
isFixed: true,
isNullable: false,
isRequired: true,
},
{
name: 'fixedNoDefault',
description: 'Fixed without default.',
type: 'STRING',
isFixed: true,
isNullable: false,
isRequired: false,
},
{
name: 'fixedSecret',
description: 'Fixed secret option.',
type: 'SECRET',
isFixed: true,
isNullable: false,
isRequired: false,
},
{
name: 'token',
description: 'Editable token.',
type: 'STRING',
defaultValue: 'default-token',
isFixed: false,
isNullable: false,
isRequired: false,
},
],
},
];

const scannerPlugins: PreconfiguredPluginDescriptor[] = [
{
id: 'SCANOSS',
type: 'SCANNER',
displayName: 'SCANOSS',
summary: 'SCANOSS scanner.',
description: 'SCANOSS scanner.',
options: [
{
name: 'url',
description: 'Base URL.',
type: 'STRING',
defaultValue: 'https://default.example/scanner',
isFixed: true,
isNullable: false,
isRequired: true,
},
{
name: 'fixedNoDefault',
description: 'Fixed without default.',
type: 'STRING',
isFixed: true,
isNullable: false,
isRequired: false,
},
{
name: 'fixedSecret',
description: 'Fixed secret option.',
type: 'SECRET',
isFixed: true,
isNullable: false,
isRequired: false,
},
{
name: 'token',
description: 'Editable token.',
type: 'STRING',
defaultValue: 'default-token',
isFixed: false,
isNullable: false,
isRequired: false,
},
],
},
];

const defaults = defaultValues(
ortRun,
advisorPlugins,
scannerPlugins,
false
);

expect(defaults.jobConfigs.advisor.config).toEqual({
OSV: {
options: {
url: 'https://default.example/advisor',
token: 'legacy-advisor-token',
},
secrets: {},
},
});

expect(defaults.jobConfigs.scanner.config).toEqual({
SCANOSS: {
options: {
url: 'https://default.example/scanner',
token: 'legacy-scanner-token',
},
secrets: {},
},
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,20 +134,24 @@ export const createPluginConfigSchema = (
};

/**
* Merge the plugin configs from the last run with the default plugin configs. The configs from the last run take
* precedence.
* Merge the plugin configs from the last run with the default plugin configs.
* For fixed options, values configured via plugin descriptors take precedence.
* For non-fixed options, values from the last run take precedence.
*/
export function mergePluginConfigs(
lastRunConfig: { [p: string]: PluginConfig } | null | undefined,
defaultConfig: Record<string, PluginConfig>
defaultConfig: Record<string, PluginConfig>,
plugins: PreconfiguredPluginDescriptor[]
): Record<string, PluginConfig> {
const merged: Record<string, PluginConfig> = {};
const pluginById = new Map(plugins.map((plugin) => [plugin.id, plugin]));

for (const pluginId of Object.keys(defaultConfig)) {
const defaultPlugin = defaultConfig[pluginId];
const ortPlugin = lastRunConfig?.[pluginId];
const pluginDescriptor = pluginById.get(pluginId);

merged[pluginId] = {
const mergedPlugin: PluginConfig = {
options: {
...(defaultPlugin?.options ?? {}),
...(ortPlugin?.options ?? {}),
Expand All @@ -157,6 +161,22 @@ export function mergePluginConfigs(
...(ortPlugin?.secrets ?? {}),
},
};

for (const option of pluginDescriptor?.options ?? []) {
if (!option.isFixed) continue;

const section = option.type === 'SECRET' ? 'secrets' : 'options';
const defaultSection = defaultPlugin?.[section] ?? {};
const defaultValue = defaultSection[option.name];

if (defaultValue !== undefined) {
mergedPlugin[section][option.name] = defaultValue;
} else {
delete mergedPlugin[section][option.name];
}
}

merged[pluginId] = mergedPlugin;
}

if (lastRunConfig) {
Expand Down Expand Up @@ -397,4 +417,77 @@ if (import.meta.vitest) {
},
});
});

it('mergePluginConfigs enforces fixed option precedence and clears missing fixed defaults', () => {
const plugins: PreconfiguredPluginDescriptor[] = [
{
id: 'SCANOSS',
type: 'SCANNER',
displayName: 'SCANOSS',
summary: 'A scanner plugin.',
description: 'A scanner plugin.',
options: [
{
name: 'url',
description: 'The API URL.',
type: 'STRING',
defaultValue: 'https://scanner.example/api',
isFixed: true,
isNullable: false,
isRequired: false,
},
{
name: 'fixedNoDefault',
description: 'A fixed option without default.',
type: 'STRING',
isFixed: true,
isNullable: false,
isRequired: false,
},
{
name: 'fixedSecret',
description: 'A fixed secret option.',
type: 'SECRET',
isFixed: true,
isNullable: false,
isRequired: false,
},
{
name: 'timeout',
description: 'Timeout in seconds.',
type: 'INTEGER',
defaultValue: '30',
isFixed: false,
isNullable: false,
isRequired: false,
},
],
},
];

const merged = mergePluginConfigs(
{
SCANOSS: {
options: {
url: 'https://old.example/api',
fixedNoDefault: 'legacy-value',
timeout: '90',
},
secrets: {
fixedSecret: 'legacy-secret',
},
},
},
getPluginDefaultValues(plugins),
plugins
);

expect(merged.SCANOSS).toEqual({
options: {
url: 'https://scanner.example/api',
timeout: '90',
},
secrets: {},
});
});
}
Loading