github.com/olli-ai/jx/v2@v2.0.400-0.20210921045218-14731b4dd448/pkg/cmd/create/create_step.go (about)

     1  package create
     2  
     3  import (
     4  	"strings"
     5  
     6  	"github.com/olli-ai/jx/v2/pkg/cmd/create/options"
     7  
     8  	"github.com/olli-ai/jx/v2/pkg/cmd/helper"
     9  
    10  	"github.com/jenkins-x/jx-logging/pkg/log"
    11  	"github.com/olli-ai/jx/v2/pkg/cmd/opts"
    12  	"github.com/olli-ai/jx/v2/pkg/cmd/templates"
    13  	"github.com/olli-ai/jx/v2/pkg/config"
    14  	"github.com/olli-ai/jx/v2/pkg/jenkinsfile"
    15  	"github.com/olli-ai/jx/v2/pkg/tekton/syntax"
    16  	"github.com/olli-ai/jx/v2/pkg/util"
    17  	"github.com/spf13/cobra"
    18  	survey "gopkg.in/AlecAivazis/survey.v1"
    19  )
    20  
    21  const (
    22  	defaultPipeline  = "release"
    23  	defaultLifecycle = "build"
    24  	defaultMode      = jenkinsfile.CreateStepModePost
    25  )
    26  
    27  var (
    28  	createStepLong = templates.LongDesc(`
    29  		Creates a step in the Jenkins X Pipeline
    30  `)
    31  
    32  	createStepExample = templates.Examples(`
    33  		# Create a new step in the Jenkins X Pipeline interactively
    34  		jx create step
    35  
    36  		# Creates a step on the command line: adding a post step to the release build lifecycle
    37  		jx create step -sh "echo hello world"
    38  
    39  		# Creates a step on the command line: adding a pre step to the pullRequest promote lifecycle
    40  		jx create step -p pullrequest -l promote -m pre -c "echo before promote"
    41  	`)
    42  )
    43  
    44  // NewStepDetails configures a new step
    45  type NewStepDetails struct {
    46  	Pipeline  string
    47  	Lifecycle string
    48  	Mode      string
    49  	Step      syntax.Step
    50  }
    51  
    52  // AddToPipeline adds the step to the given pipeline configuration
    53  func (s *NewStepDetails) AddToPipeline(projectConfig *config.ProjectConfig) error {
    54  	pipelines := projectConfig.GetOrCreatePipelineConfig()
    55  	pipeline, err := pipelines.Pipelines.GetPipeline(s.Pipeline, true)
    56  	if err != nil {
    57  		return err
    58  	}
    59  	lifecycle, err := pipeline.GetLifecycle(s.Lifecycle, true)
    60  	if err != nil {
    61  		return err
    62  	}
    63  	return lifecycle.CreateStep(s.Mode, &s.Step)
    64  }
    65  
    66  // CreateStepOptions the options for the create spring command
    67  type CreateStepOptions struct {
    68  	options.CreateOptions
    69  
    70  	Dir            string
    71  	NewStepDetails NewStepDetails
    72  }
    73  
    74  // NewCmdCreateStep creates a command object for the "create" command
    75  func NewCmdCreateStep(commonOpts *opts.CommonOptions) *cobra.Command {
    76  	options := &CreateStepOptions{
    77  		CreateOptions: options.CreateOptions{
    78  			CommonOptions: commonOpts,
    79  		},
    80  	}
    81  
    82  	cmd := &cobra.Command{
    83  		Use:     "step",
    84  		Short:   "Creates a step in the Jenkins X Pipeline",
    85  		Aliases: []string{"steps"},
    86  		Long:    createStepLong,
    87  		Example: createStepExample,
    88  		Run: func(cmd *cobra.Command, args []string) {
    89  			options.Cmd = cmd
    90  			options.Args = args
    91  			err := options.Run()
    92  			helper.CheckErr(err)
    93  		},
    94  	}
    95  
    96  	step := &options.NewStepDetails
    97  	cmd.Flags().StringVarP(&step.Pipeline, "pipeline", "p", "", "The pipeline kind to add your step. Possible values: "+strings.Join(jenkinsfile.PipelineKinds, ", "))
    98  	cmd.Flags().StringVarP(&step.Lifecycle, "lifecycle", "l", "", "The lifecycle stage to add your step. Possible values: "+strings.Join(jenkinsfile.PipelineLifecycleNames, ", "))
    99  	cmd.Flags().StringVarP(&step.Mode, "mode", "m", "", "The create mode for the new step. Possible values: "+strings.Join(jenkinsfile.CreateStepModes, ", "))
   100  	cmd.Flags().StringVarP(&step.Step.Command, "sh", "c", "", "The command to invoke for the new step")
   101  	cmd.Flags().StringVarP(&options.Dir, "dir", "d", "", "The root project directory. Defaults to the current dir")
   102  
   103  	return cmd
   104  }
   105  
   106  // Run implements the command
   107  func (o *CreateStepOptions) Run() error {
   108  	projectConfig, fileName, err := o.AddStepToProjectConfig()
   109  	if err != nil {
   110  		return err
   111  	}
   112  	err = projectConfig.SaveConfig(fileName)
   113  	if err != nil {
   114  		return err
   115  	}
   116  	log.Logger().Infof("Updated Jenkins X Pipeline file: %s", util.ColorInfo(fileName))
   117  	return nil
   118  
   119  }
   120  
   121  // AddStepToProjectConfig creates the new step, adds it to the project config, and returns the modified project config.
   122  func (o *CreateStepOptions) AddStepToProjectConfig() (*config.ProjectConfig, string, error) {
   123  	dir := o.Dir
   124  	var err error
   125  	if dir == "" {
   126  		dir, _, err := o.Git().FindGitConfigDir(o.Dir)
   127  		if err != nil {
   128  			return nil, "", err
   129  		}
   130  		if dir == "" {
   131  			dir = "."
   132  		}
   133  	}
   134  	projectConfig, fileName, err := config.LoadProjectConfig(dir)
   135  	if err != nil {
   136  		return nil, "", err
   137  	}
   138  
   139  	s := &o.NewStepDetails
   140  	err = o.configureNewStepDetails(s)
   141  	if err != nil {
   142  		return nil, "", err
   143  	}
   144  
   145  	err = s.AddToPipeline(projectConfig)
   146  	if err != nil {
   147  		return nil, "", err
   148  	}
   149  
   150  	return projectConfig, fileName, nil
   151  }
   152  
   153  func (o *CreateStepOptions) configureNewStepDetails(stepDetails *NewStepDetails) error {
   154  	s := &o.NewStepDetails
   155  	if o.BatchMode {
   156  		if s.Pipeline == "" {
   157  			s.Pipeline = defaultPipeline
   158  		}
   159  		if s.Lifecycle == "" {
   160  			s.Lifecycle = defaultLifecycle
   161  		}
   162  		if s.Mode == "" {
   163  			s.Mode = defaultMode
   164  		}
   165  		if s.Step.GetCommand() == "" {
   166  			return util.MissingOption("command")
   167  		}
   168  		return nil
   169  	}
   170  	var err error
   171  
   172  	if s.Pipeline == "" {
   173  		s.Pipeline, err = util.PickNameWithDefault(jenkinsfile.PipelineKinds, "Pick the pipeline kind: ", defaultPipeline, "which kind of pipeline do you want to add a step", o.GetIOFileHandles())
   174  		if err != nil {
   175  			return err
   176  		}
   177  	}
   178  	if s.Lifecycle == "" {
   179  		s.Lifecycle, err = util.PickNameWithDefault(jenkinsfile.PipelineLifecycleNames, "Pick the lifecycle: ", defaultLifecycle, "which lifecycle (stage) do you want to add the step", o.GetIOFileHandles())
   180  		if err != nil {
   181  			return err
   182  		}
   183  	}
   184  	if s.Mode == "" {
   185  		s.Mode, err = util.PickNameWithDefault(jenkinsfile.CreateStepModes, "Pick the create mode: ", defaultMode, "which create mode do you want to use to add the step - pre (before), post (after) or replace?", o.GetIOFileHandles())
   186  		if err != nil {
   187  			return err
   188  		}
   189  	}
   190  	if s.Step.GetCommand() == "" {
   191  		prompt := &survey.Input{
   192  			Message: "Command for the new step: ",
   193  			Help:    "The shell command executed inside the container to implement this step",
   194  		}
   195  		err := survey.AskOne(prompt, &s.Step.Command, survey.Required, survey.WithStdio(o.In, o.Out, o.Err))
   196  		if err != nil {
   197  			return err
   198  		}
   199  	}
   200  	return nil
   201  }