Repository: openshift-pipelines/pipelines-as-code
Pull request #349 (2021-11-04 09:47:02)

feat: add flags switches for cli's generate/create
Signed-off-by: Chmouel Boudjnah <chmouel@redhat.com>



Patch:
diff --git a/pkg/cmd/tknpac/generate/generate.go b/pkg/cmd/tknpac/generate/generate.go
index b4c1b76f..2ede2280 100644
--- a/pkg/cmd/tknpac/generate/generate.go
+++ b/pkg/cmd/tknpac/generate/generate.go
@@ -27,6 +27,11 @@ type Opts struct {
 
 	IOStreams *cli.IOStreams
 	CLIOpts   *cli.PacCliOpts
+
+	pipelineRunName string
+	fileName        string
+	overwrite       bool
+	language        string
 }
 
 func MakeOpts() *Opts {
@@ -58,6 +63,20 @@ func Command(ioStreams *cli.IOStreams) *cobra.Command {
 			return Generate(gopt)
 		},
 	}
+	cmd.PersistentFlags().StringVar(&gopt.event.BaseBranch, "branch", "",
+		"The target branch of the repository  event to handle (eg: main, nightly)")
+	cmd.PersistentFlags().StringVar(&gopt.event.EventType, "event-type", "",
+		"The event type of the repository event to handle (eg: pull_request, push)")
+	cmd.PersistentFlags().StringVar(&gopt.event.URL, "url", "",
+		"The repository URL from where the event will come from")
+	cmd.PersistentFlags().StringVar(&gopt.pipelineRunName, "pipeline-name", "",
+		"The pipeline name")
+	cmd.PersistentFlags().StringVar(&gopt.fileName, "file-name", "",
+		"The file name location")
+	cmd.PersistentFlags().BoolVar(&gopt.overwrite, "overwrite", false,
+		"Wether to overwrite the file if it exist")
+	cmd.PersistentFlags().StringVarP(&gopt.language, "language", "l", "",
+		"Generate for this programming language")
 	return cmd
 }
 
