@@ -317,8 +317,8 @@ public static async Task ParseStep(Runner.Server.Azure.Devops.Context context, I
317317 throw new TemplateValidationException ( new [ ] { new TemplateValidationError ( $ "{ GitHub . DistributedTask . ObjectTemplating . Tokens . TemplateTokenExtensions . GetAssertPrefix ( mstep [ 2 ] . Key ) } Unexpected yaml keys { ( mstep [ 2 ] . Key as StringToken ) ? . Value } after template reference") } ) ;
318318 }
319319 try {
320- var file = await ReadTemplate ( context , primaryValue , unparsedTokens . Count == 1 ? unparsedTokens [ 0 ] . Value . AssertMapping ( "param" ) . ToDictionary ( kv => kv . Key . AssertString ( "" ) . Value , kv => kv . Value ) : null , "step-template-root" ) ;
321- await ParseSteps ( context . ChildContext ( file , primaryValue ) , steps , ( from e in file where e . Key . AssertString ( "" ) . Value == "steps" select e . Value ) . First ( ) . AssertSequence ( "" ) ) ;
320+ var ( file , childContext ) = await ReadTemplate ( context , primaryValue , unparsedTokens . Count == 1 ? unparsedTokens [ 0 ] . Value . AssertMapping ( "param" ) . ToDictionary ( kv => kv . Key . AssertString ( "" ) . Value , kv => kv . Value ) : null , "step-template-root" ) ;
321+ await ParseSteps ( childContext , steps , ( from e in file where e . Key . AssertString ( "" ) . Value == "steps" select e . Value ) . First ( ) . AssertSequence ( "" ) ) ;
322322 } catch ( TemplateValidationException ex ) {
323323 throw new TemplateValidationException ( ex . Errors . Prepend ( new TemplateValidationError ( $ "{ GitHub . DistributedTask . ObjectTemplating . Tokens . TemplateTokenExtensions . GetAssertPrefix ( mstep [ 0 ] . Key ) } Found Errors inside Template Reference: { ex . Message } ") ) ) ;
324324 }
@@ -1307,15 +1307,13 @@ private static void CheckConditionalExpressions(TemplateContext m_context, Templ
13071307 }
13081308 }
13091309
1310- public static async Task < MappingToken > ReadTemplate ( Runner . Server . Azure . Devops . Context context , string filenameAndRef , Dictionary < string , TemplateToken > cparameters = null , string schemaName = null )
1310+ public static async Task < ( MappingToken , Context ) > ReadTemplate ( Runner . Server . Azure . Devops . Context context , string filenameAndRef , Dictionary < string , TemplateToken > cparameters = null , string schemaName = null )
13111311 {
13121312 var variables = context . VariablesProvider ? . GetVariablesForEnvironment ( "" ) ;
13131313 var ( errorTemplateFileName , token ) = await ParseTemplate ( context , filenameAndRef , schemaName ) ;
13141314
13151315 var pipelineroot = token . AssertMapping ( "root" ) ;
13161316
1317- var childContext = context . ChildContext ( pipelineroot , filenameAndRef ) ;
1318-
13191317 TemplateToken parameters = null ;
13201318 TemplateToken rawStaticVariables = null ;
13211319 foreach ( var kv in pipelineroot )
@@ -1467,6 +1465,12 @@ public static async Task<MappingToken> ReadTemplate(Runner.Server.Azure.Devops.C
14671465 }
14681466
14691467 templateContext = CreateTemplateContext ( context . TraceWriter ?? new EmptyTraceWriter ( ) , templateContext . GetFileTable ( ) . ToArray ( ) , context . Flags , contextData ) ;
1468+ // bug pipelineroot.resources.repositories.*.ref can be an expression
1469+ // can variables be referenced there?
1470+ // 2026-02-11: Yes, but then the value is null/'' if you attempt to reference templates using it
1471+ var resources = ( pipelineroot as IReadOnlyObject ) [ "resources" ] as MappingToken ;
1472+ resources = resources != null ? await TemplateEvaluator . EvaluateAsync ( templateContext , "resources" , resources , 0 , fileId ) as MappingToken : null ;
1473+ Context childContext = context . ChildContextWithResource ( resources , filenameAndRef ) ;
14701474 templateContext . EvaluateVariable = async ( tcontext , mapping , vars ) => {
14711475 string template = null ;
14721476 TemplateToken parameters = null ;
@@ -1507,7 +1511,7 @@ public static async Task<MappingToken> ReadTemplate(Runner.Server.Azure.Devops.C
15071511 else if ( template != null )
15081512 {
15091513 var evalp = parameters ;
1510- var file = await ReadTemplate ( childContext , template , evalp != null ? evalp . AssertMapping ( "param" ) . ToDictionary ( kv => kv . Key . AssertString ( "" ) . Value , kv => kv . Value ) : null , "variable-template-root" ) ;
1514+ var ( file , schildContext ) = await ReadTemplate ( childContext , template , evalp != null ? evalp . AssertMapping ( "param" ) . ToDictionary ( kv => kv . Key . AssertString ( "" ) . Value , kv => kv . Value ) : null , "variable-template-root" ) ;
15111515 IDictionary < string , VariableValue > rvars = new Dictionary < string , VariableValue > ( StringComparer . OrdinalIgnoreCase ) ;
15121516 var vartkn = ( from e in file where e . Key . AssertString ( "" ) . Value == "variables" select e . Value ) . First ( ) ;
15131517 ParseVariables ( rvars , vartkn ) ;
@@ -1530,7 +1534,7 @@ public static async Task<MappingToken> ReadTemplate(Runner.Server.Azure.Devops.C
15301534 var evaluatedResult = await TemplateEvaluator . EvaluateAsync ( templateContext , schemaName ?? "pipeline-root" , pipelineroot , 0 , fileId ) ;
15311535 templateContext . Errors . Check ( ) ;
15321536 context . TraceWriter ? . Verbose ( "{0}" , evaluatedResult . ToContextData ( ) . ToJToken ( ) . ToString ( ) ) ;
1533- return evaluatedResult . AssertMapping ( "root" ) ;
1537+ return ( evaluatedResult . AssertMapping ( "root" ) , childContext ) ;
15341538 }
15351539
15361540 public static IEnumerable < TemplateToken > NormalizeVariableDefinition ( TemplateToken vartkn )
0 commit comments