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

     1  package pr
     2  
     3  import (
     4  	"os"
     5  
     6  	"github.com/olli-ai/jx/v2/pkg/cmd/opts/step"
     7  
     8  	"github.com/olli-ai/jx/v2/pkg/gits/operations"
     9  
    10  	"github.com/jenkins-x/jx-logging/pkg/log"
    11  
    12  	"github.com/olli-ai/jx/v2/pkg/cmd/helper"
    13  	"github.com/olli-ai/jx/v2/pkg/cmd/opts"
    14  	"github.com/olli-ai/jx/v2/pkg/gits"
    15  	"github.com/olli-ai/jx/v2/pkg/util"
    16  	"github.com/pkg/errors"
    17  	"github.com/spf13/cobra"
    18  )
    19  
    20  //StepCreatePrOptions are the common options for all PR creation steps
    21  type StepCreatePrOptions struct {
    22  	step.StepCreateOptions
    23  	Results       *gits.PullRequestInfo
    24  	BranchName    string
    25  	GitURLs       []string
    26  	Base          string
    27  	Fork          bool
    28  	SrcGitURL     string
    29  	Component     string
    30  	Version       string
    31  	DryRun        bool
    32  	SkipCommit    bool
    33  	SkipAutoMerge bool
    34  	Labels        []string
    35  }
    36  
    37  // NewCmdStepCreatePr Steps a command object for the "step" command
    38  func NewCmdStepCreatePr(commonOpts *opts.CommonOptions) *cobra.Command {
    39  	options := &StepCreatePrOptions{
    40  		StepCreateOptions: step.StepCreateOptions{
    41  			StepOptions: step.StepOptions{
    42  				CommonOptions: commonOpts,
    43  			},
    44  		},
    45  	}
    46  
    47  	cmd := &cobra.Command{
    48  		Use:     "pullrequest",
    49  		Aliases: []string{"pr"},
    50  		Short:   "create pullrequest [command]",
    51  		Run: func(cmd *cobra.Command, args []string) {
    52  			options.Cmd = cmd
    53  			options.Args = args
    54  			err := options.Run()
    55  			helper.CheckErr(err)
    56  		},
    57  	}
    58  	cmd.AddCommand(NewCmdStepCreatePullRequestBrew(commonOpts))
    59  	cmd.AddCommand(NewCmdStepCreatePullRequestChart(commonOpts))
    60  	cmd.AddCommand(NewCmdStepCreatePullRequestDocker(commonOpts))
    61  	cmd.AddCommand(NewCmdStepCreatePullRequestGo(commonOpts))
    62  	cmd.AddCommand(NewCmdStepCreatePullRequestMake(commonOpts))
    63  	cmd.AddCommand(NewCmdStepCreatePullRequestQuickStarts(commonOpts))
    64  	cmd.AddCommand(NewCmdStepCreatePullRequestRegex(commonOpts))
    65  	cmd.AddCommand(NewCmdStepCreatePullRequestRepositories(commonOpts))
    66  	cmd.AddCommand(NewCmdStepCreatePullRequestVersion(commonOpts))
    67  	return cmd
    68  }
    69  
    70  // Run implements this command
    71  func (o *StepCreatePrOptions) Run() error {
    72  	return o.Cmd.Help()
    73  }
    74  
    75  //AddStepCreatePrFlags adds the common flags for all PR creation steps to the cmd and stores them in o
    76  func AddStepCreatePrFlags(cmd *cobra.Command, o *StepCreatePrOptions) {
    77  	cmd.Flags().StringArrayVarP(&o.GitURLs, "repo", "r", []string{}, "Git repo to update")
    78  	cmd.Flags().StringVarP(&o.BranchName, "branch", "", "master", "Branch to clone and generate a pull request from")
    79  	cmd.Flags().StringVarP(&o.Base, "base", "", "master", "The branch to create the pull request into")
    80  	cmd.Flags().StringVarP(&o.SrcGitURL, "src-repo", "", "", "The git repo which caused this change; if this is a dependency update this will cause commit messages to be generated which can be parsed by jx step changelog. By default this will be read from the environment variable REPO_URL")
    81  	cmd.Flags().StringVarP(&o.Component, "component", "", "", "The component of the git repo which caused this change; useful if you have a complex or monorepo setup and want to differentiate between different components from the same repo")
    82  	cmd.Flags().StringVarP(&o.Version, "version", "v", "", "The version to change. If no version is supplied the latest version is found")
    83  	cmd.Flags().BoolVarP(&o.DryRun, "dry-run", "", false, "Perform a dry run, the change will be generated and committed, but not pushed or have a PR created")
    84  	cmd.Flags().BoolVarP(&o.SkipAutoMerge, "skip-auto-merge", "", false, "Disable auto merge of the PR if status checks pass")
    85  	cmd.Flags().StringArrayVarP(&o.Labels, "labels", "", []string{}, "Labels to add to the created PR")
    86  }
    87  
    88  // ValidateOptions validates the common options for all PR creation steps
    89  func (o *StepCreatePrOptions) ValidateOptions(allowEmptyVersion bool) error {
    90  	if o.SrcGitURL == "" {
    91  		o.SrcGitURL = os.Getenv("REPO_URL")
    92  		if o.SrcGitURL != "" {
    93  			log.Logger().Infof("Using %s as source for change discovered from env var REPO_URL", o.SrcGitURL)
    94  		} else {
    95  			// see if we're in a git repo and use it
    96  			wd, err := os.Getwd()
    97  			if err != nil {
    98  				return errors.Wrapf(err, "getting working directory")
    99  			}
   100  			gitInfo, err := o.FindGitInfo(wd)
   101  			if err != nil {
   102  				log.Logger().Debugf("Unable to discover git info from current directory because %v", err)
   103  			} else {
   104  				o.SrcGitURL = gitInfo.HttpsURL()
   105  				log.Logger().Infof("Using %s as source for change discovered from git repo in %s", o.SrcGitURL, wd)
   106  			}
   107  		}
   108  
   109  	}
   110  	if o.SrcGitURL == "" {
   111  		return errors.Errorf("unable to determine source url, no argument provided, env var REPO_URL is empty and working directory is not a git repo")
   112  	}
   113  	if !allowEmptyVersion && o.Version == "" {
   114  		return util.MissingOption("version")
   115  	}
   116  	if len(o.GitURLs) == 0 {
   117  		return util.MissingOption("repo")
   118  	}
   119  	return nil
   120  }
   121  
   122  // CreatePullRequest will fork (if needed) and pull a git repo, then perform the update, and finally create or update a
   123  // PR for the change. Any open PR on the repo with the `updatebot` label will be updated.
   124  func (o *StepCreatePrOptions) CreatePullRequest(kind string, update operations.ChangeFilesFn) error {
   125  	if o.DryRun {
   126  		log.Logger().Infof("--dry-run specified. Change will be created and committed to local git repo, but not pushed. No pull request will be created or updated. A fork will still be created.")
   127  	}
   128  	op := o.createPullRequestOperation()
   129  	var err error
   130  	o.Results, err = op.CreatePullRequest(kind, update)
   131  	if err != nil {
   132  		return errors.Wrap(err, "unable to create pull request")
   133  	}
   134  	return nil
   135  }
   136  
   137  func (o *StepCreatePrOptions) createPullRequestOperation() operations.PullRequestOperation {
   138  	op := operations.PullRequestOperation{
   139  		CommonOptions: o.CommonOptions,
   140  		GitURLs:       o.GitURLs,
   141  		BranchName:    o.BranchName,
   142  		SrcGitURL:     o.SrcGitURL,
   143  		Base:          o.Base,
   144  		Version:       o.Version,
   145  		Component:     o.Component,
   146  		DryRun:        o.DryRun,
   147  		SkipCommit:    o.SkipCommit,
   148  		SkipAutoMerge: o.SkipAutoMerge,
   149  		Labels:        o.Labels,
   150  	}
   151  	authorName, authorEmail, err := gits.EnsureUserAndEmailSetup(o.Git())
   152  	if err != nil {
   153  		op.AuthorName = authorName
   154  		op.AuthorEmail = authorEmail
   155  	}
   156  	return op
   157  }