github.com/zaquestion/lab@v0.25.1/cmd/ci_run.go (about)

     1  package cmd
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"strings"
     7  
     8  	"github.com/MakeNowJust/heredoc/v2"
     9  	"github.com/pkg/errors"
    10  	"github.com/rsteube/carapace"
    11  	"github.com/spf13/cobra"
    12  	gitlab "github.com/xanzy/go-gitlab"
    13  	"github.com/zaquestion/lab/internal/action"
    14  	"github.com/zaquestion/lab/internal/git"
    15  	lab "github.com/zaquestion/lab/internal/gitlab"
    16  )
    17  
    18  // ciCreateCmd represents the run command
    19  var ciCreateCmd = &cobra.Command{
    20  	Use:     "create [branch]",
    21  	Aliases: []string{"run"},
    22  	Short:   "Create a CI pipeline",
    23  	Long: heredoc.Doc(`
    24  		Run the CI pipeline for the given or current branch if none provided.
    25  		This API uses your GitLab token to create CI pipelines
    26  
    27  		Project will be inferred from branch if not provided
    28  
    29  		Note: "lab ci create" differs from "lab ci trigger" which is a
    30  		different API`),
    31  	Example: heredoc.Doc(`
    32  		lab ci create feature_branch
    33  		lab ci create -p engineering/integration_tests master`),
    34  	PersistentPreRun: labPersistentPreRun,
    35  	Run: func(cmd *cobra.Command, args []string) {
    36  		pid, branch, err := getCIRunOptions(cmd, args)
    37  		if err != nil {
    38  			log.Fatal(err)
    39  		}
    40  		pipeline, err := lab.CICreate(pid, &gitlab.CreatePipelineOptions{Ref: &branch})
    41  		if err != nil {
    42  			log.Fatal(err)
    43  		}
    44  		fmt.Println(pipeline.WebURL)
    45  	},
    46  }
    47  
    48  var ciTriggerCmd = &cobra.Command{
    49  	Use:   "trigger [branch]",
    50  	Short: "Trigger a CI pipeline",
    51  	Long: heredoc.Doc(`
    52  		Runs a trigger for a CI pipeline on the given or current branch if none provided.
    53  		This API supports variables and must be called with a trigger token or from within GitLab CI.
    54  
    55  		Project will be inferred from branch if not provided
    56  
    57  		Note: "lab ci trigger" differs from "lab ci create" which is a different API`),
    58  	Example: heredoc.Doc(`
    59  		lab ci trigger feature_branch
    60  		lab ci trigger -p engineering/integration_tests master
    61  		lab ci trigger -p engineering/integration_tests -v foo=bar master`),
    62  	PersistentPreRun: labPersistentPreRun,
    63  	Run: func(cmd *cobra.Command, args []string) {
    64  		pid, branch, err := getCIRunOptions(cmd, args)
    65  		if err != nil {
    66  			log.Fatal(err)
    67  		}
    68  		token, err := cmd.Flags().GetString("token")
    69  		if err != nil {
    70  			log.Fatal(err)
    71  		}
    72  		vars, err := cmd.Flags().GetStringSlice("variable")
    73  		if err != nil {
    74  			log.Fatal(err)
    75  		}
    76  		ciVars, err := parseCIVariables(vars)
    77  		if err != nil {
    78  			log.Fatal(err)
    79  		}
    80  		pipeline, err := lab.CITrigger(pid, gitlab.RunPipelineTriggerOptions{
    81  			Ref:       &branch,
    82  			Token:     &token,
    83  			Variables: ciVars,
    84  		})
    85  		if err != nil {
    86  			log.Fatal(err)
    87  		}
    88  		fmt.Println(pipeline.WebURL)
    89  	},
    90  }
    91  
    92  func getCIRunOptions(cmd *cobra.Command, args []string) (string, string, error) {
    93  	branch, err := git.CurrentBranch()
    94  	if err != nil {
    95  		return "", "", err
    96  	}
    97  	if len(args) > 0 {
    98  		branch = args[0]
    99  	}
   100  
   101  	var pid string
   102  
   103  	remote, err := determineSourceRemote(branch)
   104  	if err != nil {
   105  		return "", "", err
   106  	}
   107  	rn, err := git.PathWithNamespace(remote)
   108  	if err != nil {
   109  		return "", "", err
   110  	}
   111  	pid = rn
   112  
   113  	project, err := cmd.Flags().GetString("project")
   114  	if err != nil {
   115  		return "", "", err
   116  	}
   117  	if project != "" {
   118  		_, err := lab.FindProject(project)
   119  		if err != nil {
   120  			return "", "", err
   121  		}
   122  		pid = project
   123  	}
   124  	return pid, branch, nil
   125  }
   126  
   127  func parseCIVariables(vars []string) (map[string]string, error) {
   128  	variables := make(map[string]string)
   129  	for _, v := range vars {
   130  		parts := strings.SplitN(v, "=", 2)
   131  		if len(parts) < 2 {
   132  			return nil, errors.Errorf("Invalid Variable: \"%s\", Variables must be in the format key=value", v)
   133  		}
   134  		variables[parts[0]] = parts[1]
   135  
   136  	}
   137  	return variables, nil
   138  }
   139  
   140  func init() {
   141  	ciCreateCmd.Flags().StringP("project", "p", "", "project to create pipeline on")
   142  	ciCmd.AddCommand(ciCreateCmd)
   143  	carapace.Gen(ciCreateCmd).PositionalCompletion(
   144  		action.Remotes(),
   145  	)
   146  
   147  	ciTriggerCmd.Flags().StringP("project", "p", "", "project to run pipeline trigger on")
   148  	ciTriggerCmd.Flags().StringP("token", "t", os.Getenv("CI_JOB_TOKEN"), "pipeline trigger token, optional if run within GitLabCI")
   149  	ciTriggerCmd.Flags().StringSliceP("variable", "v", []string{}, "variables to pass to pipeline")
   150  
   151  	ciCmd.AddCommand(ciTriggerCmd)
   152  	carapace.Gen(ciTriggerCmd).PositionalCompletion(
   153  		action.RemoteBranches(-1),
   154  	)
   155  }