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 }