Repository: kubesphere/ks-devops
Pull request #808 (2022-08-30 10:38:45)

Fixed: Skip github build status notifications
**What type of PR is this?**
/kind bug

**What this PR does / why we need it:**
Create github pipeline use Skip Notifications Trait plugin forbid github plugin send status notification (also include gitlab, bitbucket)
![](https://github.com/gaffeyQiu/image/blob/main/wancheng3.png?raw=true)
**Which issue(s) this PR fixes:**
#804

### Does this PR introduce a user-facing change??
<!--
If no, just write "None" in the release-note block below.
If yes, a release note is required:
Enter your extended-release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required".

Please keep the note be same as your PR title if you believe it should be in the release notes.
-->
```release-note
None
```


ks-ci-bot: @gaffeyQiu: Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our [release note process](https://git.k8s.io/community/contributors/guide/release-notes.md) to remove it.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>
ks-ci-bot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by:
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **linuxsuren** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @linuxsuren` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubesphere%2Fks-devops).

<details open>
Needs approval from an approver in each of these files:

- **[pkg/client/devops/OWNERS](https://github.com/kubesphere/ks-devops/blob/master/pkg/client/devops/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["linuxsuren"]} -->
codecov[bot]: # [Codecov](https://codecov.io/gh/kubesphere/ks-devops/pull/808?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere) Report
> Merging [#808](https://codecov.io/gh/kubesphere/ks-devops/pull/808?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere) (911fb44) into [master](https://codecov.io/gh/kubesphere/ks-devops/commit/f69d2264e742b7b55ae502443396c1281cbf0c81?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere) (f69d226) will **decrease** coverage by `0.00%`.
> The diff coverage is `0.00%`.

```diff
@@            Coverage Diff             @@
##           master     #808      +/-   ##
==========================================
- Coverage   55.10%   55.09%   -0.01%     
==========================================
  Files         183      183              
  Lines       10891    10895       +4     
==========================================
+ Hits         6001     6003       +2     
- Misses       4562     4563       +1     
- Partials      328      329       +1     
```

| Flag | Coverage Δ | |
|---|---|---|
| unittests | `55.09% <0.00%> (-0.01%)` | :arrow_down: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/kubesphere/ks-devops/pull/808?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere) | Coverage Δ | |
|---|---|---|
| [pkg/client/devops/jenkins/internal/github.go](https://codecov.io/gh/kubesphere/ks-devops/pull/808/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere#diff-cGtnL2NsaWVudC9kZXZvcHMvamVua2lucy9pbnRlcm5hbC9naXRodWIuZ28=) | `3.00% <0.00%> (-0.07%)` | :arrow_down: |
| [...ontrollers/jenkins/pipeline/pipeline\_controller.go](https://codecov.io/gh/kubesphere/ks-devops/pull/808/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere#diff-Y29udHJvbGxlcnMvamVua2lucy9waXBlbGluZS9waXBlbGluZV9jb250cm9sbGVyLmdv) | `39.39% <0.00%> (-3.79%)` | :arrow_down: |
| [cmd/controller/app/options/feature.go](https://codecov.io/gh/kubesphere/ks-devops/pull/808/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere#diff-Y21kL2NvbnRyb2xsZXIvYXBwL29wdGlvbnMvZmVhdHVyZS5nbw==) | `100.00% <0.00%> (ø)` | |
| [...rs/gitrepository/pull\_request\_status\_controller.go](https://codecov.io/gh/kubesphere/ks-devops/pull/808/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere#diff-Y29udHJvbGxlcnMvZ2l0cmVwb3NpdG9yeS9wdWxsX3JlcXVlc3Rfc3RhdHVzX2NvbnRyb2xsZXIuZ28=) | `86.20% <0.00%> (+0.09%)` | :arrow_up: |
| [...ns/devopscredential/devopscredential\_controller.go](https://codecov.io/gh/kubesphere/ks-devops/pull/808/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere#diff-Y29udHJvbGxlcnMvamVua2lucy9kZXZvcHNjcmVkZW50aWFsL2Rldm9wc2NyZWRlbnRpYWxfY29udHJvbGxlci5nbw==) | `36.73% <0.00%> (+3.40%)` | :arrow_up: |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere)

gaffeyQiu: skip-notifications-trait plugin support github, bitbucket, gitlab support is not written into the plugin documentation, But I just tested is effective，Can I continue to use this plugin support gitlab， bitbucket?
---
MR1 is not use skip-notifications-trait plugin  

LinuxSuRen: Why closed?
gaffeyQiu: Did I make a mistake？ I was just modifying the ks-jenkins repo pull request
gaffeyQiu: > Why closed?

Sorry, Please reopen it
gaffeyQiu: Reopen it
gaffeyQiu: PR1 is not use skip-notifications-trait plugin
PR2 is use skip-notifications-trait plugin
![image](https://user-images.githubusercontent.com/19790443/187643810-3318f84d-7c50-4adf-a6e0-e091c3fbcc36.png)
![image](https://user-images.githubusercontent.com/19790443/187644126-1a16d521-cac4-4f91-ab79-11e37de45c85.png)
So, I need add this line to config.xml
![image](https://user-images.githubusercontent.com/19790443/187644653-fd94c7c9-8f27-4185-9977-665160ed1a72.png)

ks-ci-bot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by:
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **linuxsuren** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @linuxsuren` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubesphere%2Fks-devops).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/kubesphere/ks-devops/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["linuxsuren"]} -->
gaffeyQiu: Why the codecov is 0%? 
`Test_MultiBranchPipelineSkipNotification()` It should be covered `if !gitSource.AcceptJenkinsNotification { xxx }`  case
![image](https://user-images.githubusercontent.com/19790443/187660161-ad36fa0a-0d81-4a34-b410-f5fb0793b732.png)

gaffeyQiu: I run `make manifests generate` generat an old version CRD, because my controller-gen is the old version, advice add validation in makefile
![image](https://user-images.githubusercontent.com/19790443/187667222-e23bafa0-24a3-43dc-8af9-e3df9d46aac5.png)
LinuxSuRen: > Why the codecov is 0%?

I guess there are different coverage methods.

![image](https://user-images.githubusercontent.com/1450685/187814704-1cd9e86f-7f2b-4c56-9bda-a42d629a66af.png)

LinuxSuRen: > And if you want to indicate the specified version of controller-gen you can refer to the practice [here](https://github.com/fluxcd/helm-controller/blob/12dc7d9dcab039bfbf8a555c825a489f3863848e/Makefile#L116).

Please feel free to help us improve it if you're interested in it.
ks-ci-bot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubesphere/ks-devops/pull/808#pullrequestreview-1092753487" title="Approved">LinuxSuRen</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubesphere%2Fks-devops).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/kubesphere/ks-devops/blob/master/OWNERS)~~ [LinuxSuRen]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
LinuxSuRen: The related PR is https://github.com/kubesphere/ks-jenkins/pull/91

Patch:
diff --git a/config/crd/bases/devops.kubesphere.io_pipelineruns.yaml b/config/crd/bases/devops.kubesphere.io_pipelineruns.yaml
index 9f4444e..f5bde48 100644
--- a/config/crd/bases/devops.kubesphere.io_pipelineruns.yaml
+++ b/config/crd/bases/devops.kubesphere.io_pipelineruns.yaml
@@ -114,6 +114,8 @@ spec:
                     properties:
                       bitbucket_server_source:
                         properties:
+                          accept_jenkins_notification:
+                            type: boolean
                           api_uri:
                             type: string
                           credential_id:
@@ -186,6 +188,8 @@ spec:
                         description: GithubSource and BitbucketServerSource have the
                           same structure, but we don't use one due to crd errors
                         properties:
+                          accept_jenkins_notification:
+                            type: boolean
                           api_uri:
                             type: string
                           credential_id:
@@ -223,6 +227,8 @@ spec:
                         type: object
                       gitlab_source:
                         properties:
+                          accept_jenkins_notification:
+                            type: boolean
                           api_uri:
                             type: string
                           credential_id:
diff --git a/config/crd/bases/devops.kubesphere.io_pipelines.yaml b/config/crd/bases/devops.kubesphere.io_pipelines.yaml
index cdb27ee..163a9b4 100644
--- a/config/crd/bases/devops.kubesphere.io_pipelines.yaml
+++ b/config/crd/bases/devops.kubesphere.io_pipelines.yaml
@@ -53,6 +53,8 @@ spec:
                 properties:
                   bitbucket_server_source:
                     properties:
+                      accept_jenkins_notification:
+                        type: boolean
                       api_uri:
                         type: string
                       credential_id:
@@ -125,6 +127,8 @@ spec:
                     description: GithubSource and BitbucketServerSource have the same
                       structure, but we don't use one due to crd errors
                     properties:
+                      accept_jenkins_notification:
+                        type: boolean
                       api_uri:
                         type: string
                       credential_id:
@@ -162,6 +166,8 @@ spec:
                     type: object
                   gitlab_source:
                     properties:
+                      accept_jenkins_notification:
+                        type: boolean
                       api_uri:
                         type: string
                       credential_id:
diff --git a/pkg/api/devops/v1alpha3/pipeline_types.go b/pkg/api/devops/v1alpha3/pipeline_types.go
index 5a93f21..d9b4662 100644
--- a/pkg/api/devops/v1alpha3/pipeline_types.go
+++ b/pkg/api/devops/v1alpha3/pipeline_types.go
@@ -177,46 +177,49 @@ type GitSource struct {
 
 // GithubSource and BitbucketServerSource have the same structure, but we don't use one due to crd errors
 type GithubSource struct {
-	ScmId                string               `json:"scm_id,omitempty" description:"uid of scm"`
-	Owner                string               `json:"owner,omitempty" mapstructure:"owner" description:"owner of github repo"`
-	Repo                 string               `json:"repo,omitempty" mapstructure:"repo" description:"repo name of github repo"`
-	CredentialId         string               `json:"credential_id,omitempty" mapstructure:"credential_id" description:"credential id to access github source"`
-	ApiUri               string               `json:"api_uri,omitempty" mapstructure:"api_uri" description:"The api url can specify the location of the github apiserver.For private cloud configuration"`
-	DiscoverBranches     int                  `json:"discover_branches,omitempty" mapstructure:"discover_branches" description:"Discover branch configuration"`
-	DiscoverPRFromOrigin int                  `json:"discover_pr_from_origin,omitempty" mapstructure:"discover_pr_from_origin" description:"Discover origin PR configuration"`
-	DiscoverPRFromForks  *DiscoverPRFromForks `json:"discover_pr_from_forks,omitempty" mapstructure:"discover_pr_from_forks" description:"Discover fork PR configuration"`
-	DiscoverTags         bool                 `json:"discover_tags,omitempty" mapstructure:"discover_tags" description:"Discover tag configuration"`
-	CloneOption          *GitCloneOption      `json:"git_clone_option,omitempty" mapstructure:"git_clone_option" description:"advavced git clone options"`
-	RegexFilter          string               `json:"regex_filter,omitempty" mapstructure:"regex_filter" description:"Regex used to match the name of the branch that needs to be run"`
+	ScmId                     string               `json:"scm_id,omitempty" description:"uid of scm"`
+	Owner                     string               `json:"owner,omitempty" mapstructure:"owner" description:"owner of github repo"`
+	Repo                      string               `json:"repo,omitempty" mapstructure:"repo" description:"repo name of github repo"`
+	CredentialId              string               `json:"credential_id,omitempty" mapstructure:"credential_id" description:"credential id to access github source"`
+	ApiUri                    string               `json:"api_uri,omitempty" mapstructure:"api_uri" description:"The api url can specify the location of the github apiserver.For private cloud configuration"`
+	DiscoverBranches          int                  `json:"discover_branches,omitempty" mapstructure:"discover_branches" description:"Discover branch configuration"`
+	DiscoverPRFromOrigin      int                  `json:"discover_pr_from_origin,omitempty" mapstructure:"discover_pr_from_origin" description:"Discover origin PR configuration"`
+	DiscoverPRFromForks       *DiscoverPRFromForks `json:"discover_pr_from_forks,omitempty" mapstructure:"discover_pr_from_forks" description:"Discover fork PR configuration"`
+	DiscoverTags              bool                 `json:"discover_tags,omitempty" mapstructure:"discover_tags" description:"Discover tag configuration"`
+	CloneOption               *GitCloneOption      `json:"git_clone_option,omitempty" mapstructure:"git_clone_option" description:"advavced git clone options"`
+	RegexFilter               string               `json:"regex_filter,omitempty" mapstructure:"regex_filter" description:"Regex used to match the name of the branch that needs to be run"`
+	AcceptJenkinsNotification bool                 `json:"accept_jenkins_notification,omitempty"  mapstructure:"accept_jenkins_notification" description:"Allow Jenkins send build status notification to Github"`
 }
 
 type GitlabSource struct {
-	ScmId                string               `json:"scm_id,omitempty" description:"uid of scm"`
-	Owner                string               `json:"owner,omitempty" mapstructure:"owner" description:"owner of gitlab repo"`
-	Repo                 string               `json:"repo,omitempty" mapstructure:"repo" description:"repo name of gitlab repo"`
-	ServerName           string               `json:"server_name,omitempty" description:"the name of gitlab server which was configured in jenkins"`
-	CredentialId         string               `json:"credential_id,omitempty" mapstructure:"credential_id" description:"credential id to access gitlab source"`
-	ApiUri               string               `json:"api_uri,omitempty" mapstructure:"api_uri" description:"The api url can specify the location of the gitlab apiserver.For private cloud configuration"`
-	DiscoverBranches     int                  `json:"discover_branches,omitempty" mapstructure:"discover_branches" description:"Discover branch configuration"`
-	DiscoverPRFromOrigin int                  `json:"discover_pr_from_origin,omitempty" mapstructure:"discover_pr_from_origin" description:"Discover origin PR configuration"`
-	DiscoverPRFromForks  *DiscoverPRFromForks `json:"discover_pr_from_forks,omitempty" mapstructure:"discover_pr_from_forks" description:"Discover fork PR configuration"`
-	DiscoverTags         bool                 `json:"discover_tags,omitempty" mapstructure:"discover_tags" description:"Discover tags configuration"`
-	CloneOption          *GitCloneOption      `json:"git_clone_option,omitempty" mapstructure:"git_clone_option" description:"advavced git clone options"`
-	RegexFilter          string               `json:"regex_filter,omitempty" mapstructure:"regex_filter" description:"Regex used to match the name of the branch that needs to be run"`
+	ScmId                     string               `json:"scm_id,omitempty" description:"uid of scm"`
+	Owner                     string               `json:"owner,omitempty" mapstructure:"owner" description:"owner of gitlab repo"`
+	Repo                      string               `json:"repo,omitempty" mapstructure:"repo" description:"repo name of gitlab repo"`
+	ServerName                string               `json:"server_name,omitempty" description:"the name of gitlab server which was configured in jenkins"`
+	CredentialId              string               `json:"credential_id,omitempty" mapstructure:"credential_id" description:"credential id to access gitlab source"`
+	ApiUri                    string               `json:"api_uri,omitempty" mapstructure:"api_uri" description:"The api url can specify the location of the gitlab apiserver.For private cloud configuration"`
+	DiscoverBranches          int                  `json:"discover_branches,omitempty" mapstructure:"discover_branches" description:"Discover branch configuration"`
+	DiscoverPRFromOrigin      int                  `json:"discover_pr_from_origin,omitempty" mapstructure:"discover_pr_from_origin" description:"Discover origin PR configuration"`
+	DiscoverPRFromForks       *DiscoverPRFromForks `json:"discover_pr_from_forks,omitempty" mapstructure:"discover_pr_from_forks" description:"Discover fork PR configuration"`
+	DiscoverTags              bool                 `json:"discover_tags,omitempty" mapstructure:"discover_tags" description:"Discover tags configuration"`
+	CloneOption               *GitCloneOption      `json:"git_clone_option,omitempty" mapstructure:"git_clone_option" description:"advavced git clone options"`
+	RegexFilter               string               `json:"regex_filter,omitempty" mapstructure:"regex_filter" description:"Regex used to match the name of the branch that needs to be run"`
+	AcceptJenkinsNotification bool                 `json:"accept_jenkins_notification,omitempty"  mapstructure:"accept_jenkins_notification" description:"Allow Jenkins send build status notification to Gitlab"`
 }
 
 type BitbucketServerSource struct {
-	ScmId                string               `json:"scm_id,omitempty" description:"uid of scm"`
-	Owner                string               `json:"owner,omitempty" mapstructure:"owner" description:"owner of github repo"`
-	Repo                 string               `json:"repo,omitempty" mapstructure:"repo" description:"repo name of github repo"`
-	CredentialId         string               `json:"credential_id,omitempty" mapstructure:"credential_id" description:"credential id to access github source"`
-	ApiUri               string               `json:"api_uri,omitempty" mapstructure:"api_uri" description:"The api url can specify the location of the github apiserver.For private cloud configuration"`
-	DiscoverBranches     int                  `json:"discover_branches,omitempty" mapstructure:"discover_branches" description:"Discover branch configuration"`
-	DiscoverPRFromOrigin int                  `json:"discover_pr_from_origin,omitempty" mapstructure:"discover_pr_from_origin" description:"Discover origin PR configuration"`
-	DiscoverPRFromForks  *DiscoverPRFromForks `json:"discover_pr_from_forks,omitempty" mapstructure:"discover_pr_from_forks" description:"Discover fork PR configuration"`
-	DiscoverTags         bool                 `json:"discover_tags,omitempty" mapstructure:"discover_tags" description:"Discover tag configuration"`
-	CloneOption          *GitCloneOption      `json:"git_clone_option,omitempty" mapstructure:"git_clone_option" description:"advavced git clone options"`
-	RegexFilter          string               `json:"regex_filter,omitempty" mapstructure:"regex_filter" description:"Regex used to match the name of the branch that needs to be run"`
+	ScmId                     string               `json:"scm_id,omitempty" description:"uid of scm"`
+	Owner                     string               `json:"owner,omitempty" mapstructure:"owner" description:"owner of github repo"`
+	Repo                      string               `json:"repo,omitempty" mapstructure:"repo" description:"repo name of github repo"`
+	CredentialId              string               `json:"credential_id,omitempty" mapstructure:"credential_id" description:"credential id to access github source"`
+	ApiUri                    string               `json:"api_uri,omitempty" mapstructure:"api_uri" description:"The api url can specify the location of the github apiserver.For private cloud configuration"`
+	DiscoverBranches          int                  `json:"discover_branches,omitempty" mapstructure:"discover_branches" description:"Discover branch configuration"`
+	DiscoverPRFromOrigin      int                  `json:"discover_pr_from_origin,omitempty" mapstructure:"discover_pr_from_origin" description:"Discover origin PR configuration"`
+	DiscoverPRFromForks       *DiscoverPRFromForks `json:"discover_pr_from_forks,omitempty" mapstructure:"discover_pr_from_forks" description:"Discover fork PR configuration"`
+	DiscoverTags              bool                 `json:"discover_tags,omitempty" mapstructure:"discover_tags" description:"Discover tag configuration"`
+	CloneOption               *GitCloneOption      `json:"git_clone_option,omitempty" mapstructure:"git_clone_option" description:"advavced git clone options"`
+	RegexFilter               string               `json:"regex_filter,omitempty" mapstructure:"regex_filter" description:"Regex used to match the name of the branch that needs to be run"`
+	AcceptJenkinsNotification bool                 `json:"accept_jenkins_notification,omitempty"  mapstructure:"accept_jenkins_notification" description:"Allow Jenkins send build status notification to Bitbucket"`
 }
 
 type MultiBranchJobTrigger struct {
diff --git a/pkg/client/devops/jenkins/internal/bitbucket.go b/pkg/client/devops/jenkins/internal/bitbucket.go
index f161704..4921ce7 100644
--- a/pkg/client/devops/jenkins/internal/bitbucket.go
+++ b/pkg/client/devops/jenkins/internal/bitbucket.go
@@ -88,6 +88,10 @@ func AppendBitbucketServerSourceToEtree(source *etree.Element, gitSource *devops
 		regexTraits.CreateAttr("plugin", "scm-api")
 		regexTraits.CreateElement("regex").SetText(gitSource.RegexFilter)
 	}
+	if !gitSource.AcceptJenkinsNotification {
+		skipNotifications := traits.CreateElement("com.cloudbees.jenkins.plugins.bitbucket.notifications.SkipNotificationsTrait")
+		skipNotifications.CreateAttr("plugin", "skip-notifications-trait")
+	}
 	return
 }
 
@@ -160,6 +164,11 @@ func GetBitbucketServerSourceFromEtree(source *etree.Element) *devopsv1alpha3.Bi
 				s.RegexFilter = regex.Text()
 			}
 		}
+
+		if skipNotificationTrait := traits.SelectElement(
+			"com.cloudbees.jenkins.plugins.bitbucket.notifications.SkipNotificationsTrait"); skipNotificationTrait == nil {
+			s.AcceptJenkinsNotification = true
+		}
 	}
 	return &s
 }
diff --git a/pkg/client/devops/jenkins/internal/github.go b/pkg/client/devops/jenkins/internal/github.go
index 042188b..b4e5ba0 100644
--- a/pkg/client/devops/jenkins/internal/github.go
+++ b/pkg/client/devops/jenkins/internal/github.go
@@ -87,6 +87,10 @@ func AppendGithubSourceToEtree(source *etree.Element, githubSource *devopsv1alph
 		regexTraits.CreateAttr("plugin", "scm-api")
 		regexTraits.CreateElement("regex").SetText(githubSource.RegexFilter)
 	}
+	if !githubSource.AcceptJenkinsNotification {
+		skipNotifications := traits.CreateElement("org.jenkinsci.plugins.github.notifications.NotificationsSkipTrait")
+		skipNotifications.CreateAttr("plugin", "skip-notifications-trait")
+	}
 	return
 }
 
