From a1bfdeb2571c366ccf36a620420db9a4f535dc81 Mon Sep 17 00:00:00 2001 From: Gayathri Vijayan <66356931+grvijayan@users.noreply.github.com> Date: Thu, 4 Dec 2025 07:14:55 +0100 Subject: [PATCH] fix(actionsV2): executing request/response type for 'all' condition (#11071) # Which Problems Are Solved In actions v2, when the condition `all` is chosen, or a specific method is not specified for a service action, the actions are not executed. # How the Problems Are Solved The wildcard suffix `.*` is used only for event groups. As global `requests`, `responses` or `services with no specified method` do not have this suffix, they were bypassing the prefix-match check. This check therefore does not apply to action types other than `event` This issue is fixed by removing the `e.ID == "event"` condition when prefix-matching execution IDs to not exclude other action types (`request`, `response`, etc). # Additional Changes N/A # Additional Context - Closes #10895 --------- Co-authored-by: Livio Spring --- internal/execution/target/router.go | 7 +- internal/execution/target/router_test.go | 86 ++++++++++++++++++++++-- 2 files changed, 83 insertions(+), 10 deletions(-) diff --git a/internal/execution/target/router.go b/internal/execution/target/router.go index 7ca5667c5..c376ca23d 100644 --- a/internal/execution/target/router.go +++ b/internal/execution/target/router.go @@ -44,8 +44,7 @@ func (r Router) Get(executionID string) ([]Target, bool) { // GetEventBestMatch returns the best matching execution targets for an event. // The following match priority is used: // 1. Exact match -// 2. Wildcard match -// 3. Prefix match ("event") +// 2. Longest matching prefix (with wildcard suffix .* for events) func (r Router) GetEventBestMatch(executionID string) ([]Target, bool) { t, ok := r.Get(executionID) if ok { @@ -53,9 +52,11 @@ func (r Router) GetEventBestMatch(executionID string) ([]Target, bool) { } var bestMatch element for _, e := range r { - if e.ID == "event" && strings.HasPrefix(executionID, e.ID) { + if strings.HasPrefix(executionID, e.ID) { bestMatch, ok = e, true } + + // .* is suffixed for "all" condition on events cut, has := strings.CutSuffix(e.ID, ".*") if has && strings.HasPrefix(executionID, cut) { bestMatch, ok = e, true diff --git a/internal/execution/target/router_test.go b/internal/execution/target/router_test.go index e0923a974..520b8daac 100644 --- a/internal/execution/target/router_test.go +++ b/internal/execution/target/router_test.go @@ -7,13 +7,31 @@ import ( ) var ( - eventGlobalTarget = Target{ExecutionID: "event", TargetID: "event_global"} - eventGroupTarget = Target{ExecutionID: "event/foo.*", TargetID: "event_group"} - eventMatchTarget = Target{ExecutionID: "event/foo.bar", TargetID: "event_specific"} - functionCallTarget1 = Target{ExecutionID: "function/Call", TargetID: "function_call_1"} - functionCallTarget2 = Target{ExecutionID: "function/Call", TargetID: "function_call_2"} + eventGlobalTarget = Target{ExecutionID: "event", TargetID: "event_global"} + eventGroupTarget = Target{ExecutionID: "event/foo.*", TargetID: "event_group"} + eventMatchTarget = Target{ExecutionID: "event/foo.bar", TargetID: "event_specific"} + functionCallTarget1 = Target{ExecutionID: "function/Call", TargetID: "function_call_1"} + functionCallTarget2 = Target{ExecutionID: "function/Call", TargetID: "function_call_2"} + requestGlobalTarget = Target{ExecutionID: "request", TargetID: "request_global"} + requestServiceTarget = Target{ExecutionID: "request/zitadel.test.TestService", TargetID: "request_service"} + requestServiceMethodTarget = Target{ExecutionID: "request/zitadel.test.TestService/TestMethod", TargetID: "request_service_method"} + responseGlobalTarget = Target{ExecutionID: "response", TargetID: "response_global"} + responseServiceTarget = Target{ExecutionID: "response/zitadel.test.TestService", TargetID: "response_service"} + responseServiceMethodTarget = Target{ExecutionID: "response/zitadel.test.TestService/TestMethod", TargetID: "response_service_method"} - testTargets = []Target{eventGlobalTarget, eventGroupTarget, eventMatchTarget, functionCallTarget1, functionCallTarget2} + testTargets = []Target{ + eventGlobalTarget, + eventGroupTarget, + eventMatchTarget, + functionCallTarget1, + functionCallTarget2, + requestGlobalTarget, + requestServiceTarget, + requestServiceMethodTarget, + responseGlobalTarget, + responseServiceTarget, + responseServiceMethodTarget, + } ) func TestBinarySearchRouter_Get(t *testing.T) { @@ -94,7 +112,7 @@ func TestBinarySearchRouter_GetEventBestMatch(t *testing.T) { name: "event group match", targets: testTargets[1:], args: args{ - id: "event/foo.bar.baz", + id: "event/foo.baz", }, wantTargets: []Target{eventGroupTarget}, wantOk: true, @@ -117,6 +135,60 @@ func TestBinarySearchRouter_GetEventBestMatch(t *testing.T) { wantTargets: []Target{functionCallTarget1, functionCallTarget2}, wantOk: true, }, + { + name: "request global match", + targets: testTargets, + args: args{ + id: "request/zitadel.test.OtherService/OtherMethod", + }, + wantTargets: []Target{requestGlobalTarget}, + wantOk: true, + }, + { + name: "request service match", + targets: testTargets, + args: args{ + id: "request/zitadel.test.TestService/RandomMethod", + }, + wantTargets: []Target{requestServiceTarget}, + wantOk: true, + }, + { + name: "request service method match", + targets: testTargets, + args: args{ + id: "request/zitadel.test.TestService/TestMethod", + }, + wantTargets: []Target{requestServiceMethodTarget}, + wantOk: true, + }, + { + name: "response global match", + targets: testTargets, + args: args{ + id: "response/zitadel.test.OtherService/OtherMethod", + }, + wantTargets: []Target{responseGlobalTarget}, + wantOk: true, + }, + { + name: "response service match", + targets: testTargets, + args: args{ + id: "response/zitadel.test.TestService/RandomMethod", + }, + wantTargets: []Target{responseServiceTarget}, + wantOk: true, + }, + { + name: "response service method match", + targets: testTargets, + args: args{ + id: "response/zitadel.test.TestService/TestMethod", + }, + wantTargets: []Target{responseServiceMethodTarget}, + wantOk: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {