github.com/zppinho/prow@v0.0.0-20240510014325-1738badeb017/pkg/plugins/dco/dco_test.go (about)

     1  /*
     2  Copyright 2018 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package dco
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  	"testing"
    23  
    24  	"github.com/sirupsen/logrus"
    25  
    26  	"sigs.k8s.io/prow/pkg/github"
    27  	"sigs.k8s.io/prow/pkg/github/fakegithub"
    28  	"sigs.k8s.io/prow/pkg/plugins"
    29  )
    30  
    31  type fakePruner struct{}
    32  
    33  func (fp *fakePruner) PruneComments(shouldPrune func(github.IssueComment) bool) {}
    34  
    35  func TestHandlePullRequest(t *testing.T) {
    36  	var testcases = []struct {
    37  		// test settings
    38  		name   string
    39  		config plugins.Dco
    40  
    41  		// PR settings
    42  		pullRequestEvent github.PullRequestEvent
    43  		commits          []github.RepositoryCommit
    44  		issueState       string
    45  		hasDCOYes        bool
    46  		hasDCONo         bool
    47  		// status of the DCO github context
    48  		status string
    49  
    50  		// expectations
    51  		addedLabel     string
    52  		removedLabel   string
    53  		expectedStatus string
    54  		// org/repo#number:body
    55  		addedComment string
    56  		// org/repo#issuecommentid
    57  		removedComment string
    58  	}{
    59  		{
    60  			name:   "should not do anything on pull request edited",
    61  			config: plugins.Dco{},
    62  			pullRequestEvent: github.PullRequestEvent{
    63  				Action:      github.PullRequestActionEdited,
    64  				PullRequest: github.PullRequest{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
    65  			},
    66  		},
    67  		{
    68  			name:   "should add 'no' label & status context and add a comment if no commits have sign off",
    69  			config: plugins.Dco{},
    70  			pullRequestEvent: github.PullRequestEvent{
    71  				Action:      github.PullRequestActionOpened,
    72  				PullRequest: github.PullRequest{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
    73  			},
    74  			commits: []github.RepositoryCommit{
    75  				{SHA: "sha", Commit: github.GitCommit{Message: "not a sign off"}},
    76  			},
    77  			issueState: "open",
    78  			hasDCONo:   false,
    79  			hasDCOYes:  false,
    80  
    81  			addedLabel:     fmt.Sprintf("/#3:%s", dcoNoLabel),
    82  			expectedStatus: github.StatusFailure,
    83  			addedComment: `/#3:Thanks for your pull request. Before we can look at it, you'll need to add a 'DCO signoff' to your commits.
    84  
    85  :memo: **Please follow instructions in the [contributing guide](https://github.com///blob/master/CONTRIBUTING.md) to update your commits with the DCO**
    86  
    87  Full details of the Developer Certificate of Origin can be found at [developercertificate.org](https://developercertificate.org/).
    88  
    89  **The list of commits missing DCO signoff**:
    90  
    91  - [sha](https://github.com///commits/sha) not a sign off
    92  
    93  <details>
    94  
    95  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-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
    96  </details>
    97  `,
    98  		},
    99  		{
   100  			name:   "should add 'no' label & status context, remove old labels and add a comment if no commits have sign off",
   101  			config: plugins.Dco{},
   102  			pullRequestEvent: github.PullRequestEvent{
   103  				Action:      github.PullRequestActionOpened,
   104  				PullRequest: github.PullRequest{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   105  			},
   106  			commits: []github.RepositoryCommit{
   107  				{SHA: "sha", Commit: github.GitCommit{Message: "not a sign off"}},
   108  			},
   109  			issueState: "open",
   110  			hasDCONo:   false,
   111  			hasDCOYes:  true,
   112  
   113  			addedLabel:     fmt.Sprintf("/#3:%s", dcoNoLabel),
   114  			removedLabel:   fmt.Sprintf("/#3:%s", dcoYesLabel),
   115  			expectedStatus: github.StatusFailure,
   116  			addedComment: `/#3:Thanks for your pull request. Before we can look at it, you'll need to add a 'DCO signoff' to your commits.
   117  
   118  :memo: **Please follow instructions in the [contributing guide](https://github.com///blob/master/CONTRIBUTING.md) to update your commits with the DCO**
   119  
   120  Full details of the Developer Certificate of Origin can be found at [developercertificate.org](https://developercertificate.org/).
   121  
   122  **The list of commits missing DCO signoff**:
   123  
   124  - [sha](https://github.com///commits/sha) not a sign off
   125  
   126  <details>
   127  
   128  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-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
   129  </details>
   130  `,
   131  		},
   132  		{
   133  			name:   "should update comment if labels and status are up to date and sign off is failing",
   134  			config: plugins.Dco{},
   135  			pullRequestEvent: github.PullRequestEvent{
   136  				Action:      github.PullRequestActionOpened,
   137  				PullRequest: github.PullRequest{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   138  			},
   139  			commits: []github.RepositoryCommit{
   140  				{SHA: "sha", Commit: github.GitCommit{Message: "not a sign off"}},
   141  			},
   142  			issueState: "open",
   143  			hasDCONo:   true,
   144  			hasDCOYes:  false,
   145  			status:     github.StatusFailure,
   146  
   147  			expectedStatus: github.StatusFailure,
   148  			addedComment: `/#3:Thanks for your pull request. Before we can look at it, you'll need to add a 'DCO signoff' to your commits.
   149  
   150  :memo: **Please follow instructions in the [contributing guide](https://github.com///blob/master/CONTRIBUTING.md) to update your commits with the DCO**
   151  
   152  Full details of the Developer Certificate of Origin can be found at [developercertificate.org](https://developercertificate.org/).
   153  
   154  **The list of commits missing DCO signoff**:
   155  
   156  - [sha](https://github.com///commits/sha) not a sign off
   157  
   158  <details>
   159  
   160  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-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
   161  </details>
   162  `,
   163  		},
   164  		{
   165  			name:   "should mark the PR as failed if just one commit is missing sign-off",
   166  			config: plugins.Dco{},
   167  			pullRequestEvent: github.PullRequestEvent{
   168  				Action:      github.PullRequestActionOpened,
   169  				PullRequest: github.PullRequest{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   170  			},
   171  			commits: []github.RepositoryCommit{
   172  				{SHA: "sha1", Commit: github.GitCommit{Message: "Signed-off-by: someone"}},
   173  				{SHA: "sha", Commit: github.GitCommit{Message: "not signed off"}},
   174  			},
   175  			issueState: "open",
   176  			hasDCONo:   false,
   177  			hasDCOYes:  true,
   178  
   179  			addedLabel:     fmt.Sprintf("/#3:%s", dcoNoLabel),
   180  			removedLabel:   fmt.Sprintf("/#3:%s", dcoYesLabel),
   181  			expectedStatus: github.StatusFailure,
   182  			addedComment: `/#3:Thanks for your pull request. Before we can look at it, you'll need to add a 'DCO signoff' to your commits.
   183  
   184  :memo: **Please follow instructions in the [contributing guide](https://github.com///blob/master/CONTRIBUTING.md) to update your commits with the DCO**
   185  
   186  Full details of the Developer Certificate of Origin can be found at [developercertificate.org](https://developercertificate.org/).
   187  
   188  **The list of commits missing DCO signoff**:
   189  
   190  - [sha](https://github.com///commits/sha) not signed off
   191  
   192  <details>
   193  
   194  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-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
   195  </details>
   196  `,
   197  		},
   198  		{
   199  			name:   "should add label and update status context if all commits are signed-off",
   200  			config: plugins.Dco{},
   201  			pullRequestEvent: github.PullRequestEvent{
   202  				Action:      github.PullRequestActionOpened,
   203  				PullRequest: github.PullRequest{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   204  			},
   205  			commits: []github.RepositoryCommit{
   206  				{SHA: "sha", Commit: github.GitCommit{Message: "Signed-off-by: someone"}},
   207  			},
   208  			issueState: "open",
   209  			hasDCONo:   false,
   210  			hasDCOYes:  false,
   211  
   212  			addedLabel:     fmt.Sprintf("/#3:%s", dcoYesLabel),
   213  			expectedStatus: github.StatusSuccess,
   214  		},
   215  		{
   216  			name:   "should add label and update status context and remove old labels if all commits are signed-off",
   217  			config: plugins.Dco{},
   218  			pullRequestEvent: github.PullRequestEvent{
   219  				Action:      github.PullRequestActionOpened,
   220  				PullRequest: github.PullRequest{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   221  			},
   222  			commits: []github.RepositoryCommit{
   223  				{SHA: "sha", Commit: github.GitCommit{Message: "Signed-off-by: someone"}},
   224  			},
   225  			issueState: "open",
   226  			hasDCONo:   true,
   227  			hasDCOYes:  false,
   228  
   229  			addedLabel:     fmt.Sprintf("/#3:%s", dcoYesLabel),
   230  			removedLabel:   fmt.Sprintf("/#3:%s", dcoNoLabel),
   231  			expectedStatus: github.StatusSuccess,
   232  		},
   233  		{
   234  			name: "should add label and update status context if an user is member of the trusted org (commit non-signed)",
   235  			config: plugins.Dco{
   236  				SkipDCOCheckForMembers: true,
   237  				TrustedOrg:             "kubernetes",
   238  			},
   239  			pullRequestEvent: github.PullRequestEvent{
   240  				Action:      github.PullRequestActionOpened,
   241  				PullRequest: github.PullRequest{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   242  			},
   243  			commits: []github.RepositoryCommit{
   244  				{
   245  					SHA:    "sha",
   246  					Commit: github.GitCommit{Message: "not signed off"},
   247  					Author: github.User{
   248  						Login: "test",
   249  					},
   250  				},
   251  			},
   252  			issueState: "open",
   253  			hasDCONo:   false,
   254  			hasDCOYes:  false,
   255  
   256  			addedLabel:     fmt.Sprintf("/#3:%s", dcoYesLabel),
   257  			expectedStatus: github.StatusSuccess,
   258  		},
   259  		{
   260  			name: "should add label and update status context if an user is member of the trusted org (one commit signed, one non-signed)",
   261  			config: plugins.Dco{
   262  				SkipDCOCheckForMembers: true,
   263  				TrustedOrg:             "kubernetes",
   264  			},
   265  			pullRequestEvent: github.PullRequestEvent{
   266  				Action:      github.PullRequestActionOpened,
   267  				PullRequest: github.PullRequest{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   268  			},
   269  			commits: []github.RepositoryCommit{
   270  				{
   271  					SHA:    "sha",
   272  					Commit: github.GitCommit{Message: "not signed off"},
   273  					Author: github.User{
   274  						Login: "test",
   275  					},
   276  				},
   277  				{
   278  					SHA:    "sha2",
   279  					Commit: github.GitCommit{Message: "Signed-off-by: someone"},
   280  					Author: github.User{
   281  						Login: "test",
   282  					},
   283  				},
   284  			},
   285  			issueState: "open",
   286  			hasDCONo:   false,
   287  			hasDCOYes:  false,
   288  
   289  			addedLabel:     fmt.Sprintf("/#3:%s", dcoYesLabel),
   290  			expectedStatus: github.StatusSuccess,
   291  		},
   292  		{
   293  			name: "should add label and update status context if one commit is signed-off and another is from a trusted user",
   294  			config: plugins.Dco{
   295  				SkipDCOCheckForMembers: true,
   296  				TrustedOrg:             "kubernetes",
   297  			},
   298  			pullRequestEvent: github.PullRequestEvent{
   299  				Action:      github.PullRequestActionOpened,
   300  				PullRequest: github.PullRequest{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   301  			},
   302  			commits: []github.RepositoryCommit{
   303  				{
   304  					SHA:    "sha",
   305  					Commit: github.GitCommit{Message: "not signed off"},
   306  					Author: github.User{
   307  						Login: "test",
   308  					},
   309  				},
   310  				{
   311  					SHA:    "sha2",
   312  					Commit: github.GitCommit{Message: "Signed-off-by: someone"},
   313  					Author: github.User{
   314  						Login: "contributor",
   315  					},
   316  				},
   317  			},
   318  			issueState: "open",
   319  			hasDCONo:   false,
   320  			hasDCOYes:  false,
   321  
   322  			addedLabel:     fmt.Sprintf("/#3:%s", dcoYesLabel),
   323  			expectedStatus: github.StatusSuccess,
   324  		},
   325  		{
   326  			name: "should fail dco check as one unsigned commit is from member not from the trusted org",
   327  			config: plugins.Dco{
   328  				SkipDCOCheckForMembers: true,
   329  				TrustedOrg:             "kubernetes",
   330  			},
   331  			pullRequestEvent: github.PullRequestEvent{
   332  				Action:      github.PullRequestActionOpened,
   333  				PullRequest: github.PullRequest{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   334  			},
   335  			commits: []github.RepositoryCommit{
   336  				{
   337  					SHA:    "sha",
   338  					Commit: github.GitCommit{Message: "Signed-off-by: someone"},
   339  					Author: github.User{
   340  						Login: "test",
   341  					},
   342  				},
   343  				{
   344  					SHA:    "sha2",
   345  					Commit: github.GitCommit{Message: "not signed off"},
   346  					Author: github.User{
   347  						Login: "test-2",
   348  					},
   349  				},
   350  			},
   351  			issueState: "open",
   352  			hasDCONo:   false,
   353  			hasDCOYes:  false,
   354  
   355  			addedLabel:     fmt.Sprintf("/#3:%s", dcoNoLabel),
   356  			expectedStatus: github.StatusFailure,
   357  			addedComment: `/#3:Thanks for your pull request. Before we can look at it, you'll need to add a 'DCO signoff' to your commits.
   358  
   359  :memo: **Please follow instructions in the [contributing guide](https://github.com///blob/master/CONTRIBUTING.md) to update your commits with the DCO**
   360  
   361  Full details of the Developer Certificate of Origin can be found at [developercertificate.org](https://developercertificate.org/).
   362  
   363  **The list of commits missing DCO signoff**:
   364  
   365  - [sha2](https://github.com///commits/sha2) not signed off
   366  
   367  <details>
   368  
   369  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-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
   370  </details>
   371  `,
   372  		},
   373  		{
   374  			name: "should add label and update status context as one unsigned commit is from member not from the trusted org",
   375  			config: plugins.Dco{
   376  				SkipDCOCheckForMembers: true,
   377  				TrustedOrg:             "kubernetes",
   378  			},
   379  			pullRequestEvent: github.PullRequestEvent{
   380  				Action:      github.PullRequestActionOpened,
   381  				PullRequest: github.PullRequest{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   382  			},
   383  			commits: []github.RepositoryCommit{
   384  				{
   385  					SHA:    "sha",
   386  					Commit: github.GitCommit{Message: "Signed-off-by: someone"},
   387  					Author: github.User{
   388  						Login: "test",
   389  					},
   390  				},
   391  				{
   392  					SHA:    "sha2",
   393  					Commit: github.GitCommit{Message: "not signed off"},
   394  					Author: github.User{
   395  						Login: "test-2",
   396  					},
   397  				},
   398  			},
   399  			issueState: "open",
   400  			hasDCONo:   false,
   401  			hasDCOYes:  true,
   402  
   403  			addedLabel:     fmt.Sprintf("/#3:%s", dcoNoLabel),
   404  			removedLabel:   fmt.Sprintf("/#3:%s", dcoYesLabel),
   405  			expectedStatus: github.StatusFailure,
   406  			addedComment: `/#3:Thanks for your pull request. Before we can look at it, you'll need to add a 'DCO signoff' to your commits.
   407  
   408  :memo: **Please follow instructions in the [contributing guide](https://github.com///blob/master/CONTRIBUTING.md) to update your commits with the DCO**
   409  
   410  Full details of the Developer Certificate of Origin can be found at [developercertificate.org](https://developercertificate.org/).
   411  
   412  **The list of commits missing DCO signoff**:
   413  
   414  - [sha2](https://github.com///commits/sha2) not signed off
   415  
   416  <details>
   417  
   418  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-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
   419  </details>
   420  `,
   421  		},
   422  		{
   423  			name: "should fail dco check as skip feature is disabled",
   424  			config: plugins.Dco{
   425  				SkipDCOCheckForMembers: false,
   426  				TrustedOrg:             "kubernetes",
   427  			},
   428  			pullRequestEvent: github.PullRequestEvent{
   429  				Action:      github.PullRequestActionOpened,
   430  				PullRequest: github.PullRequest{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   431  			},
   432  			commits: []github.RepositoryCommit{
   433  				{
   434  					SHA:    "sha",
   435  					Commit: github.GitCommit{Message: "not signed off"},
   436  					Author: github.User{
   437  						Login: "test",
   438  					},
   439  				},
   440  			},
   441  			issueState: "open",
   442  			hasDCONo:   false,
   443  			hasDCOYes:  false,
   444  
   445  			addedLabel:     fmt.Sprintf("/#3:%s", dcoNoLabel),
   446  			expectedStatus: github.StatusFailure,
   447  			addedComment: `/#3:Thanks for your pull request. Before we can look at it, you'll need to add a 'DCO signoff' to your commits.
   448  
   449  :memo: **Please follow instructions in the [contributing guide](https://github.com///blob/master/CONTRIBUTING.md) to update your commits with the DCO**
   450  
   451  Full details of the Developer Certificate of Origin can be found at [developercertificate.org](https://developercertificate.org/).
   452  
   453  **The list of commits missing DCO signoff**:
   454  
   455  - [sha](https://github.com///commits/sha) not signed off
   456  
   457  <details>
   458  
   459  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-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
   460  </details>
   461  `,
   462  		},
   463  		{
   464  			name: "should skip dco check as commit is from a collaborator",
   465  			config: plugins.Dco{
   466  				SkipDCOCheckForMembers:       true,
   467  				SkipDCOCheckForCollaborators: true,
   468  				TrustedOrg:                   "kubernetes",
   469  			},
   470  			pullRequestEvent: github.PullRequestEvent{
   471  				Action:      github.PullRequestActionOpened,
   472  				PullRequest: github.PullRequest{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   473  			},
   474  			commits: []github.RepositoryCommit{
   475  				{
   476  					SHA:    "sha",
   477  					Commit: github.GitCommit{Message: "not signed off"},
   478  					Author: github.User{
   479  						Login: "test-collaborator",
   480  					},
   481  				},
   482  			},
   483  			issueState: "open",
   484  			hasDCONo:   false,
   485  			hasDCOYes:  false,
   486  
   487  			addedLabel:     fmt.Sprintf("/#3:%s", dcoYesLabel),
   488  			expectedStatus: github.StatusSuccess,
   489  		},
   490  		{
   491  			name: "should fail dco check for a collaborator as skip dco for collaborators is disabled",
   492  			config: plugins.Dco{
   493  				SkipDCOCheckForCollaborators: false,
   494  				TrustedOrg:                   "kubernetes",
   495  			},
   496  			pullRequestEvent: github.PullRequestEvent{
   497  				Action:      github.PullRequestActionOpened,
   498  				PullRequest: github.PullRequest{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   499  			},
   500  			commits: []github.RepositoryCommit{
   501  				{
   502  					SHA:    "sha",
   503  					Commit: github.GitCommit{Message: "not signed off"},
   504  					Author: github.User{
   505  						Login: "test-collaborator",
   506  					},
   507  				},
   508  			},
   509  			issueState: "open",
   510  			hasDCONo:   false,
   511  			hasDCOYes:  false,
   512  
   513  			addedLabel:     fmt.Sprintf("/#3:%s", dcoNoLabel),
   514  			expectedStatus: github.StatusFailure,
   515  			addedComment: `/#3:Thanks for your pull request. Before we can look at it, you'll need to add a 'DCO signoff' to your commits.
   516  
   517  :memo: **Please follow instructions in the [contributing guide](https://github.com///blob/master/CONTRIBUTING.md) to update your commits with the DCO**
   518  
   519  Full details of the Developer Certificate of Origin can be found at [developercertificate.org](https://developercertificate.org/).
   520  
   521  **The list of commits missing DCO signoff**:
   522  
   523  - [sha](https://github.com///commits/sha) not signed off
   524  
   525  <details>
   526  
   527  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-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
   528  </details>
   529  `,
   530  		},
   531  		{
   532  			name: "should use custom CONTRIBUTING.md repo, branch and path in comment",
   533  			config: plugins.Dco{
   534  				ContributingRepo:   "kubernetes/org",
   535  				ContributingBranch: "main",
   536  				ContributingPath:   "docs/CONTRIBUTING.md",
   537  			},
   538  			pullRequestEvent: github.PullRequestEvent{
   539  				Action:      github.PullRequestActionOpened,
   540  				PullRequest: github.PullRequest{Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   541  			},
   542  			commits: []github.RepositoryCommit{
   543  				{
   544  					SHA:    "sha",
   545  					Commit: github.GitCommit{Message: "not signed off"},
   546  					Author: github.User{
   547  						Login: "test-collaborator",
   548  					},
   549  				},
   550  			},
   551  			issueState: "open",
   552  			hasDCONo:   false,
   553  			hasDCOYes:  false,
   554  
   555  			addedLabel:     fmt.Sprintf("/#3:%s", dcoNoLabel),
   556  			expectedStatus: github.StatusFailure,
   557  			addedComment: `/#3:Thanks for your pull request. Before we can look at it, you'll need to add a 'DCO signoff' to your commits.
   558  
   559  :memo: **Please follow instructions in the [contributing guide](https://github.com/kubernetes/org/blob/main/docs/CONTRIBUTING.md) to update your commits with the DCO**
   560  
   561  Full details of the Developer Certificate of Origin can be found at [developercertificate.org](https://developercertificate.org/).
   562  
   563  **The list of commits missing DCO signoff**:
   564  
   565  - [sha](https://github.com///commits/sha) not signed off
   566  
   567  <details>
   568  
   569  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-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
   570  </details>
   571  `,
   572  		},
   573  	}
   574  	for _, tc := range testcases {
   575  		t.Run(tc.name, func(t *testing.T) {
   576  			fc := fakegithub.NewFakeClient()
   577  			fc.CombinedStatuses = make(map[string]*github.CombinedStatus)
   578  			fc.CreatedStatuses = make(map[string][]github.Status)
   579  			fc.PullRequests = map[int]*github.PullRequest{tc.pullRequestEvent.PullRequest.Number: &tc.pullRequestEvent.PullRequest}
   580  			fc.IssueComments = make(map[int][]github.IssueComment)
   581  			fc.CommitMap = map[string][]github.RepositoryCommit{
   582  				"/#3": tc.commits,
   583  			}
   584  			fc.OrgMembers = map[string][]string{
   585  				"kubernetes": {"test"},
   586  			}
   587  			fc.Collaborators = []string{"test-collaborator"}
   588  			if tc.hasDCOYes {
   589  				fc.IssueLabelsAdded = append(fc.IssueLabelsAdded, fmt.Sprintf("/#3:%s", dcoYesLabel))
   590  			}
   591  			if tc.hasDCONo {
   592  				fc.IssueLabelsAdded = append(fc.IssueLabelsAdded, fmt.Sprintf("/#3:%s", dcoNoLabel))
   593  			}
   594  			combinedStatus := &github.CombinedStatus{
   595  				Statuses: []github.Status{},
   596  			}
   597  			if tc.status != "" {
   598  				fc.CreatedStatuses["sha"] = []github.Status{
   599  					{Context: dcoContextName, State: tc.status},
   600  				}
   601  				combinedStatus = &github.CombinedStatus{
   602  					SHA: "sha",
   603  					Statuses: []github.Status{
   604  						{Context: dcoContextName, State: tc.status},
   605  					},
   606  				}
   607  			}
   608  			fc.CombinedStatuses["sha"] = combinedStatus
   609  
   610  			if err := handlePullRequest(tc.config, fc, &fakePruner{}, logrus.WithField("plugin", pluginName), tc.pullRequestEvent); err != nil {
   611  				t.Errorf("For case %s, didn't expect error from dco plugin: %v", tc.name, err)
   612  			}
   613  			ok := tc.addedLabel == ""
   614  			if !ok {
   615  				for _, label := range fc.IssueLabelsAdded {
   616  					if reflect.DeepEqual(tc.addedLabel, label) {
   617  						ok = true
   618  						break
   619  					}
   620  				}
   621  			}
   622  			if !ok {
   623  				t.Errorf("Expected to add: %#v, Got %#v in case %s.", tc.addedLabel, fc.IssueLabelsAdded, tc.name)
   624  			}
   625  			ok = tc.removedLabel == ""
   626  			if !ok {
   627  				for _, label := range fc.IssueLabelsRemoved {
   628  					if reflect.DeepEqual(tc.removedLabel, label) {
   629  						ok = true
   630  						break
   631  					}
   632  				}
   633  			}
   634  			if !ok {
   635  				t.Errorf("Expected to remove: %#v, Got %#v in case %s.", tc.removedLabel, fc.IssueLabelsRemoved, tc.name)
   636  			}
   637  
   638  			// check status is set as expected
   639  			statuses := fc.CreatedStatuses["sha"]
   640  			if len(statuses) == 0 && tc.expectedStatus != "" {
   641  				t.Errorf("Expected dco status to be %q, but it was not set", tc.expectedStatus)
   642  			}
   643  			found := false
   644  			for _, s := range statuses {
   645  				if s.Context == dcoContextName {
   646  					found = true
   647  					if s.State != tc.expectedStatus {
   648  						t.Errorf("Expected dco status to be %q but it was %q", tc.expectedStatus, s.State)
   649  					}
   650  				}
   651  			}
   652  			if !found && tc.expectedStatus != "" {
   653  				t.Errorf("Expect dco status to be %q, but it was not found", tc.expectedStatus)
   654  			}
   655  
   656  			comments := fc.IssueCommentsAdded
   657  			if len(comments) == 0 && tc.addedComment != "" {
   658  				t.Errorf("Expected comment with body %q to be added, but it was not", tc.addedComment)
   659  				return
   660  			}
   661  			if len(comments) > 1 {
   662  				t.Errorf("did not expect more than one comment to be created")
   663  			}
   664  			if len(comments) != 0 && comments[0] != tc.addedComment {
   665  				t.Errorf("expected comment to be %q but it was %q", tc.addedComment, comments[0])
   666  			}
   667  		})
   668  	}
   669  }
   670  func TestHandleComment(t *testing.T) {
   671  	var testcases = []struct {
   672  		// test settings
   673  		name   string
   674  		config plugins.Dco
   675  
   676  		// PR settings
   677  		commentEvent github.GenericCommentEvent
   678  		pullRequests map[int]*github.PullRequest
   679  		commits      []github.RepositoryCommit
   680  		issueState   string
   681  		hasDCOYes    bool
   682  		hasDCONo     bool
   683  		// status of the DCO github context
   684  		status string
   685  
   686  		// expectations
   687  		addedLabel     string
   688  		removedLabel   string
   689  		expectedStatus string
   690  		// org/repo#number:body
   691  		addedComment string
   692  		// org/repo#issuecommentid
   693  		removedComment string
   694  	}{
   695  		{
   696  			name:   "should not do anything if comment does not match /check-dco",
   697  			config: plugins.Dco{},
   698  			commentEvent: github.GenericCommentEvent{
   699  				IssueState: "open",
   700  				Action:     github.GenericCommentActionCreated,
   701  				Body:       "not-the-trigger",
   702  				IsPR:       true,
   703  				Number:     3,
   704  			},
   705  			pullRequests: map[int]*github.PullRequest{
   706  				3: {Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   707  			},
   708  		},
   709  		{
   710  			name:   "should add 'no' label & status context and add a comment if no commits have sign off",
   711  			config: plugins.Dco{},
   712  			commentEvent: github.GenericCommentEvent{
   713  				IssueState: "open",
   714  				Action:     github.GenericCommentActionCreated,
   715  				Body:       "/check-dco",
   716  				IsPR:       true,
   717  				Number:     3,
   718  			},
   719  			pullRequests: map[int]*github.PullRequest{
   720  				3: {Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   721  			},
   722  			commits: []github.RepositoryCommit{
   723  				{SHA: "sha", Commit: github.GitCommit{Message: "not a sign off"}},
   724  			},
   725  			issueState: "open",
   726  			hasDCONo:   false,
   727  			hasDCOYes:  false,
   728  
   729  			addedLabel:     fmt.Sprintf("/#3:%s", dcoNoLabel),
   730  			expectedStatus: github.StatusFailure,
   731  			addedComment: `/#3:Thanks for your pull request. Before we can look at it, you'll need to add a 'DCO signoff' to your commits.
   732  
   733  :memo: **Please follow instructions in the [contributing guide](https://github.com///blob/master/CONTRIBUTING.md) to update your commits with the DCO**
   734  
   735  Full details of the Developer Certificate of Origin can be found at [developercertificate.org](https://developercertificate.org/).
   736  
   737  **The list of commits missing DCO signoff**:
   738  
   739  - [sha](https://github.com///commits/sha) not a sign off
   740  
   741  <details>
   742  
   743  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-sigs/prow](https://github.com/kubernetes-sigs/prow/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
   744  </details>
   745  `,
   746  		},
   747  		{
   748  			name: "should succeed as skip dco is enabled",
   749  			config: plugins.Dco{
   750  				SkipDCOCheckForMembers: true,
   751  				TrustedOrg:             "kubernetes",
   752  			},
   753  			commentEvent: github.GenericCommentEvent{
   754  				IssueState: "open",
   755  				Action:     github.GenericCommentActionCreated,
   756  				Body:       "/check-dco",
   757  				IsPR:       true,
   758  				Number:     3,
   759  			},
   760  			pullRequests: map[int]*github.PullRequest{
   761  				3: {Number: 3, Head: github.PullRequestBranch{SHA: "sha"}},
   762  			},
   763  			commits: []github.RepositoryCommit{
   764  				{
   765  					SHA:    "sha",
   766  					Commit: github.GitCommit{Message: "not a sign off"},
   767  					Author: github.User{
   768  						Login: "test",
   769  					},
   770  				},
   771  			},
   772  			issueState: "open",
   773  
   774  			expectedStatus: github.StatusSuccess,
   775  		},
   776  	}
   777  	for _, tc := range testcases {
   778  		t.Run(tc.name, func(t *testing.T) {
   779  			fc := fakegithub.NewFakeClient()
   780  			fc.CreatedStatuses = make(map[string][]github.Status)
   781  			fc.CombinedStatuses = make(map[string]*github.CombinedStatus)
   782  			fc.PullRequests = tc.pullRequests
   783  			fc.IssueComments = make(map[int][]github.IssueComment)
   784  			fc.CommitMap = map[string][]github.RepositoryCommit{
   785  				"/#3": tc.commits,
   786  			}
   787  			fc.OrgMembers = map[string][]string{
   788  				"kubernetes": {"test"},
   789  			}
   790  			if tc.hasDCOYes {
   791  				fc.IssueLabelsAdded = append(fc.IssueLabelsAdded, fmt.Sprintf("/#3:%s", dcoYesLabel))
   792  			}
   793  			if tc.hasDCONo {
   794  				fc.IssueLabelsAdded = append(fc.IssueLabelsAdded, fmt.Sprintf("/#3:%s", dcoNoLabel))
   795  			}
   796  			combinedStatus := &github.CombinedStatus{
   797  				Statuses: []github.Status{},
   798  			}
   799  			if tc.status != "" {
   800  				fc.CreatedStatuses["sha"] = []github.Status{
   801  					{Context: dcoContextName, State: tc.status},
   802  				}
   803  				combinedStatus = &github.CombinedStatus{
   804  					SHA: "sha",
   805  					Statuses: []github.Status{
   806  						{Context: dcoContextName, State: tc.status},
   807  					},
   808  				}
   809  			}
   810  			fc.CombinedStatuses["sha"] = combinedStatus
   811  
   812  			if err := handleComment(tc.config, fc, &fakePruner{}, logrus.WithField("plugin", pluginName), tc.commentEvent); err != nil {
   813  				t.Errorf("For case %s, didn't expect error from dco plugin: %v", tc.name, err)
   814  			}
   815  			ok := tc.addedLabel == ""
   816  			if !ok {
   817  				for _, label := range fc.IssueLabelsAdded {
   818  					if reflect.DeepEqual(tc.addedLabel, label) {
   819  						ok = true
   820  						break
   821  					}
   822  				}
   823  			}
   824  			if !ok {
   825  				t.Errorf("Expected to add: %#v, Got %#v in case %s.", tc.addedLabel, fc.IssueLabelsAdded, tc.name)
   826  			}
   827  			ok = tc.removedLabel == ""
   828  			if !ok {
   829  				for _, label := range fc.IssueLabelsRemoved {
   830  					if reflect.DeepEqual(tc.removedLabel, label) {
   831  						ok = true
   832  						break
   833  					}
   834  				}
   835  			}
   836  			if !ok {
   837  				t.Errorf("Expected to remove: %#v, Got %#v in case %s.", tc.removedLabel, fc.IssueLabelsRemoved, tc.name)
   838  			}
   839  
   840  			// check status is set as expected
   841  			statuses := fc.CreatedStatuses["sha"]
   842  			if len(statuses) == 0 && tc.expectedStatus != "" {
   843  				t.Errorf("Expected dco status to be %q, but it was not set", tc.expectedStatus)
   844  			}
   845  			found := false
   846  			for _, s := range statuses {
   847  				if s.Context == dcoContextName {
   848  					found = true
   849  					if s.State != tc.expectedStatus {
   850  						t.Errorf("Expected dco status to be %q but it was %q", tc.expectedStatus, s.State)
   851  					}
   852  				}
   853  			}
   854  			if !found && tc.expectedStatus != "" {
   855  				t.Errorf("Expect dco status to be %q, but it was not found", tc.expectedStatus)
   856  			}
   857  
   858  			comments := fc.IssueCommentsAdded
   859  			if len(comments) == 0 && tc.addedComment != "" {
   860  				t.Errorf("Expected comment with body %q to be added, but it was not", tc.addedComment)
   861  				return
   862  			}
   863  			if len(comments) > 1 {
   864  				t.Errorf("did not expect more than one comment to be created")
   865  			}
   866  			if len(comments) != 0 && comments[0] != tc.addedComment {
   867  				t.Errorf("expected comment to be %q but it was %q", tc.addedComment, comments[0])
   868  			}
   869  		})
   870  	}
   871  }