fix: actions v2beta with api design for GA (#10303)

# Which Problems Are Solved

Actions v2beta API does not adhere to the [API
design](https://github.com/zitadel/zitadel/blob/main/API_DESIGN.md)
fully.

# How the Problems Are Solved

- Correct body usage for ListExecutions
- Correct REST path for ListTargets and ListExecutions
- Correct attribute names for ListTargetsResponse and
ListExecutionsResponse

# Additional Changes

- Remove unused object import.

# Additional Context

Closes #10138

---------

Co-authored-by: Marco A. <marco@zitadel.com>
This commit is contained in:
Stefan Benz
2025-07-25 18:20:58 +02:00
committed by GitHub
parent c46fd01947
commit f0fa89747d
8 changed files with 73 additions and 71 deletions

View File

@@ -45,7 +45,7 @@ export class ActionsTwoActionsComponent {
switchMap(() => {
return this.actionService.listExecutions({ sortingColumn: ExecutionFieldName.ID, pagination: { asc: true } });
}),
map(({ result }) => result.map(correctlyTypeExecution)),
map(({ executions }) => executions.map(correctlyTypeExecution)),
catchError((err) => {
this.toast.showError(err);
return of([]);
@@ -59,7 +59,7 @@ export class ActionsTwoActionsComponent {
switchMap(() => {
return this.actionService.listTargets({});
}),
map(({ result }) => result),
map(({ targets }) => targets),
catchError((err) => {
this.toast.showError(err);
return of([]);

View File

@@ -115,13 +115,13 @@ export class ActionsTwoAddActionTargetComponent {
this.actionService
.listTargets({})
.then(({ result }) => {
const targets = result.reduce((acc, target) => {
.then(({ targets }) => {
const result = targets.reduce((acc, target) => {
acc.set(target.id, target);
return acc;
}, new Map<string, Target>());
targetsSignal.set({ state: 'loaded', targets });
targetsSignal.set({ state: 'loaded', targets: result });
})
.catch((error) => {
this.toast.showError(error);

View File

@@ -39,7 +39,7 @@ export class ActionsTwoTargetsComponent {
switchMap(() => {
return this.actionService.listTargets({});
}),
map(({ result }) => result),
map(({ targets }) => targets),
catchError((err) => {
this.toast.showError(err);
return of([]);

View File

@@ -477,10 +477,10 @@ func waitForExecutionOnCondition(ctx context.Context, t *testing.T, instance *in
if !assert.NoError(ttt, err) {
return
}
if !assert.Len(ttt, got.GetResult(), 1) {
if !assert.Len(ttt, got.GetExecutions(), 1) {
return
}
gotTargets := got.GetResult()[0].GetTargets()
gotTargets := got.GetExecutions()[0].GetTargets()
// always first check length, otherwise its failed anyway
if assert.Len(ttt, gotTargets, len(targets)) {
for i := range targets {
@@ -506,10 +506,10 @@ func waitForTarget(ctx context.Context, t *testing.T, instance *integration.Inst
if !assert.NoError(ttt, err) {
return
}
if !assert.Len(ttt, got.GetResult(), 1) {
if !assert.Len(ttt, got.GetTargets(), 1) {
return
}
config := got.GetResult()[0]
config := got.GetTargets()[0]
assert.Equal(ttt, config.GetEndpoint(), endpoint)
switch ty {
case domain.TargetTypeWebhook:

View File

@@ -206,7 +206,7 @@ func TestServer_GetTarget(t *testing.T) {
}
assert.NoError(ttt, err)
assert.EqualExportedValues(ttt, tt.want, got)
}, retryDuration, tick, "timeout waiting for expected target result")
}, retryDuration, tick, "timeout waiting for expected target Executions")
})
}
}
@@ -253,7 +253,7 @@ func TestServer_ListTargets(t *testing.T) {
TotalResult: 0,
AppliedLimit: 100,
},
Result: []*action.Target{},
Targets: []*action.Target{},
},
},
{
@@ -269,11 +269,11 @@ func TestServer_ListTargets(t *testing.T) {
},
}
response.Result[0].Id = resp.GetId()
response.Result[0].Name = name
response.Result[0].CreationDate = resp.GetCreationDate()
response.Result[0].ChangeDate = resp.GetCreationDate()
response.Result[0].SigningKey = resp.GetSigningKey()
response.Targets[0].Id = resp.GetId()
response.Targets[0].Name = name
response.Targets[0].CreationDate = resp.GetCreationDate()
response.Targets[0].ChangeDate = resp.GetCreationDate()
response.Targets[0].SigningKey = resp.GetSigningKey()
},
req: &action.ListTargetsRequest{
Filters: []*action.TargetSearchFilter{{}},
@@ -284,7 +284,7 @@ func TestServer_ListTargets(t *testing.T) {
TotalResult: 1,
AppliedLimit: 100,
},
Result: []*action.Target{
Targets: []*action.Target{
{
Endpoint: "https://example.com",
TargetType: &action.Target_RestWebhook{
@@ -309,11 +309,11 @@ func TestServer_ListTargets(t *testing.T) {
},
}
response.Result[0].Id = resp.GetId()
response.Result[0].Name = name
response.Result[0].CreationDate = resp.GetCreationDate()
response.Result[0].ChangeDate = resp.GetCreationDate()
response.Result[0].SigningKey = resp.GetSigningKey()
response.Targets[0].Id = resp.GetId()
response.Targets[0].Name = name
response.Targets[0].CreationDate = resp.GetCreationDate()
response.Targets[0].ChangeDate = resp.GetCreationDate()
response.Targets[0].SigningKey = resp.GetSigningKey()
},
req: &action.ListTargetsRequest{
Filters: []*action.TargetSearchFilter{{}},
@@ -324,7 +324,7 @@ func TestServer_ListTargets(t *testing.T) {
TotalResult: 1,
AppliedLimit: 100,
},
Result: []*action.Target{
Targets: []*action.Target{
{
Endpoint: "https://example.com",
TargetType: &action.Target_RestWebhook{
@@ -354,23 +354,23 @@ func TestServer_ListTargets(t *testing.T) {
},
}
response.Result[2].Id = resp1.GetId()
response.Result[2].Name = name1
response.Result[2].CreationDate = resp1.GetCreationDate()
response.Result[2].ChangeDate = resp1.GetCreationDate()
response.Result[2].SigningKey = resp1.GetSigningKey()
response.Targets[2].Id = resp1.GetId()
response.Targets[2].Name = name1
response.Targets[2].CreationDate = resp1.GetCreationDate()
response.Targets[2].ChangeDate = resp1.GetCreationDate()
response.Targets[2].SigningKey = resp1.GetSigningKey()
response.Result[1].Id = resp2.GetId()
response.Result[1].Name = name2
response.Result[1].CreationDate = resp2.GetCreationDate()
response.Result[1].ChangeDate = resp2.GetCreationDate()
response.Result[1].SigningKey = resp2.GetSigningKey()
response.Targets[1].Id = resp2.GetId()
response.Targets[1].Name = name2
response.Targets[1].CreationDate = resp2.GetCreationDate()
response.Targets[1].ChangeDate = resp2.GetCreationDate()
response.Targets[1].SigningKey = resp2.GetSigningKey()
response.Result[0].Id = resp3.GetId()
response.Result[0].Name = name3
response.Result[0].CreationDate = resp3.GetCreationDate()
response.Result[0].ChangeDate = resp3.GetCreationDate()
response.Result[0].SigningKey = resp3.GetSigningKey()
response.Targets[0].Id = resp3.GetId()
response.Targets[0].Name = name3
response.Targets[0].CreationDate = resp3.GetCreationDate()
response.Targets[0].ChangeDate = resp3.GetCreationDate()
response.Targets[0].SigningKey = resp3.GetSigningKey()
},
req: &action.ListTargetsRequest{
Filters: []*action.TargetSearchFilter{{}},
@@ -381,7 +381,7 @@ func TestServer_ListTargets(t *testing.T) {
TotalResult: 3,
AppliedLimit: 100,
},
Result: []*action.Target{
Targets: []*action.Target{
{
Endpoint: "https://example.com",
TargetType: &action.Target_RestAsync{
@@ -427,13 +427,13 @@ func TestServer_ListTargets(t *testing.T) {
require.NoError(ttt, listErr)
// always first check length, otherwise its failed anyway
if assert.Len(ttt, got.Result, len(tt.want.Result)) {
for i := range tt.want.Result {
assert.EqualExportedValues(ttt, tt.want.Result[i], got.Result[i])
if assert.Len(ttt, got.Targets, len(tt.want.Targets)) {
for i := range tt.want.Targets {
assert.EqualExportedValues(ttt, tt.want.Targets[i], got.Targets[i])
}
}
assertPaginationResponse(ttt, tt.want.Pagination, got.Pagination)
}, retryDuration, tick, "timeout waiting for expected execution result")
}, retryDuration, tick, "timeout waiting for expected execution Executions")
})
}
}
@@ -476,9 +476,9 @@ func TestServer_ListExecutions(t *testing.T) {
resp := instance.SetExecution(ctx, t, cond, []string{targetResp.GetId()})
// Set expected response with used values for SetExecution
response.Result[0].CreationDate = resp.GetSetDate()
response.Result[0].ChangeDate = resp.GetSetDate()
response.Result[0].Condition = cond
response.Executions[0].CreationDate = resp.GetSetDate()
response.Executions[0].ChangeDate = resp.GetSetDate()
response.Executions[0].Condition = cond
},
req: &action.ListExecutionsRequest{
Filters: []*action.ExecutionSearchFilter{{
@@ -503,7 +503,7 @@ func TestServer_ListExecutions(t *testing.T) {
TotalResult: 1,
AppliedLimit: 100,
},
Result: []*action.Execution{
Executions: []*action.Execution{
{
Condition: &action.Condition{
ConditionType: &action.Condition_Request{
@@ -544,10 +544,10 @@ func TestServer_ListExecutions(t *testing.T) {
}
resp := instance.SetExecution(ctx, t, cond, []string{target.GetId()})
response.Result[0].CreationDate = resp.GetSetDate()
response.Result[0].ChangeDate = resp.GetSetDate()
response.Result[0].Condition = cond
response.Result[0].Targets = []string{target.GetId()}
response.Executions[0].CreationDate = resp.GetSetDate()
response.Executions[0].ChangeDate = resp.GetSetDate()
response.Executions[0].Condition = cond
response.Executions[0].Targets = []string{target.GetId()}
},
req: &action.ListExecutionsRequest{
Filters: []*action.ExecutionSearchFilter{{}},
@@ -558,7 +558,7 @@ func TestServer_ListExecutions(t *testing.T) {
TotalResult: 1,
AppliedLimit: 100,
},
Result: []*action.Execution{
Executions: []*action.Execution{
{
Condition: &action.Condition{},
Targets: []string{""},
@@ -604,7 +604,7 @@ func TestServer_ListExecutions(t *testing.T) {
cond1 := request.Filters[0].GetInConditionsFilter().GetConditions()[0]
resp1 := instance.SetExecution(ctx, t, cond1, []string{targetResp.GetId()})
response.Result[2] = &action.Execution{
response.Executions[2] = &action.Execution{
CreationDate: resp1.GetSetDate(),
ChangeDate: resp1.GetSetDate(),
Condition: cond1,
@@ -613,7 +613,7 @@ func TestServer_ListExecutions(t *testing.T) {
cond2 := request.Filters[0].GetInConditionsFilter().GetConditions()[1]
resp2 := instance.SetExecution(ctx, t, cond2, []string{targetResp.GetId()})
response.Result[1] = &action.Execution{
response.Executions[1] = &action.Execution{
CreationDate: resp2.GetSetDate(),
ChangeDate: resp2.GetSetDate(),
Condition: cond2,
@@ -622,7 +622,7 @@ func TestServer_ListExecutions(t *testing.T) {
cond3 := request.Filters[0].GetInConditionsFilter().GetConditions()[2]
resp3 := instance.SetExecution(ctx, t, cond3, []string{targetResp.GetId()})
response.Result[0] = &action.Execution{
response.Executions[0] = &action.Execution{
CreationDate: resp3.GetSetDate(),
ChangeDate: resp3.GetSetDate(),
Condition: cond3,
@@ -640,7 +640,7 @@ func TestServer_ListExecutions(t *testing.T) {
TotalResult: 3,
AppliedLimit: 100,
},
Result: []*action.Execution{
Executions: []*action.Execution{
{}, {}, {},
},
},
@@ -653,7 +653,7 @@ func TestServer_ListExecutions(t *testing.T) {
conditions := request.Filters[0].GetInConditionsFilter().GetConditions()
for i, cond := range conditions {
resp := instance.SetExecution(ctx, t, cond, []string{targetResp.GetId()})
response.Result[(len(conditions)-1)-i] = &action.Execution{
response.Executions[(len(conditions)-1)-i] = &action.Execution{
CreationDate: resp.GetSetDate(),
ChangeDate: resp.GetSetDate(),
Condition: cond,
@@ -687,7 +687,7 @@ func TestServer_ListExecutions(t *testing.T) {
TotalResult: 10,
AppliedLimit: 100,
},
Result: []*action.Execution{
Executions: []*action.Execution{
{},
{},
{},
@@ -709,7 +709,7 @@ func TestServer_ListExecutions(t *testing.T) {
conditions := request.Filters[0].GetInConditionsFilter().GetConditions()
for i, cond := range conditions {
resp := instance.SetExecution(ctx, t, cond, []string{targetResp.GetId()})
response.Result[i] = &action.Execution{
response.Executions[i] = &action.Execution{
CreationDate: resp.GetSetDate(),
ChangeDate: resp.GetSetDate(),
Condition: cond,
@@ -744,7 +744,7 @@ func TestServer_ListExecutions(t *testing.T) {
TotalResult: 10,
AppliedLimit: 100,
},
Result: []*action.Execution{
Executions: []*action.Execution{
{},
{},
{},
@@ -774,11 +774,11 @@ func TestServer_ListExecutions(t *testing.T) {
}
require.NoError(ttt, listErr)
// always first check length, otherwise its failed anyway
if assert.Len(ttt, got.Result, len(tt.want.Result)) {
assert.EqualExportedValues(ttt, got.Result, tt.want.Result)
if assert.Len(ttt, got.Executions, len(tt.want.Executions)) {
assert.EqualExportedValues(ttt, got.Executions, tt.want.Executions)
}
assertPaginationResponse(ttt, tt.want.Pagination, got.Pagination)
}, retryDuration, tick, "timeout waiting for expected execution result")
}, retryDuration, tick, "timeout waiting for expected execution Executions")
})
}
}

View File

@@ -52,7 +52,7 @@ func (s *Server) ListTargets(ctx context.Context, req *connect.Request[action.Li
return nil, err
}
return connect.NewResponse(&action.ListTargetsResponse{
Result: targetsToPb(resp.Targets),
Targets: targetsToPb(resp.Targets),
Pagination: filter.QueryToPaginationPb(queries.SearchRequest, resp.SearchResponse),
}), nil
}
@@ -67,7 +67,7 @@ func (s *Server) ListExecutions(ctx context.Context, req *connect.Request[action
return nil, err
}
return connect.NewResponse(&action.ListExecutionsResponse{
Result: executionsToPb(resp.Executions),
Executions: executionsToPb(resp.Executions),
Pagination: filter.QueryToPaginationPb(queries.SearchRequest, resp.SearchResponse),
}), nil
}

View File

@@ -290,7 +290,7 @@ service ActionService {
// - `actions`
rpc ListTargets (ListTargetsRequest) returns (ListTargetsResponse) {
option (google.api.http) = {
post: "/v2beta/actions/targets/_search",
post: "/v2beta/actions/targets/search",
body: "*"
};
@@ -372,7 +372,8 @@ service ActionService {
// - `actions`
rpc ListExecutions (ListExecutionsRequest) returns (ListExecutionsResponse) {
option (google.api.http) = {
post: "/v2beta/actions/executions/_search"
post: "/v2beta/actions/executions/search"
body: "*"
};
option (zitadel.protoc_gen_zitadel.v2.options) = {
@@ -663,8 +664,9 @@ message ListTargetsRequest {
}
message ListTargetsResponse {
reserved 'result';
zitadel.filter.v2beta.PaginationResponse pagination = 1;
repeated Target result = 2;
repeated Target targets = 2;
}
message SetExecutionRequest {
@@ -703,8 +705,9 @@ message ListExecutionsRequest {
}
message ListExecutionsResponse {
reserved 'result';
zitadel.filter.v2beta.PaginationResponse pagination = 1;
repeated Execution result = 2;
repeated Execution executions = 2;
}
message ListExecutionFunctionsRequest{}

View File

@@ -11,7 +11,6 @@ import "validate/validate.proto";
import "zitadel/protoc_gen_zitadel/v2/options.proto";
import "google/protobuf/timestamp.proto";
import "zitadel/object/v3alpha/object.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/action/v2beta;action";