@@ -4,7 +4,7 @@ use anyhow::{Context, Result};
44use std:: collections:: { HashMap , HashSet } ;
55use std:: path:: Path ;
66
7- use super :: types:: { FrontMatter , PipelineParameter , Repository , TriggerConfig } ;
7+ use super :: types:: { FrontMatter , OnConfig , PipelineParameter , Repository } ;
88use super :: extensions:: { CompilerExtension , Extension , McpgServerConfig , McpgGatewayConfig , McpgConfig , CompileContext } ;
99use crate :: compile:: types:: McpConfig ;
1010use crate :: fuzzy_schedule;
@@ -146,14 +146,14 @@ pub fn validate_front_matter_identity(front_matter: &FrontMatter) -> Result<()>
146146 }
147147
148148 // Validate trigger.pipeline fields for newlines and ADO expressions
149- if let Some ( trigger_config) = & front_matter. triggers {
149+ if let Some ( trigger_config) = & front_matter. on_config {
150150 if let Some ( pipeline) = & trigger_config. pipeline {
151- validate:: reject_pipeline_injection ( & pipeline. name , "triggers .pipeline.name" ) ?;
151+ validate:: reject_pipeline_injection ( & pipeline. name , "on .pipeline.name" ) ?;
152152 if let Some ( project) = & pipeline. project {
153- validate:: reject_pipeline_injection ( project, "triggers .pipeline.project" ) ?;
153+ validate:: reject_pipeline_injection ( project, "on .pipeline.project" ) ?;
154154 }
155155 for branch in & pipeline. branches {
156- validate:: reject_pipeline_injection ( branch, & format ! ( "triggers .pipeline.branches entry {:?}" , branch) ) ?;
156+ validate:: reject_pipeline_injection ( branch, & format ! ( "on .pipeline.branches entry {:?}" , branch) ) ?;
157157 }
158158 }
159159 }
@@ -202,20 +202,20 @@ pub fn generate_schedule(name: &str, config: &super::types::ScheduleConfig) -> R
202202/// When `triggers.pr` is explicitly configured, PR triggers stay enabled regardless
203203/// of schedule or pipeline triggers (overrides suppression). Native ADO branch/path
204204/// filters are emitted if configured.
205- pub fn generate_pr_trigger ( triggers : & Option < TriggerConfig > , has_schedule : bool ) -> String {
206- let has_pipeline_trigger = triggers
205+ pub fn generate_pr_trigger ( on_config : & Option < OnConfig > , has_schedule : bool ) -> String {
206+ let has_pipeline_trigger = on_config
207207 . as_ref ( )
208208 . and_then ( |t| t. pipeline . as_ref ( ) )
209209 . is_some ( ) ;
210210
211- let has_pr_trigger = triggers
211+ let has_pr_trigger = on_config
212212 . as_ref ( )
213213 . and_then ( |t| t. pr . as_ref ( ) )
214214 . is_some ( ) ;
215215
216216 // Explicit triggers.pr overrides schedule/pipeline suppression
217217 if has_pr_trigger {
218- return super :: pr_filters:: generate_native_pr_trigger ( triggers . as_ref ( ) . unwrap ( ) . pr . as_ref ( ) . unwrap ( ) ) ;
218+ return super :: pr_filters:: generate_native_pr_trigger ( on_config . as_ref ( ) . unwrap ( ) . pr . as_ref ( ) . unwrap ( ) ) ;
219219 }
220220
221221 match ( has_pipeline_trigger, has_schedule) {
@@ -227,8 +227,8 @@ pub fn generate_pr_trigger(triggers: &Option<TriggerConfig>, has_schedule: bool)
227227}
228228
229229/// Generate CI trigger configuration
230- pub fn generate_ci_trigger ( triggers : & Option < TriggerConfig > , has_schedule : bool ) -> String {
231- let has_pipeline_trigger = triggers
230+ pub fn generate_ci_trigger ( on_config : & Option < OnConfig > , has_schedule : bool ) -> String {
231+ let has_pipeline_trigger = on_config
232232 . as_ref ( )
233233 . and_then ( |t| t. pipeline . as_ref ( ) )
234234 . is_some ( ) ;
@@ -241,8 +241,8 @@ pub fn generate_ci_trigger(triggers: &Option<TriggerConfig>, has_schedule: bool)
241241}
242242
243243/// Generate pipeline resource YAML for pipeline completion triggers
244- pub fn generate_pipeline_resources ( triggers : & Option < TriggerConfig > ) -> Result < String > {
245- let Some ( trigger_config) = triggers else {
244+ pub fn generate_pipeline_resources ( on_config : & Option < OnConfig > ) -> Result < String > {
245+ let Some ( trigger_config) = on_config else {
246246 return Ok ( String :: new ( ) ) ;
247247 } ;
248248
@@ -1894,7 +1894,7 @@ pub async fn compile_shared(
18941894 validate_front_matter_identity ( front_matter) ?;
18951895
18961896 // 2. Generate schedule
1897- let schedule = match & front_matter. schedule {
1897+ let schedule = match front_matter. schedule ( ) {
18981898 Some ( s) => generate_schedule ( & front_matter. name , s)
18991899 . with_context ( || format ! ( "Failed to parse schedule '{}'" , s. expression( ) ) ) ?,
19001900 None => String :: new ( ) ,
@@ -1935,10 +1935,10 @@ pub async fn compile_shared(
19351935 ) ?;
19361936 let working_directory = generate_working_directory ( & effective_workspace) ;
19371937 let trigger_repo_directory = generate_trigger_repo_directory ( & front_matter. checkout ) ;
1938- let pipeline_resources = generate_pipeline_resources ( & front_matter. triggers ) ?;
1939- let has_schedule = front_matter. schedule . is_some ( ) ;
1940- let pr_trigger = generate_pr_trigger ( & front_matter. triggers , has_schedule) ;
1941- let ci_trigger = generate_ci_trigger ( & front_matter. triggers , has_schedule) ;
1938+ let pipeline_resources = generate_pipeline_resources ( & front_matter. on_config ) ?;
1939+ let has_schedule = front_matter. has_schedule ( ) ;
1940+ let pr_trigger = generate_pr_trigger ( & front_matter. on_config , has_schedule) ;
1941+ let ci_trigger = generate_ci_trigger ( & front_matter. on_config , has_schedule) ;
19421942
19431943 // 6. Generate source path and pipeline path
19441944 let source_path = generate_source_path ( input_path) ;
@@ -1952,11 +1952,7 @@ pub async fn compile_shared(
19521952 . unwrap_or_else ( || DEFAULT_POOL . to_string ( ) ) ;
19531953
19541954 // 8. Setup/teardown jobs, parameters, prepare/finalize steps
1955- let pr_filters = front_matter
1956- . triggers
1957- . as_ref ( )
1958- . and_then ( |t| t. pr . as_ref ( ) )
1959- . and_then ( |pr| pr. filters . as_ref ( ) ) ;
1955+ let pr_filters = front_matter. pr_filters ( ) ;
19601956 let has_pr_filters = pr_filters. is_some ( ) ;
19611957 let setup_job = generate_setup_job ( & front_matter. setup , & pool, pr_filters) ;
19621958 let teardown_job = generate_teardown_job ( & front_matter. teardown , & pool) ;
@@ -2624,13 +2620,15 @@ mod tests {
26242620
26252621 #[ test]
26262622 fn test_generate_pr_trigger_pipeline_only ( ) {
2627- let triggers = Some ( crate :: compile:: types:: TriggerConfig {
2623+ let triggers = Some ( crate :: compile:: types:: OnConfig {
26282624 pipeline : Some ( crate :: compile:: types:: PipelineTrigger {
26292625 name : "Build" . into ( ) ,
26302626 project : None ,
26312627 branches : vec ! [ ] ,
2628+ filters : None ,
26322629 } ) ,
26332630 pr : None ,
2631+ schedule : None ,
26342632 } ) ;
26352633 let result = generate_pr_trigger ( & triggers, false ) ;
26362634 assert ! ( result. contains( "pr: none" ) ) ;
@@ -2639,13 +2637,15 @@ mod tests {
26392637
26402638 #[ test]
26412639 fn test_generate_pr_trigger_both_pipeline_and_schedule ( ) {
2642- let triggers = Some ( crate :: compile:: types:: TriggerConfig {
2640+ let triggers = Some ( crate :: compile:: types:: OnConfig {
26432641 pipeline : Some ( crate :: compile:: types:: PipelineTrigger {
26442642 name : "Build" . into ( ) ,
26452643 project : None ,
26462644 branches : vec ! [ ] ,
2645+ filters : None ,
26472646 } ) ,
26482647 pr : None ,
2648+ schedule : None ,
26492649 } ) ;
26502650 let result = generate_pr_trigger ( & triggers, true ) ;
26512651 assert ! ( result. contains( "pr: none" ) ) ;
@@ -2672,27 +2672,31 @@ mod tests {
26722672
26732673 #[ test]
26742674 fn test_generate_ci_trigger_pipeline_only ( ) {
2675- let triggers = Some ( crate :: compile:: types:: TriggerConfig {
2675+ let triggers = Some ( crate :: compile:: types:: OnConfig {
26762676 pipeline : Some ( crate :: compile:: types:: PipelineTrigger {
26772677 name : "Build" . into ( ) ,
26782678 project : None ,
26792679 branches : vec ! [ ] ,
2680+ filters : None ,
26802681 } ) ,
26812682 pr : None ,
2683+ schedule : None ,
26822684 } ) ;
26832685 let result = generate_ci_trigger ( & triggers, false ) ;
26842686 assert_eq ! ( result, "trigger: none" ) ;
26852687 }
26862688
26872689 #[ test]
26882690 fn test_generate_ci_trigger_both_pipeline_and_schedule ( ) {
2689- let triggers = Some ( crate :: compile:: types:: TriggerConfig {
2691+ let triggers = Some ( crate :: compile:: types:: OnConfig {
26902692 pipeline : Some ( crate :: compile:: types:: PipelineTrigger {
26912693 name : "Build" . into ( ) ,
26922694 project : None ,
26932695 branches : vec ! [ ] ,
2696+ filters : None ,
26942697 } ) ,
26952698 pr : None ,
2699+ schedule : None ,
26962700 } ) ;
26972701 let result = generate_ci_trigger ( & triggers, true ) ;
26982702 assert_eq ! ( result, "trigger: none" ) ;
@@ -2708,20 +2712,22 @@ mod tests {
27082712
27092713 #[ test]
27102714 fn test_generate_pipeline_resources_empty_trigger_config ( ) {
2711- let triggers = Some ( crate :: compile:: types:: TriggerConfig { pipeline : None , pr : None } ) ;
2715+ let triggers = Some ( crate :: compile:: types:: OnConfig { schedule : None , pipeline : None , pr : None } ) ;
27122716 let result = generate_pipeline_resources ( & triggers) . unwrap ( ) ;
27132717 assert ! ( result. is_empty( ) ) ;
27142718 }
27152719
27162720 #[ test]
27172721 fn test_generate_pipeline_resources_with_branches ( ) {
2718- let triggers = Some ( crate :: compile:: types:: TriggerConfig {
2722+ let triggers = Some ( crate :: compile:: types:: OnConfig {
27192723 pipeline : Some ( crate :: compile:: types:: PipelineTrigger {
27202724 name : "Build Pipeline" . into ( ) ,
27212725 project : Some ( "OtherProject" . into ( ) ) ,
27222726 branches : vec ! [ "main" . into( ) , "release/*" . into( ) ] ,
2727+ filters : None ,
27232728 } ) ,
27242729 pr : None ,
2730+ schedule : None ,
27252731 } ) ;
27262732 let result = generate_pipeline_resources ( & triggers) . unwrap ( ) ;
27272733 assert ! ( result. contains( "source: 'Build Pipeline'" ) ) ;
@@ -2735,13 +2741,15 @@ mod tests {
27352741
27362742 #[ test]
27372743 fn test_generate_pipeline_resources_without_branches_triggers_on_any ( ) {
2738- let triggers = Some ( crate :: compile:: types:: TriggerConfig {
2744+ let triggers = Some ( crate :: compile:: types:: OnConfig {
27392745 pipeline : Some ( crate :: compile:: types:: PipelineTrigger {
27402746 name : "My Pipeline" . into ( ) ,
27412747 project : None ,
27422748 branches : vec ! [ ] ,
2749+ filters : None ,
27432750 } ) ,
27442751 pr : None ,
2752+ schedule : None ,
27452753 } ) ;
27462754 let result = generate_pipeline_resources ( & triggers) . unwrap ( ) ;
27472755 assert ! ( result. contains( "source: 'My Pipeline'" ) ) ;
@@ -2752,13 +2760,15 @@ mod tests {
27522760
27532761 #[ test]
27542762 fn test_generate_pipeline_resources_resource_id_is_snake_case ( ) {
2755- let triggers = Some ( crate :: compile:: types:: TriggerConfig {
2763+ let triggers = Some ( crate :: compile:: types:: OnConfig {
27562764 pipeline : Some ( crate :: compile:: types:: PipelineTrigger {
27572765 name : "My Build Pipeline" . into ( ) ,
27582766 project : None ,
27592767 branches : vec ! [ ] ,
2768+ filters : None ,
27602769 } ) ,
27612770 pr : None ,
2771+ schedule : None ,
27622772 } ) ;
27632773 let result = generate_pipeline_resources ( & triggers) . unwrap ( ) ;
27642774 // The pipeline resource ID should be snake_case derived from the name
@@ -3664,49 +3674,55 @@ mod tests {
36643674 #[ test]
36653675 fn test_validate_front_matter_identity_rejects_newline_in_trigger_pipeline_name ( ) {
36663676 let mut fm = minimal_front_matter ( ) ;
3667- fm. triggers = Some ( TriggerConfig {
3677+ fm. on_config = Some ( OnConfig {
36683678 pipeline : Some ( crate :: compile:: types:: PipelineTrigger {
36693679 name : "Build\n injected: true" . to_string ( ) ,
36703680 project : None ,
36713681 branches : vec ! [ ] ,
3682+ filters : None ,
36723683 } ) ,
36733684 pr : None ,
3685+ schedule : None ,
36743686 } ) ;
36753687 let result = validate_front_matter_identity ( & fm) ;
36763688 assert ! ( result. is_err( ) ) ;
3677- assert ! ( result. unwrap_err( ) . to_string( ) . contains( "triggers .pipeline.name" ) ) ;
3689+ assert ! ( result. unwrap_err( ) . to_string( ) . contains( "on .pipeline.name" ) ) ;
36783690 }
36793691
36803692 #[ test]
36813693 fn test_validate_front_matter_identity_rejects_newline_in_trigger_pipeline_project ( ) {
36823694 let mut fm = minimal_front_matter ( ) ;
3683- fm. triggers = Some ( TriggerConfig {
3695+ fm. on_config = Some ( OnConfig {
36843696 pipeline : Some ( crate :: compile:: types:: PipelineTrigger {
36853697 name : "Build Pipeline" . to_string ( ) ,
36863698 project : Some ( "OtherProject\n injected: true" . to_string ( ) ) ,
36873699 branches : vec ! [ ] ,
3700+ filters : None ,
36883701 } ) ,
36893702 pr : None ,
3703+ schedule : None ,
36903704 } ) ;
36913705 let result = validate_front_matter_identity ( & fm) ;
36923706 assert ! ( result. is_err( ) ) ;
3693- assert ! ( result. unwrap_err( ) . to_string( ) . contains( "triggers .pipeline.project" ) ) ;
3707+ assert ! ( result. unwrap_err( ) . to_string( ) . contains( "on .pipeline.project" ) ) ;
36943708 }
36953709
36963710 #[ test]
36973711 fn test_validate_front_matter_identity_rejects_newline_in_trigger_pipeline_branch ( ) {
36983712 let mut fm = minimal_front_matter ( ) ;
3699- fm. triggers = Some ( TriggerConfig {
3713+ fm. on_config = Some ( OnConfig {
37003714 pipeline : Some ( crate :: compile:: types:: PipelineTrigger {
37013715 name : "Build Pipeline" . to_string ( ) ,
37023716 project : None ,
37033717 branches : vec ! [ "main\n injected: true" . to_string( ) ] ,
3718+ filters : None ,
37043719 } ) ,
37053720 pr : None ,
3721+ schedule : None ,
37063722 } ) ;
37073723 let result = validate_front_matter_identity ( & fm) ;
37083724 assert ! ( result. is_err( ) ) ;
3709- assert ! ( result. unwrap_err( ) . to_string( ) . contains( "triggers .pipeline.branches" ) ) ;
3725+ assert ! ( result. unwrap_err( ) . to_string( ) . contains( "on .pipeline.branches" ) ) ;
37103726 }
37113727
37123728 #[ test]
@@ -3721,13 +3737,15 @@ mod tests {
37213737 #[ test]
37223738 fn test_validate_front_matter_identity_allows_valid_trigger_pipeline_fields ( ) {
37233739 let mut fm = minimal_front_matter ( ) ;
3724- fm. triggers = Some ( TriggerConfig {
3740+ fm. on_config = Some ( OnConfig {
37253741 pipeline : Some ( crate :: compile:: types:: PipelineTrigger {
37263742 name : "Build Pipeline" . to_string ( ) ,
37273743 project : Some ( "OtherProject" . to_string ( ) ) ,
37283744 branches : vec ! [ "main" . to_string( ) , "release/*" . to_string( ) ] ,
3745+ filters : None ,
37293746 } ) ,
37303747 pr : None ,
3748+ schedule : None ,
37313749 } ) ;
37323750 let result = validate_front_matter_identity ( & fm) ;
37333751 assert ! ( result. is_ok( ) ) ;
@@ -3745,13 +3763,15 @@ mod tests {
37453763 #[ test]
37463764 fn test_validate_front_matter_identity_rejects_ado_expression_in_trigger_pipeline_name ( ) {
37473765 let mut fm = minimal_front_matter ( ) ;
3748- fm. triggers = Some ( TriggerConfig {
3766+ fm. on_config = Some ( OnConfig {
37493767 pipeline : Some ( crate :: compile:: types:: PipelineTrigger {
37503768 name : "Build $(System.AccessToken)" . to_string ( ) ,
37513769 project : None ,
37523770 branches : vec ! [ ] ,
3771+ filters : None ,
37533772 } ) ,
37543773 pr : None ,
3774+ schedule : None ,
37553775 } ) ;
37563776 let result = validate_front_matter_identity ( & fm) ;
37573777 assert ! ( result. is_err( ) ) ;
@@ -3761,13 +3781,15 @@ mod tests {
37613781 #[ test]
37623782 fn test_validate_front_matter_identity_rejects_ado_expression_in_trigger_pipeline_project ( ) {
37633783 let mut fm = minimal_front_matter ( ) ;
3764- fm. triggers = Some ( TriggerConfig {
3784+ fm. on_config = Some ( OnConfig {
37653785 pipeline : Some ( crate :: compile:: types:: PipelineTrigger {
37663786 name : "Build Pipeline" . to_string ( ) ,
37673787 project : Some ( "$(System.AccessToken)" . to_string ( ) ) ,
37683788 branches : vec ! [ ] ,
3789+ filters : None ,
37693790 } ) ,
37703791 pr : None ,
3792+ schedule : None ,
37713793 } ) ;
37723794 let result = validate_front_matter_identity ( & fm) ;
37733795 assert ! ( result. is_err( ) ) ;
@@ -3777,13 +3799,15 @@ mod tests {
37773799 #[ test]
37783800 fn test_validate_front_matter_identity_rejects_ado_expression_in_trigger_pipeline_branch ( ) {
37793801 let mut fm = minimal_front_matter ( ) ;
3780- fm. triggers = Some ( TriggerConfig {
3802+ fm. on_config = Some ( OnConfig {
37813803 pipeline : Some ( crate :: compile:: types:: PipelineTrigger {
37823804 name : "Build Pipeline" . to_string ( ) ,
37833805 project : None ,
37843806 branches : vec ! [ "$[variables['token']]" . to_string( ) ] ,
3807+ filters : None ,
37853808 } ) ,
37863809 pr : None ,
3810+ schedule : None ,
37873811 } ) ;
37883812 let result = validate_front_matter_identity ( & fm) ;
37893813 assert ! ( result. is_err( ) ) ;
@@ -3792,13 +3816,15 @@ mod tests {
37923816
37933817 #[ test]
37943818 fn test_pipeline_resources_escapes_single_quotes ( ) {
3795- let triggers = Some ( TriggerConfig {
3819+ let triggers = Some ( OnConfig {
37963820 pipeline : Some ( crate :: compile:: types:: PipelineTrigger {
37973821 name : "Build's Pipeline" . to_string ( ) ,
37983822 project : Some ( "My'Project" . to_string ( ) ) ,
37993823 branches : vec ! [ "main" . to_string( ) , "it's-branch" . to_string( ) ] ,
3824+ filters : None ,
38003825 } ) ,
38013826 pr : None ,
3827+ schedule : None ,
38023828 } ) ;
38033829 let result = generate_pipeline_resources ( & triggers) . unwrap ( ) ;
38043830 assert ! ( result. contains( "source: 'Build''s Pipeline'" ) ) ;
0 commit comments