github.com/jenkins-x/jx/v2@v2.1.155/pkg/cmd/step/git/step_git_merge.go (about) 1 package git 2 3 import ( 4 "os" 5 6 "github.com/jenkins-x/jx/v2/pkg/cmd/opts/step" 7 "github.com/jenkins-x/jx/v2/pkg/util" 8 9 "github.com/jenkins-x/jx/v2/pkg/cmd/helper" 10 11 "github.com/jenkins-x/jx/v2/pkg/prow" 12 "github.com/pkg/errors" 13 14 "github.com/jenkins-x/jx-logging/pkg/log" 15 16 "github.com/jenkins-x/jx/v2/pkg/gits" 17 18 "github.com/jenkins-x/jx/v2/pkg/cmd/opts" 19 "github.com/jenkins-x/jx/v2/pkg/cmd/templates" 20 "github.com/spf13/cobra" 21 ) 22 23 var ( 24 // StepGitMergeLong command long description 25 StepGitMergeLong = templates.LongDesc(` 26 This pipeline step merges any SHAs specified into the HEAD of master. 27 28 If no SHAs are specified then the PULL_REFS environment variable will be parsed for a branch:sha comma separated list of 29 shas to merge. For example: 30 31 master:ef08a6cd194c2687d4bc12df6bb8a86f53c348ba,2739:5b351f4eae3c4afbb90dd7787f8bf2f8c454723f,2822:bac2a1f34fd54811fb767f69543f59eb3949b2a5 32 33 `) 34 // StepGitMergeExample command example 35 StepGitMergeExample = templates.Examples(` 36 # Merge the SHAs from the PULL_REFS environment variable 37 jx step git merge 38 39 # Merge the SHA into the HEAD of master 40 jx step git merge --sha 123456a 41 42 # Merge a number of SHAs into the HEAD of master 43 jx step git merge --sha 123456a --sha 789012b 44 `) 45 ) 46 47 // StepGitMergeOptions contains the command line flags 48 type StepGitMergeOptions struct { 49 step.StepOptions 50 51 SHAs []string 52 Remote string 53 Dir string 54 BaseBranch string 55 BaseSHA string 56 } 57 58 // NewCmdStepGitMerge create the 'step git envs' command 59 func NewCmdStepGitMerge(commonOpts *opts.CommonOptions) *cobra.Command { 60 options := StepGitMergeOptions{ 61 StepOptions: step.StepOptions{ 62 CommonOptions: commonOpts, 63 }, 64 } 65 cmd := &cobra.Command{ 66 Use: "merge", 67 Short: "Merge a number of SHAs into the HEAD of master", 68 Long: StepGitMergeLong, 69 Example: StepGitMergeExample, 70 Run: func(cmd *cobra.Command, args []string) { 71 options.Cmd = cmd 72 options.Args = args 73 err := options.Run() 74 helper.CheckErr(err) 75 }, 76 } 77 78 cmd.Flags().StringArrayVarP(&options.SHAs, "sha", "", make([]string, 0), "The SHA(s) to merge, "+ 79 "if not specified then the value of the env var PULL_REFS is used") 80 cmd.Flags().StringVarP(&options.Remote, "remote", "", "origin", "The name of the remote") 81 cmd.Flags().StringVarP(&options.Dir, "dir", "", "", "The directory in which the git repo is checked out") 82 cmd.Flags().StringVarP(&options.BaseBranch, "baseBranch", "", "", "The branch to merge to, "+ 83 "if not specified then the first entry in PULL_REFS is used ") 84 cmd.Flags().StringVarP(&options.BaseSHA, "baseSHA", "", "", "The SHA to use on the base branch, "+ 85 "if not specified then the first entry in PULL_REFS is used") 86 87 return cmd 88 } 89 90 // Run implements the command 91 func (o *StepGitMergeOptions) Run() error { 92 if o.Remote == "" { 93 o.Remote = "origin" 94 } 95 96 // set dummy git config details if none set so we can do a local commit when merging 97 err := o.setGitConfig() 98 if err != nil { 99 return errors.Wrapf(err, "failed to set git config") 100 } 101 if len(o.SHAs) == 0 || o.BaseBranch == "" || o.BaseSHA == "" { 102 // Try to look in the env vars 103 if pullRefs := os.Getenv("PULL_REFS"); pullRefs != "" { 104 log.Logger().Infof("Using SHAs from PULL_REFS=%s", pullRefs) 105 pullRefs, err := prow.ParsePullRefs(pullRefs) 106 if err != nil { 107 return errors.Wrapf(err, "parsing PULL_REFS=%s", pullRefs) 108 } 109 if len(o.SHAs) == 0 { 110 o.SHAs = make([]string, 0) 111 for _, sha := range pullRefs.ToMerge { 112 o.SHAs = append(o.SHAs, sha) 113 } 114 } 115 if o.BaseBranch == "" { 116 o.BaseBranch = pullRefs.BaseBranch 117 } 118 if o.BaseSHA == "" { 119 o.BaseSHA = pullRefs.BaseSha 120 } 121 } 122 } 123 if len(o.SHAs) == 0 { 124 log.Logger().Warnf("no SHAs to merge, falling back to initial cloned commit") 125 return nil 126 } 127 128 err = gits.FetchAndMergeSHAs(o.SHAs, o.BaseBranch, o.BaseSHA, o.Remote, o.Dir, o.Git()) 129 if err != nil { 130 return errors.Wrap(err, "error during merge") 131 } 132 133 if o.Verbose { 134 commits, err := o.getMergedCommits() 135 if err != nil { 136 return errors.Wrap(err, "unable to write merge result") 137 } 138 o.logCommits(commits, o.BaseBranch) 139 } 140 141 return nil 142 } 143 144 func (o *StepGitMergeOptions) setGitConfig() error { 145 user, err := o.GetCommandOutput(o.Dir, "git", "config", "user.name") 146 if err != nil || user == "" { 147 err := o.RunCommandFromDir(o.Dir, "git", "config", "user.name", util.DefaultGitUserName) 148 if err != nil { 149 return err 150 } 151 } 152 email, err := o.GetCommandOutput(o.Dir, "git", "config", "user.email") 153 if email == "" || err != nil { 154 err := o.RunCommandFromDir(o.Dir, "git", "config", "user.email", util.DefaultGitUserEmail) 155 if err != nil { 156 return err 157 } 158 } 159 return nil 160 } 161 162 func (o *StepGitMergeOptions) getMergedCommits() ([]gits.GitCommit, error) { 163 commits, err := o.Git().GetCommits(o.Dir, o.BaseSHA, "HEAD") 164 if err != nil { 165 return nil, errors.Wrap(err, "unable to retrieve commits") 166 } 167 168 return commits, nil 169 } 170 171 func (o *StepGitMergeOptions) logCommits(commits []gits.GitCommit, base string) { 172 for _, commit := range commits { 173 log.Logger().Infof("Merged SHA %s with commit message '%s' into base branch %s", commit.SHA, commit.Subject(), base) 174 } 175 }