85 lines
3.1 KiB
TypeScript
85 lines
3.1 KiB
TypeScript
/**
|
|
* Quality gate override application logic
|
|
*
|
|
* Resolves quality gates from config overrides with 3-layer priority:
|
|
* 1. Project .takt/config.yaml piece_overrides
|
|
* 2. Global ~/.takt/config.yaml piece_overrides
|
|
* 3. Piece YAML quality_gates
|
|
*
|
|
* Merge strategy: Additive (config gates + YAML gates)
|
|
*/
|
|
|
|
import type { PieceOverrides } from '../../../core/models/persisted-global-config.js';
|
|
|
|
/**
|
|
* Apply quality gate overrides to a movement.
|
|
*
|
|
* Merge order (gates are added in this sequence):
|
|
* 1. Global override in global config (filtered by edit flag if qualityGatesEditOnly=true)
|
|
* 2. Movement-specific override in global config
|
|
* 3. Global override in project config (filtered by edit flag if qualityGatesEditOnly=true)
|
|
* 4. Movement-specific override in project config
|
|
* 5. Piece YAML quality_gates
|
|
*
|
|
* Merge strategy: Additive merge (all gates are combined, no overriding)
|
|
*
|
|
* @param movementName - Name of the movement
|
|
* @param yamlGates - Quality gates from piece YAML
|
|
* @param editFlag - Whether the movement has edit: true
|
|
* @param projectOverrides - Project-level piece_overrides (from .takt/config.yaml)
|
|
* @param globalOverrides - Global-level piece_overrides (from ~/.takt/config.yaml)
|
|
* @returns Merged quality gates array
|
|
*/
|
|
export function applyQualityGateOverrides(
|
|
movementName: string,
|
|
yamlGates: string[] | undefined,
|
|
editFlag: boolean | undefined,
|
|
projectOverrides: PieceOverrides | undefined,
|
|
globalOverrides: PieceOverrides | undefined,
|
|
): string[] | undefined {
|
|
// Track whether yamlGates was explicitly defined (even if empty)
|
|
const hasYamlGates = yamlGates !== undefined;
|
|
const gates: string[] = [];
|
|
|
|
// Collect global gates from global config
|
|
const globalGlobalGates = globalOverrides?.qualityGates;
|
|
const globalEditOnly = globalOverrides?.qualityGatesEditOnly ?? false;
|
|
if (globalGlobalGates && (!globalEditOnly || editFlag === true)) {
|
|
gates.push(...globalGlobalGates);
|
|
}
|
|
|
|
// Collect movement-specific gates from global config
|
|
const globalMovementGates = globalOverrides?.movements?.[movementName]?.qualityGates;
|
|
if (globalMovementGates) {
|
|
gates.push(...globalMovementGates);
|
|
}
|
|
|
|
// Collect global gates from project config
|
|
const projectGlobalGates = projectOverrides?.qualityGates;
|
|
const projectEditOnly = projectOverrides?.qualityGatesEditOnly ?? false;
|
|
if (projectGlobalGates && (!projectEditOnly || editFlag === true)) {
|
|
gates.push(...projectGlobalGates);
|
|
}
|
|
|
|
// Collect movement-specific gates from project config
|
|
const projectMovementGates = projectOverrides?.movements?.[movementName]?.qualityGates;
|
|
if (projectMovementGates) {
|
|
gates.push(...projectMovementGates);
|
|
}
|
|
|
|
// Add YAML gates (lowest priority)
|
|
if (yamlGates) {
|
|
gates.push(...yamlGates);
|
|
}
|
|
|
|
// Deduplicate gates (same text = same gate)
|
|
const uniqueGates = Array.from(new Set(gates));
|
|
|
|
// Return undefined only if no gates were defined anywhere
|
|
// If yamlGates was explicitly set (even if empty), return the merged array
|
|
if (uniqueGates.length > 0) {
|
|
return uniqueGates;
|
|
}
|
|
return hasYamlGates ? [] : undefined;
|
|
}
|