Skip to content

Commit

Permalink
fix(azure-devops): add check for test webhook URL (runatlantis#2809)
Browse files Browse the repository at this point in the history
* Adding check for Azure DevOps Test Webhook URL so they aren't processed like real events

* feat: customize vcs comment command executable name

* Altering case on isAzureDevOpsTestRepoURL function

* Altering case on URL parameter

* Altering checks to ensure all Azure DevOps Ignore tests pass

* Extending setup method to support Azure DevOps

* Fixing issue from merge conflict error

* gofmt

* Adding null checks to Test URL checks

* moving azuredevopsTestUrl to const

* Changing azuredevopsTestUrl to azuredevopsTestURL

* Cleaning up return statement

Co-authored-by: Ken Kaizu <[email protected]>

---------

Co-authored-by: Ken Kaizu <[email protected]>
Co-authored-by: nitrocode <[email protected]>
  • Loading branch information
3 people authored and ijames-gc committed Feb 13, 2024
1 parent 9b798e2 commit 3e4e7f6
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 0 deletions.
25 changes: 25 additions & 0 deletions server/controllers/events/events_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
}
95 changes: 95 additions & 0 deletions server/controllers/events/events_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 3e4e7f6

Please sign in to comment.