Repository: kubesphere/ks-devops
Pull request #424 (2021-12-25 07:30:58)

[release-3.2] Fix the multi-branch PipelineRun cannot be deleted
This is an automated cherry-pick of #423

```release-note
Fix the multi-branch PipelineRun cannot be deleted
```


Patch:
diff --git a/controllers/jenkins/pipelinerun/jenkins_handler.go b/controllers/jenkins/pipelinerun/jenkins_handler.go
index 40dbac6..832cabe 100644
--- a/controllers/jenkins/pipelinerun/jenkins_handler.go
+++ b/controllers/jenkins/pipelinerun/jenkins_handler.go
@@ -116,18 +116,39 @@ func (handler *jenkinsHandler) deleteJenkinsJobHistory(pipelineRun *v1alpha3.Pip
 	}
 
 	jenkinsClient := job.Client{JenkinsCore: *handler.JenkinsCore}
-	jobName := fmt.Sprintf("job/%s/job/%s", pipelineRun.Namespace, pipelineRun.Spec.PipelineRef.Name)
-	if err = jenkinsClient.DeleteHistory(jobName, buildNum); err != nil {
+	jobPath := getJenkinsJobPath(pipelineRun)
+	if err = jenkinsClient.DeleteHistory(jobPath, buildNum); err != nil {
 		// TODO improve the way to check if the desired build record was deleted
 		if strings.Contains(err.Error(), "not found resources") {
 			err = nil
 		} else {
-			err = fmt.Errorf("failed to delete Jenkins job: %s, build: %d, error: %v", jobName, buildNum, err)
+			err = fmt.Errorf("failed to delete Jenkins job: %s, build: %d, error: %v", jobPath, buildNum, err)
 		}
 	}
 	return
 }
 
+// getJenkinsJobPath returns the corresponding Jenkins job path
+// only a regular or multi-branch Pipeline supported
+func getJenkinsJobPath(run *v1alpha3.PipelineRun) (jobPath string) {
+	if run == nil || run.Spec.PipelineRef == nil {
+		return
+	}
+
+	ref := run.Spec.PipelineRef
+	if ref.Namespace == "" {
+		// only support the Pipeline and PipelineRun in the same namespace
+		// so, the namespace of ref could be empty
+		ref.Namespace = run.Namespace
+	}
+
+	jobPath = fmt.Sprintf("/job/%s/job/%s", ref.Namespace, ref.Name)
+	if run.Spec.SCM != nil && run.Spec.SCM.RefName != "" {
+		jobPath = fmt.Sprintf("%s/job/%s", jobPath, run.Spec.SCM.RefName)
+	}
+	return
+}
+
 // getJenkinsBuildNumber returns the build number of a Jenkins job build which related with a PipelineRun
 // return a negative value if there is no valid build number
 func getJenkinsBuildNumber(pipelineRun *v1alpha3.PipelineRun) (num int) {


Test patch:
diff --git a/controllers/jenkins/pipelinerun/jenkins_handler_test.go b/controllers/jenkins/pipelinerun/jenkins_handler_test.go
index b4fa937..cd3f80e 100644
--- a/controllers/jenkins/pipelinerun/jenkins_handler_test.go
+++ b/controllers/jenkins/pipelinerun/jenkins_handler_test.go
@@ -4,6 +4,7 @@ import (
 	"bytes"
 	"errors"
 	"fmt"
+	"github.com/stretchr/testify/assert"
 	"io/ioutil"
 	"net/http"
 	"testing"
@@ -220,3 +221,77 @@ var _ = Describe("Test deleteJenkinsJobHistory", func() {
 		ctrl.Finish()
 	})
 })
+
+func Test_getJenkinsJobPath(t *testing.T) {
+	type args struct {
+		pipelineRun *v1alpha3.PipelineRun
+	}
+	tests := []struct {
+		name string
+		args args
+		want string
+	}{{
+		name: "empty PipelineRun",
+		args: args{
+			pipelineRun: &v1alpha3.PipelineRun{},
+		},
+		want: "",
+	}, {
+		name: "a regular PipelineRun",
+		args: args{
+			pipelineRun: &v1alpha3.PipelineRun{
+				ObjectMeta: v1.ObjectMeta{
+					Namespace: "ns",
+					Name:      "run",
+				},
+				Spec: v1alpha3.PipelineRunSpec{
+					PipelineRef: &corev1.ObjectReference{
+						Namespace: "ns",
+						Name:      "pipeline",
+					},
+				},
+			},
+		},
+		want: "/job/ns/job/pipeline",
+	}, {
+		name: "a regular PipelineRun without ns in the ref",
+		args: args{
+			pipelineRun: &v1alpha3.PipelineRun{
+				ObjectMeta: v1.ObjectMeta{
+					Namespace: "ns",
+					Name:      "run",
+				},
+				Spec: v1alpha3.PipelineRunSpec{
+					PipelineRef: &corev1.ObjectReference{
+						Name: "pipeline",
+					},
+				},
+			},
+		},
+		want: "/job/ns/job/pipeline",
+	}, {
+		name: "a multi-branch PipelineRun",
+		args: args{
+			pipelineRun: &v1alpha3.PipelineRun{
+				ObjectMeta: v1.ObjectMeta{
+					Namespace: "ns",
+					Name:      "run",
+				},
+				Spec: v1alpha3.PipelineRunSpec{
+					SCM: &v1alpha3.SCM{
+						RefName: "master",
+					},
+					PipelineRef: &corev1.ObjectReference{
+						Name: "pipeline",
+					},
+				},
+			},
+		},
+		want: "/job/ns/job/pipeline/job/master",
+	}}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			assert.Equalf(t, tt.want, getJenkinsJobPath(tt.args.pipelineRun), "getJenkinsJobPath(%v)", tt.args.pipelineRun)
+		})
+	}
+}