@@ -375,6 +375,22 @@ func (as *ActionService) cleanupChains() {
375375// MaxCascadeDepth bounds action-triggered mutation chains across consumers.
376376const MaxCascadeDepth = 5
377377
378+ func matchesStatusTransition (fromStatusID , toStatusID * int , oldValues , newValues map [string ]any ) bool {
379+ if fromStatusID != nil {
380+ oldStatusID := utils .InterfaceToIntPtr (oldValues ["status_id" ])
381+ if oldStatusID == nil || * oldStatusID != * fromStatusID {
382+ return false
383+ }
384+ }
385+ if toStatusID != nil {
386+ newStatusID := utils .InterfaceToIntPtr (newValues ["status_id" ])
387+ if newStatusID == nil || * newStatusID != * toStatusID {
388+ return false
389+ }
390+ }
391+ return true
392+ }
393+
378394// matchesTrigger checks if an action's trigger matches the event
379395func (as * ActionService ) matchesTrigger (action * models.Action , event * models.ActionEvent ) bool {
380396 if action .TriggerType != event .EventType {
@@ -408,75 +424,70 @@ func (as *ActionService) matchesTrigger(action *models.Action, event *models.Act
408424
409425 switch event .EventType {
410426 case models .ActionTriggerStatusTransition :
411- if config .FromStatusID != nil {
412- oldStatusID := utils .InterfaceToIntPtr (event .OldValues ["status_id" ])
413- if oldStatusID == nil || * oldStatusID != * config .FromStatusID {
414- return false
415- }
416- }
417- if config .ToStatusID != nil {
418- newStatusID := utils .InterfaceToIntPtr (event .NewValues ["status_id" ])
419- if newStatusID == nil || * newStatusID != * config .ToStatusID {
420- return false
421- }
422- }
423- // Match the destination status category when configured.
424- if config .ToStatusCategoryIsCompleted != nil {
425- newStatusID := utils .InterfaceToIntPtr (event .NewValues ["status_id" ])
426- if newStatusID == nil {
427- return false
428- }
429- st , err := NewStatusService (as .db ).GetStatus (* newStatusID )
430- if err != nil || st == nil {
431- return false
432- }
433- if st .IsCompleted != * config .ToStatusCategoryIsCompleted {
434- return false
435- }
436- }
427+ return matchesStatusTransition (config .FromStatusID , config .ToStatusID , event .OldValues , event .NewValues ) &&
428+ as .matchesDestinationStatusCategory (config .ToStatusCategoryIsCompleted , event .NewValues )
437429
438430 case models .ActionTriggerItemCreated , models .ActionTriggerItemUpdated :
439- // Normalize item type IDs before comparing them.
440- if config .ItemTypeID != nil {
441- itemTypeID := utils .InterfaceToIntPtr (event .NewValues ["item_type_id" ])
442- if itemTypeID == nil || * itemTypeID != * config .ItemTypeID {
443- return false
444- }
445- }
446- if event .EventType == models .ActionTriggerItemUpdated && config .FieldName != "" {
447- if _ , changed := event .NewValues [config .FieldName ]; ! changed {
448- return false
449- }
450- }
431+ return matchesItemActionTrigger (config , event )
451432
452433 case models .ActionTriggerItemLinked :
453- // Normalize link type IDs before comparing them.
454- if config .LinkTypeID != nil {
455- linkTypeID := utils .InterfaceToIntPtr (event .NewValues ["link_type_id" ])
456- if linkTypeID == nil || * linkTypeID != * config .LinkTypeID {
457- return false
458- }
459- }
434+ return matchesItemLinkTrigger (config .LinkTypeID , event .NewValues )
460435
461436 case models .ActionTriggerSCMTagCreated , models .ActionTriggerSCMReleaseBranchCreated ,
462437 models .ActionTriggerSCMPRLinked , models .ActionTriggerSCMPRMerged :
463- if config .WorkspaceRepositoryID != nil {
464- repoID := utils .InterfaceToIntPtr (event .NewValues ["repo.workspace_repository_id" ])
465- if repoID == nil || * repoID != * config .WorkspaceRepositoryID {
466- return false
467- }
468- }
469- if config .RepositoryFullName != "" {
470- fullName := fmt .Sprintf ("%v" , event .NewValues ["repo.full_name" ])
471- if ! strings .EqualFold (fullName , config .RepositoryFullName ) {
472- return false
473- }
474- }
438+ return matchesSCMActionTrigger (config , event .NewValues )
475439 }
476440
477441 return true
478442}
479443
444+ func (as * ActionService ) matchesDestinationStatusCategory (isCompleted * bool , newValues map [string ]any ) bool {
445+ if isCompleted == nil {
446+ return true
447+ }
448+ newStatusID := utils .InterfaceToIntPtr (newValues ["status_id" ])
449+ if newStatusID == nil {
450+ return false
451+ }
452+ status , err := NewStatusService (as .db ).GetStatus (* newStatusID )
453+ return err == nil && status != nil && status .IsCompleted == * isCompleted
454+ }
455+
456+ func matchesItemActionTrigger (config models.ActionTriggerConfig , event * models.ActionEvent ) bool {
457+ if config .ItemTypeID != nil {
458+ itemTypeID := utils .InterfaceToIntPtr (event .NewValues ["item_type_id" ])
459+ if itemTypeID == nil || * itemTypeID != * config .ItemTypeID {
460+ return false
461+ }
462+ }
463+ if event .EventType == models .ActionTriggerItemUpdated && config .FieldName != "" {
464+ _ , changed := event .NewValues [config .FieldName ]
465+ return changed
466+ }
467+ return true
468+ }
469+
470+ func matchesItemLinkTrigger (linkTypeID * int , newValues map [string ]any ) bool {
471+ if linkTypeID == nil {
472+ return true
473+ }
474+ eventLinkTypeID := utils .InterfaceToIntPtr (newValues ["link_type_id" ])
475+ return eventLinkTypeID != nil && * eventLinkTypeID == * linkTypeID
476+ }
477+
478+ func matchesSCMActionTrigger (config models.ActionTriggerConfig , newValues map [string ]any ) bool {
479+ if config .WorkspaceRepositoryID != nil {
480+ repositoryID := utils .InterfaceToIntPtr (newValues ["repo.workspace_repository_id" ])
481+ if repositoryID == nil || * repositoryID != * config .WorkspaceRepositoryID {
482+ return false
483+ }
484+ }
485+ if config .RepositoryFullName == "" {
486+ return true
487+ }
488+ return strings .EqualFold (fmt .Sprintf ("%v" , newValues ["repo.full_name" ]), config .RepositoryFullName )
489+ }
490+
480491// executeAction executes an action's flow
481492func (as * ActionService ) executeAction (action * models.Action , event * models.ActionEvent , chain * ExecutionChain ) error {
482493 return as .executeActionForEvent (action , event , chain , "" )
0 commit comments