github.com/actions-on-google/gactions@v3.2.0+incompatible/cmd/gactions/cli/cli.go (about)

     1  // Copyright 2020 Google LLC
     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  //     https://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 cli contains shared CLI initialization steps.
    16  package cli
    17  
    18  import (
    19  	"context"
    20  
    21  	"github.com/actions-on-google/gactions/api/sdk"
    22  	"github.com/actions-on-google/gactions/cmd/gactions/cli/decrypt"
    23  	"github.com/actions-on-google/gactions/cmd/gactions/cli/deploy"
    24  	"github.com/actions-on-google/gactions/cmd/gactions/cli/encrypt"
    25  	"github.com/actions-on-google/gactions/cmd/gactions/cli/ginit"
    26  	"github.com/actions-on-google/gactions/cmd/gactions/cli/login"
    27  	"github.com/actions-on-google/gactions/cmd/gactions/cli/logout"
    28  	"github.com/actions-on-google/gactions/cmd/gactions/cli/notices"
    29  	"github.com/actions-on-google/gactions/cmd/gactions/cli/pull"
    30  	"github.com/actions-on-google/gactions/cmd/gactions/cli/push"
    31  	"github.com/actions-on-google/gactions/cmd/gactions/cli/releasechannels"
    32  	"github.com/actions-on-google/gactions/cmd/gactions/cli/version"
    33  	"github.com/actions-on-google/gactions/cmd/gactions/cli/versions"
    34  	"github.com/actions-on-google/gactions/log"
    35  	"github.com/actions-on-google/gactions/project/studio"
    36  	"github.com/spf13/cobra"
    37  )
    38  
    39  const (
    40  	verboseFlagName  = "verbose"
    41  	consumerFlagName = "consumer"
    42  )
    43  
    44  // Command returns a *cobra.Command setup with the common set of commands
    45  // and configuration already done.
    46  func Command(ctx context.Context, name string, debug bool, ver string) *cobra.Command {
    47  	root := &cobra.Command{
    48  		Use:           name,
    49  		Short:         "Command Line Interface for Google Actions SDK",
    50  		SilenceUsage:  true,
    51  		SilenceErrors: true, // Would like to print errors ourselves.
    52  	}
    53  	root.PersistentFlags().BoolP(verboseFlagName, "v", false, "Display additional error information")
    54  
    55  	root.PersistentFlags().String(consumerFlagName, "", "String identifying the caller to Google")
    56  	// This field is hidden as it's not documented and only used by tooling partners using the CLI.
    57  	root.PersistentFlags().MarkHidden(consumerFlagName)
    58  
    59  	projectRoot, err := studio.FindProjectRoot()
    60  	if err != nil {
    61  		projectRoot = "" // not found
    62  	}
    63  	// clientNotSoSecretJSON comes from go_embed_data rule in the BUILD file.
    64  	// The client secret is encoded directly into the source code. It's okay
    65  	// to do this based on the Google OAuth2 docs (see reference below).
    66  	// Reference:
    67  	//   https://developers.google.com/identity/protocols/OAuth2#installed
    68  	project := studio.New(clientNotSoSecretJSON, projectRoot)
    69  	ginit.AddCommand(ctx, root, project)
    70  	push.AddCommand(ctx, root, project)
    71  	deploy.AddCommand(ctx, root, project)
    72  	login.AddCommand(ctx, root, project)
    73  	logout.AddCommand(root, project)
    74  	pull.AddCommand(ctx, root, project)
    75  	encrypt.AddCommand(ctx, root, project)
    76  	decrypt.AddCommand(ctx, root, project)
    77  	version.AddCommand(root)
    78  	notices.AddCommand(root)
    79  	releasechannels.AddCommand(ctx, root, project)
    80  	versions.AddCommand(ctx, root, project)
    81  
    82  	root.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
    83  		// Init logging first since functions below may call log.
    84  		if err := initLogging(cmd, debug); err != nil {
    85  			return err
    86  		}
    87  		if err := setConsumer(cmd); err != nil {
    88  			return err
    89  		}
    90  		return nil
    91  	}
    92  	return root
    93  }
    94  
    95  func setConsumer(cmd *cobra.Command) error {
    96  	consumer, err := cmd.Flags().GetString(consumerFlagName)
    97  	if err != nil {
    98  		return err
    99  	}
   100  	sdk.Consumer = consumer
   101  	log.Debugf("Set consumer to %s\n", consumer)
   102  	return nil
   103  }
   104  
   105  func initLogging(cmd *cobra.Command, debug bool) error {
   106  	isVerbose, err := cmd.Flags().GetBool(verboseFlagName)
   107  	if err != nil {
   108  		return err
   109  	}
   110  	if isVerbose {
   111  		log.Severity = log.InfoLevel
   112  	}
   113  	// debug is the most permissive level
   114  	if debug {
   115  		log.Severity = log.DebugLevel
   116  	}
   117  	return nil
   118  }
   119  
   120  // Execute runs the command and displays errors. Returns the exit code for the CLI.
   121  func Execute(cmd *cobra.Command) int {
   122  	if err := cmd.Execute(); err != nil {
   123  		log.Error(err)
   124  		return 1
   125  	}
   126  	return 0
   127  }