@@ -78,7 +97,9 @@ func Generate(o *Opts) error {
 
 func (o *Opts) targetEvent() error {
 	var choice string
-
+	if o.event.EventType != "" {
+		return nil
+	}
 	msg := "Enter the Git event type for triggering the pipeline: "
 
 	eventLabels := make([]string, 0, len(eventTypes))
@@ -140,38 +161,35 @@ func (o *Opts) branchOrTag() error {
 // directory.
 func (o *Opts) samplePipeline() error {
 	cs := o.IOStreams.ColorScheme()
-
-	fname := fmt.Sprintf("%s.yaml", strings.ReplaceAll(o.event.EventType, "_", "-"))
-	fpath := filepath.Join(o.GitInfo.TopLevelPath, ".tekton", fname)
-	relpath, _ := filepath.Rel(o.GitInfo.TopLevelPath, fpath)
-
-	var reply bool
-	msg := fmt.Sprintf("Would you like me to create a basic PipelineRun into the file %s ?", relpath)
-	if err := prompt.SurveyAskOne(&survey.Confirm{Message: msg, Default: true}, &reply); err != nil {
-		return err
-	}
-
-	if !reply {
-		return nil
-	}
-
-	if _, err := os.Stat(filepath.Join(o.GitInfo.TopLevelPath, ".tekton")); os.IsNotExist(err) {
-		if err := os.MkdirAll(filepath.Join(o.GitInfo.TopLevelPath, ".tekton"), 0o755); err != nil {
-			return err
+	var relpath, fpath string
+
+	if o.fileName != "" {
+		fpath = o.fileName
+		relpath = fpath
+	} else {
+		fname := fmt.Sprintf("%s.yaml", strings.ReplaceAll(o.event.EventType, "_", "-"))
+		fpath = filepath.Join(o.GitInfo.TopLevelPath, ".tekton", fname)
+		relpath, _ = filepath.Rel(o.GitInfo.TopLevelPath, fpath)
+		if _, err := os.Stat(filepath.Join(o.GitInfo.TopLevelPath, ".tekton")); os.IsNotExist(err) {
+			if err := os.MkdirAll(filepath.Join(o.GitInfo.TopLevelPath, ".tekton"), 0o755); err != nil {
+				return err
+			}
+			fmt.Fprintf(o.IOStreams.Out, "%s Directory %s has been created.\n",
+				cs.InfoIcon(),
+				cs.Bold(".tekton"),
+			)
 		}
-		fmt.Fprintf(o.IOStreams.Out, "%s Directory %s has been created.\n",
-			cs.InfoIcon(),
-			cs.Bold(".tekton"),
-		)
 	}
 
-	if _, err := os.Stat(fpath); !os.IsNotExist(err) {
+	if _, err := os.Stat(fpath); !os.IsNotExist(err) && !o.overwrite {
 		var overwrite bool
-		msg := fmt.Sprintf("There is already a file named: %s would you like me to override it?", fpath)
-		if err := prompt.SurveyAskOne(&survey.Confirm{Message: msg, Default: false}, &reply); err != nil {
+		msg := fmt.Sprintf("There is already a file named: %s would you like me to override it?", relpath)
+		if err := prompt.SurveyAskOne(&survey.Confirm{Message: msg, Default: false}, &overwrite); err != nil {
 			return err
 		}
 		if !overwrite {
+			fmt.Fprintf(o.IOStreams.ErrOut, "%s Not overwriting file, exiting...\n", cs.WarningIcon())
+			fmt.Fprintf(o.IOStreams.ErrOut, "%s Feel free to use the -f flag if you want to target another file name\n...", cs.InfoIcon())
 			return nil
 		}
 	}
@@ -184,7 +202,7 @@ func (o *Opts) samplePipeline() error {
 	// nolint: gosec
 	err = ioutil.WriteFile(fpath, tmpl.Bytes(), 0o644)
 	if err != nil {
-		return err
+		return fmt.Errorf("cannot write template to %s: %w", fpath, err)
 	}
 
 	fmt.Fprintf(o.IOStreams.Out, "%s A basic template has been created in %s, feel free to customize it.\n",
diff --git a/pkg/cmd/tknpac/generate/template.go b/pkg/cmd/tknpac/generate/template.go
index f8da3d07..0a7d43e8 100644
--- a/pkg/cmd/tknpac/generate/template.go
+++ b/pkg/cmd/tknpac/generate/template.go
@@ -56,25 +56,27 @@ var pipelineRunTmpl = `---
 apiVersion: tekton.dev/v1beta1
 kind: PipelineRun
 metadata:
-  name: [[ .prName ]]
+  name: << .prName >>
   annotations:
-    # The event we are targeting (ie: pull_request, push)
-    pipelinesascode.tekton.dev/on-event: "[ [[ .event.EventType ]] ]"
+    # The event we are targeting as seen from the webhook payload
+    # this can be an array too, i.e: [pull_request, push]
+    pipelinesascode.tekton.dev/on-event: "<< .event.EventType >>"
 
     # The branch or tag we are targeting (ie: main, refs/tags/*)
-    pipelinesascode.tekton.dev/on-target-branch: "[ [[ .event.BaseBranch ]] ]"
+    pipelinesascode.tekton.dev/on-target-branch: "<< .event.BaseBranch >>"
 
-    # Fetch the git-clone task from hub, we are able to reference it with taskRef
-    pipelinesascode.tekton.dev/task: "[ git-clone ]"
-    [[- if .extra_task.AnnotationTask ]]
+    # Fetch the git-clone task from hub, we are able to reference later on it
+    # with taskRef and it will automatically be embedded into our pipeline.
+    pipelinesascode.tekton.dev/task: "git-clone"
+    <<- if .extra_task.AnnotationTask >>
 
-    # Task for [[.extra_task.Language ]]
-    pipelinesascode.tekton.dev/task-1: "[ [[ .extra_task.AnnotationTask ]] ]"
-    [[ end ]]
+    # Task for <<.extra_task.Language >>
+    pipelinesascode.tekton.dev/task-1: "[<< .extra_task.AnnotationTask >>]"
+    << end >>
     # You can add more tasks in here to reuse, browse the one you like from here
     # https://hub.tekton.dev/
     # example:
-    # pipelinesascode.tekton.dev/task-2: "[ maven, buildah ]"
+    # pipelinesascode.tekton.dev/task-2: "[maven, buildah]"
 
     # How many runs we want to keep attached to this event
     pipelinesascode.tekton.dev/max-keep-runs: "5"
@@ -106,8 +108,10 @@ spec:
           - name: url
             value: $(params.repo_url)
           - name: revision
-            value: $(params.revision)
-      [[ .extra_task.Task ]]
+            value: $(params.revision)      
+      << if .extra_task.Task>>
+      << .extra_task.Task >>
+      <<- end >>
       # Customize this task if you like, or just do a taskRef
       # to one of the hub task.
       - name: noop-task
@@ -141,7 +145,14 @@ spec:
       secretName: "pac-git-basic-auth-{{repo_owner}}-{{repo_name}}"
 `
 
-func (o *Opts) detectLanguage() langOpts {
+func (o *Opts) detectLanguage() (langOpts, error) {
+	if o.language != "" {
+		if _, ok := languageDetection[o.language]; !ok {
+			return langOpts{}, fmt.Errorf("no template available for %s", o.language)
+		}
+		return languageDetection[o.language], nil
+	}
+
 	cs := o.IOStreams.ColorScheme()
 	for _, v := range languageDetection {
 		fpath := filepath.Join(o.GitInfo.TopLevelPath, v.detectionFile)
@@ -150,22 +161,26 @@ func (o *Opts) detectLanguage() langOpts {
 				cs.SuccessIcon(),
 				cs.Bold(v.Language),
 			)
-			return v
+			return v, nil
 		}
 	}
-	return langOpts{}
+	return langOpts{}, nil
 }
 
 func (o *Opts) genTmpl() (bytes.Buffer, error) {
 	var outputBuffer bytes.Buffer
-	t := template.Must(template.New("PipelineRun").Delims("[[", "]]").Parse(pipelineRunTmpl))
+	t := template.Must(template.New("PipelineRun").Delims("<<", ">>").Parse(pipelineRunTmpl))
 	prName := fmt.Sprintf("%s-%s",
 		filepath.Base(o.GitInfo.URL),
 		strings.ReplaceAll(o.event.EventType, "_", "-"))
+	lang, err := o.detectLanguage()
+	if err != nil {
+		return bytes.Buffer{}, err
+	}
 	data := map[string]interface{}{
 		"prName":                  prName,
 		"event":                   o.event,
-		"extra_task":              o.detectLanguage(),
+		"extra_task":              lang,
 		"language_specific_tasks": "",
 	}
 	if err := t.Execute(&outputBuffer, data); err != nil {
diff --git a/pkg/cmd/tknpac/repository/create.go b/pkg/cmd/tknpac/repository/create.go
index 8ae40a3a..f492ed12 100644
--- a/pkg/cmd/tknpac/repository/create.go
+++ b/pkg/cmd/tknpac/repository/create.go
@@ -79,13 +79,8 @@ func CreateCommand(run *params.Run, ioStreams *cli.IOStreams) *cobra.Command {
 	}
 
 	cmd.PersistentFlags().BoolP(noColorFlag, "C", !ioStreams.ColorEnabled(), "disable coloring")
-	cmd.PersistentFlags().StringVar(&createOpts.repository.Name, "name", "", "The repository name")
-	cmd.PersistentFlags().StringVar(&createOpts.event.BaseBranch, "branch", "",
-		"The target branch of the repository  event to handle (eg: main, nightly)")
-	cmd.PersistentFlags().StringVar(&createOpts.event.EventType, "event-type", "",
-		"The event type of the repository event to handle (eg: pull_request, push)")
-	cmd.PersistentFlags().StringVar(&createOpts.event.URL, "url", "",
-		"The repository URL from where the event will come from")
+	cmd.PersistentFlags().StringVar(&createOpts.repository.Name, "name", "", "Repository name")
+	cmd.PersistentFlags().StringVar(&createOpts.event.URL, "url", "", "Repository URL")
 	cmd.PersistentFlags().StringVarP(&createOpts.repository.Namespace, "namespace", "n", "",
 		"The target namespace where the runs will be created")
 


Test patch:
diff --git a/pkg/cmd/tknpac/generate/generate_test.go b/pkg/cmd/tknpac/generate/generate_test.go
index 3fc44b31..f14e746e 100644
--- a/pkg/cmd/tknpac/generate/generate_test.go
+++ b/pkg/cmd/tknpac/generate/generate_test.go
@@ -31,14 +31,6 @@ func TestGetRepoURL(t *testing.T) {
 		checkRegInGeneratedFile []*regexp.Regexp
 		addExtraFilesInRepo     map[string]string
 	}{
-		{
-			name: "generate no pipelinerun",
-			askStubs: func(as *prompt.AskStubber) {
-				as.StubOne(0)     // pull_request
-				as.StubOne("")    // default as main
-				as.StubOne(false) // no pipelinerun generation
-			},
-		},
 		{
 			name: "pull request default",
 			askStubs: func(as *prompt.AskStubber) {
@@ -60,7 +52,6 @@ func TestGetRepoURL(t *testing.T) {
 			askStubs: func(as *prompt.AskStubber) {
 				as.StubOneDefault() // pull_request
 				as.StubOne("")      // default as main
-				as.StubOne(true)    // pipelinerun generation
 				as.StubOne(false)   // overwrite
 			},
 			addExtraFilesInRepo: map[string]string{
@@ -79,7 +70,6 @@ func TestGetRepoURL(t *testing.T) {
 			askStubs: func(as *prompt.AskStubber) {
 				as.StubOneDefault() // pull_request
 				as.StubOne("")      // default as main
-				as.StubOne(true)    // pipelinerun generation
 			},
 			addExtraFilesInRepo: map[string]string{
 				"go.mod": "random string",
@@ -101,7 +91,6 @@ func TestGetRepoURL(t *testing.T) {
 				// I can't see to make the stubbing work for push :\
 				as.StubOneDefault() // pull_request
 				as.StubOne("")      // default as main
-				as.StubOne(true)    // pipelinerun generation
 			},
 			addExtraFilesInRepo: map[string]string{
 				"setup.py": "random string",