Skip to content

Commit 6b74b8d

Browse files
feat: query product releases (Cr 24615) (#755)
## What <!-- What is changing in this PR? --> ## Why <!-- Why are these changes being made? --> ## Notes <!-- Add any additional notes here --> --------- Co-authored-by: Noam Gal <[email protected]>
1 parent a7c7757 commit 6b74b8d

File tree

9 files changed

+512
-2
lines changed

9 files changed

+512
-2
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
VERSION=v0.1.64
1+
VERSION=v0.1.65
22

33
OUT_DIR=dist
44
YEAR?=$(shell date +"%Y")

cmd/commands/product-release.go

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
// Copyright 2024 The Codefresh Authors.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package commands
16+
17+
import (
18+
"context"
19+
"encoding/json"
20+
"fmt"
21+
"strings"
22+
23+
"github.com/codefresh-io/cli-v2/pkg/util"
24+
25+
"github.com/codefresh-io/go-sdk/pkg/client"
26+
platmodel "github.com/codefresh-io/go-sdk/pkg/model/promotion-orchestrator"
27+
"github.com/spf13/cobra"
28+
)
29+
30+
type (
31+
productReleaseSlice struct {
32+
Edges []productReleaseEdge `json:"edges"`
33+
}
34+
35+
productReleaseEdge struct {
36+
Node map[string]any `json:"node"`
37+
}
38+
)
39+
40+
func NewProductReleaseCommand() *cobra.Command {
41+
cmd := &cobra.Command{
42+
Use: "product-release",
43+
Short: "Manage product releases of Codefresh account",
44+
PersistentPreRunE: cfConfig.RequireAuthentication,
45+
Args: cobra.NoArgs, // Workaround for subcommand usage errors. See: https://github.com/spf13/cobra/issues/706
46+
Run: func(cmd *cobra.Command, args []string) {
47+
cmd.HelpFunc()(cmd, args)
48+
exit(1)
49+
},
50+
}
51+
52+
cmd.AddCommand(newProductReleaseListCommand())
53+
54+
return cmd
55+
}
56+
57+
func newProductReleaseListCommand() *cobra.Command {
58+
var (
59+
pageLimit int
60+
statuses []string
61+
promotionFlows []string
62+
)
63+
64+
cmd := &cobra.Command{
65+
Use: "list",
66+
Short: "List all product releases",
67+
Args: cobra.MaximumNArgs(1),
68+
Example: util.Doc(`
69+
<BIN> product-release list <product-name>
70+
<BIN> product-release list <product-name> --page-limit 3
71+
<BIN> product-release list <product-name> --status RUNNING,FAILED --promotion-flows base-flow,flow-2
72+
`),
73+
RunE: func(cmd *cobra.Command, args []string) error {
74+
ctx := cmd.Context()
75+
if len(args) == 0 {
76+
return fmt.Errorf("missing product name")
77+
}
78+
79+
releaseStatus, err := toProductReleaseStatus(statuses)
80+
if err != nil {
81+
return fmt.Errorf("failed to convert status: %w", err)
82+
}
83+
84+
filterArgs := platmodel.ProductReleaseFiltersArgs{
85+
Statuses: releaseStatus,
86+
PromotionFlows: promotionFlows,
87+
}
88+
return runProductReleaseList(ctx, filterArgs, args[0], pageLimit)
89+
},
90+
}
91+
92+
cmd.Flags().StringSliceVarP(&statuses, "status", "s", []string{}, "Filter by statuses, comma seperated array RUNNING|SUCCEEDED|SUSPENDED|FAILED")
93+
cmd.Flags().StringSliceVar(&promotionFlows, "promotion-flows", []string{}, "Filter by promotion flows, comma seperated array")
94+
cmd.Flags().IntVar(&pageLimit, "page-limit", 20, "page limit number, limited to 50")
95+
96+
return cmd
97+
}
98+
99+
// client here is for mock testings usage
100+
func runProductReleaseList(ctx context.Context, filterArgs platmodel.ProductReleaseFiltersArgs, productName string, pageLimit int) error {
101+
query := `
102+
query getProductReleasesList(
103+
$productName: String!
104+
$filters: ProductReleaseFiltersArgs!
105+
$pagination: SlicePaginationArgs
106+
) {
107+
productReleases(productName: $productName, filters: $filters, pagination: $pagination) {
108+
edges {
109+
node {
110+
releaseId
111+
steps {
112+
environmentName
113+
status
114+
}
115+
status
116+
}
117+
}
118+
}
119+
}`
120+
// add pagination - default for now is last 20
121+
variables := map[string]any{
122+
"filters": filterArgs,
123+
"productName": productName,
124+
"pagination": platmodel.SlicePaginationArgs{
125+
First: &pageLimit,
126+
},
127+
}
128+
129+
productReleasesPage, err := client.GraphqlAPI[productReleaseSlice](ctx, cfConfig.NewClient().InternalClient(), query, variables)
130+
if err != nil {
131+
return fmt.Errorf("failed to get product releases: %w", err)
132+
}
133+
134+
if len(productReleasesPage.Edges) == 0 {
135+
fmt.Println("No product releases found")
136+
return nil
137+
}
138+
139+
nodes := extractNodesFromEdges(productReleasesPage.Edges)
140+
resJSON, err := json.MarshalIndent(nodes, "", "\t")
141+
if err != nil {
142+
return fmt.Errorf("failed to marshal product releases: %w", err)
143+
}
144+
145+
fmt.Println(string(resJSON))
146+
return nil
147+
}
148+
149+
func toProductReleaseStatus(statuses []string) ([]platmodel.ProductReleaseStatus, error) {
150+
var result []platmodel.ProductReleaseStatus
151+
152+
for _, statusString := range statuses {
153+
productReleaseStatus := strings.ToUpper(strings.TrimSpace(statusString))
154+
status := platmodel.ProductReleaseStatus(productReleaseStatus)
155+
if !status.IsValid() {
156+
return nil, fmt.Errorf("invalid product release status: %s", statusString)
157+
}
158+
159+
result = append(result, platmodel.ProductReleaseStatus(productReleaseStatus))
160+
}
161+
162+
return result, nil
163+
}
164+
165+
func extractNodesFromEdges(edges []productReleaseEdge) []map[string]any {
166+
res := []map[string]any{}
167+
for _, edge := range edges {
168+
res = append(res, edge.Node)
169+
}
170+
171+
return res
172+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
[
2+
{
3+
"releaseId": "669fac7668fc487b38c2ad19",
4+
"status": "FAILED",
5+
"steps": [
6+
{
7+
"environmentName": "my-env",
8+
"status": "SUCCEEDED"
9+
},
10+
{
11+
"environmentName": "staging",
12+
"status": "SUCCEEDED"
13+
},
14+
{
15+
"environmentName": "prod",
16+
"status": "FAILED"
17+
}
18+
]
19+
},
20+
{
21+
"releaseId": "669fac7668fc487b38c2ad18",
22+
"status": "FAILED",
23+
"steps": [
24+
{
25+
"environmentName": "my-env",
26+
"status": "SUCCEEDED"
27+
},
28+
{
29+
"environmentName": "staging",
30+
"status": "SUCCEEDED"
31+
},
32+
{
33+
"environmentName": "prod",
34+
"status": "FAILED"
35+
}
36+
]
37+
}
38+
]

0 commit comments

Comments
 (0)