Skip to content

Commit c3a98e0

Browse files
rcoy-vKristian
authored and
Kristian
committed
Add option on put to delete previous comments (#120)
* Add option on put to delete previous comments * Refactor github import in e2e tests
1 parent 6ae74fe commit c3a98e0

File tree

7 files changed

+306
-15
lines changed

7 files changed

+306
-15
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@ build/*
33

44
# Taskfile
55
.task
6+
7+
# Editor
8+
.idea/

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ empty commit to the PR*.
117117
| `target_url` | No | `$ATC_DEFAULT_URL/builds/$BUILD_ID` | The target URL for the status, where users are sent when clicking details (defaults to the Concourse build page). |
118118
| `description` | No | `Concourse CI build failed` | The description status on the specified pull request. |
119119
| `description_file` | No | `my-output/description.txt` | Path to file containing the description status to add to the pull request |
120+
| `delete_previous_comments` | No | `true` | Boolean. Previous comments made on the pull request by this resource will be deleted before making the new comment. Useful for removing outdated information. |
120121

121122
Note that `comment`, `comment_file` and `target_url` will all expand environment variables, so in the examples above `$ATC_DEFAULT_URL` will be replaced by the public URL of the Concourse ATCs.
122123
See https://concourse-ci.org/implementing-resource-types.html#resource-metadata for more details about metadata that is available via environment variables.

e2e/e2e_test.go

Lines changed: 135 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,19 @@
33
package e2e_test
44

55
import (
6+
"context"
7+
"fmt"
8+
"github.com/google/go-github/github"
9+
"github.com/stretchr/testify/assert"
610
"io/ioutil"
711
"os"
812
"os/exec"
913
"path/filepath"
14+
"strconv"
1015
"strings"
1116
"testing"
1217
"time"
1318

14-
"github.com/stretchr/testify/assert"
1519
"github.com/stretchr/testify/require"
1620
resource "github.com/telia-oss/github-pr-resource"
1721
)
@@ -172,11 +176,11 @@ func TestCheckE2E(t *testing.T) {
172176

173177
for _, tc := range tests {
174178
t.Run(tc.description, func(t *testing.T) {
175-
github, err := resource.NewGithubClient(&tc.source)
179+
githubClient, err := resource.NewGithubClient(&tc.source)
176180
require.NoError(t, err)
177181

178182
input := resource.CheckRequest{Source: tc.source, Version: tc.version}
179-
output, err := resource.Check(input, github)
183+
output, err := resource.Check(input, githubClient)
180184

181185
if assert.NoError(t, err) {
182186
assert.Equal(t, tc.expected, output)
@@ -380,15 +384,15 @@ func TestGetAndPutE2E(t *testing.T) {
380384
require.NoError(t, err)
381385
defer os.RemoveAll(dir)
382386

383-
github, err := resource.NewGithubClient(&tc.source)
387+
githubClient, err := resource.NewGithubClient(&tc.source)
384388
require.NoError(t, err)
385389

386390
git, err := resource.NewGitClient(&tc.source, dir, ioutil.Discard)
387391
require.NoError(t, err)
388392

389393
// Get (output and files)
390394
getRequest := resource.GetRequest{Source: tc.source, Version: tc.version, Params: tc.getParameters}
391-
getOutput, err := resource.Get(getRequest, github, git, dir)
395+
getOutput, err := resource.Get(getRequest, githubClient, git, dir)
392396

393397
require.NoError(t, err)
394398
assert.Equal(t, tc.version, getOutput.Version)
@@ -423,14 +427,139 @@ func TestGetAndPutE2E(t *testing.T) {
423427

424428
// Put
425429
putRequest := resource.PutRequest{Source: tc.source, Params: tc.putParameters}
426-
putOutput, err := resource.Put(putRequest, github, dir)
430+
putOutput, err := resource.Put(putRequest, githubClient, dir)
427431

428432
require.NoError(t, err)
429433
assert.Equal(t, tc.version, putOutput.Version)
430434
})
431435
}
432436
}
433437

438+
func TestPutCommentsE2E(t *testing.T) {
439+
owner := "rcoy-v"
440+
repo := "github-pr-resource-e2e"
441+
442+
tests := []struct {
443+
description, branch string
444+
source resource.Source
445+
getParams resource.GetParameters
446+
putParameters resource.PutParameters
447+
previousComments, expectedComments []string
448+
}{
449+
{
450+
description: "delete previous comments removes old comments and makes new one",
451+
branch: "delete-previous-comments-remove-old-add-new",
452+
source: resource.Source{
453+
Repository: fmt.Sprintf("%s/%s", owner, repo),
454+
V3Endpoint: "https://api.github.com/",
455+
V4Endpoint: "https://api.github.com/graphql",
456+
AccessToken: os.Getenv("GITHUB_ACCESS_TOKEN"),
457+
},
458+
getParams: resource.GetParameters{},
459+
putParameters: resource.PutParameters{
460+
Comment: "new comment",
461+
DeletePreviousComments: true,
462+
},
463+
previousComments: []string{"old comment"},
464+
expectedComments: []string{
465+
"new comment",
466+
},
467+
},
468+
{
469+
description: "delete previous comments removes all comments when no new comment",
470+
branch: "delete-previous-comments-remove-old",
471+
source: resource.Source{
472+
Repository: fmt.Sprintf("%s/%s", owner, repo),
473+
V3Endpoint: "https://api.github.com/",
474+
V4Endpoint: "https://api.github.com/graphql",
475+
AccessToken: os.Getenv("GITHUB_ACCESS_TOKEN"),
476+
},
477+
getParams: resource.GetParameters{},
478+
putParameters: resource.PutParameters{
479+
DeletePreviousComments: true,
480+
},
481+
previousComments: []string{"old comment"},
482+
expectedComments: []string{},
483+
},
484+
{
485+
description: "delete previous comments should not delete comments when false",
486+
branch: "delete-previous-comments-false",
487+
source: resource.Source{
488+
Repository: fmt.Sprintf("%s/%s", owner, repo),
489+
V3Endpoint: "https://api.github.com/",
490+
V4Endpoint: "https://api.github.com/graphql",
491+
AccessToken: os.Getenv("GITHUB_ACCESS_TOKEN"),
492+
},
493+
getParams: resource.GetParameters{},
494+
putParameters: resource.PutParameters{
495+
Comment: "new comment",
496+
DeletePreviousComments: false,
497+
},
498+
previousComments: []string{"should not delete"},
499+
expectedComments: []string{
500+
"should not delete",
501+
"new comment",
502+
},
503+
},
504+
}
505+
506+
for _, tc := range tests {
507+
t.Run(tc.description, func(t *testing.T) {
508+
dir, err := ioutil.TempDir("", "github-pr-resource")
509+
require.NoError(t, err)
510+
defer os.RemoveAll(dir)
511+
512+
githubClient, err := resource.NewGithubClient(&tc.source)
513+
require.NoError(t, err)
514+
515+
git, err := resource.NewGitClient(&tc.source, dir, ioutil.Discard)
516+
require.NoError(t, err)
517+
518+
pullRequest, _, err := githubClient.V3.PullRequests.Create(context.TODO(), owner, repo, &github.NewPullRequest{
519+
Title: github.String(tc.description),
520+
Base: github.String("master"),
521+
Head: github.String(fmt.Sprintf("%s:%s", owner, tc.branch)),
522+
})
523+
require.NoError(t, err)
524+
525+
for _, comment := range tc.previousComments {
526+
_, _, err = githubClient.V3.Issues.CreateComment(context.TODO(), owner, repo, pullRequest.GetNumber(), &github.IssueComment{
527+
Body: github.String(comment),
528+
})
529+
require.NoError(t, err)
530+
}
531+
532+
getRequest := resource.GetRequest{Source: tc.source, Version: resource.Version{
533+
PR: strconv.Itoa(pullRequest.GetNumber()),
534+
Commit: pullRequest.GetHead().GetSHA(),
535+
}, Params: tc.getParams}
536+
_, err = resource.Get(getRequest, githubClient, git, dir)
537+
require.NoError(t, err)
538+
539+
putRequest := resource.PutRequest{
540+
Source: tc.source,
541+
Params: tc.putParameters,
542+
}
543+
544+
_, err = resource.Put(putRequest, githubClient, dir)
545+
require.NoError(t, err)
546+
547+
comments, _, err := githubClient.V3.Issues.ListComments(context.TODO(), owner, repo, pullRequest.GetNumber(), nil)
548+
require.NoError(t, err)
549+
550+
require.Len(t, comments, len(tc.expectedComments))
551+
for index, comment := range comments {
552+
require.Equal(t, tc.expectedComments[index], comment.GetBody())
553+
}
554+
555+
_, _, err = githubClient.V3.PullRequests.Edit(context.TODO(), owner, repo, pullRequest.GetNumber(), &github.PullRequest{
556+
State: github.String("closed"),
557+
})
558+
require.NoError(t, err)
559+
})
560+
}
561+
}
562+
434563
func gitHistory(t *testing.T, directory string) map[int]string {
435564
cmd := exec.Command("git", "log", "--oneline", "--pretty=format:%s")
436565
cmd.Dir = directory

fakes/fake_github.go

Lines changed: 73 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

github.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type Github interface {
2626
GetPullRequest(string, string) (*PullRequest, error)
2727
GetChangedFiles(string, string) ([]ChangedFileObject, error)
2828
UpdateCommitStatus(string, string, string, string, string, string) error
29+
DeletePreviousComments(string) error
2930
}
3031

3132
// GithubClient for handling requests to the Github V3 and V4 APIs.
@@ -355,6 +356,56 @@ func (m *GithubClient) UpdateCommitStatus(commitRef, baseContext, statusContext,
355356
return err
356357
}
357358

359+
func (m *GithubClient) DeletePreviousComments(prNumber string) error {
360+
pr, err := strconv.Atoi(prNumber)
361+
if err != nil {
362+
return fmt.Errorf("failed to convert pull request number to int: %s", err)
363+
}
364+
365+
var getComments struct {
366+
Viewer struct {
367+
Login string
368+
}
369+
Repository struct {
370+
PullRequest struct {
371+
Id string
372+
Comments struct {
373+
Edges []struct {
374+
Node struct {
375+
DatabaseId int64
376+
Author struct {
377+
Login string
378+
}
379+
}
380+
}
381+
} `graphql:"comments(last:$commentsLast)"`
382+
} `graphql:"pullRequest(number:$prNumber)"`
383+
} `graphql:"repository(owner:$repositoryOwner,name:$repositoryName)"`
384+
}
385+
386+
vars := map[string]interface{}{
387+
"repositoryOwner": githubv4.String(m.Owner),
388+
"repositoryName": githubv4.String(m.Repository),
389+
"prNumber": githubv4.Int(pr),
390+
"commentsLast": githubv4.Int(100),
391+
}
392+
393+
if err := m.V4.Query(context.TODO(), &getComments, vars); err != nil {
394+
return err
395+
}
396+
397+
for _, e := range getComments.Repository.PullRequest.Comments.Edges {
398+
if e.Node.Author.Login == getComments.Viewer.Login {
399+
_, err := m.V3.Issues.DeleteComment(context.TODO(), m.Owner, m.Repository, e.Node.DatabaseId)
400+
if err != nil {
401+
return err
402+
}
403+
}
404+
}
405+
406+
return nil
407+
}
408+
358409
func parseRepository(s string) (string, string, error) {
359410
parts := strings.Split(s, "/")
360411
if len(parts) != 2 {

0 commit comments

Comments
 (0)