Skip to content

Commit

Permalink
Fix failing pipeline show command when anchor tags are used in the pi…
Browse files Browse the repository at this point in the history
…peline.yaml files

Add support for analysing multiple pipelines in show command
  • Loading branch information
nikhilsbhat committed Dec 22, 2023
1 parent abc9438 commit aaad5c3
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 37 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
cover.out
cover.html
gocd-cli
helm-images.yaml
helm-images.yaml
sample_pipeline.gocd.yaml
2 changes: 1 addition & 1 deletion cmd/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func setCLIClient(_ *cobra.Command, _ []string) error {
goCDClient := gocd.NewClient(
cliCfg.URL,
cliCfg.Auth,
cliCfg.LogLevel,
cliCfg.APILogLevel,
caContent,
)

Expand Down
1 change: 1 addition & 0 deletions cmd/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type Config struct {
YAML bool `yaml:"-"`
NoColor bool `yaml:"-"`
LogLevel string `yaml:"-"`
APILogLevel string `yaml:"-"`
FromFile string `yaml:"-"`
ToFile string `yaml:"-"`
skipCacheConfig bool
Expand Down
5 changes: 4 additions & 1 deletion cmd/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ func registerGlobalFlags(cmd *cobra.Command) {
cmd.PersistentFlags().StringVarP(&cliCfg.CaPath, "ca-file-path", "", "",
"path to file containing CA cert used to authenticate GoCD server, if you have one")
cmd.PersistentFlags().StringVarP(&cliCfg.LogLevel, "log-level", "l", "info",
"log level for gocd cli, log levels supported by [https://github.com/sirupsen/logrus] will work")
"log level for GoCD cli, log levels supported by [https://github.com/sirupsen/logrus] will work")
cmd.PersistentFlags().StringVarP(&cliCfg.APILogLevel, "api-log-level", "", "info",
"log level for GoCD API calls, this sets log level to [https://pkg.go.dev/github.com/go-resty/resty/v2#Client.SetLogger],"+
"log levels supported by [https://github.com/sirupsen/logrus] will work")
cmd.PersistentFlags().BoolVarP(&cliCfg.JSON, "json", "", false,
"enable this to Render output in JSON format")
cmd.PersistentFlags().BoolVarP(&cliCfg.YAML, "yaml", "", false,
Expand Down
80 changes: 49 additions & 31 deletions cmd/pipelines.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"strings"
"time"

goYAML "github.com/goccy/go-yaml"
"github.com/nikhilsbhat/gocd-cli/pkg/errors"
"github.com/nikhilsbhat/gocd-cli/pkg/render"
"github.com/nikhilsbhat/gocd-sdk-go"
Expand Down Expand Up @@ -1078,6 +1079,8 @@ func getPipelineFilesCommand() *cobra.Command {
Example: `gocd-cli pipeline find --path /path/to/pipelines --pattern *.gocd.yaml --pattern *.gocd.json`,
RunE: func(cmd *cobra.Command, args []string) error {
cliLogger.Debugf("searching GoCD pipelines under '%s'", goCDPipelinesPath)
cliLogger.Debug("Below is a list of files that may be identified as GoCD's pipeline files. " +
"A single file may contain multiple pipeline configurations. Use the command 'gocd-cli pipeline show' to see the pipelines in a given file.")

return filepath.Walk(goCDPipelinesPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
Expand Down Expand Up @@ -1120,7 +1123,7 @@ func getPipelineFilesCommand() *cobra.Command {
}

func showPipelineCommand() *cobra.Command {
var goCDPipeline string
var detailed bool

showPipelinePipelineCmd := &cobra.Command{
Use: "show",
Expand All @@ -1129,56 +1132,71 @@ func showPipelineCommand() *cobra.Command {
PreRunE: setCLIClient,
Example: `gocd-cli show --pipeline /path/to/sample.gocd.yaml`,
RunE: func(cmd *cobra.Command, args []string) error {
cliLogger.Debugf("analysing GoCD pipeline file '%s'", goCDPipeline)
detailedPipelineNames := make(map[string][]string, 0)
pipelineNames := make([]string, 0)

fileData, err := os.ReadFile(goCDPipeline)
if err != nil {
cliLogger.Errorf("reading GoCD pipeline file errored with '%s'", err.Error())
for _, goCDPipeline := range goCDPipelines {
cliLogger.Debugf("analysing GoCD pipeline file '%s'", goCDPipeline)

return err
}
fileData, err := os.ReadFile(goCDPipeline)
if err != nil {
cliLogger.Errorf("reading GoCD pipeline file errored with '%s'", err.Error())

type Pipelines struct {
Config map[string]interface{} `json:"pipelines,omitempty" yaml:"pipelines,omitempty"`
}
return err
}

var fileJSON Pipelines
type Pipelines struct {
Config map[string]interface{} `json:"pipelines,omitempty" yaml:"pipelines,omitempty"`
}

object := render.Object(fileData)
var fileYAML Pipelines

switch objType := object.CheckFileType(cliLogger); objType {
case render.FileTypeYAML:
if err = yaml.Unmarshal(fileData, &fileJSON); err != nil {
cliLogger.Errorf("deserializing yaml GoCD pipeline file errored with '%s'", err.Error())
object := render.Object(fileData)

return err
}
case render.FileTypeJSON:
if err = json.Unmarshal(fileData, &fileJSON); err != nil {
cliLogger.Errorf("deserializing json GoCD pipeline file errored with '%s'", err.Error())
switch objType := object.CheckFileType(cliLogger); objType {
case render.FileTypeYAML:
if err = goYAML.Unmarshal(fileData, &fileYAML); err != nil {
cliLogger.Errorf("deserializing yaml GoCD pipeline file errored with '%s'", err.Error())

return err
return err
}

for _, val := range reflect.ValueOf(fileYAML.Config).MapKeys() {
pipelineNames = append(pipelineNames, val.String())
}
case render.FileTypeJSON:
var fileJSON map[string]interface{}

if err = json.Unmarshal(fileData, &fileJSON); err != nil {
cliLogger.Errorf("deserializing json GoCD pipeline file errored with '%s'", err.Error())

return err
}

pipelineNames = append(pipelineNames, fileJSON["name"].(string))
default:
cliLogger.Errorf("the command `pipeline show` does not support reading pipeline config file that was passed")

return &errors.UnknownObjectTypeError{Name: objType}
}
default:
cliLogger.Errorf("the command `pipeline show` does not support reading pipeline config file that was passed")

return &errors.UnknownObjectTypeError{Name: objType}
detailedPipelineNames[goCDPipeline] = pipelineNames
}

pipelineNames := make([]string, 0)

for _, val := range reflect.ValueOf(fileJSON.Config).MapKeys() {
pipelineNames = append(pipelineNames, val.String())
if detailed {
return cliRenderer.Render(detailedPipelineNames)
}

return cliRenderer.Render(pipelineNames)
},
}

showPipelinePipelineCmd.PersistentFlags().StringVarP(&goCDPipeline, "pipeline", "f", "",
showPipelinePipelineCmd.PersistentFlags().StringSliceVarP(&goCDPipelines, "pipelines", "f", nil,
"path to GoCD pipeline config file to identify pipeline names")
showPipelinePipelineCmd.PersistentFlags().BoolVarP(&detailed, "detailed", "", false,
"when enabled prints the information in detail")

if err := showPipelinePipelineCmd.MarkPersistentFlagRequired("pipeline"); err != nil {
if err := showPipelinePipelineCmd.MarkPersistentFlagRequired("pipelines"); err != nil {
cliLogger.Fatalf("%v", err)
}

Expand Down
7 changes: 6 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,29 @@ go 1.21

require (
github.com/ghodss/yaml v1.0.0
github.com/goccy/go-yaml v1.11.2
github.com/nikhilsbhat/gocd-sdk-go v0.1.9-0.20230914073201-732c431eb78e
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.6.1
github.com/stretchr/testify v1.8.2
github.com/thedevsaddam/gojsonq/v2 v2.5.2
github.com/thoas/go-funk v0.9.3
github.com/tidwall/gjson v1.16.0
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
)

require (
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fatih/color v1.10.0 // indirect
github.com/go-resty/resty/v2 v2.7.0 // indirect
github.com/imdario/mergo v0.3.15 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/jinzhu/copier v0.4.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mattn/go-colorable v0.1.8 // indirect
github.com/mattn/go-isatty v0.0.12 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
Expand All @@ -30,5 +35,5 @@ require (
github.com/tidwall/pretty v1.2.0 // indirect
golang.org/x/net v0.15.0 // indirect
golang.org/x/sys v0.12.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
)
24 changes: 24 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,22 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
github.com/goccy/go-yaml v1.11.2 h1:joq77SxuyIs9zzxEjgyLBugMQ9NEgTWxXfz2wVqwAaQ=
github.com/goccy/go-yaml v1.11.2/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM=
github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
Expand All @@ -18,6 +30,12 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/nikhilsbhat/gocd-sdk-go v0.1.9-0.20230914073201-732c431eb78e h1:mNeqFt0S4/j+1BEglKPspSH1PrD7jaA0TmcbE8MTQP4=
github.com/nikhilsbhat/gocd-sdk-go v0.1.9-0.20230914073201-732c431eb78e/go.mod h1:ubwvA7YgcWDUXiCghrJGRKTdeVuXpDmNzIp6ZvVzdfk=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
Expand Down Expand Up @@ -52,9 +70,13 @@ github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand All @@ -63,6 +85,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
Expand Down
4 changes: 2 additions & 2 deletions pkg/render/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package render
import (
"encoding/json"

goYAML "github.com/goccy/go-yaml"
"github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
)

// Object implements method that check for file content type.
Expand All @@ -27,7 +27,7 @@ func IsJSON(content string) bool {
func IsYAML(content string) bool {
var js interface{}

return yaml.Unmarshal([]byte(content), &js) == nil
return goYAML.Unmarshal([]byte(content), &js) == nil
}

// CheckFileType checks the file type of the content passed, it validates for YAML/JSON.
Expand Down
25 changes: 25 additions & 0 deletions pkg/render/object_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package render_test

import (
"fmt"
"os"
"testing"

"github.com/nikhilsbhat/gocd-cli/pkg/render"
goCdLogger "github.com/nikhilsbhat/gocd-sdk-go/pkg/logger"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v2"
)

var log *logrus.Logger
Expand Down Expand Up @@ -51,3 +54,25 @@ name: "testing`)
assert.Equal(t, "unknown", actual)
})
}

func TestYAML(t *testing.T) {
t.Run("", func(t *testing.T) {
fileData, err := os.ReadFile("/Users/nikhil.bhat/my-opensource/gocd-cli/sampl_pipeline.gocd.yaml")
assert.NoError(t, err)

yamlMap := make(map[interface{}]interface{})
err = yaml.Unmarshal(fileData, &yamlMap)
assert.NoError(t, err)

plainYaml, err := yaml.Marshal(yamlMap)
assert.NoError(t, err)

var out map[string]interface{}
err = yaml.Unmarshal(plainYaml, &out)
assert.NoError(t, err)

fmt.Printf("%v", out)

assert.Equal(t, "", out)
})
}

0 comments on commit aaad5c3

Please sign in to comment.