@@ -157,6 +161,11 @@ func GetGithubSourcefromEtree(source *etree.Element) *devopsv1alpha3.GithubSourc
 				githubSource.RegexFilter = regex.Text()
 			}
 		}
+
+		if skipNotificationTrait := traits.SelectElement(
+			"org.jenkinsci.plugins.github.notifications.NotificationsSkipTrait"); skipNotificationTrait == nil {
+			githubSource.AcceptJenkinsNotification = true
+		}
 	}
 	return &githubSource
 }
diff --git a/pkg/client/devops/jenkins/internal/gitlab.go b/pkg/client/devops/jenkins/internal/gitlab.go
index 8969653..73a293d 100644
--- a/pkg/client/devops/jenkins/internal/gitlab.go
+++ b/pkg/client/devops/jenkins/internal/gitlab.go
@@ -86,6 +86,10 @@ func AppendGitlabSourceToEtree(source *etree.Element, gitSource *devopsv1alpha3.
 		regexTraits.CreateAttr("plugin", "scm-api")
 		regexTraits.CreateElement("regex").SetText(gitSource.RegexFilter)
 	}
+	if !gitSource.AcceptJenkinsNotification {
+		traits.CreateElement("io.jenkins.plugins.gitlabbranchsource.GitLabSkipNotificationsTrait")
+	}
+
 	return
 }
 
