diff --git a/server/controllers/events/events_controller.go b/server/controllers/events/events_controller.go index 34fcf05f33..e0c644f5f5 100644 --- a/server/controllers/events/events_controller.go +++ b/server/controllers/events/events_controller.go @@ -43,6 +43,9 @@ const bitbucketCloudRequestIDHeader = "X-Request-UUID" const bitbucketServerRequestIDHeader = "X-Request-ID" const bitbucketServerSignatureHeader = "X-Hub-Signature" +// The URL used for Azure DevOps test webhooks +const azuredevopsTestURL = "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079" + // VCSEventsController handles all webhook requests which signify 'events' in the // VCS host, ex. GitHub. type VCSEventsController struct { @@ -639,6 +642,11 @@ func (e *VCSEventsController) HandleAzureDevopsPullRequestCommentedEvent(w http. return } + if isAzureDevOpsTestRepoURL(resource.PullRequest.GetRepository()) { + e.respond(w, logging.Debug, http.StatusOK, "Ignoring Azure DevOps Test Event with Repo URL: %v %s", resource.PullRequest.Repository.URL, azuredevopsReqID) + return + } + createdBy := resource.PullRequest.GetCreatedBy() user := models.User{Username: createdBy.GetUniqueName()} baseRepo, err := e.Parser.ParseAzureDevopsRepo(resource.PullRequest.GetRepository()) @@ -681,6 +689,16 @@ func (e *VCSEventsController) HandleAzureDevopsPullRequestEvent(w http.ResponseW } } + resource, ok := event.Resource.(*azuredevops.GitPullRequest) + if !ok || event.PayloadType != azuredevops.PullRequestEvent { + e.respond(w, logging.Error, http.StatusBadRequest, "Event.Resource is nil or received bad event type %v; %s", event.Resource, azuredevopsReqID) + return + } + if isAzureDevOpsTestRepoURL(resource.GetRepository()) { + e.respond(w, logging.Debug, http.StatusOK, "Ignoring Azure DevOps Test Event with Repo URL: %v %s", resource.Repository.URL, azuredevopsReqID) + return + } + pull, pullEventType, baseRepo, headRepo, user, err := e.Parser.ParseAzureDevopsPullEvent(*event) if err != nil { e.respond(w, logging.Error, http.StatusBadRequest, "Error parsing pull data: %s %s", err, azuredevopsReqID) @@ -730,3 +748,10 @@ func (e *VCSEventsController) commentNotAllowlisted(baseRepo models.Repo, pullNu e.Logger.Err("unable to comment on pull request: %s", err) } } + +func isAzureDevOpsTestRepoURL(repository *azuredevops.GitRepository) bool { + if repository == nil { + return false + } + return repository.GetURL() == azuredevopsTestURL +} diff --git a/server/controllers/events/events_controller_test.go b/server/controllers/events/events_controller_test.go index 28b9d0d9ff..87e479029c 100644 --- a/server/controllers/events/events_controller_test.go +++ b/server/controllers/events/events_controller_test.go @@ -561,6 +561,101 @@ func TestPost_AzureDevopsPullRequestDeletedCommentIgnoreEvent(t *testing.T) { }) } +func TestPost_AzureDevopsPullRequestCommentWebhookTestIgnoreEvent(t *testing.T) { + t.Log("when the event is an azure devops webhook test we ignore it") + e, _, _, ado, _, _, _, _, _ := setup(t) + + event := `{ + "subscriptionId": "11111111-1111-1111-1111-111111111111", + "notificationId": 1, + "id": "22222222-2222-2222-2222-222222222222", + "eventType": "%s", + "publisherId": "tfs", + "message": { + "text": "%s" + }, + "resource": { + "pullRequest": { + "repository":{ + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079" + } + }, + "comment": { + "content": "This is my comment." + } + }}` + + cases := []struct { + eventType string + message string + }{ + { + "ms.vss-code.git-pullrequest-comment-event", + "Jamal Hartnett has edited a pull request comment", + }, + } + + for _, c := range cases { + t.Run(c.message, func(t *testing.T) { + payload := fmt.Sprintf(event, c.eventType, c.message) + req, _ := http.NewRequest("GET", "", strings.NewReader(payload)) + req.Header.Set(azuredevopsHeader, "reqID") + When(ado.Validate(req, user, secret)).ThenReturn([]byte(payload), nil) + w := httptest.NewRecorder() + e.Parser = &events.EventParser{} + e.Post(w, req) + ResponseContains(t, w, http.StatusOK, "Ignoring Azure DevOps Test Event with Repo URL") + }) + } +} + +func TestPost_AzureDevopsPullRequestWebhookTestIgnoreEvent(t *testing.T) { + t.Log("when the event is an azure devops webhook tests we ignore it") + e, _, _, ado, _, _, _, _, _ := setup(t) + + event := `{ + "subscriptionId": "11111111-1111-1111-1111-111111111111", + "notificationId": 1, + "id": "22222222-2222-2222-2222-222222222222", + "eventType": "%s", + "publisherId": "tfs", + "message": { + "text": "%s" + }, + "resource": { + "repository":{ + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079" + } + }}` + + cases := []struct { + eventType string + message string + }{ + { + "git.pullrequest.created", + "Jamal Hartnett created a new pull request", + }, + { + "git.pullrequest.updated", + "Jamal Hartnett marked the pull request as completed", + }, + } + + for _, c := range cases { + t.Run(c.message, func(t *testing.T) { + payload := fmt.Sprintf(event, c.eventType, c.message) + req, _ := http.NewRequest("GET", "", strings.NewReader(payload)) + req.Header.Set(azuredevopsHeader, "reqID") + When(ado.Validate(req, user, secret)).ThenReturn([]byte(payload), nil) + w := httptest.NewRecorder() + e.Parser = &events.EventParser{} + e.Post(w, req) + ResponseContains(t, w, http.StatusOK, "Ignoring Azure DevOps Test Event with Repo URL") + }) + } +} + func TestPost_AzureDevopsPullRequestCommentPassingIgnores(t *testing.T) { t.Log("when the event should not be ignored it should pass through all ignore statements without error") e, _, _, ado, _, _, _, _, _ := setup(t)