@@ -415,58 +415,67 @@ async function genManifestsAction(
415415
416416 // Check if composition.yaml exists
417417 let manifest : Manifest
418+ let usedDefaultTemplate = false
418419 const yamlFilePath = path . join ( functionDir , "composition.yaml" )
419420
420421 if ( fs . existsSync ( yamlFilePath ) ) {
421422 // Use the function's own composition.yaml as template
422423 const yamlContent = fs . readFileSync ( yamlFilePath , { encoding : "utf8" } )
423424 manifest = YAML . parse ( yamlContent )
424425 } else {
425- // Use the generic template from templates/composition.default.yaml
426- // Get the directory name from the import.meta.url
427- const __filename = fileURLToPath ( import . meta. url )
428- const __dirname = path . dirname ( __filename )
429- const genericTemplatePath = path . join ( __dirname , "templates/composition.default.yaml" )
430-
431- if ( ! fs . existsSync ( genericTemplatePath ) ) {
432- moduleLogger . error ( `Generic template not found: ${ genericTemplatePath } ` )
433- continue
434- }
435-
436- const templateContent = fs . readFileSync ( genericTemplatePath , {
437- encoding : "utf8" ,
438- } )
439- manifest = YAML . parse ( templateContent )
440-
441- // Update the name in the manifest to match the function name
442- if ( manifest . metadata && manifest . metadata . name ) {
443- manifest . metadata . name = manifest . metadata . name . replace ( "__FUNCTION_NAME__" , functionName )
444- }
426+ // Try a root-level composition.default.yaml first, then fall back to packaged template
427+ const rootDefaultPath = path . join ( cwd ( ) , "composition.default.yaml" )
428+ if ( fs . existsSync ( rootDefaultPath ) ) {
429+ moduleLogger . info ( `Using root composition template: ${ rootDefaultPath } ` )
430+ const templateContent = fs . readFileSync ( rootDefaultPath , { encoding : "utf8" } )
431+ manifest = YAML . parse ( templateContent )
432+ usedDefaultTemplate = true
433+ } else {
434+ // Use the generic template from templates/composition.default.yaml
435+ // Get the directory name from the import.meta.url
436+ const __filename = fileURLToPath ( import . meta. url )
437+ const __dirname = path . dirname ( __filename )
438+ const genericTemplatePath = path . join ( __dirname , "templates/composition.default.yaml" )
439+
440+ if ( ! fs . existsSync ( genericTemplatePath ) ) {
441+ moduleLogger . error ( `Generic template not found: ${ genericTemplatePath } ` )
442+ continue
443+ }
445444
446- // Update the apiVersion in the compositeTypeRef using the already loaded XRD
447- if ( manifest . spec && manifest . spec . compositeTypeRef ) {
448- const group = xrdManifest . spec . group
449- const version = getLatestKubernetesVersion ( xrdManifest . spec . versions )
450- const apiVersion = `${ group } /${ version } `
451-
452- manifest . spec . compositeTypeRef . apiVersion = apiVersion
453- manifest . spec . compositeTypeRef . kind = xrdManifest . spec . names . kind
454- moduleLogger . debug (
455- `Set compositeTypeRef.apiVersion to ${ apiVersion } (latest version) from XRD for ${ functionName } `
456- )
445+ const templateContent = fs . readFileSync ( genericTemplatePath , {
446+ encoding : "utf8" ,
447+ } )
448+ manifest = YAML . parse ( templateContent )
449+ usedDefaultTemplate = true
457450 }
451+ }
458452
459- // Update the step name
460- if ( manifest . spec && manifest . spec . pipeline && Array . isArray ( manifest . spec . pipeline ) ) {
461- for ( let i = 0 ; i < manifest . spec . pipeline . length ; i ++ ) {
462- const step = manifest . spec . pipeline [ i ] . step
463- if ( step ) {
464- manifest . spec . pipeline [ i ] . step = step . replace ( "__FUNCTION_NAME__" , functionName )
465- }
453+ // Always perform variable substitution templating, regardless of source
454+ if ( manifest . metadata && typeof manifest . metadata . name === "string" ) {
455+ manifest . metadata . name = manifest . metadata . name . replace ( "__FUNCTION_NAME__" , functionName )
456+ }
457+ if ( manifest . spec && Array . isArray ( manifest . spec . pipeline ) ) {
458+ for ( let i = 0 ; i < manifest . spec . pipeline . length ; i ++ ) {
459+ const step = manifest . spec . pipeline [ i ] . step
460+ if ( typeof step === "string" ) {
461+ manifest . spec . pipeline [ i ] . step = step . replace ( "__FUNCTION_NAME__" , functionName )
466462 }
467463 }
468464 }
469465
466+ // If using a default template (root or packaged), derive compositeTypeRef from XRD
467+ if ( usedDefaultTemplate && manifest . spec && manifest . spec . compositeTypeRef ) {
468+ const group = xrdManifest . spec . group
469+ const version = getLatestKubernetesVersion ( xrdManifest . spec . versions )
470+ const apiVersion = `${ group } /${ version } `
471+
472+ manifest . spec . compositeTypeRef . apiVersion = apiVersion
473+ manifest . spec . compositeTypeRef . kind = xrdManifest . spec . names . kind
474+ moduleLogger . debug (
475+ `Set compositeTypeRef.apiVersion to ${ apiVersion } (latest version) from XRD for ${ functionName } `
476+ )
477+ }
478+
470479 // Ensure the pipeline exists
471480 if (
472481 ! manifest . spec ||
0 commit comments