diff --git a/.circleci/config.yml b/.circleci/config.yml index 5e2d75f43..9505556f9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,7 +11,7 @@ workflows: requires: - test - coverage - # - lint disable lint check for now + - lint filters: branches: only: master diff --git a/client/client.go b/client/client.go index 42cc31f5c..043c73a14 100644 --- a/client/client.go +++ b/client/client.go @@ -22,9 +22,9 @@ func NewClient(endpoint string, logger *logger.Logger) *graphql.Client { } -// newAuthorizedRequest returns a new GraphQL request with the +// NewAuthorizedRequest returns a new GraphQL request with the // authorization headers set for CircleCI auth. -func newAuthorizedRequest(token, query string) *graphql.Request { +func NewAuthorizedRequest(token, query string) *graphql.Request { req := graphql.NewRequest(query) req.Header.Set("Authorization", token) return req @@ -34,7 +34,7 @@ func newAuthorizedRequest(token, query string) *graphql.Request { // Then it will execute the given query using graphql.Client.Run. // This function will return the unmarshalled response as JSON. func Run(client *graphql.Client, token, query string) (map[string]interface{}, error) { - req := newAuthorizedRequest(token, query) + req := NewAuthorizedRequest(token, query) ctx := context.Background() var resp map[string]interface{} err := client.Run(ctx, req, &resp) diff --git a/cmd/config.go b/cmd/config.go index 9f82ebedf..509d89458 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -5,6 +5,7 @@ import ( "context" "io/ioutil" + "github.com/CircleCI-Public/circleci-cli/client" "github.com/pkg/errors" "github.com/machinebox/graphql" @@ -54,11 +55,10 @@ type buildConfigResponse struct { } } -func queryAPI(query string, variables map[string]string, response interface{}) error { - ctx := context.Background() +func queryAPI(ctx context.Context, query string, variables map[string]string, response interface{}) error { + + request := client.NewAuthorizedRequest(viper.GetString("token"), query) - request := graphql.NewRequest(query) - request.Header.Set("Authorization", viper.GetString("token")) for varName, varValue := range variables { request.Var(varName, varValue) } @@ -69,6 +69,7 @@ func queryAPI(query string, variables map[string]string, response interface{}) e } func loadYaml(path string) (string, error) { + config, err := ioutil.ReadFile(path) if err != nil { @@ -91,19 +92,21 @@ func (response buildConfigResponse) processErrors() error { return errors.New(buffer.String()) } -func validateConfig(cmd *cobra.Command, args []string) error { +func configQuery(ctx context.Context) (*buildConfigResponse, error) { + query := ` query ValidateConfig ($config: String!) { buildConfig(configYaml: $config) { valid, errors { message }, - sourceYaml + sourceYaml, + outputYaml } }` config, err := loadYaml(configPath) if err != nil { - return err + return nil, err } variables := map[string]string{ @@ -111,45 +114,38 @@ func validateConfig(cmd *cobra.Command, args []string) error { } var response buildConfigResponse - err = queryAPI(query, variables, &response) + err = queryAPI(ctx, query, variables, &response) + if err != nil { + return nil, errors.Wrap(err, "Unable to validate config") + } + + return &response, nil +} + +func validateConfig(cmd *cobra.Command, args []string) error { + ctx := context.Background() + response, err := configQuery(ctx) + if err != nil { - return errors.New("Unable to validate config") + return err } if !response.BuildConfig.Valid { return response.processErrors() } - Logger.Infoln("Config is valid") + Logger.Infof("Config file at %s is valid", configPath) return nil } func expandConfig(cmd *cobra.Command, args []string) error { - query := ` - query ExpandConfig($config: String!) { - buildConfig(configYaml: $config) { - outputYaml - valid - errors { message } - } - } - ` + ctx := context.Background() + response, err := configQuery(ctx) - config, err := loadYaml(configPath) if err != nil { return err } - variables := map[string]string{ - "config": config, - } - - var response buildConfigResponse - err = queryAPI(query, variables, &response) - if err != nil { - return errors.New("Unable to expand config") - } - if !response.BuildConfig.Valid { return response.processErrors() } diff --git a/cmd/config_test.go b/cmd/config_test.go index e9ad0dffa..0becff835 100644 --- a/cmd/config_test.go +++ b/cmd/config_test.go @@ -131,18 +131,18 @@ var _ = Describe("Config", func() { }` expectedRequestJson := ` { - "query": "\n\t\tquery ValidateConfig ($config: String!) {\n\t\t\tbuildConfig(configYaml: $config) {\n\t\t\t\tvalid,\n\t\t\t\terrors { message },\n\t\t\t\tsourceYaml\n\t\t\t}\n\t\t}", - "variables": { - "config": "some config" - } - }` + "query": "\n\t\tquery ValidateConfig ($config: String!) {\n\t\t\tbuildConfig(configYaml: $config) {\n\t\t\t\tvalid,\n\t\t\t\terrors { message },\n\t\t\t\tsourceYaml,\n\t\t\t\toutputYaml\n\t\t\t}\n\t\t}", + "variables": { + "config": "some config" + } + }` appendPostHandler(testServer, token, http.StatusOK, expectedRequestJson, gqlResponse) session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) Expect(err).ShouldNot(HaveOccurred()) - Eventually(session.Out).Should(gbytes.Say("Config is valid")) + Eventually(session.Out).Should(gbytes.Say("Config file at .*circleci/config.yaml is valid")) Eventually(session).Should(gexec.Exit(0)) }) @@ -161,11 +161,11 @@ var _ = Describe("Config", func() { }` expectedRequestJson := ` { - "query": "\n\t\tquery ValidateConfig ($config: String!) {\n\t\t\tbuildConfig(configYaml: $config) {\n\t\t\t\tvalid,\n\t\t\t\terrors { message },\n\t\t\t\tsourceYaml\n\t\t\t}\n\t\t}", - "variables": { - "config": "some config" - } - }` + "query": "\n\t\tquery ValidateConfig ($config: String!) {\n\t\t\tbuildConfig(configYaml: $config) {\n\t\t\t\tvalid,\n\t\t\t\terrors { message },\n\t\t\t\tsourceYaml,\n\t\t\t\toutputYaml\n\t\t\t}\n\t\t}", + "variables": { + "config": "some config" + } + }` appendPostHandler(testServer, token, http.StatusOK, expectedRequestJson, gqlResponse) @@ -208,11 +208,11 @@ var _ = Describe("Config", func() { }` expectedRequestJson := ` { - "query": "\n\t\tquery ExpandConfig($config: String!) {\n\t\t\tbuildConfig(configYaml: $config) {\n\t\t\t\toutputYaml\n\t\t\t\tvalid\n\t\t\t\terrors { message }\n\t\t\t}\n\t\t}\n\t", - "variables": { - "config": "some config" - } - }` + "query": "\n\t\tquery ValidateConfig ($config: String!) {\n\t\t\tbuildConfig(configYaml: $config) {\n\t\t\t\tvalid,\n\t\t\t\terrors { message },\n\t\t\t\tsourceYaml,\n\t\t\t\toutputYaml\n\t\t\t}\n\t\t}", + "variables": { + "config": "some config" + } + }` appendPostHandler(testServer, token, http.StatusOK, expectedRequestJson, gqlResponse) @@ -239,11 +239,11 @@ var _ = Describe("Config", func() { }` expectedRequestJson := ` { - "query": "\n\t\tquery ExpandConfig($config: String!) {\n\t\t\tbuildConfig(configYaml: $config) {\n\t\t\t\toutputYaml\n\t\t\t\tvalid\n\t\t\t\terrors { message }\n\t\t\t}\n\t\t}\n\t", - "variables": { - "config": "some config" - } - }` + "query": "\n\t\tquery ValidateConfig ($config: String!) {\n\t\t\tbuildConfig(configYaml: $config) {\n\t\t\t\tvalid,\n\t\t\t\terrors { message },\n\t\t\t\tsourceYaml,\n\t\t\t\toutputYaml\n\t\t\t}\n\t\t}", + "variables": { + "config": "some config" + } + }` appendPostHandler(testServer, token, http.StatusOK, expectedRequestJson, gqlResponse) diff --git a/cmd/root.go b/cmd/root.go index eaf11bb32..d8ef586b9 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -11,6 +11,8 @@ import ( "github.com/spf13/viper" ) +var defaultEndpoint = "https://circleci.com/graphql-unstable" + // Execute adds all child commands to rootCmd and // sets flags appropriately. This function is called // by main.main(). It only needs to happen once to @@ -76,7 +78,7 @@ func init() { } rootCmd.PersistentFlags().BoolP("verbose", "v", false, "Enable verbose logging.") - rootCmd.PersistentFlags().StringP("endpoint", "e", "https://circleci.com/graphql-unstable", "the endpoint of your CircleCI GraphQL API") + rootCmd.PersistentFlags().StringP("endpoint", "e", defaultEndpoint, "the endpoint of your CircleCI GraphQL API") rootCmd.PersistentFlags().StringP("token", "t", "", "your token for using CircleCI") for _, flag := range []string{"endpoint", "token", "verbose"} {