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 <[email protected]>
This commit is contained in:
Gayathri Vijayan
2025-12-04 06:14:55 +00:00
committed by GitHub
co-authored by Livio Spring
parent e26859d644
commit a1bfdeb257
2 changed files with 83 additions and 10 deletions
+4 -3
View File
@@ -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
+79 -7
View File
@@ -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) {