private static void ApplyStepOverrides(PhasesTemplateReference reference, PhasesTemplate template) { // Select by phase name. var byPhaseNames = (reference.PhaseSelectors ?? new List <PhaseSelector>(0)) .Join(inner: (template.Phases ?? new List <IPhase>(0)).Cast <Phase>(), outerKeySelector: (PhaseSelector phaseSelector) => phaseSelector.Name, innerKeySelector: (Phase phase) => phase.Name, resultSelector: (PhaseSelector phaseSelector, Phase phase) => new { Selector = phaseSelector, Phase = phase }) .ToArray(); foreach (var byPhaseName in byPhaseNames) { // Select by phase name + job name. var byPhaseNamesAndJobNames = (byPhaseName.Selector.JobSelectors ?? new List <JobSelector>(0)) .Join(inner: (byPhaseName.Phase.Jobs ?? new List <IJob>(0)).Cast <Job>(), outerKeySelector: (JobSelector jobSelector) => jobSelector.Name, innerKeySelector: (Job job) => job.Name, resultSelector: (JobSelector jobSelector, Job job) => new { Selector = jobSelector, Job = job }) .ToArray(); foreach (var byPhaseNameAndJobName in byPhaseNamesAndJobNames) { // Apply overrides from phase + job selectors. ApplyStepOverrides(byPhaseNameAndJobName.Selector.StepOverrides, byPhaseNameAndJobName.Job.Steps); } } // Select by job name. var allJobs = (template.Phases ?? new List <IPhase>(0)) .Cast <Phase>() .SelectMany((Phase phase) => phase.Jobs ?? new List <IJob>(0)) .Concat(template.Jobs ?? new List <IJob>(0)) .Cast <Job>() .ToArray(); var byJobNames = (reference.JobSelectors ?? new List <JobSelector>(0)) .Join(inner: allJobs, outerKeySelector: (JobSelector jobSelector) => jobSelector.Name, innerKeySelector: (Job job) => job.Name, resultSelector: (JobSelector jobSelector, Job job) => new { Selector = jobSelector, Job = job }) .ToArray(); // Apply overrides from job selectors. foreach (var byJobName in byJobNames) { ApplyStepOverrides(byJobName.Selector.StepOverrides, byJobName.Job.Steps); } // Apply overrides from phase selectors. foreach (var byPhaseName in byPhaseNames) { foreach (Job job in byPhaseName.Phase.Jobs ?? new List <IJob>(0)) { ApplyStepOverrides(byPhaseName.Selector.StepOverrides, job.Steps); } } // Apply unqualified overrides. var allStepLists = allJobs .Select((Job job) => job.Steps ?? new List <IStep>(0)) .Concat(new[] { template.Steps ?? new List <IStep>(0) }) .ToArray(); foreach (List <IStep> stepList in allStepLists) { ApplyStepOverrides(reference.StepOverrides, stepList); } }
private void ResolveTemplates(List <IPhase> phases, String defaultRoot, CancellationToken cancellationToken, ref Int32 fileCount) { for (int i = 0; i < (phases?.Count ?? 0);) { if (phases[i] is PhasesTemplateReference) { // Load the template. var reference = phases[i] as PhasesTemplateReference; String templateFilePath = m_fileProvider.ResolvePath(defaultRoot: defaultRoot, path: reference.Name); PipelineFile <PhasesTemplate> templateFile = LoadFile <PhasesTemplate, PhasesTemplateConverter>(templateFilePath, reference.Parameters, cancellationToken, ref fileCount); PhasesTemplate template = templateFile.Object; // Resolve template references within the template. if (template.Jobs != null) { ResolveTemplates(template.Jobs, defaultRoot: templateFile.Directory, cancellationToken: cancellationToken, fileCount: ref fileCount); } else if (template.Steps != null) { ResolveTemplates(template.Steps, defaultRoot: templateFile.Directory, cancellationToken: cancellationToken, fileCount: ref fileCount); } // Merge the template. ApplyStepOverrides(reference, template); phases.RemoveAt(i); if (template.Phases != null) { phases.InsertRange(i, template.Phases); i += template.Phases.Count; } else if (template.Jobs != null) { var newPhase = new Phase { Jobs = template.Jobs }; phases.Insert(i, newPhase); i++; } else if (template.Steps != null) { var newJob = new Job { Steps = template.Steps }; var newPhase = new Phase { Jobs = new List <IJob>(new IJob[] { newJob }) }; phases.Insert(i, newPhase); i++; } } else { // Resolve nested template references. var phase = phases[i] as Phase; if (phase.Jobs != null) { ResolveTemplates(phase.Jobs, defaultRoot, cancellationToken, ref fileCount); } else if (phase.Variables != null) { ResolveTemplates(phase.Variables, defaultRoot, cancellationToken, ref fileCount); } else if (phase.Steps != null) { ResolveTemplates(phase.Steps, defaultRoot, cancellationToken, ref fileCount); } i++; } } }