@@ -286,6 +286,255 @@ func TestReplacePlaceHoldersVariablesJSONOutput(t *testing.T) {
286286 }
287287}
288288
289+ func TestReplacePlaceHoldersVariablesCelPrefix (t * testing.T ) {
290+ tests := []struct {
291+ name string
292+ template string
293+ expected string
294+ dicto map [string ]string
295+ headers http.Header
296+ changedFiles map [string ]any
297+ rawEvent any
298+ }{
299+ {
300+ name : "cel: prefix with simple body access" ,
301+ template : `result: {{ cel: body.hello }}` ,
302+ expected : `result: world` ,
303+ dicto : map [string ]string {},
304+ changedFiles : map [string ]any {},
305+ headers : http.Header {},
306+ rawEvent : map [string ]string {
307+ "hello" : "world" ,
308+ },
309+ },
310+ {
311+ name : "cel: prefix with ternary expression" ,
312+ template : `status: {{ cel: body.action == "opened" ? "new-pr" : "updated-pr" }}` ,
313+ expected : `status: new-pr` ,
314+ dicto : map [string ]string {},
315+ changedFiles : map [string ]any {},
316+ headers : http.Header {},
317+ rawEvent : map [string ]any {
318+ "action" : "opened" ,
319+ },
320+ },
321+ {
322+ name : "cel: prefix with ternary expression - else branch" ,
323+ template : `status: {{ cel: body.action == "opened" ? "new-pr" : "updated-pr" }}` ,
324+ expected : `status: updated-pr` ,
325+ dicto : map [string ]string {},
326+ changedFiles : map [string ]any {},
327+ headers : http.Header {},
328+ rawEvent : map [string ]any {
329+ "action" : "synchronize" ,
330+ },
331+ },
332+ {
333+ name : "cel: prefix with pac namespace access" ,
334+ template : `branch: {{ cel: pac.target_branch }}` ,
335+ expected : `branch: main` ,
336+ dicto : map [string ]string {
337+ "target_branch" : "main" ,
338+ },
339+ changedFiles : map [string ]any {},
340+ headers : http.Header {},
341+ rawEvent : map [string ]any {},
342+ },
343+ {
344+ name : "cel: prefix with pac namespace conditional" ,
345+ template : `env: {{ cel: pac.target_branch == "main" ? "production" : "staging" }}` ,
346+ expected : `env: production` ,
347+ dicto : map [string ]string {
348+ "target_branch" : "main" ,
349+ },
350+ changedFiles : map [string ]any {},
351+ headers : http.Header {},
352+ rawEvent : map [string ]any {},
353+ },
354+ {
355+ name : "cel: prefix with pac namespace - staging branch" ,
356+ template : `env: {{ cel: pac.target_branch == "main" ? "production" : "staging" }}` ,
357+ expected : `env: staging` ,
358+ dicto : map [string ]string {
359+ "target_branch" : "develop" ,
360+ },
361+ changedFiles : map [string ]any {},
362+ headers : http.Header {},
363+ rawEvent : map [string ]any {},
364+ },
365+ {
366+ name : "cel: prefix with has() function" ,
367+ template : `has_field: {{ cel: has(body.optional_field) ? body.optional_field : "default" }}` ,
368+ expected : `has_field: custom_value` ,
369+ dicto : map [string ]string {},
370+ changedFiles : map [string ]any {},
371+ headers : http.Header {},
372+ rawEvent : map [string ]any {
373+ "optional_field" : "custom_value" ,
374+ },
375+ },
376+ {
377+ name : "cel: prefix with has() function - field missing" ,
378+ template : `has_field: {{ cel: has(body.optional_field) ? body.optional_field : "default" }}` ,
379+ expected : `has_field: default` ,
380+ dicto : map [string ]string {},
381+ changedFiles : map [string ]any {},
382+ headers : http.Header {},
383+ rawEvent : map [string ]any {},
384+ },
385+ {
386+ name : "cel: prefix with files access" ,
387+ template : `go_files: {{ cel: files.all.exists(f, f.endsWith(".go")) ? "yes" : "no" }}` ,
388+ expected : `go_files: yes` ,
389+ dicto : map [string ]string {},
390+ changedFiles : map [string ]any {
391+ "all" : []string {"main.go" , "README.md" },
392+ },
393+ headers : http.Header {},
394+ rawEvent : map [string ]any {},
395+ },
396+ {
397+ name : "cel: prefix with files access - no go files" ,
398+ template : `go_files: {{ cel: files.all.exists(f, f.endsWith(".go")) ? "yes" : "no" }}` ,
399+ expected : `go_files: no` ,
400+ dicto : map [string ]string {},
401+ changedFiles : map [string ]any {
402+ "all" : []string {"README.md" , "config.yaml" },
403+ },
404+ headers : http.Header {},
405+ rawEvent : map [string ]any {},
406+ },
407+ {
408+ name : "cel: prefix with headers access" ,
409+ template : `event: {{ cel: headers["X-GitHub-Event"] }}` ,
410+ expected : `event: push` ,
411+ dicto : map [string ]string {},
412+ changedFiles : map [string ]any {},
413+ headers : http.Header {
414+ "X-GitHub-Event" : []string {"push" },
415+ },
416+ rawEvent : map [string ]any {},
417+ },
418+ {
419+ name : "cel: prefix with boolean result" ,
420+ template : `is_draft: {{ cel: body.draft == true }}` ,
421+ expected : `is_draft: false` ,
422+ dicto : map [string ]string {},
423+ changedFiles : map [string ]any {},
424+ headers : http.Header {},
425+ rawEvent : map [string ]any {
426+ "draft" : false ,
427+ },
428+ },
429+ {
430+ name : "cel: prefix with invalid expression returns empty string" ,
431+ template : `invalid: {{ cel: invalid.syntax[ }}` ,
432+ expected : `invalid: ` ,
433+ dicto : map [string ]string {},
434+ changedFiles : map [string ]any {},
435+ headers : http.Header {},
436+ rawEvent : map [string ]any {},
437+ },
438+ {
439+ name : "cel: prefix with evaluation error returns empty string" ,
440+ template : `error: {{ cel: body.nonexistent.deep.field }}` ,
441+ expected : `error: ` ,
442+ dicto : map [string ]string {},
443+ changedFiles : map [string ]any {},
444+ headers : http.Header {},
445+ rawEvent : map [string ]any {},
446+ },
447+ {
448+ name : "cel: prefix with extra whitespace" ,
449+ template : `result: {{ cel: body.hello }}` ,
450+ expected : `result: world` ,
451+ dicto : map [string ]string {},
452+ changedFiles : map [string ]any {},
453+ headers : http.Header {},
454+ rawEvent : map [string ]string {
455+ "hello" : "world" ,
456+ },
457+ },
458+ {
459+ name : "cel: prefix with string concatenation" ,
460+ template : `greeting: {{ cel: "Hello, " + body.name + "!" }}` ,
461+ expected : `greeting: Hello, World!` ,
462+ dicto : map [string ]string {},
463+ changedFiles : map [string ]any {},
464+ headers : http.Header {},
465+ rawEvent : map [string ]any {
466+ "name" : "World" ,
467+ },
468+ },
469+ {
470+ name : "cel: prefix with size function" ,
471+ template : `count: {{ cel: body.items.size() }}` ,
472+ expected : `count: 3` ,
473+ dicto : map [string ]string {},
474+ changedFiles : map [string ]any {},
475+ headers : http.Header {},
476+ rawEvent : map [string ]any {
477+ "items" : []string {"a" , "b" , "c" },
478+ },
479+ },
480+ {
481+ name : "cel: prefix with complex nested conditional (merge commit detection)" ,
482+ template : `commit_type: {{ cel: has(body.head_commit) && body.head_commit.message.startsWith("Merge") ? "merge" : "regular" }}` ,
483+ expected : `commit_type: merge` ,
484+ dicto : map [string ]string {},
485+ changedFiles : map [string ]any {},
486+ headers : http.Header {},
487+ rawEvent : map [string ]any {
488+ "head_commit" : map [string ]any {
489+ "message" : "Merge pull request #123" ,
490+ },
491+ },
492+ },
493+ {
494+ name : "cel: prefix with complex nested conditional - regular commit" ,
495+ template : `commit_type: {{ cel: has(body.head_commit) && body.head_commit.message.startsWith("Merge") ? "merge" : "regular" }}` ,
496+ expected : `commit_type: regular` ,
497+ dicto : map [string ]string {},
498+ changedFiles : map [string ]any {},
499+ headers : http.Header {},
500+ rawEvent : map [string ]any {
501+ "head_commit" : map [string ]any {
502+ "message" : "Fix bug in parser" ,
503+ },
504+ },
505+ },
506+ {
507+ name : "cel: prefix mixed with regular placeholders" ,
508+ template : `branch: {{ target_branch }}, check: {{ cel: pac.target_branch == "main" ? "prod" : "dev" }}` ,
509+ expected : `branch: main, check: prod` ,
510+ dicto : map [string ]string {
511+ "target_branch" : "main" ,
512+ },
513+ changedFiles : map [string ]any {},
514+ headers : http.Header {},
515+ rawEvent : map [string ]any {},
516+ },
517+ {
518+ name : "cel: prefix with nil rawEvent still works" ,
519+ template : `result: {{ cel: pac.revision }}` ,
520+ expected : `result: abc123` ,
521+ dicto : map [string ]string {"revision" : "abc123" },
522+ changedFiles : map [string ]any {},
523+ headers : http.Header {},
524+ rawEvent : nil ,
525+ },
526+ }
527+
528+ for _ , tt := range tests {
529+ t .Run (tt .name , func (t * testing.T ) {
530+ got := ReplacePlaceHoldersVariables (tt .template , tt .dicto , tt .rawEvent , tt .headers , tt .changedFiles )
531+ if d := cmp .Diff (got , tt .expected ); d != "" {
532+ t .Fatalf ("-got, +want: %v" , d )
533+ }
534+ })
535+ }
536+ }
537+
289538func TestReplacePlaceHoldersVariablesEdgeCases (t * testing.T ) {
290539 tests := []struct {
291540 name string
0 commit comments