@@ -156,6 +160,11 @@ func GetGitlabSourceFromEtree(source *etree.Element) (gitSource *devopsv1alpha3.
 				gitSource.RegexFilter = regex.Text()
 			}
 		}
+
+		if skipNotificationTrait := traits.SelectElement(
+			"io.jenkins.plugins.gitlabbranchsource.GitLabSkipNotificationsTrait"); skipNotificationTrait == nil {
+			gitSource.AcceptJenkinsNotification = true
+		}
 	}
 	return
 }


Test patch:
diff --git a/pkg/client/devops/jenkins/internal/common_test.go b/pkg/client/devops/jenkins/internal/common_test.go
index b3aa5ea..56c0526 100644
--- a/pkg/client/devops/jenkins/internal/common_test.go
+++ b/pkg/client/devops/jenkins/internal/common_test.go
@@ -16,7 +16,12 @@ limitations under the License.
 
 package internal
 
-import "testing"
+import (
+	"github.com/beevik/etree"
+	"github.com/stretchr/testify/assert"
+	devopsv1alpha3 "kubesphere.io/devops/pkg/api/devops/v1alpha3"
+	"testing"
+)
 
 func TestCommonSituation(t *testing.T) {
 	// make sure these functions do not panic
@@ -28,3 +33,53 @@ func TestCommonSituation(t *testing.T) {
 	AppendSingleSvnSourceToEtree(nil, nil)
 	AppendSvnSourceToEtree(nil, nil)
 }
+
+func TestSkipJenkinsNotification(t *testing.T) {
+	PRForks := &devopsv1alpha3.DiscoverPRFromForks{
+		Strategy: 1,
+		Trust:    1,
+	}
+
+	// github
+	source := etree.NewDocument().CreateElement("source")
+	AppendGithubSourceToEtree(source, &devopsv1alpha3.GithubSource{DiscoverPRFromForks: PRForks})
+	githubSource := GetGithubSourcefromEtree(source)
+	assert.False(t, githubSource.AcceptJenkinsNotification)
+
+	// gitlab
+	source = etree.NewDocument().CreateElement("source")
+	AppendGitlabSourceToEtree(source, &devopsv1alpha3.GitlabSource{DiscoverPRFromForks: PRForks})
+	gitlabSource := GetGitlabSourceFromEtree(source)
+	assert.False(t, gitlabSource.AcceptJenkinsNotification)
+
+	// bitbucketServer
+	source = etree.NewDocument().CreateElement("source")
+	AppendBitbucketServerSourceToEtree(source, &devopsv1alpha3.BitbucketServerSource{DiscoverPRFromForks: PRForks})
+	bitbucketServerSource := GetBitbucketServerSourceFromEtree(source)
+	assert.False(t, bitbucketServerSource.AcceptJenkinsNotification)
+}
+
+func TestAcceptJenkinsNotification(t *testing.T) {
+	PRForks := &devopsv1alpha3.DiscoverPRFromForks{
+		Strategy: 1,
+		Trust:    1,
+	}
+
+	// github
+	source := etree.NewDocument().CreateElement("source")
+	AppendGithubSourceToEtree(source, &devopsv1alpha3.GithubSource{DiscoverPRFromForks: PRForks, AcceptJenkinsNotification: true})
+	githubSource := GetGithubSourcefromEtree(source)
+	assert.True(t, githubSource.AcceptJenkinsNotification)
+
+	// gitlab
+	source = etree.NewDocument().CreateElement("source")
+	AppendGitlabSourceToEtree(source, &devopsv1alpha3.GitlabSource{DiscoverPRFromForks: PRForks, AcceptJenkinsNotification: true})
+	gitlabSource := GetGitlabSourceFromEtree(source)
+	assert.True(t, gitlabSource.AcceptJenkinsNotification)
+
+	// bitbucketServer
+	source = etree.NewDocument().CreateElement("source")
+	AppendBitbucketServerSourceToEtree(source, &devopsv1alpha3.BitbucketServerSource{DiscoverPRFromForks: PRForks, AcceptJenkinsNotification: true})
+	bitbucketServerSource := GetBitbucketServerSourceFromEtree(source)
+	assert.True(t, bitbucketServerSource.AcceptJenkinsNotification)
+}