in src/config-loader.ts [61:139]
export function validateConfigs(mergedFlags: FeatureFlag[]) {
const duplicationFeatureFlags = mergedFlags.reduce<{ [key: string]: number }>(
(acc, ff) => {
if (!ff.id) {
throw new ValidationError('Feature flag id is missing')
}
const { id } = ff
acc[id] = (acc[id] || 0) + 1
return acc
},
{}
)
const duplicates = mergedFlags.filter(
ff => duplicationFeatureFlags[ff.id] > 1
)
if (duplicates.length > 0) {
const duplicateIds = duplicates.map(ff => ff.id).join(', ')
const message = `Feature flag is defined multiple times which is not allowed: ${duplicateIds}`
core.error(message)
throw new ArgumentError(message)
}
core.info(`Found ${mergedFlags.length} feature flags in configuration files`)
// default_when_enabled is required
const defaultWhenEnabledErrors = mergedFlags.map(f => {
if (!f.allocation?.default_when_enabled) {
const message = `Feature flag ${f.id} is missing default_when_enabled`
core.error(message)
return {
message,
isValid: false
}
}
return { isValid: true }
})
if (defaultWhenEnabledErrors.some(e => !e.isValid)) {
throw new ValidationError(
'Default_when_enabled is required: ' +
defaultWhenEnabledErrors.map(e => e.message).join(', ')
)
}
const allocationErrors = mergedFlags.map(f => {
// allocation should only refer to existing variants
const variantNames = f.variants?.map(v => v.name) || []
const allocationVariants =
f.allocation?.percentile?.map(p => p.variant) || []
if (!!f.allocation?.default_when_enabled) {
allocationVariants.push(f.allocation.default_when_enabled)
}
if (!!f.allocation?.default_when_disabled) {
allocationVariants.push(f.allocation.default_when_disabled)
}
const invalidVariants = allocationVariants.filter(
v => !variantNames.includes(v)
)
if (invalidVariants.length > 0) {
const message = `Feature flag ${f.id} has allocation to non-existing variants: ${invalidVariants}`
core.error(message)
return {
message,
isValid: false
}
}
return { isValid: true }
})
if (allocationErrors.some(e => !e.isValid)) {
throw new ValidationError(
'Allocation error: ' + allocationErrors.map(e => e.message).join(', ')
)
}
}