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

     1  package pr
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/olli-ai/jx/v2/pkg/cmd/opts/step"
     8  
     9  	"github.com/olli-ai/jx/v2/pkg/gits/operations"
    10  
    11  	"github.com/olli-ai/jx/v2/pkg/gits"
    12  	"github.com/pkg/errors"
    13  
    14  	"github.com/jenkins-x/jx-logging/pkg/log"
    15  	"github.com/olli-ai/jx/v2/pkg/cmd/helper"
    16  	"github.com/olli-ai/jx/v2/pkg/cmd/opts"
    17  	"github.com/olli-ai/jx/v2/pkg/cmd/templates"
    18  	"github.com/olli-ai/jx/v2/pkg/util"
    19  	"github.com/spf13/cobra"
    20  )
    21  
    22  var (
    23  	createtPullRequestGoLong = templates.LongDesc(`
    24  		Creates a Pull Request to change a go module dependency, updating the go.mod and go.sum files to use a new version
    25  
    26  		Files named Makefile or Makefile.* will be updated
    27  `)
    28  
    29  	createtPullRequestGoExample = templates.Examples(`
    30  		# update a go dependency 
    31  		jx step create pr go --name github.com/myorg/myrepo --version v1.2.3 --repo https://github.com/jenkins-x/cloud-environments.git
    32  
    33  		# update a go dependency using a custom build step (to update the 'go.sum' file) 
    34  		jx step create pr go --name github.com/myorg/myrepo --version v1.2.3 --build "make something" --repo https://github.com/jenkins-x/cloud-environments.git
    35  					`)
    36  )
    37  
    38  // StepCreatetPullRequestGoOptions contains the command line flags
    39  type StepCreatetPullRequestGoOptions struct {
    40  	StepCreatePrOptions
    41  
    42  	Name         string
    43  	BuildCommand string
    44  	FailOnBuild  bool
    45  }
    46  
    47  // NewCmdStepCreatePullRequestGo Creates a new Command object
    48  func NewCmdStepCreatePullRequestGo(commonOpts *opts.CommonOptions) *cobra.Command {
    49  	options := &StepCreatetPullRequestGoOptions{
    50  		StepCreatePrOptions: StepCreatePrOptions{
    51  			StepCreateOptions: step.StepCreateOptions{
    52  				StepOptions: step.StepOptions{
    53  					CommonOptions: commonOpts,
    54  				},
    55  			},
    56  		},
    57  	}
    58  
    59  	cmd := &cobra.Command{
    60  		Use:     "go",
    61  		Short:   "Creates a Pull Request on a git repository updating a go module dependency",
    62  		Long:    createtPullRequestGoLong,
    63  		Example: createtPullRequestGoExample,
    64  		Aliases: []string{"golang"},
    65  		Run: func(cmd *cobra.Command, args []string) {
    66  			options.Cmd = cmd
    67  			options.Args = args
    68  			err := options.Run()
    69  			helper.CheckErr(err)
    70  		},
    71  	}
    72  	AddStepCreatePrFlags(cmd, &options.StepCreatePrOptions)
    73  	cmd.Flags().StringVarP(&options.Name, "name", "", "", "The name of the go module dependency to use when doing updates")
    74  	cmd.Flags().StringVarP(&options.BuildCommand, "build", "", "make build", "The build command to update the 'go.sum' file after the change to the source")
    75  	cmd.Flags().BoolVarP(&options.FailOnBuild, "fail-on-build", "", false, "Should we fail to create the Pull Request if the build command fails. Its common for incompatible changes to the go code to fail to build so we usually want to go ahead with the Pull Request anyway")
    76  	return cmd
    77  }
    78  
    79  // ValidateGoOptions validates the common options for make pr steps
    80  func (o *StepCreatetPullRequestGoOptions) ValidateGoOptions() error {
    81  	if err := o.ValidateOptions(false); err != nil {
    82  		return errors.WithStack(err)
    83  	}
    84  	if o.Name == "" {
    85  		return util.MissingOption("name")
    86  	}
    87  	if o.SrcGitURL == "" {
    88  		log.Logger().Warnf("srcRepo is not provided so generated PR will not be correctly linked in release notesPR")
    89  	}
    90  
    91  	return nil
    92  }
    93  
    94  // Run implements this command
    95  func (o *StepCreatetPullRequestGoOptions) Run() error {
    96  	// lets make sure the version starts with a v for go style version tags
    97  	if !strings.HasPrefix(o.Version, "v") {
    98  		o.Version = "v" + o.Version
    99  	}
   100  	if err := o.ValidateGoOptions(); err != nil {
   101  		return errors.WithStack(err)
   102  	}
   103  	regex := fmt.Sprintf(`(?m)^\s*\Q%s\E\s+(?P<version>.+)`, o.Name)
   104  	regexFn, err := operations.CreatePullRequestRegexFn(o.Version, regex, "go.mod")
   105  	if err != nil {
   106  		return errors.WithStack(err)
   107  	}
   108  	fn := func(dir string, gitInfo *gits.GitRepository) ([]string, error) {
   109  		answer, err := regexFn(dir, gitInfo)
   110  		if err != nil {
   111  			return nil, errors.WithStack(err)
   112  		}
   113  		err = o.runGoBuild(dir)
   114  		if err != nil {
   115  			log.Logger().Errorf("failed to run build after modifying go.mod")
   116  			return nil, errors.WithStack(err)
   117  		}
   118  		return answer, nil
   119  	}
   120  	err = o.CreatePullRequest("go", fn)
   121  	if err != nil {
   122  		return errors.WithStack(err)
   123  	}
   124  	return nil
   125  }
   126  
   127  func (o *StepCreatetPullRequestGoOptions) runGoBuild(dir string) error {
   128  	build := o.BuildCommand
   129  	if build == "" {
   130  		log.Logger().Warn("no build command so we will not change the 'go.sum' command")
   131  		return nil
   132  	}
   133  	log.Logger().Infof("running the build command: %s in the directory %s to update the 'go.sum' file\n", util.ColorInfo(build), dir)
   134  
   135  	values := strings.Split(build, " ")
   136  	cmd := util.Command{
   137  		Dir:  dir,
   138  		Name: values[0],
   139  		Args: values[1:],
   140  	}
   141  	_, err := cmd.RunWithoutRetry()
   142  	if err != nil {
   143  		if o.FailOnBuild {
   144  			return errors.Wrapf(err, "running %s", cmd.String())
   145  		}
   146  		log.Logger().Warnf("failed to run %s so the Pull Request will probably need some manual work to make it pass the CI tests. Failure: %s", cmd.String(), err.Error())
   147  	}
   148  	return nil
   149  }