-
-
Notifications
You must be signed in to change notification settings - Fork 153
Expand file tree
/
Copy pathworkflows.go
More file actions
219 lines (182 loc) · 6.43 KB
/
workflows.go
File metadata and controls
219 lines (182 loc) · 6.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
package list
import (
"fmt"
"github.com/spf13/cobra"
"github.com/spf13/viper"
e "github.com/cloudposse/atmos/internal/exec"
"github.com/cloudposse/atmos/pkg/config"
"github.com/cloudposse/atmos/pkg/flags"
"github.com/cloudposse/atmos/pkg/flags/global"
"github.com/cloudposse/atmos/pkg/list/column"
"github.com/cloudposse/atmos/pkg/list/extract"
"github.com/cloudposse/atmos/pkg/list/filter"
"github.com/cloudposse/atmos/pkg/list/format"
"github.com/cloudposse/atmos/pkg/list/renderer"
listSort "github.com/cloudposse/atmos/pkg/list/sort"
"github.com/cloudposse/atmos/pkg/schema"
"github.com/cloudposse/atmos/pkg/ui"
)
var workflowsParser *flags.StandardParser
// WorkflowsOptions contains parsed flags for the workflows command.
type WorkflowsOptions struct {
global.Flags
File string
Format string
Columns []string
Sort string
}
// workflowsCmd lists atmos workflows.
var workflowsCmd = &cobra.Command{
Use: "workflows",
Short: "List all Atmos workflows with filtering, sorting, and formatting options",
Long: `List Atmos workflows with support for filtering by file, custom column selection, sorting, and multiple output formats.`,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
// Get Viper instance for flag/env precedence.
v := viper.GetViper()
// Skip stack validation for workflows (honors --base-path, --config, --config-path, --profile).
if err := checkAtmosConfig(cmd, v, true); err != nil {
return err
}
// Parse flags using StandardParser with Viper precedence.
if err := workflowsParser.BindFlagsToViper(cmd, v); err != nil {
return err
}
opts := &WorkflowsOptions{
Flags: flags.ParseGlobalFlags(cmd, v),
File: v.GetString("file"),
Format: v.GetString("format"),
Columns: v.GetStringSlice("columns"),
Sort: v.GetString("sort"),
}
return listWorkflowsWithOptions(cmd, args, opts)
},
}
// columnsCompletionForWorkflows provides dynamic tab completion for --columns flag.
// Returns column names from atmos.yaml workflows.list.columns configuration.
func columnsCompletionForWorkflows(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
// Load atmos configuration with CLI flags.
configAndStacksInfo, err := e.ProcessCommandLineArgs("list", cmd, args, nil)
if err != nil {
return nil, cobra.ShellCompDirectiveNoFileComp
}
atmosConfig, err := config.InitCliConfig(configAndStacksInfo, false)
if err != nil {
return nil, cobra.ShellCompDirectiveNoFileComp
}
// Extract column names from atmos.yaml configuration.
if len(atmosConfig.Workflows.List.Columns) > 0 {
var columnNames []string
for _, col := range atmosConfig.Workflows.List.Columns {
columnNames = append(columnNames, col.Name)
}
return columnNames, cobra.ShellCompDirectiveNoFileComp
}
// If no custom columns configured, return empty list.
return nil, cobra.ShellCompDirectiveNoFileComp
}
func init() {
// Create parser with workflows-specific flags using flag wrappers.
workflowsParser = NewListParser(
WithFormatFlag,
WithWorkflowsColumnsFlag,
WithSortFlag,
WithFileFlag,
)
// Register flags.
workflowsParser.RegisterFlags(workflowsCmd)
// Register dynamic tab completion for --columns flag.
if err := workflowsCmd.RegisterFlagCompletionFunc("columns", columnsCompletionForWorkflows); err != nil {
panic(err)
}
// Bind flags to Viper for environment variable support.
if err := workflowsParser.BindToViper(viper.GetViper()); err != nil {
panic(err)
}
}
func listWorkflowsWithOptions(cmd *cobra.Command, args []string, opts *WorkflowsOptions) error {
// Process command line args to get real ConfigAndStacksInfo with CLI flags.
configAndStacksInfo, err := e.ProcessCommandLineArgs("list", cmd, args, nil)
if err != nil {
return err
}
atmosConfig, err := config.InitCliConfig(configAndStacksInfo, false)
if err != nil {
return err
}
// If format is empty, check command-specific config.
if opts.Format == "" && atmosConfig.Workflows.List.Format != "" {
opts.Format = atmosConfig.Workflows.List.Format
}
// Extract workflows into structured data.
workflows, err := extract.Workflows(&atmosConfig, opts.File)
if err != nil {
return err
}
if len(workflows) == 0 {
ui.Info("No workflows found")
return nil
}
// Build filters.
filters := buildWorkflowFilters(opts)
// Get column configuration.
columns := getWorkflowColumns(&atmosConfig, opts.Columns)
// Build column selector.
selector, err := column.NewSelector(columns, column.BuildColumnFuncMap())
if err != nil {
return fmt.Errorf("error creating column selector: %w", err)
}
// Build sorters.
sorters, err := buildWorkflowSorters(opts.Sort)
if err != nil {
return fmt.Errorf("error parsing sort specification: %w", err)
}
// Create renderer and execute pipeline.
outputFormat := format.Format(opts.Format)
r := renderer.New(filters, selector, sorters, outputFormat, "")
return r.Render(workflows)
}
// buildWorkflowFilters creates filters based on command options.
func buildWorkflowFilters(opts *WorkflowsOptions) []filter.Filter {
var filters []filter.Filter
// File filter already handled by extraction logic.
// Add any additional filters here in the future.
return filters
}
// getWorkflowColumns returns column configuration.
func getWorkflowColumns(atmosConfig *schema.AtmosConfiguration, columnsFlag []string) []column.Config {
// If --columns flag is provided, parse it and return.
if len(columnsFlag) > 0 {
return parseColumnsFlag(columnsFlag)
}
// Check atmos.yaml for workflows.list.columns configuration.
if len(atmosConfig.Workflows.List.Columns) > 0 {
var configs []column.Config
for _, col := range atmosConfig.Workflows.List.Columns {
configs = append(configs, column.Config{
Name: col.Name,
Value: col.Value,
Width: col.Width,
})
}
return configs
}
// Default columns for workflows.
return []column.Config{
{Name: "File", Value: "{{ .file }}"},
{Name: "Workflow", Value: "{{ .workflow }}"},
{Name: "Description", Value: "{{ .description }}"},
{Name: "Steps", Value: "{{ .steps }}"},
}
}
// buildWorkflowSorters creates sorters from sort specification.
func buildWorkflowSorters(sortSpec string) ([]*listSort.Sorter, error) {
if sortSpec == "" {
// Default sort: by file ascending, then workflow ascending.
return []*listSort.Sorter{
listSort.NewSorter("File", listSort.Ascending),
listSort.NewSorter("Workflow", listSort.Ascending),
}, nil
}
return listSort.ParseSortSpec(sortSpec)
}