From 80eafc507b5f397d32b577e3bafa6a35b95c7989 Mon Sep 17 00:00:00 2001 From: Kyle Ellrott Date: Tue, 2 Jan 2024 16:30:44 -0800 Subject: [PATCH 1/8] Adding method to scan directory of sifter files and list their outputs --- cmd/root.go | 2 ++ cmd/scan/main.go | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 cmd/scan/main.go diff --git a/cmd/root.go b/cmd/root.go index d23161c..86df762 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -5,6 +5,7 @@ import ( "github.com/bmeg/sifter/cmd/inspect" "github.com/bmeg/sifter/cmd/run" + "github.com/bmeg/sifter/cmd/scan" "github.com/spf13/cobra" ) @@ -18,6 +19,7 @@ var RootCmd = &cobra.Command{ func init() { RootCmd.AddCommand(run.Cmd) RootCmd.AddCommand(inspect.Cmd) + RootCmd.AddCommand(scan.Cmd) } var genBashCompletionCmd = &cobra.Command{ diff --git a/cmd/scan/main.go b/cmd/scan/main.go new file mode 100644 index 0000000..6991de0 --- /dev/null +++ b/cmd/scan/main.go @@ -0,0 +1,68 @@ +package scan + +import ( + "fmt" + "io/fs" + "path/filepath" + "strings" + + "github.com/bmeg/sifter/playbook" + "github.com/spf13/cobra" +) + +var jsonOut = false + +// Cmd is the declaration of the command line +var Cmd = &cobra.Command{ + Use: "scan ", + Short: "Scan for outputs", + Args: cobra.MinimumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + + baseDir := args[0] + + ScanSifter(baseDir, func(pb *playbook.Playbook) { + + for pname, p := range pb.Pipelines { + emitName := "" + for _, s := range p { + if s.Emit != nil { + emitName = s.Emit.Name + } + } + if emitName != "" { + for _, s := range p { + if s.ObjectValidate != nil { + outdir := pb.GetDefaultOutDir() + outname := fmt.Sprintf("%s.%s.%s.json.gz", pb.Name, pname, emitName) + outpath := filepath.Join(outdir, outname) + //outpath, _ = filepath.Rel(baseDir, outpath) + fmt.Printf("%s\t%s\n", s.ObjectValidate.Title, outpath) + } + } + } + } + + }) + + return nil + }, +} + +func init() { + flags := Cmd.Flags() + flags.BoolVarP(&jsonOut, "json", "j", jsonOut, "Output JSON") +} + +func ScanSifter(baseDir string, userFunc func(*playbook.Playbook)) { + filepath.Walk(baseDir, + func(path string, info fs.FileInfo, err error) error { + if strings.HasSuffix(path, ".yaml") { + pb := playbook.Playbook{} + if parseErr := playbook.ParseFile(path, &pb); parseErr == nil { + userFunc(&pb) + } + } + return nil + }) +} From 51a570fb203a2f7e00ca790e7a7e1b4073d3f662 Mon Sep 17 00:00:00 2001 From: Kyle Ellrott Date: Wed, 3 Jan 2024 15:51:04 -0800 Subject: [PATCH 2/8] Adding command for scanning for sifter scripts --- cmd/scan/main.go | 168 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 157 insertions(+), 11 deletions(-) diff --git a/cmd/scan/main.go b/cmd/scan/main.go index 6991de0..2dee020 100644 --- a/cmd/scan/main.go +++ b/cmd/scan/main.go @@ -1,28 +1,39 @@ package scan import ( + "encoding/json" "fmt" "io/fs" + "os" "path/filepath" "strings" "github.com/bmeg/sifter/playbook" + "github.com/bmeg/sifter/task" "github.com/spf13/cobra" ) var jsonOut = false +var objectsOnly = false +var baseDir = "" -// Cmd is the declaration of the command line -var Cmd = &cobra.Command{ - Use: "scan ", +type ScanEntry struct { + ObjectType string `json:"objectType"` + SifterFile string `json:"sifterFile"` + Outfile string `json:"outFile"` +} + +var ObjectCommand = &cobra.Command{ + Use: "objects", Short: "Scan for outputs", Args: cobra.MinimumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - baseDir := args[0] + scanDir := args[0] - ScanSifter(baseDir, func(pb *playbook.Playbook) { + outputs := []ScanEntry{} + ScanSifter(scanDir, func(pb *playbook.Playbook) { for pname, p := range pb.Pipelines { emitName := "" for _, s := range p { @@ -32,26 +43,161 @@ var Cmd = &cobra.Command{ } if emitName != "" { for _, s := range p { + outdir := pb.GetDefaultOutDir() + outname := fmt.Sprintf("%s.%s.%s.json.gz", pb.Name, pname, emitName) + outpath := filepath.Join(outdir, outname) + o := ScanEntry{SifterFile: pb.GetPath(), Outfile: outpath} if s.ObjectValidate != nil { - outdir := pb.GetDefaultOutDir() - outname := fmt.Sprintf("%s.%s.%s.json.gz", pb.Name, pname, emitName) - outpath := filepath.Join(outdir, outname) //outpath, _ = filepath.Rel(baseDir, outpath) - fmt.Printf("%s\t%s\n", s.ObjectValidate.Title, outpath) + //fmt.Printf("%s\t%s\n", s.ObjectValidate.Title, outpath) + o.ObjectType = s.ObjectValidate.Title + } + if objectsOnly { + if o.ObjectType != "" { + outputs = append(outputs, o) + } + } else { + outputs = append(outputs, o) } } } } + }) + + if jsonOut { + j := json.NewEncoder(os.Stdout) + j.SetIndent("", " ") + j.Encode(outputs) + } else { + for _, i := range outputs { + fmt.Printf("%s\t%s\n", i.ObjectType, i.Outfile) + } + } + + return nil + + }, +} + +type ScriptEntry struct { + Path string `json:"path"` + Inputs []string `json:"inputs"` + Outputs []string `json:"outputs"` +} + +func removeDuplicates(s []string) []string { + t := map[string]bool{} + + for _, i := range s { + t[i] = true + } + out := []string{} + for k := range t { + out = append(out, k) + } + return out +} + +func relPathArray(basedir string, paths []string) []string { + out := []string{} + for _, i := range paths { + if o, err := filepath.Rel(baseDir, i); err == nil { + out = append(out, o) + } + } + return out +} + +var ScriptCommand = &cobra.Command{ + Use: "scripts", + Short: "Scan for scripts", + Args: cobra.MinimumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + + scanDir := args[0] + + scripts := []ScriptEntry{} + if baseDir == "" { + baseDir, _ = os.Getwd() + } + baseDir, _ = filepath.Abs(baseDir) + //fmt.Printf("basedir: %s\n", baseDir) + + userInputs := map[string]string{} + + ScanSifter(scanDir, func(pb *playbook.Playbook) { + path := pb.GetPath() + scriptDir := filepath.Dir(path) + + config, _ := pb.PrepConfig(userInputs, baseDir) + + task := task.NewTask(pb.Name, scriptDir, baseDir, pb.GetDefaultOutDir(), config) + sourcePath, _ := filepath.Abs(path) + + cmdPath, _ := filepath.Rel(baseDir, sourcePath) + + inputs := []string{} + outputs := []string{} + for _, p := range pb.GetConfigFields() { + if p.IsDir() || p.IsFile() { + inputs = append(inputs, config[p.Name]) + } + } + //inputs = append(inputs, sourcePath) + + sinks, _ := pb.GetOutputs(task) + for _, v := range sinks { + outputs = append(outputs, v...) + } + + emitters, _ := pb.GetEmitters(task) + for _, v := range emitters { + outputs = append(outputs, v) + } + + //for _, e := range pb.Inputs { + //} + + s := ScriptEntry{ + Path: cmdPath, + Outputs: relPathArray(baseDir, removeDuplicates(outputs)), + Inputs: relPathArray(baseDir, removeDuplicates(inputs)), + } + scripts = append(scripts, s) }) + if jsonOut { + e := json.NewEncoder(os.Stdout) + e.SetIndent("", " ") + e.Encode(scripts) + } else { + for _, i := range scripts { + fmt.Printf("%s\n", i) + } + } + return nil }, } +// Cmd is the declaration of the command line +var Cmd = &cobra.Command{ + Use: "scan", +} + func init() { - flags := Cmd.Flags() - flags.BoolVarP(&jsonOut, "json", "j", jsonOut, "Output JSON") + Cmd.AddCommand(ObjectCommand) + Cmd.AddCommand(ScriptCommand) + + objFlags := ObjectCommand.Flags() + objFlags.BoolVarP(&objectsOnly, "objects", "s", objectsOnly, "Objects Only") + objFlags.BoolVarP(&jsonOut, "json", "j", jsonOut, "Output JSON") + + scriptFlags := ScriptCommand.Flags() + scriptFlags.StringVarP(&baseDir, "base", "b", baseDir, "Base Dir") + scriptFlags.BoolVarP(&jsonOut, "json", "j", jsonOut, "Output JSON") + } func ScanSifter(baseDir string, userFunc func(*playbook.Playbook)) { From d8ede7308bb2e48357685c286d3c262843214652 Mon Sep 17 00:00:00 2001 From: Kyle Ellrott Date: Sat, 13 Jan 2024 13:02:22 -0800 Subject: [PATCH 3/8] Adding graph build plan method --- cmd/graph_plan/main.go | 193 +++++++++++++++++++++++++++++++++++++++++ cmd/root.go | 2 + 2 files changed, 195 insertions(+) create mode 100644 cmd/graph_plan/main.go diff --git a/cmd/graph_plan/main.go b/cmd/graph_plan/main.go new file mode 100644 index 0000000..83c2040 --- /dev/null +++ b/cmd/graph_plan/main.go @@ -0,0 +1,193 @@ +package graph_plan + +import ( + "fmt" + "html/template" + "io/fs" + "log" + "os" + "path/filepath" + "strings" + + "github.com/bmeg/sifter/evaluate" + "github.com/bmeg/sifter/playbook" + "github.com/bmeg/sifter/task" + "github.com/spf13/cobra" +) + +type ObjectConvertStep struct { + Name string + Input string + Class string + Schema string +} + +type GraphBuildStep struct { + Name string + Outdir string + Objects []ObjectConvertStep +} + +var graphScript string = ` + +name: {{.Name}} +class: sifter + +outdir: {{.Outdir}} + +config: +{{range .Objects}} + {{.Name}}: {{.Input}} + {{.Name}}Schema: {{.Schema}} +{{end}} + +inputs: +{{range .Objects}} + {{.Name}}: + jsonLoad: + input: "{{ "{{config." }}{{.Name}}{{"}}"}}" +{{end}} + +pipelines: +{{range .Objects}} + {{.Name}}-graph: + - from: {{.Name}} + - graphBuild: + schema: "{{ "{{config."}}{{.Name}}Schema{{ "}}" }}" + title: {{.Class}} +{{end}} +` + +func contains(n string, c []string) bool { + for _, c := range c { + if n == c { + return true + } + } + return false +} + +func uniqueName(name string, used []string) string { + if !contains(name, used) { + return name + } + for i := 1; ; i++ { + f := fmt.Sprintf("%s_%d", name, i) + if !contains(f, used) { + return f + } + } +} + +var outScriptDir = "" +var outDataDir = "./" + +// Cmd is the declaration of the command line +var Cmd = &cobra.Command{ + Use: "graph-plan", + Short: "Scan directory to plan operations", + Args: cobra.MinimumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + + baseDir, _ := filepath.Abs(args[0]) + + if outScriptDir != "" { + baseDir, _ = filepath.Abs(outScriptDir) + } else if len(args) > 1 { + return fmt.Errorf("for multiple input directories, based dir must be defined") + } + + _ = baseDir + + outDataDir, _ = filepath.Abs(outDataDir) + outScriptDir, _ = filepath.Abs(outScriptDir) + //outScriptDir, _ = filepath.Rel(baseDir, outScriptDir) + + userInputs := map[string]string{} + + for _, dir := range args { + startDir, _ := filepath.Abs(dir) + filepath.Walk(startDir, + func(path string, info fs.FileInfo, err error) error { + if strings.HasSuffix(path, ".yaml") { + log.Printf("Scanning: %s", path) + pb := playbook.Playbook{} + if sifterErr := playbook.ParseFile(path, &pb); sifterErr == nil { + if len(pb.Pipelines) > 0 || len(pb.Inputs) > 0 { + + localInputs, err := pb.PrepConfig(userInputs, baseDir) + if err == nil { + scriptDir := filepath.Dir(path) + task := task.NewTask(pb.Name, scriptDir, baseDir, pb.GetDefaultOutDir(), localInputs) + + curDataDir, err := filepath.Rel(outScriptDir, outDataDir) + if err != nil { + log.Printf("Path error: %s", err) + } + + gb := GraphBuildStep{Name: pb.Name, Objects: []ObjectConvertStep{}, Outdir: curDataDir} + + for pname, p := range pb.Pipelines { + emitName := "" + for _, s := range p { + if s.Emit != nil { + emitName = s.Emit.Name + } + } + if emitName != "" { + for _, s := range p { + if s.ObjectValidate != nil { + schema, _ := evaluate.ExpressionString(s.ObjectValidate.Schema, task.GetConfig(), map[string]any{}) + outdir := pb.GetDefaultOutDir() + outname := fmt.Sprintf("%s.%s.%s.json.gz", pb.Name, pname, emitName) + + outpath := filepath.Join(outdir, outname) + outpath, _ = filepath.Rel(outScriptDir, outpath) + + schemaPath, _ := filepath.Rel(outScriptDir, schema) + + _ = schemaPath + + objCreate := ObjectConvertStep{Name: pname, Input: outpath, Class: s.ObjectValidate.Title, Schema: schemaPath} + gb.Objects = append(gb.Objects, objCreate) + + } + } + } + } + + if len(gb.Objects) > 0 { + log.Printf("Found %d objects", len(gb.Objects)) + tmpl, err := template.New("graphscript").Parse(graphScript) + if err != nil { + panic(err) + } + + outfile, err := os.Create(filepath.Join(outScriptDir, fmt.Sprintf("%s.yaml", pb.Name))) + if err != nil { + fmt.Printf("Error: %s\n", err) + } + err = tmpl.Execute(outfile, gb) + outfile.Close() + if err != nil { + fmt.Printf("Error: %s\n", err) + } + } + } + } + } else { + //log.Printf("Error: %s", sifterErr) + } + } + return nil + }) + } + return nil + }, +} + +func init() { + flags := Cmd.Flags() + flags.StringVarP(&outScriptDir, "dir", "C", outScriptDir, "Change Directory for script base") + flags.StringVarP(&outDataDir, "out", "o", outDataDir, "Change output Directory") +} diff --git a/cmd/root.go b/cmd/root.go index d23161c..d0c7474 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -3,6 +3,7 @@ package cmd import ( "os" + "github.com/bmeg/sifter/cmd/graph_plan" "github.com/bmeg/sifter/cmd/inspect" "github.com/bmeg/sifter/cmd/run" "github.com/spf13/cobra" @@ -18,6 +19,7 @@ var RootCmd = &cobra.Command{ func init() { RootCmd.AddCommand(run.Cmd) RootCmd.AddCommand(inspect.Cmd) + RootCmd.AddCommand(graph_plan.Cmd) } var genBashCompletionCmd = &cobra.Command{ From cce225b1e1bc6c41d7262606430ef485cc5013bb Mon Sep 17 00:00:00 2001 From: Kyle Ellrott Date: Mon, 29 Jan 2024 15:24:55 -0800 Subject: [PATCH 4/8] Adding more output to script scanning --- cmd/scan/main.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/scan/main.go b/cmd/scan/main.go index 2dee020..493b732 100644 --- a/cmd/scan/main.go +++ b/cmd/scan/main.go @@ -80,6 +80,7 @@ var ObjectCommand = &cobra.Command{ } type ScriptEntry struct { + Name string `json:"name"` Path string `json:"path"` Inputs []string `json:"inputs"` Outputs []string `json:"outputs"` @@ -161,6 +162,7 @@ var ScriptCommand = &cobra.Command{ s := ScriptEntry{ Path: cmdPath, + Name: pb.Name, Outputs: relPathArray(baseDir, removeDuplicates(outputs)), Inputs: relPathArray(baseDir, removeDuplicates(inputs)), } @@ -183,7 +185,8 @@ var ScriptCommand = &cobra.Command{ // Cmd is the declaration of the command line var Cmd = &cobra.Command{ - Use: "scan", + Use: "scan", + Short: "Scan for scripts or objects", } func init() { From bf7c7877d25923bf07985460e57203f9ad84b1e9 Mon Sep 17 00:00:00 2001 From: Kyle Ellrott Date: Mon, 29 Jan 2024 16:51:25 -0800 Subject: [PATCH 5/8] Fixing lint issues --- cmd/{graph_plan => graphplan}/main.go | 2 +- cmd/root.go | 4 ++-- cmd/run/run.go | 2 +- cmd/scan/main.go | 12 ++++++------ task/task.go | 6 +++--- transform/object_validate.go | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) rename cmd/{graph_plan => graphplan}/main.go (98%) diff --git a/cmd/graph_plan/main.go b/cmd/graphplan/main.go similarity index 98% rename from cmd/graph_plan/main.go rename to cmd/graphplan/main.go index 30366de..3b8843e 100644 --- a/cmd/graph_plan/main.go +++ b/cmd/graphplan/main.go @@ -1,4 +1,4 @@ -package graph_plan +package graphplan import ( "log" diff --git a/cmd/root.go b/cmd/root.go index 99a0e6e..2e889eb 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -3,7 +3,7 @@ package cmd import ( "os" - "github.com/bmeg/sifter/cmd/graph_plan" + "github.com/bmeg/sifter/cmd/graphplan" "github.com/bmeg/sifter/cmd/inspect" "github.com/bmeg/sifter/cmd/run" "github.com/bmeg/sifter/cmd/scan" @@ -20,7 +20,7 @@ var RootCmd = &cobra.Command{ func init() { RootCmd.AddCommand(run.Cmd) RootCmd.AddCommand(inspect.Cmd) - RootCmd.AddCommand(graph_plan.Cmd) + RootCmd.AddCommand(graphplan.Cmd) RootCmd.AddCommand(scan.Cmd) } diff --git a/cmd/run/run.go b/cmd/run/run.go index 574fdb5..07ad0b9 100644 --- a/cmd/run/run.go +++ b/cmd/run/run.go @@ -21,7 +21,7 @@ func ExecuteFile(playFile string, workDir string, outDir string, inputs map[stri a, _ := filepath.Abs(playFile) baseDir := filepath.Dir(a) log.Printf("basedir: %s", baseDir) - log.Printf("playbook: %s", pb) + log.Printf("playbook: %#v", pb) return Execute(pb, baseDir, workDir, outDir, inputs) } diff --git a/cmd/scan/main.go b/cmd/scan/main.go index 493b732..f1fbe48 100644 --- a/cmd/scan/main.go +++ b/cmd/scan/main.go @@ -17,7 +17,7 @@ var jsonOut = false var objectsOnly = false var baseDir = "" -type ScanEntry struct { +type Entry struct { ObjectType string `json:"objectType"` SifterFile string `json:"sifterFile"` Outfile string `json:"outFile"` @@ -31,9 +31,9 @@ var ObjectCommand = &cobra.Command{ scanDir := args[0] - outputs := []ScanEntry{} + outputs := []Entry{} - ScanSifter(scanDir, func(pb *playbook.Playbook) { + PathWalker(scanDir, func(pb *playbook.Playbook) { for pname, p := range pb.Pipelines { emitName := "" for _, s := range p { @@ -46,7 +46,7 @@ var ObjectCommand = &cobra.Command{ outdir := pb.GetDefaultOutDir() outname := fmt.Sprintf("%s.%s.%s.json.gz", pb.Name, pname, emitName) outpath := filepath.Join(outdir, outname) - o := ScanEntry{SifterFile: pb.GetPath(), Outfile: outpath} + o := Entry{SifterFile: pb.GetPath(), Outfile: outpath} if s.ObjectValidate != nil { //outpath, _ = filepath.Rel(baseDir, outpath) //fmt.Printf("%s\t%s\n", s.ObjectValidate.Title, outpath) @@ -127,7 +127,7 @@ var ScriptCommand = &cobra.Command{ userInputs := map[string]string{} - ScanSifter(scanDir, func(pb *playbook.Playbook) { + PathWalker(scanDir, func(pb *playbook.Playbook) { path := pb.GetPath() scriptDir := filepath.Dir(path) @@ -203,7 +203,7 @@ func init() { } -func ScanSifter(baseDir string, userFunc func(*playbook.Playbook)) { +func PathWalker(baseDir string, userFunc func(*playbook.Playbook)) { filepath.Walk(baseDir, func(path string, info fs.FileInfo, err error) error { if strings.HasSuffix(path, ".yaml") { diff --git a/task/task.go b/task/task.go index da33da2..721aeb4 100644 --- a/task/task.go +++ b/task/task.go @@ -107,10 +107,10 @@ func (m *Task) BaseDir() string { func (m *Task) Emit(n string, e map[string]interface{}, useName bool) error { - new_name := m.GetName() + "." + n + newName := m.GetName() + "." + n if useName { temp := strings.Split(n, ".") - new_name = temp[len(temp)-1] + newName = temp[len(temp)-1] } - return m.Emitter.Emit(new_name, e, useName) + return m.Emitter.Emit(newName, e, useName) } diff --git a/transform/object_validate.go b/transform/object_validate.go index 28ee452..08838cc 100644 --- a/transform/object_validate.go +++ b/transform/object_validate.go @@ -10,7 +10,7 @@ import ( "github.com/bmeg/sifter/evaluate" "github.com/bmeg/sifter/task" "github.com/santhosh-tekuri/jsonschema/v5" - _ "github.com/santhosh-tekuri/jsonschema/v5/httploader" + _ "github.com/santhosh-tekuri/jsonschema/v5/httploader" // setup the httploader for the jsonschema checker ) type ObjectValidateStep struct { From e8376048527772c7ba02ac4cc339dc922385660a Mon Sep 17 00:00:00 2001 From: Kyle Ellrott Date: Mon, 29 Jan 2024 16:56:53 -0800 Subject: [PATCH 6/8] Updating lint test --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3691d9c..53011b8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -40,4 +40,4 @@ jobs: with: # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version version: v1.50.1 - args: --timeout 2m --disable-all -E gofmt + args: --timeout 2m From 66071a354434d656cf7b8c0d3aac100651833c0a Mon Sep 17 00:00:00 2001 From: Kyle Ellrott Date: Mon, 29 Jan 2024 17:04:35 -0800 Subject: [PATCH 7/8] Removing depricated linter --- .golangci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.golangci.yml b/.golangci.yml index d9a5733..0bbd141 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -23,6 +23,5 @@ linters: - goimports - misspell - typecheck - - golint - gosimple - govet \ No newline at end of file From dec97a1fc7da23417c8e022cb3625f2c4259509e Mon Sep 17 00:00:00 2001 From: Kyle Ellrott Date: Mon, 29 Jan 2024 17:10:34 -0800 Subject: [PATCH 8/8] Updating github actions --- .github/workflows/tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 53011b8..a00af99 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -33,11 +33,11 @@ jobs: steps: - uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.21 - uses: actions/checkout@v3 - name: golangci-lint uses: golangci/golangci-lint-action@v3 with: # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version - version: v1.50.1 - args: --timeout 2m + version: v1.54 + # args: --timeout 2m