github.com/olli-ai/jx/v2@v2.0.400-0.20210921045218-14731b4dd448/pkg/cmd/step/step_custom_pipeline.go (about) 1 package step 2 3 import ( 4 "fmt" 5 "net/url" 6 "os" 7 "path/filepath" 8 "strings" 9 "time" 10 11 "github.com/olli-ai/jx/v2/pkg/cmd/opts/step" 12 "github.com/olli-ai/jx/v2/pkg/gits" 13 14 "github.com/olli-ai/jx/v2/pkg/cmd/helper" 15 16 "github.com/jenkins-x/jx-logging/pkg/log" 17 "github.com/olli-ai/jx/v2/pkg/cmd/opts" 18 "github.com/olli-ai/jx/v2/pkg/cmd/templates" 19 "github.com/olli-ai/jx/v2/pkg/jenkins" 20 "github.com/olli-ai/jx/v2/pkg/jenkinsfile" 21 "github.com/olli-ai/jx/v2/pkg/util" 22 "github.com/pkg/errors" 23 "github.com/spf13/cobra" 24 ) 25 26 // StepCustomPipelineOptions contains the command line arguments for this command 27 type StepCustomPipelineOptions struct { 28 step.StepOptions 29 30 MultiBranchProject bool 31 Dir string 32 Jenkinsfile string 33 JenkinsPath string 34 JenkinsSelector opts.JenkinsSelectorOptions 35 } 36 37 var ( 38 stepCustomPipelineLong = templates.LongDesc(` 39 This pipeline step lazily creates a Pipeline job inside a custom Jenkins App and then triggers it 40 41 `) 42 43 stepCustomPipelineExample = templates.Examples(` 44 # triggers the Jenkinsfile in the current directory in the custom Jenkins App 45 jx step custom pipeline 46 `) 47 ) 48 49 // NewCmdStepCustomPipeline creates the new command 50 func NewCmdStepCustomPipeline(commonOpts *opts.CommonOptions) *cobra.Command { 51 options := StepCustomPipelineOptions{ 52 StepOptions: step.StepOptions{ 53 CommonOptions: commonOpts, 54 }, 55 JenkinsSelector: opts.JenkinsSelectorOptions{ 56 UseCustomJenkins: true, 57 }, 58 } 59 cmd := &cobra.Command{ 60 Use: "custom pipeline", 61 Short: "Triggers a pipeline in a custom Jenkins server using the local Jenkinsfile", 62 Long: stepCustomPipelineLong, 63 Example: stepCustomPipelineExample, 64 Run: func(cmd *cobra.Command, args []string) { 65 options.Cmd = cmd 66 options.Args = args 67 err := options.Run() 68 helper.CheckErr(err) 69 }, 70 } 71 72 cmd.Flags().StringVarP(&options.JenkinsSelector.CustomJenkinsName, "jenkins-name", "j", "", "The name of the custom Jenkins App if you don't wish to use the default execution engine in Jenkins X") 73 74 cmd.Flags().BoolVarP(&options.MultiBranchProject, "multi-branch-project", "", false, "Use a Multi Branch Project in Jenkins") 75 cmd.Flags().StringVarP(&options.Dir, "dir", "d", ".", "the directory to look for the Jenkisnfile inside") 76 cmd.Flags().StringVarP(&options.Jenkinsfile, "jenkinsfile", "f", jenkinsfile.Name, "The name of the Jenkinsfile to use") 77 cmd.Flags().StringVarP(&options.JenkinsPath, "jenkins-path", "p", "", "The Jenkins folder path to create the pipeline inside. If not specified it defaults to the git 'owner/repoName/branch'") 78 return cmd 79 } 80 81 // Run implements the command 82 func (o *StepCustomPipelineOptions) Run() error { 83 jenkinsClient, err := o.CreateCustomJenkinsClient(&o.JenkinsSelector) 84 if err != nil { 85 return err 86 } 87 if o.Dir == "" { 88 o.Dir, err = os.Getwd() 89 if err != nil { 90 return err 91 } 92 } 93 if o.Jenkinsfile == "" { 94 o.Jenkinsfile = jenkinsfile.Name 95 } 96 jenkinsfileName := filepath.Join(o.Dir, o.Jenkinsfile) 97 exists, err := util.FileExists(jenkinsfileName) 98 if err != nil { 99 return err 100 } 101 if !exists { 102 return fmt.Errorf("%s does not exist", jenkinsfileName) 103 } 104 105 gitInfo, err := o.FindGitInfo(o.Dir) 106 if err != nil { 107 return err 108 } 109 110 gitKind, err := o.GitServerKind(gitInfo) 111 if err != nil { 112 return err 113 } 114 115 branch, err := o.Git().Branch(o.Dir) 116 if err != nil { 117 return err 118 } 119 if branch == "" { 120 branch = "master" 121 } 122 123 if o.JenkinsPath == "" { 124 o.JenkinsPath = fmt.Sprintf("%s/%s/%s", gitInfo.Organisation, gitInfo.Name, branch) 125 } 126 127 paths := strings.Split(o.JenkinsPath, "/") 128 last := len(paths) - 1 129 for i, path := range paths { 130 folderPath := paths[0 : i+1] 131 folder, err := jenkinsClient.GetJobByPath(folderPath...) 132 fullPath := util.UrlJoin(folderPath...) 133 jobURL := util.UrlJoin(jenkinsClient.BaseURL(), fullPath) 134 135 if i < last { 136 // lets ensure there's a folder 137 err = o.Retry(3, time.Second*10, func() error { 138 if err != nil { 139 folderXML := jenkins.CreateFolderXML(jobURL, path) 140 if i == 0 { 141 err = jenkinsClient.CreateJobWithXML(folderXML, path) 142 if err != nil { 143 return errors.Wrapf(err, "failed to create the %s folder at %s in Jenkins", path, jobURL) 144 } 145 } else { 146 folders := strings.Join(paths[0:i], "/job/") 147 err = jenkinsClient.CreateFolderJobWithXML(folderXML, folders, path) 148 if err != nil { 149 return errors.Wrapf(err, "failed to create the %s folder in folders %s at %s in Jenkins", path, folders, jobURL) 150 } 151 } 152 } else { 153 c := folder.Class 154 if c != "com.cloudbees.hudson.plugins.folder.Folder" { 155 log.Logger().Warnf("Warning the folder %s is of class %s", jobURL, c) 156 } 157 } 158 return nil 159 }) 160 if err != nil { 161 return err 162 } 163 } else { 164 gitURL := gits.HttpCloneURL(gitInfo, gitKind) 165 log.Logger().Infof("Using git URL %s and branch %s", util.ColorInfo(gitURL), util.ColorInfo(branch)) 166 167 err = o.Retry(3, time.Second*10, func() error { 168 if err != nil { 169 pipelineXML := jenkins.CreatePipelineXML(gitURL, branch, o.Jenkinsfile) 170 if i == 0 { 171 err = jenkinsClient.CreateJobWithXML(pipelineXML, path) 172 if err != nil { 173 return errors.Wrapf(err, "failed to create the %s pipeline at %s in Jenkins", path, jobURL) 174 } 175 } else { 176 folders := strings.Join(paths[0:i], "/job/") 177 err = jenkinsClient.CreateFolderJobWithXML(pipelineXML, folders, path) 178 if err != nil { 179 return errors.Wrapf(err, "failed to create the %s pipeline in folders %s at %s in Jenkins", path, folders, jobURL) 180 } 181 } 182 } 183 return nil 184 }) 185 if err != nil { 186 return err 187 } 188 189 job, err := jenkinsClient.GetJobByPath(paths...) 190 if err != nil { 191 return err 192 } 193 job.Url = jenkins.SwitchJenkinsBaseURL(job.Url, jenkinsClient.BaseURL()) 194 jobPath := strings.Join(paths, "/") 195 log.Logger().Infof("triggering pipeline job %s", util.ColorInfo(jobPath)) 196 err = jenkinsClient.Build(job, url.Values{}) 197 if err != nil { 198 return errors.Wrapf(err, "failed to trigger job %s", jobPath) 199 } 200 } 201 } 202 return nil 203 }