From 1ae15cc231276b5f9598968f6f2557df7ddc8480 Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Sun, 8 Nov 2020 00:43:30 +0100 Subject: [PATCH 001/282] Add a vet step to drone config --- .drone.yml | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/.drone.yml b/.drone.yml index 4a688bf36..6636d8200 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,15 +1,31 @@ +--- kind: pipeline +type: docker name: default -workspace: - base: /go - path: src/github.com/drone/go-scm - +platform: + os: linux + arch: amd64 steps: +- name: vet + image: golang:1.15 + commands: + - go vet ./... + volumes: + - name: gopath + path: /go + - name: test - image: golang:1.11 + image: golang:1.15 commands: - - go get github.com/google/go-cmp/cmp - - go get github.com/h2non/gock - - go test -cover github.com/drone/go-scm/scm/... + - go test -cover ./... + volumes: + - name: gopath + path: /go + +volumes: +- name: gopath + temp: {} + +... From 1e40e2b8ab3df2f8f18196359e0050d85a5ddfd2 Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Sun, 8 Nov 2020 00:55:46 +0100 Subject: [PATCH 002/282] Make go vet happy --- scm/example_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scm/example_test.go b/scm/example_test.go index 7055616a2..f95aaff7d 100644 --- a/scm/example_test.go +++ b/scm/example_test.go @@ -91,7 +91,7 @@ func ExampleRepository_list() { } } -func ExampleBranch_find() { +func ExampleGitService_FindBranch() { client, err := github.New("https://api.github.com") if err != nil { log.Fatal(err) @@ -105,7 +105,7 @@ func ExampleBranch_find() { log.Println(branch.Name, branch.Sha) } -func ExampleBranch_list() { +func ExampleGitService_ListBranches() { client, err := github.New("https://api.github.com") if err != nil { log.Fatal(err) @@ -126,7 +126,7 @@ func ExampleBranch_list() { } } -func ExampleTag_find() { +func ExampleGitService_FindTag() { client, err := github.New("https://api.github.com") if err != nil { log.Fatal(err) @@ -140,7 +140,7 @@ func ExampleTag_find() { log.Println(tag.Name, tag.Sha) } -func ExampleTag_list() { +func ExampleGitService_ListTags() { client, err := github.New("https://api.github.com") if err != nil { log.Fatal(err) From dcc18c0bf3e7857a5d2482209553bc7c32fa9ea1 Mon Sep 17 00:00:00 2001 From: bakito Date: Wed, 30 Dec 2020 10:56:57 +0100 Subject: [PATCH 003/282] use access json header / extend error message parsing --- .gitignore | 1 + scm/driver/stash/stash.go | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index cbc620eda..2cada1ba5 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ *.out _*.md .vscode +.idea cmd \ No newline at end of file diff --git a/scm/driver/stash/stash.go b/scm/driver/stash/stash.go index 3eada146e..363ac64d8 100644 --- a/scm/driver/stash/stash.go +++ b/scm/driver/stash/stash.go @@ -9,6 +9,7 @@ import ( "bytes" "context" "encoding/json" + "fmt" "io" "net/url" "strings" @@ -64,15 +65,16 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface req := &scm.Request{ Method: method, Path: path, + Header: map[string][]string{ + "Accept": {"application/json"}, + }, } // if we are posting or putting data, we need to // write it to the body of the request. if in != nil { buf := new(bytes.Buffer) json.NewEncoder(buf).Encode(in) - req.Header = map[string][]string{ - "Content-Type": {"application/json"}, - } + req.Header["Content-Type"] = []string{"application/json"} req.Body = buf } @@ -121,7 +123,9 @@ type pagination struct { // Error represents a Stash error. type Error struct { - Errors []struct { + Message string `json:"message"` + Status int `json:"status-code"` + Errors []struct { Message string `json:"message"` ExceptionName string `json:"exceptionName"` CurrentVersion int `json:"currentVersion"` @@ -131,6 +135,9 @@ type Error struct { func (e *Error) Error() string { if len(e.Errors) == 0 { + if len(e.Message) > 0 { + return fmt.Sprintf("bitbucket: status: %d message: %s", e.Status, e.Message) + } return "bitbucket: undefined error" } return e.Errors[0].Message From 02f5d30cf6db6a6e21cf78183b5d5947472a5bbc Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Tue, 16 Mar 2021 11:29:48 -0400 Subject: [PATCH 004/282] update blob hash comment [CI SKIP] --- scm/content.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scm/content.go b/scm/content.go index e28dc7b56..4d7434917 100644 --- a/scm/content.go +++ b/scm/content.go @@ -12,7 +12,8 @@ type ( Path string Data []byte - // the has of the blob. this is the equivalent + // the hash of the blob, sometimes referred to + // as the blob id or blob sha. this is the equivalent // to running the git hash-object command. Hash string } From 9f58e9df3ec0fa117d27e1eff83f6c24a60d9d0c Mon Sep 17 00:00:00 2001 From: TP Honey Date: Tue, 16 Mar 2021 16:33:32 +0000 Subject: [PATCH 005/282] (feat) gitlab contents.Find returns hash/blob --- scm/driver/gitlab/content.go | 1 + scm/driver/gitlab/testdata/content.json.golden | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/scm/driver/gitlab/content.go b/scm/driver/gitlab/content.go index f4263489c..196c593ee 100644 --- a/scm/driver/gitlab/content.go +++ b/scm/driver/gitlab/content.go @@ -34,6 +34,7 @@ func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm return &scm.Content{ Path: out.FilePath, Data: raw, + Hash: out.BlobID, }, res, err } diff --git a/scm/driver/gitlab/testdata/content.json.golden b/scm/driver/gitlab/testdata/content.json.golden index 73abcc029..c8e3a8c25 100644 --- a/scm/driver/gitlab/testdata/content.json.golden +++ b/scm/driver/gitlab/testdata/content.json.golden @@ -1,4 +1,5 @@ { "Path": "app/models/key.rb", - "Data": "cmVxdWlyZSAnZGlnZXN0L21kNScKCmNsYXNzIEtleSA8IEFjdGl2ZVJlY29yZDo6QmFzZQogIGluY2x1ZGUgR2l0bGFiOjpDdXJyZW50U2V0dGluZ3MKICBpbmNsdWRlIFNvcnRhYmxlCgogIGJlbG9uZ3NfdG8gOnVzZXIKCiAgYmVmb3JlX3ZhbGlkYXRpb24gOmdlbmVyYXRlX2ZpbmdlcnByaW50CgogIHZhbGlkYXRlcyA6dGl0bGUsCiAgICBwcmVzZW5jZTogdHJ1ZSwKICAgIGxlbmd0aDogeyBtYXhpbXVtOiAyNTUgfQoKICB2YWxpZGF0ZXMgOmtleSwKICAgIHByZXNlbmNlOiB0cnVlLAogICAgbGVuZ3RoOiB7IG1heGltdW06IDUwMDAgfSwKICAgIGZvcm1hdDogeyB3aXRoOiAvXEEoc3NofGVjZHNhKS0uKlxaLyB9CgogIHZhbGlkYXRlcyA6ZmluZ2VycHJpbnQsCiAgICB1bmlxdWVuZXNzOiB0cnVlLAogICAgcHJlc2VuY2U6IHsgbWVzc2FnZTogJ2Nhbm5vdCBiZSBnZW5lcmF0ZWQnIH0KCiAgdmFsaWRhdGUgOmtleV9tZWV0c19yZXN0cmljdGlvbnMKCiAgZGVsZWdhdGUgOm5hbWUsIDplbWFpbCwgdG86IDp1c2VyLCBwcmVmaXg6IHRydWUKCiAgYWZ0ZXJfY29tbWl0IDphZGRfdG9fc2hlbGwsIG9uOiA6Y3JlYXRlCiAgYWZ0ZXJfY3JlYXRlIDpwb3N0X2NyZWF0ZV9ob29rCiAgYWZ0ZXJfY3JlYXRlIDpyZWZyZXNoX3VzZXJfY2FjaGUKICBhZnRlcl9jb21taXQgOnJlbW92ZV9mcm9tX3NoZWxsLCBvbjogOmRlc3Ryb3kKICBhZnRlcl9kZXN0cm95IDpwb3N0X2Rlc3Ryb3lfaG9vawogIGFmdGVyX2Rlc3Ryb3kgOnJlZnJlc2hfdXNlcl9jYWNoZQoKICBkZWYga2V5PSh2YWx1ZSkKICAgIHZhbHVlJi5kZWxldGUhKCJcblxyIikKICAgIHZhbHVlLnN0cmlwISB1bmxlc3MgdmFsdWUuYmxhbms=" + "Data": "cmVxdWlyZSAnZGlnZXN0L21kNScKCmNsYXNzIEtleSA8IEFjdGl2ZVJlY29yZDo6QmFzZQogIGluY2x1ZGUgR2l0bGFiOjpDdXJyZW50U2V0dGluZ3MKICBpbmNsdWRlIFNvcnRhYmxlCgogIGJlbG9uZ3NfdG8gOnVzZXIKCiAgYmVmb3JlX3ZhbGlkYXRpb24gOmdlbmVyYXRlX2ZpbmdlcnByaW50CgogIHZhbGlkYXRlcyA6dGl0bGUsCiAgICBwcmVzZW5jZTogdHJ1ZSwKICAgIGxlbmd0aDogeyBtYXhpbXVtOiAyNTUgfQoKICB2YWxpZGF0ZXMgOmtleSwKICAgIHByZXNlbmNlOiB0cnVlLAogICAgbGVuZ3RoOiB7IG1heGltdW06IDUwMDAgfSwKICAgIGZvcm1hdDogeyB3aXRoOiAvXEEoc3NofGVjZHNhKS0uKlxaLyB9CgogIHZhbGlkYXRlcyA6ZmluZ2VycHJpbnQsCiAgICB1bmlxdWVuZXNzOiB0cnVlLAogICAgcHJlc2VuY2U6IHsgbWVzc2FnZTogJ2Nhbm5vdCBiZSBnZW5lcmF0ZWQnIH0KCiAgdmFsaWRhdGUgOmtleV9tZWV0c19yZXN0cmljdGlvbnMKCiAgZGVsZWdhdGUgOm5hbWUsIDplbWFpbCwgdG86IDp1c2VyLCBwcmVmaXg6IHRydWUKCiAgYWZ0ZXJfY29tbWl0IDphZGRfdG9fc2hlbGwsIG9uOiA6Y3JlYXRlCiAgYWZ0ZXJfY3JlYXRlIDpwb3N0X2NyZWF0ZV9ob29rCiAgYWZ0ZXJfY3JlYXRlIDpyZWZyZXNoX3VzZXJfY2FjaGUKICBhZnRlcl9jb21taXQgOnJlbW92ZV9mcm9tX3NoZWxsLCBvbjogOmRlc3Ryb3kKICBhZnRlcl9kZXN0cm95IDpwb3N0X2Rlc3Ryb3lfaG9vawogIGFmdGVyX2Rlc3Ryb3kgOnJlZnJlc2hfdXNlcl9jYWNoZQoKICBkZWYga2V5PSh2YWx1ZSkKICAgIHZhbHVlJi5kZWxldGUhKCJcblxyIikKICAgIHZhbHVlLnN0cmlwISB1bmxlc3MgdmFsdWUuYmxhbms=", + "Hash": "79f7bbd25901e8334750839545a9bd021f0e4c83" } \ No newline at end of file From e60760092d8be75661ee153248f0158e5dcc5359 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Thu, 18 Mar 2021 16:51:10 +0000 Subject: [PATCH 006/282] (feat) add ListCommits for gitea --- scm/driver/gitea/git.go | 19 ++++++++------ scm/driver/gitea/git_test.go | 25 +++++++++++++++---- scm/driver/gitea/testdata/commit.json | 1 + scm/driver/gitea/testdata/commit.json.golden | 11 ++++++++ scm/driver/gitea/testdata/commits.json | 4 ++- scm/driver/gitea/testdata/commits.json.golden | 24 ++++++++++-------- 6 files changed, 59 insertions(+), 25 deletions(-) create mode 100644 scm/driver/gitea/testdata/commit.json create mode 100644 scm/driver/gitea/testdata/commit.json.golden diff --git a/scm/driver/gitea/git.go b/scm/driver/gitea/git.go index d20580561..e1ea1651b 100644 --- a/scm/driver/gitea/git.go +++ b/scm/driver/gitea/git.go @@ -55,7 +55,10 @@ func (s *gitService) ListBranches(ctx context.Context, repo string, opts scm.Lis } func (s *gitService) ListCommits(ctx context.Context, repo string, _ scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + path := fmt.Sprintf("api/v1/repos/%s/commits", repo) + out := []*commitInfo{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertCommitList(out), res, err } func (s *gitService) ListTags(ctx context.Context, repo string, _ scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { @@ -142,13 +145,13 @@ func convertBranch(src *branch) *scm.Reference { } } -// func convertCommitList(src []*commit) []*scm.Commit { -// dst := []*scm.Commit{} -// for _, v := range src { -// dst = append(dst, convertCommitInfo(v)) -// } -// return dst -// } +func convertCommitList(src []*commitInfo) []*scm.Commit { + dst := []*scm.Commit{} + for _, v := range src { + dst = append(dst, convertCommitInfo(v)) + } + return dst +} func convertCommitInfo(src *commitInfo) *scm.Commit { return &scm.Commit{ diff --git a/scm/driver/gitea/git_test.go b/scm/driver/gitea/git_test.go index 65f139bea..de91410ce 100644 --- a/scm/driver/gitea/git_test.go +++ b/scm/driver/gitea/git_test.go @@ -24,7 +24,7 @@ func TestGitFindCommit(t *testing.T) { Get("/api/v1/repos/gitea/gitea/git/commits/c43399cad8766ee521b873a32c1652407c5a4630"). Reply(200). Type("application/json"). - File("testdata/commits.json") + File("testdata/commit.json") client, _ := New("https://try.gitea.io") got, _, err := client.Git.FindCommit( @@ -37,7 +37,7 @@ func TestGitFindCommit(t *testing.T) { } want := new(scm.Commit) - raw, _ := ioutil.ReadFile("testdata/commits.json.golden") + raw, _ := ioutil.ReadFile("testdata/commit.json.golden") json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { @@ -47,10 +47,25 @@ func TestGitFindCommit(t *testing.T) { } func TestGitListCommits(t *testing.T) { + gock.New("https://try.gitea.io"). + Get("/api/v1/repos/go-gitea/gitea/commits"). + Reply(200). + Type("application/json"). + File("testdata/commits.json") + client, _ := New("https://try.gitea.io") - _, _, err := client.Git.ListCommits(context.Background(), "go-gitea/gitea", scm.CommitListOptions{}) - if err != scm.ErrNotSupported { - t.Errorf("Expect Not Supported error") + got, _, err := client.Git.ListCommits(context.Background(), "go-gitea/gitea", scm.CommitListOptions{}) + if err != nil { + t.Error(err) + } + + want := []*scm.Commit{} + raw, _ := ioutil.ReadFile("testdata/commits.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) } } diff --git a/scm/driver/gitea/testdata/commit.json b/scm/driver/gitea/testdata/commit.json new file mode 100644 index 000000000..1478fa4be --- /dev/null +++ b/scm/driver/gitea/testdata/commit.json @@ -0,0 +1 @@ +{"url":"https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/c43399cad8766ee521b873a32c1652407c5a4630","sha":"c43399cad8766ee521b873a32c1652407c5a4630","html_url":"https://try.gitea.io/gitea/gitea/commits/c43399cad8766ee521b873a32c1652407c5a4630","commit":{"url":"https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/c43399cad8766ee521b873a32c1652407c5a4630","author":{"name":"Lewis Cowles","email":"lewiscowles@me.com","date":"2018-09-09T03:36:08Z"},"committer":{"name":"Lunny Xiao","email":"xiaolunwen@gmail.com","date":"2018-09-09T03:36:08Z"},"message":"Fixes repo branch endpoint summary (#4893)","tree":{"url":"https://try.gitea.io/api/v1/repos/gitea/gitea/trees/c43399cad8766ee521b873a32c1652407c5a4630","sha":"c43399cad8766ee521b873a32c1652407c5a4630"}},"author":null,"committer":{"id":3,"login":"lunny","full_name":"Lunny Xiao","email":"xiaolunwen@gmail.com","avatar_url":"https://secure.gravatar.com/avatar/271fc56bcea89c6f69ab0024b59b3f81?d=identicon","language":"zh-CN","username":"lunny"},"parents":[{"url":"https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/d293a2b9d6722dffde7998c953c3087e47a38a83","sha":"d293a2b9d6722dffde7998c953c3087e47a38a83"}]} \ No newline at end of file diff --git a/scm/driver/gitea/testdata/commit.json.golden b/scm/driver/gitea/testdata/commit.json.golden new file mode 100644 index 000000000..da61dbddd --- /dev/null +++ b/scm/driver/gitea/testdata/commit.json.golden @@ -0,0 +1,11 @@ +{ + "committer": { + "name": "Lunny Xiao", + "login": "lunny", + "email": "xiaolunwen@gmail.com", + "avatar": "https://secure.gravatar.com/avatar/271fc56bcea89c6f69ab0024b59b3f81?d=identicon" + }, + "link": "https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/c43399cad8766ee521b873a32c1652407c5a4630", + "sha": "c43399cad8766ee521b873a32c1652407c5a4630", + "message": "Fixes repo branch endpoint summary (#4893)" +} \ No newline at end of file diff --git a/scm/driver/gitea/testdata/commits.json b/scm/driver/gitea/testdata/commits.json index 1478fa4be..eab09211b 100644 --- a/scm/driver/gitea/testdata/commits.json +++ b/scm/driver/gitea/testdata/commits.json @@ -1 +1,3 @@ -{"url":"https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/c43399cad8766ee521b873a32c1652407c5a4630","sha":"c43399cad8766ee521b873a32c1652407c5a4630","html_url":"https://try.gitea.io/gitea/gitea/commits/c43399cad8766ee521b873a32c1652407c5a4630","commit":{"url":"https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/c43399cad8766ee521b873a32c1652407c5a4630","author":{"name":"Lewis Cowles","email":"lewiscowles@me.com","date":"2018-09-09T03:36:08Z"},"committer":{"name":"Lunny Xiao","email":"xiaolunwen@gmail.com","date":"2018-09-09T03:36:08Z"},"message":"Fixes repo branch endpoint summary (#4893)","tree":{"url":"https://try.gitea.io/api/v1/repos/gitea/gitea/trees/c43399cad8766ee521b873a32c1652407c5a4630","sha":"c43399cad8766ee521b873a32c1652407c5a4630"}},"author":null,"committer":{"id":3,"login":"lunny","full_name":"Lunny Xiao","email":"xiaolunwen@gmail.com","avatar_url":"https://secure.gravatar.com/avatar/271fc56bcea89c6f69ab0024b59b3f81?d=identicon","language":"zh-CN","username":"lunny"},"parents":[{"url":"https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/d293a2b9d6722dffde7998c953c3087e47a38a83","sha":"d293a2b9d6722dffde7998c953c3087e47a38a83"}]} \ No newline at end of file +[ + {"url":"https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/c43399cad8766ee521b873a32c1652407c5a4630","sha":"c43399cad8766ee521b873a32c1652407c5a4630","html_url":"https://try.gitea.io/gitea/gitea/commits/c43399cad8766ee521b873a32c1652407c5a4630","commit":{"url":"https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/c43399cad8766ee521b873a32c1652407c5a4630","author":{"name":"Lewis Cowles","email":"lewiscowles@me.com","date":"2018-09-09T03:36:08Z"},"committer":{"name":"Lunny Xiao","email":"xiaolunwen@gmail.com","date":"2018-09-09T03:36:08Z"},"message":"Fixes repo branch endpoint summary (#4893)","tree":{"url":"https://try.gitea.io/api/v1/repos/gitea/gitea/trees/c43399cad8766ee521b873a32c1652407c5a4630","sha":"c43399cad8766ee521b873a32c1652407c5a4630"}},"author":null,"committer":{"id":3,"login":"lunny","full_name":"Lunny Xiao","email":"xiaolunwen@gmail.com","avatar_url":"https://secure.gravatar.com/avatar/271fc56bcea89c6f69ab0024b59b3f81?d=identicon","language":"zh-CN","username":"lunny"},"parents":[{"url":"https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/d293a2b9d6722dffde7998c953c3087e47a38a83","sha":"d293a2b9d6722dffde7998c953c3087e47a38a83"}]} +] \ No newline at end of file diff --git a/scm/driver/gitea/testdata/commits.json.golden b/scm/driver/gitea/testdata/commits.json.golden index da61dbddd..bb9d78ed4 100644 --- a/scm/driver/gitea/testdata/commits.json.golden +++ b/scm/driver/gitea/testdata/commits.json.golden @@ -1,11 +1,13 @@ -{ - "committer": { - "name": "Lunny Xiao", - "login": "lunny", - "email": "xiaolunwen@gmail.com", - "avatar": "https://secure.gravatar.com/avatar/271fc56bcea89c6f69ab0024b59b3f81?d=identicon" - }, - "link": "https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/c43399cad8766ee521b873a32c1652407c5a4630", - "sha": "c43399cad8766ee521b873a32c1652407c5a4630", - "message": "Fixes repo branch endpoint summary (#4893)" -} \ No newline at end of file +[ + { + "committer": { + "name": "Lunny Xiao", + "login": "lunny", + "email": "xiaolunwen@gmail.com", + "avatar": "https://secure.gravatar.com/avatar/271fc56bcea89c6f69ab0024b59b3f81?d=identicon" + }, + "link": "https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/c43399cad8766ee521b873a32c1652407c5a4630", + "sha": "c43399cad8766ee521b873a32c1652407c5a4630", + "message": "Fixes repo branch endpoint summary (#4893)" + } +] \ No newline at end of file From c53d8273e29786ce768d67ecb631b4491fe4d902 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Thu, 18 Mar 2021 19:26:38 +0000 Subject: [PATCH 007/282] (feat) adding ListCommits for stash --- scm/driver/stash/git.go | 7 +- scm/driver/stash/git_test.go | 23 +++++- scm/driver/stash/testdata/commits.json | 73 ++++++++++++++++++- scm/driver/stash/testdata/commits.json.golden | 22 +++++- 4 files changed, 119 insertions(+), 6 deletions(-) diff --git a/scm/driver/stash/git.go b/scm/driver/stash/git.go index bd1080d0b..bd896977a 100644 --- a/scm/driver/stash/git.go +++ b/scm/driver/stash/git.go @@ -69,7 +69,12 @@ func (s *gitService) ListBranches(ctx context.Context, repo string, opts scm.Lis } func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + namespace, name := scm.Split(repo) + path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/commits", namespace, name) + out := new(commits) + res, err := s.client.do(ctx, "GET", path, nil, out) + copyPagination(out.pagination, res) + return convertCommitList(out), res, err } func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { diff --git a/scm/driver/stash/git_test.go b/scm/driver/stash/git_test.go index 9d8209327..4ce37595e 100644 --- a/scm/driver/stash/git_test.go +++ b/scm/driver/stash/git_test.go @@ -94,10 +94,27 @@ func TestGitFindTag(t *testing.T) { } func TestGitListCommits(t *testing.T) { + defer gock.Off() + + gock.New("http://example.com:7990"). + Get("/rest/api/1.0/projects/PRJ/repos/my-repo/commits"). + Reply(200). + Type("application/json"). + File("testdata/commits.json") + client, _ := New("http://example.com:7990") - _, _, err := client.Git.ListCommits(context.Background(), "PRJ/my-repo", scm.CommitListOptions{Ref: "master", Page: 1, Size: 30}) - if err != scm.ErrNotSupported { - t.Errorf("Expect Not Supported error") + got, _, err := client.Git.ListCommits(context.Background(), "PRJ/my-repo", scm.CommitListOptions{}) + if err != nil { + t.Error(err) + } + + want := []*scm.Commit{} + raw, _ := ioutil.ReadFile("testdata/commits.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) } } diff --git a/scm/driver/stash/testdata/commits.json b/scm/driver/stash/testdata/commits.json index 9e26dfeeb..ac9da334b 100644 --- a/scm/driver/stash/testdata/commits.json +++ b/scm/driver/stash/testdata/commits.json @@ -1 +1,72 @@ -{} \ No newline at end of file +{ + "size": 1, + "limit": 25, + "isLastPage": true, + "values": [ +{ + "id": "131cb13f4aed12e725177bc4b7c28db67839bf9f", + "displayId": "131cb13f4ae", + "author": { + "name": "jcitizen", + "emailAddress": "jane@example.com", + "id": 1, + "displayName": "Jane Citizen", + "active": true, + "slug": "jcitizen", + "type": "NORMAL", + "links": { + "self": [ + { + "href": "http://example.com:7990/users/jcitizen" + } + ] + } + }, + "authorTimestamp": 1530720102000, + "committer": { + "name": "jcitizen", + "emailAddress": "jane@example.com", + "id": 1, + "displayName": "Jane Citizen", + "active": true, + "slug": "jcitizen", + "type": "NORMAL", + "links": { + "self": [ + { + "href": "http://example.com:7990/users/jcitizen" + } + ] + } + }, + "committerTimestamp": 1530720102000, + "message": "update files", + "parents": [ + { + "id": "4f4b0ef1714a5b6cafdaf2f53c7f5f5b38fb9348", + "displayId": "4f4b0ef1714", + "author": { + "name": "Jane Citizen", + "emailAddress": "jane@example.com" + }, + "authorTimestamp": 1530719890000, + "committer": { + "name": "Jane Citizen", + "emailAddress": "jane@example.com" + }, + "committerTimestamp": 1530719890000, + "message": "update files", + "parents": [ + { + "id": "f636fe22d302c852df1a68fff2d744039fe55b3d", + "displayId": "f636fe22d30" + } + ] + } + ] +} +], +"start": 0, +"authorCount": 1, +"totalCount": 1 +} \ No newline at end of file diff --git a/scm/driver/stash/testdata/commits.json.golden b/scm/driver/stash/testdata/commits.json.golden index 0637a088a..33d1ffec4 100644 --- a/scm/driver/stash/testdata/commits.json.golden +++ b/scm/driver/stash/testdata/commits.json.golden @@ -1 +1,21 @@ -[] \ No newline at end of file +[ + { + "Sha": "131cb13f4aed12e725177bc4b7c28db67839bf9f", + "Message": "update files", + "Author": { + "Name": "Jane Citizen", + "Email": "jane@example.com", + "Date": "2018-07-04T09:01:42-07:00", + "Login": "jcitizen", + "Avatar": "https://www.gravatar.com/avatar/9e26471d35a78862c17e467d87cddedf.jpg" + }, + "Committer": { + "Name": "Jane Citizen", + "Email": "jane@example.com", + "Date": "2018-07-04T09:01:42-07:00", + "Login": "jcitizen", + "Avatar": "https://www.gravatar.com/avatar/9e26471d35a78862c17e467d87cddedf.jpg" + }, + "Link": "" + } +] \ No newline at end of file From 67c2f0fb6c019491af07ba4c15ff1a079672c386 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Sat, 20 Mar 2021 11:07:09 +0000 Subject: [PATCH 008/282] (change) return hash/object_id for files changed in github. --- scm/driver/github/pr.go | 1 + scm/driver/github/testdata/changes.json.golden | 3 ++- scm/driver/github/testdata/compare.json.golden | 3 ++- scm/driver/github/testdata/pr_files.json.golden | 3 ++- scm/pr.go | 1 + 5 files changed, 8 insertions(+), 3 deletions(-) diff --git a/scm/driver/github/pr.go b/scm/driver/github/pr.go index c3aebf5d2..0a3ddf1a1 100644 --- a/scm/driver/github/pr.go +++ b/scm/driver/github/pr.go @@ -182,5 +182,6 @@ func convertChange(from *file) *scm.Change { Added: from.Status == "added", Deleted: from.Status == "deleted", Renamed: from.Status == "moved", + Hash: from.Sha, } } diff --git a/scm/driver/github/testdata/changes.json.golden b/scm/driver/github/testdata/changes.json.golden index 9b502353c..0b2830c91 100644 --- a/scm/driver/github/testdata/changes.json.golden +++ b/scm/driver/github/testdata/changes.json.golden @@ -3,6 +3,7 @@ "Path": "file1.txt", "Added": true, "Renamed": false, - "Deleted": false + "Deleted": false, + "Hash": "bbcd538c8e72b8c175046e27cc8f907076331401" } ] \ No newline at end of file diff --git a/scm/driver/github/testdata/compare.json.golden b/scm/driver/github/testdata/compare.json.golden index f502bc0db..109f94042 100644 --- a/scm/driver/github/testdata/compare.json.golden +++ b/scm/driver/github/testdata/compare.json.golden @@ -3,6 +3,7 @@ "Path": "README", "Added": false, "Renamed": false, - "Deleted": false + "Deleted": false, + "Hash": "980a0d5f19a64b4b30a87d4206aade58726b60e3" } ] diff --git a/scm/driver/github/testdata/pr_files.json.golden b/scm/driver/github/testdata/pr_files.json.golden index 9b502353c..0b2830c91 100644 --- a/scm/driver/github/testdata/pr_files.json.golden +++ b/scm/driver/github/testdata/pr_files.json.golden @@ -3,6 +3,7 @@ "Path": "file1.txt", "Added": true, "Renamed": false, - "Deleted": false + "Deleted": false, + "Hash": "bbcd538c8e72b8c175046e27cc8f907076331401" } ] \ No newline at end of file diff --git a/scm/pr.go b/scm/pr.go index 65b2d5683..12b9cb918 100644 --- a/scm/pr.go +++ b/scm/pr.go @@ -55,6 +55,7 @@ type ( Added bool Renamed bool Deleted bool + Hash string } Label struct { From cc923c652effd9381ca7c2965eb880075d9d3a1d Mon Sep 17 00:00:00 2001 From: TP Honey Date: Tue, 23 Mar 2021 09:15:15 +0000 Subject: [PATCH 009/282] Update changelog for 1.9.0 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2311d619d..1f7123545 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.9.0 +### Added +- Added issue_comment parsing for github webhook, from [@aman-harness](https://github.com/aman-harness). See [#91](https://github.com/drone/go-scm/pull/91). +- Added Pr in issue, from [@aman-harness](https://github.com/aman-harness). See [#93](https://github.com/drone/go-scm/pull/93). +- gitlab contents. Find returns hash/blob, from [@tphoney](https://github.com/tphoney). See [#97](https://github.com/drone/go-scm/pull/97). +- add ListCommits for gitea and stash, from [@tphoney](https://github.com/tphoney). See [#98](https://github.com/drone/go-scm/pull/98). + +### Changed +- retry with event subset for legacy stash versions, from [@bakito](https://github.com/bakito). See [#90](https://github.com/drone/go-scm/pull/90). + ## 1.8.0 ### Added - Support for GitLab visibility attribute, from [@bradrydzewski](https://github.com/bradrydzewski). See [79951ad](https://github.com/drone/go-scm/commit/79951ad7a0d0b1989ea84d99be31fcb9320ae348). From 83016452168a3a8f0b2b528f038910feaf106425 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Tue, 23 Mar 2021 09:35:09 +0000 Subject: [PATCH 010/282] Update changelog for 1.10.0 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f7123545..08283ef86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.10.0 +### Added +- return hash/object_id for files changed in github, from [@tphoney](https://github.com/tphoney). See [#99](https://github.com/drone/go-scm/pull/99). + ## 1.9.0 ### Added - Added issue_comment parsing for github webhook, from [@aman-harness](https://github.com/aman-harness). See [#91](https://github.com/drone/go-scm/pull/91). From b514328be2d008a5f40152159e8e7a04dbe91217 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Thu, 25 Mar 2021 12:24:28 +0000 Subject: [PATCH 011/282] (feat) normalise sha usage, fix updates, bitbucket cloud update/create --- go.sum | 3 +- scm/content.go | 12 +- scm/driver/bitbucket/bitbucket.go | 43 +- scm/driver/bitbucket/content.go | 57 ++- scm/driver/bitbucket/content_test.go | 141 ++++- scm/driver/bitbucket/testdata/content.json | 31 ++ .../bitbucket/testdata/content.json.fail | 4 + .../bitbucket/testdata/content.json.golden | 5 +- .../bitbucket/testdata/content_fail.json | 6 + .../bitbucket/testdata/content_list.json | 278 +++++++++- .../testdata/content_update.json.fail | 9 + scm/driver/gitea/testdata/commit.json | 40 +- scm/driver/gitea/testdata/commits.json | 40 +- scm/driver/gitea/testdata/content_list.json | 483 +++++++++++++++++- scm/driver/github/content.go | 7 +- scm/driver/github/content_test.go | 36 +- scm/driver/github/pr.go | 4 +- .../github/testdata/changes.json.golden | 2 +- .../github/testdata/compare.json.golden | 2 +- .../github/testdata/content.json.golden | 2 +- .../github/testdata/content_update.json.fail | 4 + .../github/testdata/pr_files.json.golden | 2 +- scm/driver/gitlab/content.go | 9 +- scm/driver/gitlab/content_test.go | 27 + .../gitlab/testdata/content.json.golden | 3 +- scm/driver/gitlab/testdata/content_list.json | 143 +++++- .../gitlab/testdata/content_update.json.fail | 3 + scm/pr.go | 3 +- 28 files changed, 1350 insertions(+), 49 deletions(-) create mode 100644 scm/driver/bitbucket/testdata/content.json create mode 100644 scm/driver/bitbucket/testdata/content.json.fail create mode 100644 scm/driver/bitbucket/testdata/content_fail.json create mode 100644 scm/driver/bitbucket/testdata/content_update.json.fail create mode 100644 scm/driver/github/testdata/content_update.json.fail create mode 100644 scm/driver/gitlab/testdata/content_update.json.fail diff --git a/go.sum b/go.sum index 5f9a39cba..7dbe62ae1 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,4 @@ github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/h2non/gock v1.0.9 h1:17gCehSo8ZOgEsFKpQgqHiR7VLyjxdAG3lkhVvO9QZU= -github.com/h2non/gock v1.0.9/go.mod h1:CZMcB0Lg5IWnr9bF79pPMg9WeV6WumxQiUJ1UvdO1iE= \ No newline at end of file +github.com/h2non/gock v1.0.9/go.mod h1:CZMcB0Lg5IWnr9bF79pPMg9WeV6WumxQiUJ1UvdO1iE= diff --git a/scm/content.go b/scm/content.go index 4d7434917..ffa2966e6 100644 --- a/scm/content.go +++ b/scm/content.go @@ -9,13 +9,10 @@ import "context" type ( // Content stores the contents of a repository file. Content struct { - Path string - Data []byte - - // the hash of the blob, sometimes referred to - // as the blob id or blob sha. this is the equivalent - // to running the git hash-object command. - Hash string + Path string + Data []byte + Sha string + BlobID string } // ContentParams provide parameters for creating and @@ -26,6 +23,7 @@ type ( Message string Data []byte Sha string + BlobID string Signature Signature } diff --git a/scm/driver/bitbucket/bitbucket.go b/scm/driver/bitbucket/bitbucket.go index 8aaa9ae74..f02f5e9b2 100644 --- a/scm/driver/bitbucket/bitbucket.go +++ b/scm/driver/bitbucket/bitbucket.go @@ -10,6 +10,7 @@ import ( "context" "encoding/json" "io" + "mime/multipart" "net/url" "strings" @@ -65,12 +66,44 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface // if we are posting or putting data, we need to // write it to the body of the request. if in != nil { - buf := new(bytes.Buffer) - json.NewEncoder(buf).Encode(in) - req.Header = map[string][]string{ - "Content-Type": {"application/json"}, + // create or update content + switch content := in.(type) { + case *contentCreateUpdate: + // add the content to the multipart + myReader := strings.NewReader(string(content.Content)) + var b bytes.Buffer + w := multipart.NewWriter(&b) + var fw io.Writer + fw, _ = w.CreateFormFile(content.Files, "") + _, _ = io.Copy(fw, myReader) + // add the other fields + if content.Message != "" { + _ = w.WriteField("message", content.Message) + } + if content.Branch != "" { + _ = w.WriteField("branch", content.Branch) + } + if content.Sha != "" { + _ = w.WriteField("parents", content.Sha) + } + if content.Author != "" { + _ = w.WriteField("author", content.Author) + } + w.Close() + // write the multipart response to the body + req.Body = &b + // write the content type that contains the length of the multipart + req.Header = map[string][]string{ + "Content-Type": {w.FormDataContentType()}, + } + default: + buf := new(bytes.Buffer) + json.NewEncoder(buf).Encode(in) + req.Header = map[string][]string{ + "Content-Type": {"application/json"}, + } + req.Body = buf } - req.Body = buf } // execute the http request diff --git a/scm/driver/bitbucket/content.go b/scm/driver/bitbucket/content.go index 079b67439..aa7194f48 100644 --- a/scm/driver/bitbucket/content.go +++ b/scm/driver/bitbucket/content.go @@ -20,18 +20,51 @@ func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm endpoint := fmt.Sprintf("/2.0/repositories/%s/src/%s/%s", repo, ref, path) out := new(bytes.Buffer) res, err := s.client.do(ctx, "GET", endpoint, nil, out) - return &scm.Content{ + content := &scm.Content{ Path: path, Data: out.Bytes(), - }, res, err + } + if err != nil { + return content, res, err + } + metaEndpoint := fmt.Sprintf("/2.0/repositories/%s/src/%s/%s?format=meta", repo, ref, path) + metaOut := new(metaContent) + metaRes, metaErr := s.client.do(ctx, "GET", metaEndpoint, nil, metaOut) + if metaErr == nil { + content.Sha = metaOut.Commit.Hash + return content, metaRes, metaErr + } else { + // do not risk that returning an error if getting the meta fails. + return content, res, err + } } func (s *contentService) Create(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { - return nil, scm.ErrNotSupported + endpoint := fmt.Sprintf("/2.0/repositories/%s/src", repo) + in := &contentCreateUpdate{ + Files: path, + Message: params.Message, + Branch: params.Branch, + Content: params.Data, + Author: fmt.Sprintf("%s <%s>", params.Signature.Name, params.Signature.Email), + } + res, err := s.client.do(ctx, "POST", endpoint, in, nil) + return res, err } func (s *contentService) Update(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { - return nil, scm.ErrNotSupported + // https://jira.atlassian.com/browse/BCLOUD-20424?error=login_required&error_description=Login+required&state=196d85f7-a181-4b63-babe-0b567858d8f5 ugh :( + endpoint := fmt.Sprintf("/2.0/repositories/%s/src", repo) + in := &contentCreateUpdate{ + Files: path, + Message: params.Message, + Branch: params.Branch, + Content: params.Data, + Sha: params.Sha, + Author: fmt.Sprintf("%s <%s>", params.Signature.Name, params.Signature.Email), + } + res, err := s.client.do(ctx, "POST", endpoint, in, nil) + return res, err } func (s *contentService) Delete(ctx context.Context, repo, path, ref string) (*scm.Response, error) { @@ -57,6 +90,22 @@ type content struct { Attributes []string `json:"attributes"` } +type metaContent struct { + Path string `json:"path"` + Commit struct { + Hash string `json:"hash"` + } `json:"commit"` +} + +type contentCreateUpdate struct { + Files string `json:"files"` + Branch string `json:"branch"` + Message string `json:"message"` + Content []byte `json:"content"` + Sha string `json:"sha"` + Author string `json:"author"` +} + func convertContentInfoList(from *contents) []*scm.ContentInfo { to := []*scm.ContentInfo{} for _, v := range from.Values { diff --git a/scm/driver/bitbucket/content_test.go b/scm/driver/bitbucket/content_test.go index d6a87da01..54aa977ac 100644 --- a/scm/driver/bitbucket/content_test.go +++ b/scm/driver/bitbucket/content_test.go @@ -25,6 +25,13 @@ func TestContentFind(t *testing.T) { Type("text/plain"). File("testdata/content.txt") + gock.New("https://api.bitbucket.org"). + MatchParam("format", "meta"). + Get("/2.0/repositories/atlassian/atlaskit/src/425863f9dbe56d70c8dcdbf2e4e0805e85591fcc/README"). + Reply(200). + Type("application/json"). + File("testdata/content.json") + client, _ := New("https://api.bitbucket.org") got, _, err := client.Contents.Find(context.Background(), "atlassian/atlaskit", "README", "425863f9dbe56d70c8dcdbf2e4e0805e85591fcc") if err != nil { @@ -41,19 +48,137 @@ func TestContentFind(t *testing.T) { } } +func TestContentFindNoMeta(t *testing.T) { + defer gock.Off() + + gock.New("https://api.bitbucket.org"). + Get("/2.0/repositories/atlassian/atlaskit/src/425863f9dbe56d70c8dcdbf2e4e0805e85591fcc/README"). + Reply(200). + Type("text/plain"). + File("testdata/content.txt") + + gock.New("https://api.bitbucket.org"). + MatchParam("format", "meta"). + Get("/2.0/repositories/atlassian/atlaskit/src/425863f9dbe56d70c8dcdbf2e4e0805e85591fcc/README"). + Reply(404). + Type("application/json"). + File("testdata/content_fail.json") + + client, _ := New("https://api.bitbucket.org") + got, _, err := client.Contents.Find(context.Background(), "atlassian/atlaskit", "README", "425863f9dbe56d70c8dcdbf2e4e0805e85591fcc") + if err != nil { + t.Error(err) + } + + want := new(scm.Content) + raw, _ := ioutil.ReadFile("testdata/content.json.fail") + json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + func TestContentCreate(t *testing.T) { - content := new(contentService) - _, err := content.Create(context.Background(), "atlassian/atlaskit", "README", nil) - if err != scm.ErrNotSupported { - t.Errorf("Expect Not Supported error") + defer gock.Off() + + gock.New("https://api.bitbucket.org"). + Post("/2.0/repositories/atlassian/atlaskit/src"). + Reply(201). + Type("application/json") + + params := &scm.ContentParams{ + Message: "my commit message", + Data: []byte("bXkgbmV3IGZpbGUgY29udGVudHM="), + Signature: scm.Signature{ + Name: "Monalisa Octocat", + Email: "octocat@github.com", + }, + } + + client := NewDefault() + res, err := client.Contents.Create( + context.Background(), + "atlassian/atlaskit", + "test/hello", + params, + ) + + if err != nil { + t.Error(err) + return + } + + if res.Status != 201 { + t.Errorf("Unexpected Results") } + } func TestContentUpdate(t *testing.T) { - content := new(contentService) - _, err := content.Update(context.Background(), "atlassian/atlaskit", "README", nil) - if err != scm.ErrNotSupported { - t.Errorf("Expect Not Supported error") + defer gock.Off() + + gock.New("https://api.bitbucket.org"). + Post("/2.0/repositories/atlassian/atlaskit/src"). + Reply(201). + Type("application/json") + + params := &scm.ContentParams{ + Message: "my commit message", + Data: []byte("bXkgbmV3IGZpbGUgY29udGVudHM="), + Signature: scm.Signature{ + Name: "Monalisa Octocat", + Email: "octocat@github.com", + }, + } + + client := NewDefault() + res, err := client.Contents.Update( + context.Background(), + "atlassian/atlaskit", + "test/hello", + params, + ) + + if err != nil { + t.Error(err) + return + } + + if res.Status != 201 { + t.Errorf("Unexpected Results") + } +} + +func TestContentUpdateBadCommitID(t *testing.T) { + defer gock.Off() + + gock.New("https://api.bitbucket.org"). + Post("/2.0/repositories/atlassian/atlaskit/src"). + Reply(400). + Type("application/json"). + File("testdata/content_update.json.fail") + + params := &scm.ContentParams{ + Message: "my commit message", + Data: []byte("bXkgbmV3IGZpbGUgY29udGVudHM="), + Sha: "bad commit", + Signature: scm.Signature{ + Name: "Monalisa Octocat", + Email: "octocat@github.com", + }, + } + + client := NewDefault() + _, err := client.Contents.Update( + context.Background(), + "atlassian/atlaskit", + "test/hello", + params, + ) + if err.Error() != "parents: Commit not found: 1a7eba6c-d4fe-47b7-b767-859abc660efc" { + t.Errorf("Expecting 'parents: Commit not found: 1a7eba6c-d4fe-47b7-b767-859abc660efc'") } } diff --git a/scm/driver/bitbucket/testdata/content.json b/scm/driver/bitbucket/testdata/content.json new file mode 100644 index 000000000..8a4d8820e --- /dev/null +++ b/scm/driver/bitbucket/testdata/content.json @@ -0,0 +1,31 @@ +{ + "mimetype": null, + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/tphoney/scm-test/src/0846a192175701903ddd9264ece31922d8437c1a/README.md" + }, + "meta": { + "href": "https://api.bitbucket.org/2.0/repositories/tphoney/scm-test/src/0846a192175701903ddd9264ece31922d8437c1a/README.md?format=meta" + }, + "history": { + "href": "https://api.bitbucket.org/2.0/repositories/tphoney/scm-test/filehistory/0846a192175701903ddd9264ece31922d8437c1a/README.md" + } + }, + "escaped_path": "README.md", + "path": "README.md", + "commit": { + "type": "commit", + "hash": "0846a192175701903ddd9264ece31922d8437c1a", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/tphoney/scm-test/commit/0846a192175701903ddd9264ece31922d8437c1a" + }, + "html": { + "href": "https://bitbucket.org/tphoney/scm-test/commits/0846a192175701903ddd9264ece31922d8437c1a" + } + } + }, + "attributes": [], + "type": "commit_file", + "size": 39 +} \ No newline at end of file diff --git a/scm/driver/bitbucket/testdata/content.json.fail b/scm/driver/bitbucket/testdata/content.json.fail new file mode 100644 index 000000000..5c12f59e2 --- /dev/null +++ b/scm/driver/bitbucket/testdata/content.json.fail @@ -0,0 +1,4 @@ +{ + "Path": "README", + "Data": "SEVMTE8gV09STEQK" +} diff --git a/scm/driver/bitbucket/testdata/content.json.golden b/scm/driver/bitbucket/testdata/content.json.golden index b31f9dcdc..f7e307b61 100644 --- a/scm/driver/bitbucket/testdata/content.json.golden +++ b/scm/driver/bitbucket/testdata/content.json.golden @@ -1,4 +1,5 @@ { "Path": "README", - "Data": "SEVMTE8gV09STEQK" -} \ No newline at end of file + "Data": "SEVMTE8gV09STEQK", + "Sha": "0846a192175701903ddd9264ece31922d8437c1a" +} diff --git a/scm/driver/bitbucket/testdata/content_fail.json b/scm/driver/bitbucket/testdata/content_fail.json new file mode 100644 index 000000000..d8bf6879d --- /dev/null +++ b/scm/driver/bitbucket/testdata/content_fail.json @@ -0,0 +1,6 @@ +{ + "type": "error", + "error": { + "message": "No such file or directory: README.md.asdas" + } +} \ No newline at end of file diff --git a/scm/driver/bitbucket/testdata/content_list.json b/scm/driver/bitbucket/testdata/content_list.json index 7d3e5b2ed..9ea2f3523 100644 --- a/scm/driver/bitbucket/testdata/content_list.json +++ b/scm/driver/bitbucket/testdata/content_list.json @@ -1 +1,277 @@ -{"pagelen":10,"values":[{"path":"packages/activity/build","type":"commit_directory","links":{"self":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/build/"},"meta":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/build/?format=meta"}},"commit":{"type":"commit","hash":"710db794f15bd187db9e7a7b952aac48ebac08bb","links":{"self":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/commit/710db794f15bd187db9e7a7b952aac48ebac08bb"},"html":{"href":"https://bitbucket.org/atlassian/atlaskit/commits/710db794f15bd187db9e7a7b952aac48ebac08bb"}}}},{"path":"packages/activity/dist","type":"commit_directory","links":{"self":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/dist/"},"meta":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/dist/?format=meta"}},"commit":{"type":"commit","hash":"710db794f15bd187db9e7a7b952aac48ebac08bb","links":{"self":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/commit/710db794f15bd187db9e7a7b952aac48ebac08bb"},"html":{"href":"https://bitbucket.org/atlassian/atlaskit/commits/710db794f15bd187db9e7a7b952aac48ebac08bb"}}}},{"path":"packages/activity/docs","type":"commit_directory","links":{"self":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/docs/"},"meta":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/docs/?format=meta"}},"commit":{"type":"commit","hash":"710db794f15bd187db9e7a7b952aac48ebac08bb","links":{"self":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/commit/710db794f15bd187db9e7a7b952aac48ebac08bb"},"html":{"href":"https://bitbucket.org/atlassian/atlaskit/commits/710db794f15bd187db9e7a7b952aac48ebac08bb"}}}},{"path":"packages/activity/src","type":"commit_directory","links":{"self":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/src/"},"meta":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/src/?format=meta"}},"commit":{"type":"commit","hash":"710db794f15bd187db9e7a7b952aac48ebac08bb","links":{"self":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/commit/710db794f15bd187db9e7a7b952aac48ebac08bb"},"html":{"href":"https://bitbucket.org/atlassian/atlaskit/commits/710db794f15bd187db9e7a7b952aac48ebac08bb"}}}},{"path":"packages/activity/test","type":"commit_directory","links":{"self":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/test/"},"meta":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/test/?format=meta"}},"commit":{"type":"commit","hash":"710db794f15bd187db9e7a7b952aac48ebac08bb","links":{"self":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/commit/710db794f15bd187db9e7a7b952aac48ebac08bb"},"html":{"href":"https://bitbucket.org/atlassian/atlaskit/commits/710db794f15bd187db9e7a7b952aac48ebac08bb"}}}},{"mimetype":null,"links":{"self":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/.npmignore"},"meta":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/.npmignore?format=meta"},"history":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/filehistory/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/.npmignore"}},"path":"packages/activity/.npmignore","commit":{"type":"commit","hash":"710db794f15bd187db9e7a7b952aac48ebac08bb","links":{"self":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/commit/710db794f15bd187db9e7a7b952aac48ebac08bb"},"html":{"href":"https://bitbucket.org/atlassian/atlaskit/commits/710db794f15bd187db9e7a7b952aac48ebac08bb"}}},"attributes":[],"type":"commit_file","size":10},{"mimetype":null,"links":{"self":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/LICENSE"},"meta":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/LICENSE?format=meta"},"history":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/filehistory/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/LICENSE"}},"path":"packages/activity/LICENSE","commit":{"type":"commit","hash":"710db794f15bd187db9e7a7b952aac48ebac08bb","links":{"self":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/commit/710db794f15bd187db9e7a7b952aac48ebac08bb"},"html":{"href":"https://bitbucket.org/atlassian/atlaskit/commits/710db794f15bd187db9e7a7b952aac48ebac08bb"}}},"attributes":[],"type":"commit_file","size":558},{"mimetype":"text/vnd.trolltech.linguist","links":{"self":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/index.ts"},"meta":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/index.ts?format=meta"},"history":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/filehistory/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/index.ts"}},"path":"packages/activity/index.ts","commit":{"type":"commit","hash":"710db794f15bd187db9e7a7b952aac48ebac08bb","links":{"self":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/commit/710db794f15bd187db9e7a7b952aac48ebac08bb"},"html":{"href":"https://bitbucket.org/atlassian/atlaskit/commits/710db794f15bd187db9e7a7b952aac48ebac08bb"}}},"attributes":[],"type":"commit_file","size":494},{"mimetype":"application/json","links":{"self":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/package.json"},"meta":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/package.json?format=meta"},"history":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/filehistory/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/package.json"}},"path":"packages/activity/package.json","commit":{"type":"commit","hash":"710db794f15bd187db9e7a7b952aac48ebac08bb","links":{"self":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/commit/710db794f15bd187db9e7a7b952aac48ebac08bb"},"html":{"href":"https://bitbucket.org/atlassian/atlaskit/commits/710db794f15bd187db9e7a7b952aac48ebac08bb"}}},"attributes":[],"type":"commit_file","size":1914},{"mimetype":"text/vnd.trolltech.linguist","links":{"self":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/package.json.d.ts"},"meta":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/package.json.d.ts?format=meta"},"history":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/filehistory/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/package.json.d.ts"}},"path":"packages/activity/package.json.d.ts","commit":{"type":"commit","hash":"710db794f15bd187db9e7a7b952aac48ebac08bb","links":{"self":{"href":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/commit/710db794f15bd187db9e7a7b952aac48ebac08bb"},"html":{"href":"https://bitbucket.org/atlassian/atlaskit/commits/710db794f15bd187db9e7a7b952aac48ebac08bb"}}},"attributes":[],"type":"commit_file","size":61}],"page":1,"next":"https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/master/packages/activity?page=8xhd"} \ No newline at end of file +{ + "pagelen": 10, + "values": [ + { + "path": "packages/activity/build", + "type": "commit_directory", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/build/" + }, + "meta": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/build/?format=meta" + } + }, + "commit": { + "type": "commit", + "hash": "710db794f15bd187db9e7a7b952aac48ebac08bb", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/commit/710db794f15bd187db9e7a7b952aac48ebac08bb" + }, + "html": { + "href": "https://bitbucket.org/atlassian/atlaskit/commits/710db794f15bd187db9e7a7b952aac48ebac08bb" + } + } + } + }, + { + "path": "packages/activity/dist", + "type": "commit_directory", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/dist/" + }, + "meta": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/dist/?format=meta" + } + }, + "commit": { + "type": "commit", + "hash": "710db794f15bd187db9e7a7b952aac48ebac08bb", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/commit/710db794f15bd187db9e7a7b952aac48ebac08bb" + }, + "html": { + "href": "https://bitbucket.org/atlassian/atlaskit/commits/710db794f15bd187db9e7a7b952aac48ebac08bb" + } + } + } + }, + { + "path": "packages/activity/docs", + "type": "commit_directory", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/docs/" + }, + "meta": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/docs/?format=meta" + } + }, + "commit": { + "type": "commit", + "hash": "710db794f15bd187db9e7a7b952aac48ebac08bb", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/commit/710db794f15bd187db9e7a7b952aac48ebac08bb" + }, + "html": { + "href": "https://bitbucket.org/atlassian/atlaskit/commits/710db794f15bd187db9e7a7b952aac48ebac08bb" + } + } + } + }, + { + "path": "packages/activity/src", + "type": "commit_directory", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/src/" + }, + "meta": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/src/?format=meta" + } + }, + "commit": { + "type": "commit", + "hash": "710db794f15bd187db9e7a7b952aac48ebac08bb", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/commit/710db794f15bd187db9e7a7b952aac48ebac08bb" + }, + "html": { + "href": "https://bitbucket.org/atlassian/atlaskit/commits/710db794f15bd187db9e7a7b952aac48ebac08bb" + } + } + } + }, + { + "path": "packages/activity/test", + "type": "commit_directory", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/test/" + }, + "meta": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/test/?format=meta" + } + }, + "commit": { + "type": "commit", + "hash": "710db794f15bd187db9e7a7b952aac48ebac08bb", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/commit/710db794f15bd187db9e7a7b952aac48ebac08bb" + }, + "html": { + "href": "https://bitbucket.org/atlassian/atlaskit/commits/710db794f15bd187db9e7a7b952aac48ebac08bb" + } + } + } + }, + { + "mimetype": null, + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/.npmignore" + }, + "meta": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/.npmignore?format=meta" + }, + "history": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/filehistory/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/.npmignore" + } + }, + "path": "packages/activity/.npmignore", + "commit": { + "type": "commit", + "hash": "710db794f15bd187db9e7a7b952aac48ebac08bb", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/commit/710db794f15bd187db9e7a7b952aac48ebac08bb" + }, + "html": { + "href": "https://bitbucket.org/atlassian/atlaskit/commits/710db794f15bd187db9e7a7b952aac48ebac08bb" + } + } + }, + "attributes": [], + "type": "commit_file", + "size": 10 + }, + { + "mimetype": null, + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/LICENSE" + }, + "meta": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/LICENSE?format=meta" + }, + "history": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/filehistory/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/LICENSE" + } + }, + "path": "packages/activity/LICENSE", + "commit": { + "type": "commit", + "hash": "710db794f15bd187db9e7a7b952aac48ebac08bb", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/commit/710db794f15bd187db9e7a7b952aac48ebac08bb" + }, + "html": { + "href": "https://bitbucket.org/atlassian/atlaskit/commits/710db794f15bd187db9e7a7b952aac48ebac08bb" + } + } + }, + "attributes": [], + "type": "commit_file", + "size": 558 + }, + { + "mimetype": "text/vnd.trolltech.linguist", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/index.ts" + }, + "meta": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/index.ts?format=meta" + }, + "history": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/filehistory/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/index.ts" + } + }, + "path": "packages/activity/index.ts", + "commit": { + "type": "commit", + "hash": "710db794f15bd187db9e7a7b952aac48ebac08bb", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/commit/710db794f15bd187db9e7a7b952aac48ebac08bb" + }, + "html": { + "href": "https://bitbucket.org/atlassian/atlaskit/commits/710db794f15bd187db9e7a7b952aac48ebac08bb" + } + } + }, + "attributes": [], + "type": "commit_file", + "size": 494 + }, + { + "mimetype": "application/json", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/package.json" + }, + "meta": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/package.json?format=meta" + }, + "history": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/filehistory/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/package.json" + } + }, + "path": "packages/activity/package.json", + "commit": { + "type": "commit", + "hash": "710db794f15bd187db9e7a7b952aac48ebac08bb", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/commit/710db794f15bd187db9e7a7b952aac48ebac08bb" + }, + "html": { + "href": "https://bitbucket.org/atlassian/atlaskit/commits/710db794f15bd187db9e7a7b952aac48ebac08bb" + } + } + }, + "attributes": [], + "type": "commit_file", + "size": 1914 + }, + { + "mimetype": "text/vnd.trolltech.linguist", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/package.json.d.ts" + }, + "meta": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/package.json.d.ts?format=meta" + }, + "history": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/filehistory/710db794f15bd187db9e7a7b952aac48ebac08bb/packages/activity/package.json.d.ts" + } + }, + "path": "packages/activity/package.json.d.ts", + "commit": { + "type": "commit", + "hash": "710db794f15bd187db9e7a7b952aac48ebac08bb", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/commit/710db794f15bd187db9e7a7b952aac48ebac08bb" + }, + "html": { + "href": "https://bitbucket.org/atlassian/atlaskit/commits/710db794f15bd187db9e7a7b952aac48ebac08bb" + } + } + }, + "attributes": [], + "type": "commit_file", + "size": 61 + } + ], + "page": 1, + "next": "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/master/packages/activity?page=8xhd" +} \ No newline at end of file diff --git a/scm/driver/bitbucket/testdata/content_update.json.fail b/scm/driver/bitbucket/testdata/content_update.json.fail new file mode 100644 index 000000000..085a52569 --- /dev/null +++ b/scm/driver/bitbucket/testdata/content_update.json.fail @@ -0,0 +1,9 @@ +{ + "type": "error", + "error": { + "fields": { + "parents": [] + }, + "message": "parents: Commit not found: 1a7eba6c-d4fe-47b7-b767-859abc660efc" + } +} \ No newline at end of file diff --git a/scm/driver/gitea/testdata/commit.json b/scm/driver/gitea/testdata/commit.json index 1478fa4be..d43d473de 100644 --- a/scm/driver/gitea/testdata/commit.json +++ b/scm/driver/gitea/testdata/commit.json @@ -1 +1,39 @@ -{"url":"https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/c43399cad8766ee521b873a32c1652407c5a4630","sha":"c43399cad8766ee521b873a32c1652407c5a4630","html_url":"https://try.gitea.io/gitea/gitea/commits/c43399cad8766ee521b873a32c1652407c5a4630","commit":{"url":"https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/c43399cad8766ee521b873a32c1652407c5a4630","author":{"name":"Lewis Cowles","email":"lewiscowles@me.com","date":"2018-09-09T03:36:08Z"},"committer":{"name":"Lunny Xiao","email":"xiaolunwen@gmail.com","date":"2018-09-09T03:36:08Z"},"message":"Fixes repo branch endpoint summary (#4893)","tree":{"url":"https://try.gitea.io/api/v1/repos/gitea/gitea/trees/c43399cad8766ee521b873a32c1652407c5a4630","sha":"c43399cad8766ee521b873a32c1652407c5a4630"}},"author":null,"committer":{"id":3,"login":"lunny","full_name":"Lunny Xiao","email":"xiaolunwen@gmail.com","avatar_url":"https://secure.gravatar.com/avatar/271fc56bcea89c6f69ab0024b59b3f81?d=identicon","language":"zh-CN","username":"lunny"},"parents":[{"url":"https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/d293a2b9d6722dffde7998c953c3087e47a38a83","sha":"d293a2b9d6722dffde7998c953c3087e47a38a83"}]} \ No newline at end of file +{ + "url": "https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/c43399cad8766ee521b873a32c1652407c5a4630", + "sha": "c43399cad8766ee521b873a32c1652407c5a4630", + "html_url": "https://try.gitea.io/gitea/gitea/commits/c43399cad8766ee521b873a32c1652407c5a4630", + "commit": { + "url": "https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/c43399cad8766ee521b873a32c1652407c5a4630", + "author": { + "name": "Lewis Cowles", + "email": "lewiscowles@me.com", + "date": "2018-09-09T03:36:08Z" + }, + "committer": { + "name": "Lunny Xiao", + "email": "xiaolunwen@gmail.com", + "date": "2018-09-09T03:36:08Z" + }, + "message": "Fixes repo branch endpoint summary (#4893)", + "tree": { + "url": "https://try.gitea.io/api/v1/repos/gitea/gitea/trees/c43399cad8766ee521b873a32c1652407c5a4630", + "sha": "c43399cad8766ee521b873a32c1652407c5a4630" + } + }, + "author": null, + "committer": { + "id": 3, + "login": "lunny", + "full_name": "Lunny Xiao", + "email": "xiaolunwen@gmail.com", + "avatar_url": "https://secure.gravatar.com/avatar/271fc56bcea89c6f69ab0024b59b3f81?d=identicon", + "language": "zh-CN", + "username": "lunny" + }, + "parents": [ + { + "url": "https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/d293a2b9d6722dffde7998c953c3087e47a38a83", + "sha": "d293a2b9d6722dffde7998c953c3087e47a38a83" + } + ] +} \ No newline at end of file diff --git a/scm/driver/gitea/testdata/commits.json b/scm/driver/gitea/testdata/commits.json index eab09211b..936a6029d 100644 --- a/scm/driver/gitea/testdata/commits.json +++ b/scm/driver/gitea/testdata/commits.json @@ -1,3 +1,41 @@ [ - {"url":"https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/c43399cad8766ee521b873a32c1652407c5a4630","sha":"c43399cad8766ee521b873a32c1652407c5a4630","html_url":"https://try.gitea.io/gitea/gitea/commits/c43399cad8766ee521b873a32c1652407c5a4630","commit":{"url":"https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/c43399cad8766ee521b873a32c1652407c5a4630","author":{"name":"Lewis Cowles","email":"lewiscowles@me.com","date":"2018-09-09T03:36:08Z"},"committer":{"name":"Lunny Xiao","email":"xiaolunwen@gmail.com","date":"2018-09-09T03:36:08Z"},"message":"Fixes repo branch endpoint summary (#4893)","tree":{"url":"https://try.gitea.io/api/v1/repos/gitea/gitea/trees/c43399cad8766ee521b873a32c1652407c5a4630","sha":"c43399cad8766ee521b873a32c1652407c5a4630"}},"author":null,"committer":{"id":3,"login":"lunny","full_name":"Lunny Xiao","email":"xiaolunwen@gmail.com","avatar_url":"https://secure.gravatar.com/avatar/271fc56bcea89c6f69ab0024b59b3f81?d=identicon","language":"zh-CN","username":"lunny"},"parents":[{"url":"https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/d293a2b9d6722dffde7998c953c3087e47a38a83","sha":"d293a2b9d6722dffde7998c953c3087e47a38a83"}]} + { + "url": "https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/c43399cad8766ee521b873a32c1652407c5a4630", + "sha": "c43399cad8766ee521b873a32c1652407c5a4630", + "html_url": "https://try.gitea.io/gitea/gitea/commits/c43399cad8766ee521b873a32c1652407c5a4630", + "commit": { + "url": "https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/c43399cad8766ee521b873a32c1652407c5a4630", + "author": { + "name": "Lewis Cowles", + "email": "lewiscowles@me.com", + "date": "2018-09-09T03:36:08Z" + }, + "committer": { + "name": "Lunny Xiao", + "email": "xiaolunwen@gmail.com", + "date": "2018-09-09T03:36:08Z" + }, + "message": "Fixes repo branch endpoint summary (#4893)", + "tree": { + "url": "https://try.gitea.io/api/v1/repos/gitea/gitea/trees/c43399cad8766ee521b873a32c1652407c5a4630", + "sha": "c43399cad8766ee521b873a32c1652407c5a4630" + } + }, + "author": null, + "committer": { + "id": 3, + "login": "lunny", + "full_name": "Lunny Xiao", + "email": "xiaolunwen@gmail.com", + "avatar_url": "https://secure.gravatar.com/avatar/271fc56bcea89c6f69ab0024b59b3f81?d=identicon", + "language": "zh-CN", + "username": "lunny" + }, + "parents": [ + { + "url": "https://try.gitea.io/api/v1/repos/gitea/gitea/git/commits/d293a2b9d6722dffde7998c953c3087e47a38a83", + "sha": "d293a2b9d6722dffde7998c953c3087e47a38a83" + } + ] + } ] \ No newline at end of file diff --git a/scm/driver/gitea/testdata/content_list.json b/scm/driver/gitea/testdata/content_list.json index 72efd49f6..87535a882 100644 --- a/scm/driver/gitea/testdata/content_list.json +++ b/scm/driver/gitea/testdata/content_list.json @@ -1 +1,482 @@ -[{"name":"advanced.en-us.md","path":"docs/content/doc/advanced.en-us.md","sha":"de2bfeed6f2d3ea1d2f91e457e9450efc582bb31","type":"file","size":192,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/advanced.en-us.md?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/advanced.en-us.md","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/de2bfeed6f2d3ea1d2f91e457e9450efc582bb31","download_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/advanced.en-us.md","submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/advanced.en-us.md?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/de2bfeed6f2d3ea1d2f91e457e9450efc582bb31","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/advanced.en-us.md"}},{"name":"advanced.fr-fr.md","path":"docs/content/doc/advanced.fr-fr.md","sha":"04734a8f81f5641de2b6d738bc9b777c2cc541c6","type":"file","size":190,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/advanced.fr-fr.md?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/advanced.fr-fr.md","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/04734a8f81f5641de2b6d738bc9b777c2cc541c6","download_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/advanced.fr-fr.md","submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/advanced.fr-fr.md?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/04734a8f81f5641de2b6d738bc9b777c2cc541c6","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/advanced.fr-fr.md"}},{"name":"advanced.zh-cn.md","path":"docs/content/doc/advanced.zh-cn.md","sha":"1f7ebf81e723a0ba82a89eec18a2706ac1b0dace","type":"file","size":188,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/advanced.zh-cn.md?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/advanced.zh-cn.md","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/1f7ebf81e723a0ba82a89eec18a2706ac1b0dace","download_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/advanced.zh-cn.md","submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/advanced.zh-cn.md?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/1f7ebf81e723a0ba82a89eec18a2706ac1b0dace","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/advanced.zh-cn.md"}},{"name":"advanced","path":"docs/content/doc/advanced","sha":"8c43a4fb023735dfd026014bae92ad91414b88bd","type":"dir","size":0,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/advanced?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/advanced","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/8c43a4fb023735dfd026014bae92ad91414b88bd","download_url":null,"submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/advanced?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/8c43a4fb023735dfd026014bae92ad91414b88bd","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/advanced"}},{"name":"features.en-us.md","path":"docs/content/doc/features.en-us.md","sha":"9cc90b46a0d17864e5ce1749dbd1609a0921f8f7","type":"file","size":192,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features.en-us.md?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features.en-us.md","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/9cc90b46a0d17864e5ce1749dbd1609a0921f8f7","download_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/features.en-us.md","submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features.en-us.md?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/9cc90b46a0d17864e5ce1749dbd1609a0921f8f7","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features.en-us.md"}},{"name":"features.zh-cn.md","path":"docs/content/doc/features.zh-cn.md","sha":"68d2f71b11f6bb5b1ca31adad00bc0f6ed3e94d8","type":"file","size":188,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features.zh-cn.md?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features.zh-cn.md","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/68d2f71b11f6bb5b1ca31adad00bc0f6ed3e94d8","download_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/features.zh-cn.md","submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features.zh-cn.md?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/68d2f71b11f6bb5b1ca31adad00bc0f6ed3e94d8","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features.zh-cn.md"}},{"name":"features.zh-tw.md","path":"docs/content/doc/features.zh-tw.md","sha":"889e0df88213a937914ba43bb52956d0e54b1c98","type":"file","size":188,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features.zh-tw.md?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features.zh-tw.md","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/889e0df88213a937914ba43bb52956d0e54b1c98","download_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/features.zh-tw.md","submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features.zh-tw.md?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/889e0df88213a937914ba43bb52956d0e54b1c98","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features.zh-tw.md"}},{"name":"features","path":"docs/content/doc/features","sha":"e212486606cf756b3b626f0a5bb1dd386b83b698","type":"dir","size":0,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/e212486606cf756b3b626f0a5bb1dd386b83b698","download_url":null,"submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/e212486606cf756b3b626f0a5bb1dd386b83b698","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features"}},{"name":"help.en-us.md","path":"docs/content/doc/help.en-us.md","sha":"5ad1dd7f1edb3b78a3e3fba2113ecd5b10625dc4","type":"file","size":176,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/help.en-us.md?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/help.en-us.md","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/5ad1dd7f1edb3b78a3e3fba2113ecd5b10625dc4","download_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/help.en-us.md","submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/help.en-us.md?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/5ad1dd7f1edb3b78a3e3fba2113ecd5b10625dc4","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/help.en-us.md"}},{"name":"help.zh-cn.md","path":"docs/content/doc/help.zh-cn.md","sha":"6af7aa1719b99e35874b76911aff29b9ad4bbc68","type":"file","size":180,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/help.zh-cn.md?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/help.zh-cn.md","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/6af7aa1719b99e35874b76911aff29b9ad4bbc68","download_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/help.zh-cn.md","submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/help.zh-cn.md?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/6af7aa1719b99e35874b76911aff29b9ad4bbc68","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/help.zh-cn.md"}},{"name":"help","path":"docs/content/doc/help","sha":"91adc879a877f6c44aab1f27453bfa2679e4c3a0","type":"dir","size":0,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/help?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/help","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/91adc879a877f6c44aab1f27453bfa2679e4c3a0","download_url":null,"submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/help?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/91adc879a877f6c44aab1f27453bfa2679e4c3a0","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/help"}},{"name":"installation.en-us.md","path":"docs/content/doc/installation.en-us.md","sha":"4257521d973b0d28a7040f9030f701bbd1bf7bef","type":"file","size":208,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.en-us.md?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.en-us.md","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/4257521d973b0d28a7040f9030f701bbd1bf7bef","download_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/installation.en-us.md","submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.en-us.md?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/4257521d973b0d28a7040f9030f701bbd1bf7bef","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.en-us.md"}},{"name":"installation.fr-fr.md","path":"docs/content/doc/installation.fr-fr.md","sha":"55b48bda3eca4e459c12e44d54de9c4573d9b0b7","type":"file","size":208,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.fr-fr.md?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.fr-fr.md","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/55b48bda3eca4e459c12e44d54de9c4573d9b0b7","download_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/installation.fr-fr.md","submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.fr-fr.md?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/55b48bda3eca4e459c12e44d54de9c4573d9b0b7","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.fr-fr.md"}},{"name":"installation.zh-cn.md","path":"docs/content/doc/installation.zh-cn.md","sha":"8f57e0f00c273619c1ce66f04f7536f62d830e88","type":"file","size":196,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.zh-cn.md?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.zh-cn.md","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/8f57e0f00c273619c1ce66f04f7536f62d830e88","download_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/installation.zh-cn.md","submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.zh-cn.md?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/8f57e0f00c273619c1ce66f04f7536f62d830e88","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.zh-cn.md"}},{"name":"installation.zh-tw.md","path":"docs/content/doc/installation.zh-tw.md","sha":"f955e994ac09834f546212a6ec494978a4d10039","type":"file","size":196,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.zh-tw.md?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.zh-tw.md","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/f955e994ac09834f546212a6ec494978a4d10039","download_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/installation.zh-tw.md","submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.zh-tw.md?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/f955e994ac09834f546212a6ec494978a4d10039","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.zh-tw.md"}},{"name":"installation","path":"docs/content/doc/installation","sha":"2a3ff66218ae980c07444b8c97b710b3d7b5b846","type":"dir","size":0,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/2a3ff66218ae980c07444b8c97b710b3d7b5b846","download_url":null,"submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/2a3ff66218ae980c07444b8c97b710b3d7b5b846","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation"}},{"name":"upgrade.en-us.md","path":"docs/content/doc/upgrade.en-us.md","sha":"9623ff9f1eaf74e9ebc03f5869bc0b9d2b3372d3","type":"file","size":188,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.en-us.md?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.en-us.md","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/9623ff9f1eaf74e9ebc03f5869bc0b9d2b3372d3","download_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/upgrade.en-us.md","submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.en-us.md?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/9623ff9f1eaf74e9ebc03f5869bc0b9d2b3372d3","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.en-us.md"}},{"name":"upgrade.fr-fr.md","path":"docs/content/doc/upgrade.fr-fr.md","sha":"ca08daf9c096bf027ba95a13b44c5fe4d0a47afe","type":"file","size":198,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.fr-fr.md?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.fr-fr.md","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/ca08daf9c096bf027ba95a13b44c5fe4d0a47afe","download_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/upgrade.fr-fr.md","submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.fr-fr.md?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/ca08daf9c096bf027ba95a13b44c5fe4d0a47afe","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.fr-fr.md"}},{"name":"upgrade.zh-cn.md","path":"docs/content/doc/upgrade.zh-cn.md","sha":"d12e150b9cbce2c26acb64c724914cec8667bb5d","type":"file","size":186,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.zh-cn.md?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.zh-cn.md","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/d12e150b9cbce2c26acb64c724914cec8667bb5d","download_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/upgrade.zh-cn.md","submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.zh-cn.md?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/d12e150b9cbce2c26acb64c724914cec8667bb5d","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.zh-cn.md"}},{"name":"upgrade.zh-tw.md","path":"docs/content/doc/upgrade.zh-tw.md","sha":"b57fccbdd578e9c981171838a9dd1e152f69bce9","type":"file","size":186,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.zh-tw.md?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.zh-tw.md","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/b57fccbdd578e9c981171838a9dd1e152f69bce9","download_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/upgrade.zh-tw.md","submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.zh-tw.md?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/b57fccbdd578e9c981171838a9dd1e152f69bce9","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.zh-tw.md"}},{"name":"upgrade","path":"docs/content/doc/upgrade","sha":"ff064862ee6ca9aa7bfda908c5354c83fbac25a4","type":"dir","size":0,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/ff064862ee6ca9aa7bfda908c5354c83fbac25a4","download_url":null,"submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/ff064862ee6ca9aa7bfda908c5354c83fbac25a4","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade"}},{"name":"usage.en-us.md","path":"docs/content/doc/usage.en-us.md","sha":"6be9769d64603f93e05e099a8b2dcbceae1e98df","type":"file","size":180,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/usage.en-us.md?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/usage.en-us.md","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/6be9769d64603f93e05e099a8b2dcbceae1e98df","download_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/usage.en-us.md","submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/usage.en-us.md?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/6be9769d64603f93e05e099a8b2dcbceae1e98df","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/usage.en-us.md"}},{"name":"usage.zh-cn.md","path":"docs/content/doc/usage.zh-cn.md","sha":"c533df662481ea381cba02f0cb7996a3c1b377fd","type":"file","size":194,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/usage.zh-cn.md?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/usage.zh-cn.md","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/c533df662481ea381cba02f0cb7996a3c1b377fd","download_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/usage.zh-cn.md","submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/usage.zh-cn.md?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/c533df662481ea381cba02f0cb7996a3c1b377fd","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/usage.zh-cn.md"}},{"name":"usage","path":"docs/content/doc/usage","sha":"ac7d00a3401c3299068e09da540badfaf29d5e58","type":"dir","size":0,"encoding":null,"content":null,"target":null,"url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/usage?ref=master","html_url":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/usage","git_url":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/ac7d00a3401c3299068e09da540badfaf29d5e58","download_url":null,"submodule_git_url":null,"_links":{"self":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/usage?ref=master","git":"https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/ac7d00a3401c3299068e09da540badfaf29d5e58","html":"https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/usage"}}] \ No newline at end of file +[ + { + "name": "advanced.en-us.md", + "path": "docs/content/doc/advanced.en-us.md", + "sha": "de2bfeed6f2d3ea1d2f91e457e9450efc582bb31", + "type": "file", + "size": 192, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/advanced.en-us.md?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/advanced.en-us.md", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/de2bfeed6f2d3ea1d2f91e457e9450efc582bb31", + "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/advanced.en-us.md", + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/advanced.en-us.md?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/de2bfeed6f2d3ea1d2f91e457e9450efc582bb31", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/advanced.en-us.md" + } + }, + { + "name": "advanced.fr-fr.md", + "path": "docs/content/doc/advanced.fr-fr.md", + "sha": "04734a8f81f5641de2b6d738bc9b777c2cc541c6", + "type": "file", + "size": 190, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/advanced.fr-fr.md?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/advanced.fr-fr.md", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/04734a8f81f5641de2b6d738bc9b777c2cc541c6", + "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/advanced.fr-fr.md", + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/advanced.fr-fr.md?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/04734a8f81f5641de2b6d738bc9b777c2cc541c6", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/advanced.fr-fr.md" + } + }, + { + "name": "advanced.zh-cn.md", + "path": "docs/content/doc/advanced.zh-cn.md", + "sha": "1f7ebf81e723a0ba82a89eec18a2706ac1b0dace", + "type": "file", + "size": 188, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/advanced.zh-cn.md?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/advanced.zh-cn.md", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/1f7ebf81e723a0ba82a89eec18a2706ac1b0dace", + "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/advanced.zh-cn.md", + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/advanced.zh-cn.md?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/1f7ebf81e723a0ba82a89eec18a2706ac1b0dace", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/advanced.zh-cn.md" + } + }, + { + "name": "advanced", + "path": "docs/content/doc/advanced", + "sha": "8c43a4fb023735dfd026014bae92ad91414b88bd", + "type": "dir", + "size": 0, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/advanced?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/advanced", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/8c43a4fb023735dfd026014bae92ad91414b88bd", + "download_url": null, + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/advanced?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/8c43a4fb023735dfd026014bae92ad91414b88bd", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/advanced" + } + }, + { + "name": "features.en-us.md", + "path": "docs/content/doc/features.en-us.md", + "sha": "9cc90b46a0d17864e5ce1749dbd1609a0921f8f7", + "type": "file", + "size": 192, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features.en-us.md?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features.en-us.md", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/9cc90b46a0d17864e5ce1749dbd1609a0921f8f7", + "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/features.en-us.md", + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features.en-us.md?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/9cc90b46a0d17864e5ce1749dbd1609a0921f8f7", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features.en-us.md" + } + }, + { + "name": "features.zh-cn.md", + "path": "docs/content/doc/features.zh-cn.md", + "sha": "68d2f71b11f6bb5b1ca31adad00bc0f6ed3e94d8", + "type": "file", + "size": 188, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features.zh-cn.md?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features.zh-cn.md", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/68d2f71b11f6bb5b1ca31adad00bc0f6ed3e94d8", + "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/features.zh-cn.md", + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features.zh-cn.md?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/68d2f71b11f6bb5b1ca31adad00bc0f6ed3e94d8", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features.zh-cn.md" + } + }, + { + "name": "features.zh-tw.md", + "path": "docs/content/doc/features.zh-tw.md", + "sha": "889e0df88213a937914ba43bb52956d0e54b1c98", + "type": "file", + "size": 188, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features.zh-tw.md?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features.zh-tw.md", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/889e0df88213a937914ba43bb52956d0e54b1c98", + "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/features.zh-tw.md", + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features.zh-tw.md?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/889e0df88213a937914ba43bb52956d0e54b1c98", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features.zh-tw.md" + } + }, + { + "name": "features", + "path": "docs/content/doc/features", + "sha": "e212486606cf756b3b626f0a5bb1dd386b83b698", + "type": "dir", + "size": 0, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/e212486606cf756b3b626f0a5bb1dd386b83b698", + "download_url": null, + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/e212486606cf756b3b626f0a5bb1dd386b83b698", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features" + } + }, + { + "name": "help.en-us.md", + "path": "docs/content/doc/help.en-us.md", + "sha": "5ad1dd7f1edb3b78a3e3fba2113ecd5b10625dc4", + "type": "file", + "size": 176, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/help.en-us.md?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/help.en-us.md", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/5ad1dd7f1edb3b78a3e3fba2113ecd5b10625dc4", + "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/help.en-us.md", + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/help.en-us.md?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/5ad1dd7f1edb3b78a3e3fba2113ecd5b10625dc4", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/help.en-us.md" + } + }, + { + "name": "help.zh-cn.md", + "path": "docs/content/doc/help.zh-cn.md", + "sha": "6af7aa1719b99e35874b76911aff29b9ad4bbc68", + "type": "file", + "size": 180, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/help.zh-cn.md?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/help.zh-cn.md", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/6af7aa1719b99e35874b76911aff29b9ad4bbc68", + "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/help.zh-cn.md", + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/help.zh-cn.md?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/6af7aa1719b99e35874b76911aff29b9ad4bbc68", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/help.zh-cn.md" + } + }, + { + "name": "help", + "path": "docs/content/doc/help", + "sha": "91adc879a877f6c44aab1f27453bfa2679e4c3a0", + "type": "dir", + "size": 0, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/help?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/help", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/91adc879a877f6c44aab1f27453bfa2679e4c3a0", + "download_url": null, + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/help?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/91adc879a877f6c44aab1f27453bfa2679e4c3a0", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/help" + } + }, + { + "name": "installation.en-us.md", + "path": "docs/content/doc/installation.en-us.md", + "sha": "4257521d973b0d28a7040f9030f701bbd1bf7bef", + "type": "file", + "size": 208, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.en-us.md?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.en-us.md", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/4257521d973b0d28a7040f9030f701bbd1bf7bef", + "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/installation.en-us.md", + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.en-us.md?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/4257521d973b0d28a7040f9030f701bbd1bf7bef", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.en-us.md" + } + }, + { + "name": "installation.fr-fr.md", + "path": "docs/content/doc/installation.fr-fr.md", + "sha": "55b48bda3eca4e459c12e44d54de9c4573d9b0b7", + "type": "file", + "size": 208, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.fr-fr.md?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.fr-fr.md", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/55b48bda3eca4e459c12e44d54de9c4573d9b0b7", + "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/installation.fr-fr.md", + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.fr-fr.md?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/55b48bda3eca4e459c12e44d54de9c4573d9b0b7", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.fr-fr.md" + } + }, + { + "name": "installation.zh-cn.md", + "path": "docs/content/doc/installation.zh-cn.md", + "sha": "8f57e0f00c273619c1ce66f04f7536f62d830e88", + "type": "file", + "size": 196, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.zh-cn.md?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.zh-cn.md", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/8f57e0f00c273619c1ce66f04f7536f62d830e88", + "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/installation.zh-cn.md", + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.zh-cn.md?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/8f57e0f00c273619c1ce66f04f7536f62d830e88", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.zh-cn.md" + } + }, + { + "name": "installation.zh-tw.md", + "path": "docs/content/doc/installation.zh-tw.md", + "sha": "f955e994ac09834f546212a6ec494978a4d10039", + "type": "file", + "size": 196, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.zh-tw.md?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.zh-tw.md", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/f955e994ac09834f546212a6ec494978a4d10039", + "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/installation.zh-tw.md", + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.zh-tw.md?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/f955e994ac09834f546212a6ec494978a4d10039", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.zh-tw.md" + } + }, + { + "name": "installation", + "path": "docs/content/doc/installation", + "sha": "2a3ff66218ae980c07444b8c97b710b3d7b5b846", + "type": "dir", + "size": 0, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/2a3ff66218ae980c07444b8c97b710b3d7b5b846", + "download_url": null, + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/2a3ff66218ae980c07444b8c97b710b3d7b5b846", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation" + } + }, + { + "name": "upgrade.en-us.md", + "path": "docs/content/doc/upgrade.en-us.md", + "sha": "9623ff9f1eaf74e9ebc03f5869bc0b9d2b3372d3", + "type": "file", + "size": 188, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.en-us.md?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.en-us.md", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/9623ff9f1eaf74e9ebc03f5869bc0b9d2b3372d3", + "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/upgrade.en-us.md", + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.en-us.md?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/9623ff9f1eaf74e9ebc03f5869bc0b9d2b3372d3", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.en-us.md" + } + }, + { + "name": "upgrade.fr-fr.md", + "path": "docs/content/doc/upgrade.fr-fr.md", + "sha": "ca08daf9c096bf027ba95a13b44c5fe4d0a47afe", + "type": "file", + "size": 198, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.fr-fr.md?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.fr-fr.md", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/ca08daf9c096bf027ba95a13b44c5fe4d0a47afe", + "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/upgrade.fr-fr.md", + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.fr-fr.md?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/ca08daf9c096bf027ba95a13b44c5fe4d0a47afe", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.fr-fr.md" + } + }, + { + "name": "upgrade.zh-cn.md", + "path": "docs/content/doc/upgrade.zh-cn.md", + "sha": "d12e150b9cbce2c26acb64c724914cec8667bb5d", + "type": "file", + "size": 186, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.zh-cn.md?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.zh-cn.md", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/d12e150b9cbce2c26acb64c724914cec8667bb5d", + "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/upgrade.zh-cn.md", + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.zh-cn.md?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/d12e150b9cbce2c26acb64c724914cec8667bb5d", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.zh-cn.md" + } + }, + { + "name": "upgrade.zh-tw.md", + "path": "docs/content/doc/upgrade.zh-tw.md", + "sha": "b57fccbdd578e9c981171838a9dd1e152f69bce9", + "type": "file", + "size": 186, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.zh-tw.md?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.zh-tw.md", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/b57fccbdd578e9c981171838a9dd1e152f69bce9", + "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/upgrade.zh-tw.md", + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.zh-tw.md?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/b57fccbdd578e9c981171838a9dd1e152f69bce9", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.zh-tw.md" + } + }, + { + "name": "upgrade", + "path": "docs/content/doc/upgrade", + "sha": "ff064862ee6ca9aa7bfda908c5354c83fbac25a4", + "type": "dir", + "size": 0, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/ff064862ee6ca9aa7bfda908c5354c83fbac25a4", + "download_url": null, + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/ff064862ee6ca9aa7bfda908c5354c83fbac25a4", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade" + } + }, + { + "name": "usage.en-us.md", + "path": "docs/content/doc/usage.en-us.md", + "sha": "6be9769d64603f93e05e099a8b2dcbceae1e98df", + "type": "file", + "size": 180, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/usage.en-us.md?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/usage.en-us.md", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/6be9769d64603f93e05e099a8b2dcbceae1e98df", + "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/usage.en-us.md", + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/usage.en-us.md?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/6be9769d64603f93e05e099a8b2dcbceae1e98df", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/usage.en-us.md" + } + }, + { + "name": "usage.zh-cn.md", + "path": "docs/content/doc/usage.zh-cn.md", + "sha": "c533df662481ea381cba02f0cb7996a3c1b377fd", + "type": "file", + "size": 194, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/usage.zh-cn.md?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/usage.zh-cn.md", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/c533df662481ea381cba02f0cb7996a3c1b377fd", + "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/usage.zh-cn.md", + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/usage.zh-cn.md?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/c533df662481ea381cba02f0cb7996a3c1b377fd", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/usage.zh-cn.md" + } + }, + { + "name": "usage", + "path": "docs/content/doc/usage", + "sha": "ac7d00a3401c3299068e09da540badfaf29d5e58", + "type": "dir", + "size": 0, + "encoding": null, + "content": null, + "target": null, + "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/usage?ref=master", + "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/usage", + "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/ac7d00a3401c3299068e09da540badfaf29d5e58", + "download_url": null, + "submodule_git_url": null, + "_links": { + "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/usage?ref=master", + "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/ac7d00a3401c3299068e09da540badfaf29d5e58", + "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/usage" + } + } +] \ No newline at end of file diff --git a/scm/driver/github/content.go b/scm/driver/github/content.go index 16ae4b506..b292befed 100644 --- a/scm/driver/github/content.go +++ b/scm/driver/github/content.go @@ -22,9 +22,10 @@ func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm res, err := s.client.do(ctx, "GET", endpoint, nil, out) raw, _ := base64.StdEncoding.DecodeString(out.Content) return &scm.Content{ - Hash: out.Sha, Path: out.Path, Data: raw, + // NB the sha returned for github rest api is the blob sha, not the commit sha + BlobID: out.Sha, }, res, err } @@ -34,7 +35,6 @@ func (s *contentService) Create(ctx context.Context, repo, path string, params * Message: params.Message, Branch: params.Branch, Content: params.Data, - Sha: params.Sha, Committer: commitAuthor{ Name: params.Signature.Name, Email: params.Signature.Email, @@ -55,7 +55,8 @@ func (s *contentService) Update(ctx context.Context, repo, path string, params * Message: params.Message, Branch: params.Branch, Content: params.Data, - Sha: params.Sha, + // NB the sha passed to github rest api is the blob sha, not the commit sha + Sha: params.BlobID, Committer: commitAuthor{ Name: params.Signature.Name, Email: params.Signature.Email, diff --git a/scm/driver/github/content_test.go b/scm/driver/github/content_test.go index 5187c713f..1c8692812 100644 --- a/scm/driver/github/content_test.go +++ b/scm/driver/github/content_test.go @@ -101,7 +101,7 @@ func TestContentUpdate(t *testing.T) { params := &scm.ContentParams{ Message: "a new commit message", Data: []byte("bXkgdXBkYXRlZCBmaWxlIGNvbnRlbnRz"), - Sha: "95b966ae1c166bd92f8ae7d1c313e738c731dfc3", + BlobID: "95b966ae1c166bd92f8ae7d1c313e738c731dfc3", Signature: scm.Signature{ Name: "Monalisa Octocat", Email: "octocat@github.com", @@ -109,7 +109,7 @@ func TestContentUpdate(t *testing.T) { } client := NewDefault() - res, err := client.Contents.Create( + res, err := client.Contents.Update( context.Background(), "octocat/hello-world", "test/hello", @@ -126,6 +126,38 @@ func TestContentUpdate(t *testing.T) { } } +func TestContentUpdateBadBlobID(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Put("/repos/octocat/hello-world/contents/test/hello"). + Reply(401). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/content_update.json.fail") + + params := &scm.ContentParams{ + Message: "a new commit message", + Data: []byte("bXkgdXBkYXRlZCBmaWxlIGNvbnRlbnRz"), + BlobID: "95b966ae1c166bd92f8ae7d1c313e738c731dfc3", + Signature: scm.Signature{ + Name: "Monalisa Octocat", + Email: "octocat@github.com", + }, + } + + client := NewDefault() + _, err := client.Contents.Update( + context.Background(), + "octocat/hello-world", + "test/hello", + params, + ) + if err.Error() != "newfile does not match" { + t.Errorf("Expecting 'newfile does not match'") + } +} + func TestContentDelete(t *testing.T) { content := new(contentService) _, err := content.Delete(context.Background(), "octocat/hello-world", "README", "master") diff --git a/scm/driver/github/pr.go b/scm/driver/github/pr.go index 0a3ddf1a1..af332f00e 100644 --- a/scm/driver/github/pr.go +++ b/scm/driver/github/pr.go @@ -111,7 +111,7 @@ type prInput struct { } type file struct { - Sha string `json:"sha"` + BlobID string `json:"sha"` Filename string `json:"filename"` Status string `json:"status"` Additions int `json:"additions"` @@ -182,6 +182,6 @@ func convertChange(from *file) *scm.Change { Added: from.Status == "added", Deleted: from.Status == "deleted", Renamed: from.Status == "moved", - Hash: from.Sha, + BlobID: from.BlobID, } } diff --git a/scm/driver/github/testdata/changes.json.golden b/scm/driver/github/testdata/changes.json.golden index 0b2830c91..b5034d7cf 100644 --- a/scm/driver/github/testdata/changes.json.golden +++ b/scm/driver/github/testdata/changes.json.golden @@ -4,6 +4,6 @@ "Added": true, "Renamed": false, "Deleted": false, - "Hash": "bbcd538c8e72b8c175046e27cc8f907076331401" + "BlobID": "bbcd538c8e72b8c175046e27cc8f907076331401" } ] \ No newline at end of file diff --git a/scm/driver/github/testdata/compare.json.golden b/scm/driver/github/testdata/compare.json.golden index 109f94042..fb8197d1f 100644 --- a/scm/driver/github/testdata/compare.json.golden +++ b/scm/driver/github/testdata/compare.json.golden @@ -4,6 +4,6 @@ "Added": false, "Renamed": false, "Deleted": false, - "Hash": "980a0d5f19a64b4b30a87d4206aade58726b60e3" + "BlobID": "980a0d5f19a64b4b30a87d4206aade58726b60e3" } ] diff --git a/scm/driver/github/testdata/content.json.golden b/scm/driver/github/testdata/content.json.golden index 4c414c519..d58e10b30 100644 --- a/scm/driver/github/testdata/content.json.golden +++ b/scm/driver/github/testdata/content.json.golden @@ -1,5 +1,5 @@ { "Path": "README", "Data": "SGVsbG8gV29ybGQhCg==", - "Hash": "980a0d5f19a64b4b30a87d4206aade58726b60e3" + "BlobID": "980a0d5f19a64b4b30a87d4206aade58726b60e3" } \ No newline at end of file diff --git a/scm/driver/github/testdata/content_update.json.fail b/scm/driver/github/testdata/content_update.json.fail new file mode 100644 index 000000000..1ae315d60 --- /dev/null +++ b/scm/driver/github/testdata/content_update.json.fail @@ -0,0 +1,4 @@ +{ + "message": "newfile does not match", + "documentation_url": "https://docs.github.com/rest/reference/repos#create-or-update-file-contents" +} \ No newline at end of file diff --git a/scm/driver/github/testdata/pr_files.json.golden b/scm/driver/github/testdata/pr_files.json.golden index 0b2830c91..b5034d7cf 100644 --- a/scm/driver/github/testdata/pr_files.json.golden +++ b/scm/driver/github/testdata/pr_files.json.golden @@ -4,6 +4,6 @@ "Added": true, "Renamed": false, "Deleted": false, - "Hash": "bbcd538c8e72b8c175046e27cc8f907076331401" + "BlobID": "bbcd538c8e72b8c175046e27cc8f907076331401" } ] \ No newline at end of file diff --git a/scm/driver/gitlab/content.go b/scm/driver/gitlab/content.go index 196c593ee..d82e1a3b1 100644 --- a/scm/driver/gitlab/content.go +++ b/scm/driver/gitlab/content.go @@ -32,9 +32,10 @@ func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm } } return &scm.Content{ - Path: out.FilePath, - Data: raw, - Hash: out.BlobID, + Path: out.FilePath, + Data: raw, + Sha: out.CommitID, + BlobID: out.BlobID, }, res, err } @@ -62,6 +63,7 @@ func (s *contentService) Update(ctx context.Context, repo, path string, params * Encoding: "base64", AuthorName: params.Signature.Name, AuthorEmail: params.Signature.Email, + LastCommitID: params.Sha, } res, err := s.client.do(ctx, "PUT", endpoint, in, nil) return res, err @@ -97,6 +99,7 @@ type createUpdateContent struct { Encoding string `json:"encoding"` AuthorEmail string `json:"author_email"` AuthorName string `json:"author_name"` + LastCommitID string `json:"last_commit_id"` } type object struct { diff --git a/scm/driver/gitlab/content_test.go b/scm/driver/gitlab/content_test.go index 16e7b44a1..29349fa95 100644 --- a/scm/driver/gitlab/content_test.go +++ b/scm/driver/gitlab/content_test.go @@ -114,6 +114,33 @@ func TestContentUpdate(t *testing.T) { } } +func TestContentUpdateBadCommitID(t *testing.T) { + defer gock.Off() + + gock.New("https://gitlab.com"). + Put("/api/v4/projects/diaspora/diaspora/repository/files/app/project.rb"). + Reply(400). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/content_update.json.fail") + + client := NewDefault() + params := &scm.ContentParams{ + Message: "update file", + Data: []byte("bXkgbmV3IGZpbGUgY29udGVudHM="), + Sha: "bad sha", + Signature: scm.Signature{ + Name: "Firstname Lastname", + Email: "kubesphere@example.com", + }, + } + + _, err := client.Contents.Update(context.Background(), "diaspora/diaspora", "app/project.rb", params) + if err.Error() != "You are attempting to update a file that has changed since you started editing it." { + t.Errorf("Expecting error 'You are attempting to update a file that has changed since you started editing it.'") + } +} + func TestContentDelete(t *testing.T) { content := new(contentService) _, err := content.Delete(context.Background(), "octocat/hello-world", "README", "master") diff --git a/scm/driver/gitlab/testdata/content.json.golden b/scm/driver/gitlab/testdata/content.json.golden index c8e3a8c25..ede685526 100644 --- a/scm/driver/gitlab/testdata/content.json.golden +++ b/scm/driver/gitlab/testdata/content.json.golden @@ -1,5 +1,6 @@ { "Path": "app/models/key.rb", "Data": "cmVxdWlyZSAnZGlnZXN0L21kNScKCmNsYXNzIEtleSA8IEFjdGl2ZVJlY29yZDo6QmFzZQogIGluY2x1ZGUgR2l0bGFiOjpDdXJyZW50U2V0dGluZ3MKICBpbmNsdWRlIFNvcnRhYmxlCgogIGJlbG9uZ3NfdG8gOnVzZXIKCiAgYmVmb3JlX3ZhbGlkYXRpb24gOmdlbmVyYXRlX2ZpbmdlcnByaW50CgogIHZhbGlkYXRlcyA6dGl0bGUsCiAgICBwcmVzZW5jZTogdHJ1ZSwKICAgIGxlbmd0aDogeyBtYXhpbXVtOiAyNTUgfQoKICB2YWxpZGF0ZXMgOmtleSwKICAgIHByZXNlbmNlOiB0cnVlLAogICAgbGVuZ3RoOiB7IG1heGltdW06IDUwMDAgfSwKICAgIGZvcm1hdDogeyB3aXRoOiAvXEEoc3NofGVjZHNhKS0uKlxaLyB9CgogIHZhbGlkYXRlcyA6ZmluZ2VycHJpbnQsCiAgICB1bmlxdWVuZXNzOiB0cnVlLAogICAgcHJlc2VuY2U6IHsgbWVzc2FnZTogJ2Nhbm5vdCBiZSBnZW5lcmF0ZWQnIH0KCiAgdmFsaWRhdGUgOmtleV9tZWV0c19yZXN0cmljdGlvbnMKCiAgZGVsZWdhdGUgOm5hbWUsIDplbWFpbCwgdG86IDp1c2VyLCBwcmVmaXg6IHRydWUKCiAgYWZ0ZXJfY29tbWl0IDphZGRfdG9fc2hlbGwsIG9uOiA6Y3JlYXRlCiAgYWZ0ZXJfY3JlYXRlIDpwb3N0X2NyZWF0ZV9ob29rCiAgYWZ0ZXJfY3JlYXRlIDpyZWZyZXNoX3VzZXJfY2FjaGUKICBhZnRlcl9jb21taXQgOnJlbW92ZV9mcm9tX3NoZWxsLCBvbjogOmRlc3Ryb3kKICBhZnRlcl9kZXN0cm95IDpwb3N0X2Rlc3Ryb3lfaG9vawogIGFmdGVyX2Rlc3Ryb3kgOnJlZnJlc2hfdXNlcl9jYWNoZQoKICBkZWYga2V5PSh2YWx1ZSkKICAgIHZhbHVlJi5kZWxldGUhKCJcblxyIikKICAgIHZhbHVlLnN0cmlwISB1bmxlc3MgdmFsdWUuYmxhbms=", - "Hash": "79f7bbd25901e8334750839545a9bd021f0e4c83" + "Sha": "d5a3ff139356ce33e37e73add446f16869741b50", + "BlobID": "79f7bbd25901e8334750839545a9bd021f0e4c83" } \ No newline at end of file diff --git a/scm/driver/gitlab/testdata/content_list.json b/scm/driver/gitlab/testdata/content_list.json index 333176ee6..7a4d1b60b 100644 --- a/scm/driver/gitlab/testdata/content_list.json +++ b/scm/driver/gitlab/testdata/content_list.json @@ -1 +1,142 @@ -[{"id":"ff85b01e96cca1db128a3ea0b3643667f50e464f","name":"ansi2json","type":"tree","path":"lib/gitlab/ci/ansi2json","mode":"040000"},{"id":"b044e0902a1d468d0e59ca733da6c22c4710af20","name":"build","type":"tree","path":"lib/gitlab/ci/build","mode":"040000"},{"id":"80cecd7647164c63768f52b431509d04d7f7dcf6","name":"config","type":"tree","path":"lib/gitlab/ci/config","mode":"040000"},{"id":"1d53ca741903e40610728c07b637da21fbf9f394","name":"parsers","type":"tree","path":"lib/gitlab/ci/parsers","mode":"040000"},{"id":"1a8b0f4be2707c3d7bdede2865c4a2c8a4af99a9","name":"pipeline","type":"tree","path":"lib/gitlab/ci/pipeline","mode":"040000"},{"id":"42afb52861c8f807f6ccf95e98607638b6d30f22","name":"reports","type":"tree","path":"lib/gitlab/ci/reports","mode":"040000"},{"id":"1cf9d5d945923d8a3f820b5b39aa65431b271375","name":"status","type":"tree","path":"lib/gitlab/ci/status","mode":"040000"},{"id":"f02f0b133c976074cec2b3babc88966f2ef32374","name":"templates","type":"tree","path":"lib/gitlab/ci/templates","mode":"040000"},{"id":"f2f31cbc4e89da99530cd30d7fc5f4d989d05b90","name":"trace","type":"tree","path":"lib/gitlab/ci/trace","mode":"040000"},{"id":"8d06f84b4a11604dacb1e37eb3c99094f2bccbd8","name":"variables","type":"tree","path":"lib/gitlab/ci/variables","mode":"040000"},{"id":"eb5d78ebcd41aee923ad02c8fe4b340d87254d59","name":"ansi2html.rb","type":"blob","path":"lib/gitlab/ci/ansi2html.rb","mode":"100644"},{"id":"79114d35916cc46aff83b225c3fcef3e47fe0719","name":"ansi2json.rb","type":"blob","path":"lib/gitlab/ci/ansi2json.rb","mode":"100644"},{"id":"3fbfdffe277f296e8f116f078e80adbe072a158b","name":"charts.rb","type":"blob","path":"lib/gitlab/ci/charts.rb","mode":"100644"},{"id":"9c1e6277e95ee74775a45cadd3628bc05e777660","name":"config.rb","type":"blob","path":"lib/gitlab/ci/config.rb","mode":"100644"},{"id":"1d7e7ea0f9af2839512d89488f4873f0edd4a6dc","name":"cron_parser.rb","type":"blob","path":"lib/gitlab/ci/cron_parser.rb","mode":"100644"},{"id":"58d55b1bd6f394aeff2cb579efa48970b52f095b","name":"mask_secret.rb","type":"blob","path":"lib/gitlab/ci/mask_secret.rb","mode":"100644"},{"id":"1625cb841b694deea23c816761e09b4337affc03","name":"model.rb","type":"blob","path":"lib/gitlab/ci/model.rb","mode":"100644"},{"id":"c76cd5ff28512ed90616be13d9e776b83124eab2","name":"parsers.rb","type":"blob","path":"lib/gitlab/ci/parsers.rb","mode":"100644"},{"id":"941f7178dacf36fce67fdfa538f1d8ef50e5d6da","name":"trace.rb","type":"blob","path":"lib/gitlab/ci/trace.rb","mode":"100644"},{"id":"f6a3abefcfb350d9ff69560a579b3c9473612a8b","name":"yaml_processor.rb","type":"blob","path":"lib/gitlab/ci/yaml_processor.rb","mode":"100644"}] \ No newline at end of file +[ + { + "id": "ff85b01e96cca1db128a3ea0b3643667f50e464f", + "name": "ansi2json", + "type": "tree", + "path": "lib/gitlab/ci/ansi2json", + "mode": "040000" + }, + { + "id": "b044e0902a1d468d0e59ca733da6c22c4710af20", + "name": "build", + "type": "tree", + "path": "lib/gitlab/ci/build", + "mode": "040000" + }, + { + "id": "80cecd7647164c63768f52b431509d04d7f7dcf6", + "name": "config", + "type": "tree", + "path": "lib/gitlab/ci/config", + "mode": "040000" + }, + { + "id": "1d53ca741903e40610728c07b637da21fbf9f394", + "name": "parsers", + "type": "tree", + "path": "lib/gitlab/ci/parsers", + "mode": "040000" + }, + { + "id": "1a8b0f4be2707c3d7bdede2865c4a2c8a4af99a9", + "name": "pipeline", + "type": "tree", + "path": "lib/gitlab/ci/pipeline", + "mode": "040000" + }, + { + "id": "42afb52861c8f807f6ccf95e98607638b6d30f22", + "name": "reports", + "type": "tree", + "path": "lib/gitlab/ci/reports", + "mode": "040000" + }, + { + "id": "1cf9d5d945923d8a3f820b5b39aa65431b271375", + "name": "status", + "type": "tree", + "path": "lib/gitlab/ci/status", + "mode": "040000" + }, + { + "id": "f02f0b133c976074cec2b3babc88966f2ef32374", + "name": "templates", + "type": "tree", + "path": "lib/gitlab/ci/templates", + "mode": "040000" + }, + { + "id": "f2f31cbc4e89da99530cd30d7fc5f4d989d05b90", + "name": "trace", + "type": "tree", + "path": "lib/gitlab/ci/trace", + "mode": "040000" + }, + { + "id": "8d06f84b4a11604dacb1e37eb3c99094f2bccbd8", + "name": "variables", + "type": "tree", + "path": "lib/gitlab/ci/variables", + "mode": "040000" + }, + { + "id": "eb5d78ebcd41aee923ad02c8fe4b340d87254d59", + "name": "ansi2html.rb", + "type": "blob", + "path": "lib/gitlab/ci/ansi2html.rb", + "mode": "100644" + }, + { + "id": "79114d35916cc46aff83b225c3fcef3e47fe0719", + "name": "ansi2json.rb", + "type": "blob", + "path": "lib/gitlab/ci/ansi2json.rb", + "mode": "100644" + }, + { + "id": "3fbfdffe277f296e8f116f078e80adbe072a158b", + "name": "charts.rb", + "type": "blob", + "path": "lib/gitlab/ci/charts.rb", + "mode": "100644" + }, + { + "id": "9c1e6277e95ee74775a45cadd3628bc05e777660", + "name": "config.rb", + "type": "blob", + "path": "lib/gitlab/ci/config.rb", + "mode": "100644" + }, + { + "id": "1d7e7ea0f9af2839512d89488f4873f0edd4a6dc", + "name": "cron_parser.rb", + "type": "blob", + "path": "lib/gitlab/ci/cron_parser.rb", + "mode": "100644" + }, + { + "id": "58d55b1bd6f394aeff2cb579efa48970b52f095b", + "name": "mask_secret.rb", + "type": "blob", + "path": "lib/gitlab/ci/mask_secret.rb", + "mode": "100644" + }, + { + "id": "1625cb841b694deea23c816761e09b4337affc03", + "name": "model.rb", + "type": "blob", + "path": "lib/gitlab/ci/model.rb", + "mode": "100644" + }, + { + "id": "c76cd5ff28512ed90616be13d9e776b83124eab2", + "name": "parsers.rb", + "type": "blob", + "path": "lib/gitlab/ci/parsers.rb", + "mode": "100644" + }, + { + "id": "941f7178dacf36fce67fdfa538f1d8ef50e5d6da", + "name": "trace.rb", + "type": "blob", + "path": "lib/gitlab/ci/trace.rb", + "mode": "100644" + }, + { + "id": "f6a3abefcfb350d9ff69560a579b3c9473612a8b", + "name": "yaml_processor.rb", + "type": "blob", + "path": "lib/gitlab/ci/yaml_processor.rb", + "mode": "100644" + } +] \ No newline at end of file diff --git a/scm/driver/gitlab/testdata/content_update.json.fail b/scm/driver/gitlab/testdata/content_update.json.fail new file mode 100644 index 000000000..a92bd370f --- /dev/null +++ b/scm/driver/gitlab/testdata/content_update.json.fail @@ -0,0 +1,3 @@ +{ + "message": "You are attempting to update a file that has changed since you started editing it." +} \ No newline at end of file diff --git a/scm/pr.go b/scm/pr.go index 12b9cb918..8c049e93e 100644 --- a/scm/pr.go +++ b/scm/pr.go @@ -55,7 +55,8 @@ type ( Added bool Renamed bool Deleted bool - Hash string + Sha string + BlobID string } Label struct { From 06b198c30e1157563f87a2d6f359c062c84d7964 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Wed, 7 Apr 2021 10:08:43 +0100 Subject: [PATCH 012/282] Update changelog for 1.11.0 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08283ef86..c0d9139c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.11.0 +### Added +- normalise sha in content, add bitbucket create/update, from [@tphoney](https://github.com/tphoney). See [#101](https://github.com/drone/go-scm/pull/101). + ## 1.10.0 ### Added - return hash/object_id for files changed in github, from [@tphoney](https://github.com/tphoney). See [#99](https://github.com/drone/go-scm/pull/99). From 2ef64416d9574ff74f42011fb57704ecb77a23c5 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Thu, 8 Apr 2021 16:51:32 +0100 Subject: [PATCH 013/282] (feat) return sha/blob_id for content.list --- scm/content.go | 6 +- scm/driver/bitbucket/content.go | 12 ++- .../testdata/content_list.json.golden | 30 ++++--- scm/driver/github/content.go | 4 +- .../github/testdata/content_list.json.golden | 78 ++++++++++++------- 5 files changed, 88 insertions(+), 42 deletions(-) diff --git a/scm/content.go b/scm/content.go index ffa2966e6..ce2cef31d 100644 --- a/scm/content.go +++ b/scm/content.go @@ -29,8 +29,10 @@ type ( // ContentInfo stores the kind of any content in a repository. ContentInfo struct { - Path string - Kind ContentKind + Path string + Sha string + BlobID string + Kind ContentKind } // ContentService provides access to repositroy content. diff --git a/scm/driver/bitbucket/content.go b/scm/driver/bitbucket/content.go index aa7194f48..8dac19c64 100644 --- a/scm/driver/bitbucket/content.go +++ b/scm/driver/bitbucket/content.go @@ -85,8 +85,11 @@ type contents struct { } type content struct { - Path string `json:"path"` - Type string `json:"type"` + Path string `json:"path"` + Type string `json:"type"` + Commit struct { + Hash string `json:"hash"` + } `json:"commit"` Attributes []string `json:"attributes"` } @@ -115,7 +118,10 @@ func convertContentInfoList(from *contents) []*scm.ContentInfo { } func convertContentInfo(from *content) *scm.ContentInfo { - to := &scm.ContentInfo{Path: from.Path} + to := &scm.ContentInfo{ + Path: from.Path, + Sha: from.Commit.Hash, + } switch from.Type { case "commit_file": to.Kind = func() scm.ContentKind { diff --git a/scm/driver/bitbucket/testdata/content_list.json.golden b/scm/driver/bitbucket/testdata/content_list.json.golden index c0dc728b1..6ec39c44e 100644 --- a/scm/driver/bitbucket/testdata/content_list.json.golden +++ b/scm/driver/bitbucket/testdata/content_list.json.golden @@ -1,42 +1,52 @@ [ { "path": "packages/activity/build", - "kind": "directory" + "kind": "directory", + "Sha": "710db794f15bd187db9e7a7b952aac48ebac08bb" }, { "path": "packages/activity/dist", - "kind": "directory" + "kind": "directory", + "Sha": "710db794f15bd187db9e7a7b952aac48ebac08bb" }, { "path": "packages/activity/docs", - "kind": "directory" + "kind": "directory", + "Sha": "710db794f15bd187db9e7a7b952aac48ebac08bb" }, { "path": "packages/activity/src", - "kind": "directory" + "kind": "directory", + "Sha": "710db794f15bd187db9e7a7b952aac48ebac08bb" }, { "path": "packages/activity/test", - "kind": "directory" + "kind": "directory", + "Sha": "710db794f15bd187db9e7a7b952aac48ebac08bb" }, { "path": "packages/activity/.npmignore", - "kind": "file" + "kind": "file", + "Sha": "710db794f15bd187db9e7a7b952aac48ebac08bb" }, { "path": "packages/activity/LICENSE", - "kind": "file" + "kind": "file", + "Sha": "710db794f15bd187db9e7a7b952aac48ebac08bb" }, { "path": "packages/activity/index.ts", - "kind": "file" + "kind": "file", + "Sha": "710db794f15bd187db9e7a7b952aac48ebac08bb" }, { "path": "packages/activity/package.json", - "kind": "file" + "kind": "file", + "Sha": "710db794f15bd187db9e7a7b952aac48ebac08bb" }, { "path": "packages/activity/package.json.d.ts", - "kind": "file" + "kind": "file", + "Sha": "710db794f15bd187db9e7a7b952aac48ebac08bb" } ] diff --git a/scm/driver/github/content.go b/scm/driver/github/content.go index b292befed..58fc17698 100644 --- a/scm/driver/github/content.go +++ b/scm/driver/github/content.go @@ -112,7 +112,9 @@ func convertContentInfoList(from []*content) []*scm.ContentInfo { } func convertContentInfo(from *content) *scm.ContentInfo { - to := &scm.ContentInfo{Path: from.Path} + to := &scm.ContentInfo{ + Path: from.Path, + BlobID: from.Sha} switch from.Type { case "file": to.Kind = scm.ContentKindFile diff --git a/scm/driver/github/testdata/content_list.json.golden b/scm/driver/github/testdata/content_list.json.golden index 1ecb4b434..3843e16eb 100644 --- a/scm/driver/github/testdata/content_list.json.golden +++ b/scm/driver/github/testdata/content_list.json.golden @@ -1,106 +1,132 @@ [ { "path": "scm/driver/github/content.go", - "kind": "file" + "kind": "file", + "BlobID": "6049c0a9f0859fe56344559006f739a3a81475fb" }, { "path": "scm/driver/github/content_test.go", - "kind": "file" + "kind": "file", + "BlobID": "bec0acdbdf9b5be391a749f13aa6ea223f7f6b2e" }, { "path": "scm/driver/github/git.go", - "kind": "file" + "kind": "file", + "BlobID": "fb07733ece5525869d630df704a76ab29dde227c" }, { "path": "scm/driver/github/git_test.go", - "kind": "file" + "kind": "file", + "BlobID": "4bc40050b43314f637c10b767c53c3d548fd359a" }, { "path": "scm/driver/github/github.go", - "kind": "file" + "kind": "file", + "BlobID": "82f31511232a18a949e8035aa2f346a90754a387" }, { "path": "scm/driver/github/github_test.go", - "kind": "file" + "kind": "file", + "BlobID": "8d82e48e410796f27cc92fcb5bd9ffbed154b6cb" }, { "path": "scm/driver/github/integration", - "kind": "directory" + "kind": "directory", + "BlobID": "f29b9ffe7db8788d4db88de3128015927297f3e1" }, { "path": "scm/driver/github/issue.go", - "kind": "file" + "kind": "file", + "BlobID": "b360d4a3b70f368d44734aebac3803de1f9e2bc4" }, { "path": "scm/driver/github/issue_test.go", - "kind": "file" + "kind": "file", + "BlobID": "d6ff16f2eedd1a34200071b97ee5fed0b10e8dad" }, { "path": "scm/driver/github/linker.go", - "kind": "file" + "kind": "file", + "BlobID": "92d8da78b2a0433c2df15392fd6211091280e037" }, { "path": "scm/driver/github/linker_test.go", - "kind": "file" + "kind": "file", + "BlobID": "b952f3e5a7ae77a0fa789f3ecfc5bfc46aede1ef" }, { "path": "scm/driver/github/org.go", - "kind": "file" + "kind": "file", + "BlobID": "9d4f534054ad4719c25e1551fa2d2bca949f7dc9" }, { "path": "scm/driver/github/org_test.go", - "kind": "file" + "kind": "file", + "BlobID": "b36c00d8e9042ad23f244cee678837cf752d30e9" }, { "path": "scm/driver/github/pr.go", - "kind": "file" + "kind": "file", + "BlobID": "a008cbe0473c1f4a4fd9b345c85326120ec4fc35" }, { "path": "scm/driver/github/pr_test.go", - "kind": "file" + "kind": "file", + "BlobID": "6ab42e0a467f593ab805a0ed2992c209ecbe4914" }, { "path": "scm/driver/github/repo.go", - "kind": "file" + "kind": "file", + "BlobID": "19eb345a307550d356a1d3f50fc56b48a363acf2" }, { "path": "scm/driver/github/repo_test.go", - "kind": "file" + "kind": "file", + "BlobID": "73880b97306f3e6b6ac9b410b3e10b45f0bede8c" }, { "path": "scm/driver/github/review.go", - "kind": "file" + "kind": "file", + "BlobID": "efb31fb34c89d564e4c7381a4cd5a2bf097d8c1b" }, { "path": "scm/driver/github/review_test.go", - "kind": "file" + "kind": "file", + "BlobID": "3aaf08ba51ffb1626a73ab8719e4d0d7d5b0ce5f" }, { "path": "scm/driver/github/testdata", - "kind": "directory" + "kind": "directory", + "BlobID": "2668c2a5e6a9c5cf4d66e72942e12d85527915b4" }, { "path": "scm/driver/github/user.go", - "kind": "file" + "kind": "file", + "BlobID": "4b04b38a805b833f6bd37166e4256a66722b879b" }, { "path": "scm/driver/github/user_test.go", - "kind": "file" + "kind": "file", + "BlobID": "86e5b709daeced102302fba8e46e48e9457adbd3" }, { "path": "scm/driver/github/util.go", - "kind": "file" + "kind": "file", + "BlobID": "a6b3c55a7a8924e53e94ee35e6839e5a0a78d724" }, { "path": "scm/driver/github/util_test.go", - "kind": "file" + "kind": "file", + "BlobID": "c6a2664339b965396a861fd224e3bb9733757444" }, { "path": "scm/driver/github/webhook.go", - "kind": "file" + "kind": "file", + "BlobID": "1789ca55651f7d7903fce3e985212b96592f8800" }, { "path": "scm/driver/github/webhook_test.go", - "kind": "file" + "kind": "file", + "BlobID": "136f2e0e55a4ed961af1b67d45d72fa84a68943a" } ] From 439c92bc86a7a0f9ce0d1b15461068d2edbc453b Mon Sep 17 00:00:00 2001 From: TP Honey Date: Fri, 9 Apr 2021 13:40:13 +0100 Subject: [PATCH 014/282] Update changelog for 1.12.0 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0d9139c5..7fdb4c949 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.12.0 +### Added +- return sha/blob_id for content.list, from [@tphoney](https://github.com/tphoney). See [#102](https://github.com/drone/go-scm/pull/102). + ## 1.11.0 ### Added - normalise sha in content, add bitbucket create/update, from [@tphoney](https://github.com/tphoney). See [#101](https://github.com/drone/go-scm/pull/101). From c98c8f5f634439714594cea5f585ae1874b3624e Mon Sep 17 00:00:00 2001 From: TP Honey Date: Mon, 12 Apr 2021 17:18:05 +0100 Subject: [PATCH 015/282] (feat) add create branch functionality --- scm/driver/bitbucket/git.go | 20 ++++ scm/driver/bitbucket/git_test.go | 25 +++++ .../bitbucket/testdata/branch_create.json | 103 ++++++++++++++++++ scm/driver/gitea/git.go | 4 + scm/driver/github/git.go | 14 +++ scm/driver/github/git_test.go | 32 ++++++ scm/driver/github/testdata/branch_create.json | 10 ++ scm/driver/gitlab/git.go | 14 +++ scm/driver/gitlab/git_test.go | 27 +++++ scm/driver/gitlab/testdata/branch_create.json | 27 +++++ scm/driver/gogs/git.go | 4 + scm/driver/stash/git.go | 4 + scm/git.go | 9 ++ 13 files changed, 293 insertions(+) create mode 100644 scm/driver/bitbucket/testdata/branch_create.json create mode 100644 scm/driver/github/testdata/branch_create.json create mode 100644 scm/driver/gitlab/testdata/branch_create.json diff --git a/scm/driver/bitbucket/git.go b/scm/driver/bitbucket/git.go index 79b6cae29..dcbc6c005 100644 --- a/scm/driver/bitbucket/git.go +++ b/scm/driver/bitbucket/git.go @@ -16,6 +16,17 @@ type gitService struct { client *wrapper } +func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.CreateBranch) (*scm.Response, error) { + path := fmt.Sprintf("2.0/repositories/%s/refs/branches", repo) + in := &createBranch{ + Name: params.Name, + Target: target{ + Hash: params.Sha, + }, + } + return s.client.do(ctx, "POST", path, in, nil) +} + func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { path := fmt.Sprintf("2.0/repositories/%s/refs/branches/%s", repo, name) out := new(branch) @@ -85,6 +96,15 @@ type branch struct { } `json:"target"` } +type createBranch struct { + Name string `json:"name"` + Target target `json:"target"` +} + +type target struct { + Hash string `json:"hash"` +} + type commits struct { pagination Values []*commit `json:"values"` diff --git a/scm/driver/bitbucket/git_test.go b/scm/driver/bitbucket/git_test.go index 7a15e8a83..8b305fa77 100644 --- a/scm/driver/bitbucket/git_test.go +++ b/scm/driver/bitbucket/git_test.go @@ -41,6 +41,31 @@ func TestGitFindCommit(t *testing.T) { } } +func TestGitCreateBranch(t *testing.T) { + defer gock.Off() + + gock.New("https://api.bitbucket.org"). + Post("/2.0/repositories/atlassian/stash-example-plugin/refs/branches"). + Reply(201). + Type("application/json"). + File("testdata/branch_create.json") + + params := &scm.CreateBranch{ + Name: "yooo", + Sha: "2e684d13a43afd86cb48ea36d9f40f43e791fae9", + } + client, _ := New("https://api.bitbucket.org") + res, err := client.Git.CreateBranch(context.Background(), "atlassian/stash-example-plugin", params) + + if err != nil { + t.Error(err) + return + } + + if res.Status != 201 { + t.Errorf("Unexpected Results") + } +} func TestGitFindBranch(t *testing.T) { defer gock.Off() diff --git a/scm/driver/bitbucket/testdata/branch_create.json b/scm/driver/bitbucket/testdata/branch_create.json new file mode 100644 index 000000000..ec47672a5 --- /dev/null +++ b/scm/driver/bitbucket/testdata/branch_create.json @@ -0,0 +1,103 @@ +{ + "name": "yooo", + "links": { + "commits": { + "href": "https://api.bitbucket.org/2.0/repositories/tphoney/scm-test/commits/yooo" + }, + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/tphoney/scm-test/refs/branches/yooo" + }, + "html": { + "href": "https://bitbucket.org/tphoney/scm-test/branch/yooo" + } + }, + "default_merge_strategy": "merge_commit", + "merge_strategies": [ + "merge_commit", + "squash", + "fast_forward" + ], + "type": "branch", + "target": { + "hash": "2e684d13a43afd86cb48ea36d9f40f43e791fae9", + "repository": { + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/tphoney/scm-test" + }, + "html": { + "href": "https://bitbucket.org/tphoney/scm-test" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7Bb918ca22-3472-4053-b234-c61deee57314%7D?ts=default" + } + }, + "type": "repository", + "name": "scm-test", + "full_name": "tphoney/scm-test", + "uuid": "{b918ca22-3472-4053-b234-c61deee57314}" + }, + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/tphoney/scm-test/commit/2e684d13a43afd86cb48ea36d9f40f43e791fae9" + }, + "comments": { + "href": "https://api.bitbucket.org/2.0/repositories/tphoney/scm-test/commit/2e684d13a43afd86cb48ea36d9f40f43e791fae9/comments" + }, + "patch": { + "href": "https://api.bitbucket.org/2.0/repositories/tphoney/scm-test/patch/2e684d13a43afd86cb48ea36d9f40f43e791fae9" + }, + "html": { + "href": "https://bitbucket.org/tphoney/scm-test/commits/2e684d13a43afd86cb48ea36d9f40f43e791fae9" + }, + "diff": { + "href": "https://api.bitbucket.org/2.0/repositories/tphoney/scm-test/diff/2e684d13a43afd86cb48ea36d9f40f43e791fae9" + }, + "approve": { + "href": "https://api.bitbucket.org/2.0/repositories/tphoney/scm-test/commit/2e684d13a43afd86cb48ea36d9f40f43e791fae9/approve" + }, + "statuses": { + "href": "https://api.bitbucket.org/2.0/repositories/tphoney/scm-test/commit/2e684d13a43afd86cb48ea36d9f40f43e791fae9/statuses" + } + }, + "author": { + "raw": "TP Honey ", + "type": "author", + "user": { + "display_name": "TP Honey", + "uuid": "{1d020398-429a-4fb3-9339-7e2096b1ecaf}", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B1d020398-429a-4fb3-9339-7e2096b1ecaf%7D" + }, + "html": { + "href": "https://bitbucket.org/%7B1d020398-429a-4fb3-9339-7e2096b1ecaf%7D/" + }, + "avatar": { + "href": "https://secure.gravatar.com/avatar/cb9ef853b678d8a34ce0734e57a24f2f?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FTH-3.png" + } + }, + "nickname": "thomas.honey", + "type": "user", + "account_id": "60259ce77db80e006a2e0935" + } + }, + "parents": [ + { + "hash": "ba88d4dd3c98b442a77588ff1e623a16f2656a63", + "type": "commit", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/tphoney/scm-test/commit/ba88d4dd3c98b442a77588ff1e623a16f2656a63" + }, + "html": { + "href": "https://bitbucket.org/tphoney/scm-test/commits/ba88d4dd3c98b442a77588ff1e623a16f2656a63" + } + } + } + ], + "date": "2021-04-01T10:38:26+00:00", + "message": "asdasd created online with Bitbucket", + "type": "commit" + } +} \ No newline at end of file diff --git a/scm/driver/gitea/git.go b/scm/driver/gitea/git.go index e1ea1651b..21d4c100d 100644 --- a/scm/driver/gitea/git.go +++ b/scm/driver/gitea/git.go @@ -17,6 +17,10 @@ type gitService struct { client *wrapper } +func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.CreateBranch) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { path := fmt.Sprintf("api/v1/repos/%s/branches/%s", repo, name) out := new(branch) diff --git a/scm/driver/github/git.go b/scm/driver/github/git.go index 79cd8b450..0ef94db44 100644 --- a/scm/driver/github/git.go +++ b/scm/driver/github/git.go @@ -16,6 +16,15 @@ type gitService struct { client *wrapper } +func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.CreateBranch) (*scm.Response, error) { + path := fmt.Sprintf("repos/%s/git/refs", repo) + in := &createBranch{ + Ref: scm.ExpandRef(params.Name, "refs/heads"), + Sha: params.Sha, + } + return s.client.do(ctx, "POST", path, in, nil) +} + func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { path := fmt.Sprintf("repos/%s/branches/%s", repo, name) out := new(branch) @@ -72,6 +81,11 @@ func (s *gitService) CompareChanges(ctx context.Context, repo, source, target st return convertChangeList(out.Files), res, err } +type createBranch struct { + Ref string `json:"ref"` + Sha string `json:"sha"` +} + type branch struct { Name string `json:"name"` Commit commit `json:"commit"` diff --git a/scm/driver/github/git_test.go b/scm/driver/github/git_test.go index 6e8a3707b..e708c67cd 100644 --- a/scm/driver/github/git_test.go +++ b/scm/driver/github/git_test.go @@ -106,6 +106,38 @@ func TestGitFindTag(t *testing.T) { t.Run("Rate", testRate(res)) } +func TestGitCreateBranch(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Post("/repos/octocat/hello-world/git/refs"). + Reply(201). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/branch_create.json") + + params := &scm.CreateBranch{ + Name: "Hello", + Sha: "312797ba52425353dec56871a255e2a36fc96344", + } + + client := NewDefault() + res, err := client.Git.CreateBranch( + context.Background(), + "octocat/hello-world", + params, + ) + + if err != nil { + t.Error(err) + return + } + + if res.Status != 201 { + t.Errorf("Unexpected Results") + } +} + func TestGitListCommits(t *testing.T) { defer gock.Off() diff --git a/scm/driver/github/testdata/branch_create.json b/scm/driver/github/testdata/branch_create.json new file mode 100644 index 000000000..90f12b96a --- /dev/null +++ b/scm/driver/github/testdata/branch_create.json @@ -0,0 +1,10 @@ +{ + "ref": "refs/heads/Hello", + "node_id": "MDM6UmVmMzQ0NDI5MDA5OnJlZnMvaGVhZHMvSGVsbG8=", + "url": "https://api.github.com/repos/tphoney/scm-test/git/refs/heads/Hello", + "object": { + "sha": "312797ba52425353dec56871a255e2a36fc96344", + "type": "commit", + "url": "https://api.github.com/repos/tphoney/scm-test/git/commits/312797ba52425353dec56871a255e2a36fc96344" + } +} \ No newline at end of file diff --git a/scm/driver/gitlab/git.go b/scm/driver/gitlab/git.go index 7b7e78d09..e9a1cffef 100644 --- a/scm/driver/gitlab/git.go +++ b/scm/driver/gitlab/git.go @@ -16,6 +16,15 @@ type gitService struct { client *wrapper } +func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.CreateBranch) (*scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/repository/branches", encode(repo)) + in := &createBranch{ + Branch: params.Name, + Ref: params.Sha, + } + return s.client.do(ctx, "POST", path, in, nil) +} + func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { path := fmt.Sprintf("api/v4/projects/%s/repository/branches/%s", encode(repo), name) out := new(branch) @@ -79,6 +88,11 @@ type branch struct { } } +type createBranch struct { + Branch string `json:"branch"` + Ref string `json:"ref"` +} + type commit struct { ID string `json:"id"` Title string `json:"title"` diff --git a/scm/driver/gitlab/git_test.go b/scm/driver/gitlab/git_test.go index dab63658b..6315b85b9 100644 --- a/scm/driver/gitlab/git_test.go +++ b/scm/driver/gitlab/git_test.go @@ -80,6 +80,33 @@ func TestGitFindBranch(t *testing.T) { t.Run("Rate", testRate(res)) } +func TestGitCreateBranch(t *testing.T) { + defer gock.Off() + + gock.New("https://gitlab.com"). + Post("/api/v4/projects/diaspora/diaspora/repository/branches"). + Reply(201). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/branch_create.json") + + params := &scm.CreateBranch{ + Name: "yooo", + Sha: "0efb1bed7c6a4871cb4ddb862ecc2111e11f31ee", + } + + client := NewDefault() + res, err := client.Git.CreateBranch(context.Background(), "diaspora/diaspora", params) + + if err != nil { + t.Error(err) + return + } + + if res.Status != 201 { + t.Errorf("Unexpected Results") + } +} func TestGitFindTag(t *testing.T) { defer gock.Off() diff --git a/scm/driver/gitlab/testdata/branch_create.json b/scm/driver/gitlab/testdata/branch_create.json new file mode 100644 index 000000000..2c82cc7a3 --- /dev/null +++ b/scm/driver/gitlab/testdata/branch_create.json @@ -0,0 +1,27 @@ +{ + "name": "yooo", + "commit": { + "id": "0efb1bed7c6a4871cb4ddb862ecc2111e11f31ee", + "short_id": "0efb1bed", + "created_at": "2021-04-07T08:16:54.000+00:00", + "parent_ids": [ + "4d8cf0b0d2a3f9dd54ec1f204a95f08a0f318199" + ], + "title": "message1", + "message": "message1", + "author_name": "tp honey", + "author_email": "tp@harness.io", + "authored_date": "2021-04-07T08:16:54.000+00:00", + "committer_name": "TP Honey", + "committer_email": "tp@harness.io", + "committed_date": "2021-04-07T08:16:54.000+00:00", + "web_url": "https://gitlab.com/tphoney/test_repo/-/commit/0efb1bed7c6a4871cb4ddb862ecc2111e11f31ee" + }, + "merged": true, + "protected": false, + "developers_can_push": false, + "developers_can_merge": false, + "can_push": true, + "default": false, + "web_url": "https://gitlab.com/tphoney/test_repo/-/tree/yooo" +} \ No newline at end of file diff --git a/scm/driver/gogs/git.go b/scm/driver/gogs/git.go index 3956547de..2cb3c687e 100644 --- a/scm/driver/gogs/git.go +++ b/scm/driver/gogs/git.go @@ -16,6 +16,10 @@ type gitService struct { client *wrapper } +func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.CreateBranch) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { path := fmt.Sprintf("api/v1/repos/%s/branches/%s", repo, name) out := new(branch) diff --git a/scm/driver/stash/git.go b/scm/driver/stash/git.go index bd896977a..eae5a9942 100644 --- a/scm/driver/stash/git.go +++ b/scm/driver/stash/git.go @@ -19,6 +19,10 @@ type gitService struct { client *wrapper } +func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.CreateBranch) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + func (s *gitService) FindBranch(ctx context.Context, repo, branch string) (*scm.Reference, *scm.Response, error) { namespace, name := scm.Split(repo) path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/branches?filterText=%s", namespace, name, branch) diff --git a/scm/git.go b/scm/git.go index a5bda8e1c..d775a4fe8 100644 --- a/scm/git.go +++ b/scm/git.go @@ -13,6 +13,12 @@ import ( const EmptyCommit = "0000000000000000000000000000000000000000" type ( + // CreateBranch provides a SHA for creating a branch. + CreateBranch struct { + Name string + Sha string + } + // Reference represents a git reference. Reference struct { Name string @@ -51,6 +57,9 @@ type ( // GitService provides access to git resources. GitService interface { + // CreateBranch creates a git branch by name given a sha. + CreateBranch(ctx context.Context, repo string, params *CreateBranch) (*Response, error) + // FindBranch finds a git branch by name. FindBranch(ctx context.Context, repo, name string) (*Reference, *Response, error) From be4dde17ebbcab1e6ed72c6258992c58ee57f270 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Wed, 14 Apr 2021 08:32:50 +0100 Subject: [PATCH 016/282] Update changelog for 1.13.0 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fdb4c949..465d56a30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.13.0 +### Added +- Create branch functionality, from [@tphoney](https://github.com/tphoney). See [#103](https://github.com/drone/go-scm/pull/103). + ## 1.12.0 ### Added - return sha/blob_id for content.list, from [@tphoney](https://github.com/tphoney). See [#102](https://github.com/drone/go-scm/pull/102). From 17f93ac2179be602f0c0247f2d8e90a82989a184 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Wed, 14 Apr 2021 12:30:01 +0100 Subject: [PATCH 017/282] (fix) gitlab, content.find return last_commit_id not commit_id --- scm/driver/gitlab/content.go | 2 +- scm/driver/gitlab/testdata/content.json.golden | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scm/driver/gitlab/content.go b/scm/driver/gitlab/content.go index d82e1a3b1..4c8fd8218 100644 --- a/scm/driver/gitlab/content.go +++ b/scm/driver/gitlab/content.go @@ -34,7 +34,7 @@ func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm return &scm.Content{ Path: out.FilePath, Data: raw, - Sha: out.CommitID, + Sha: out.LastCommitID, BlobID: out.BlobID, }, res, err } diff --git a/scm/driver/gitlab/testdata/content.json.golden b/scm/driver/gitlab/testdata/content.json.golden index ede685526..0d3df102b 100644 --- a/scm/driver/gitlab/testdata/content.json.golden +++ b/scm/driver/gitlab/testdata/content.json.golden @@ -1,6 +1,6 @@ { "Path": "app/models/key.rb", "Data": "cmVxdWlyZSAnZGlnZXN0L21kNScKCmNsYXNzIEtleSA8IEFjdGl2ZVJlY29yZDo6QmFzZQogIGluY2x1ZGUgR2l0bGFiOjpDdXJyZW50U2V0dGluZ3MKICBpbmNsdWRlIFNvcnRhYmxlCgogIGJlbG9uZ3NfdG8gOnVzZXIKCiAgYmVmb3JlX3ZhbGlkYXRpb24gOmdlbmVyYXRlX2ZpbmdlcnByaW50CgogIHZhbGlkYXRlcyA6dGl0bGUsCiAgICBwcmVzZW5jZTogdHJ1ZSwKICAgIGxlbmd0aDogeyBtYXhpbXVtOiAyNTUgfQoKICB2YWxpZGF0ZXMgOmtleSwKICAgIHByZXNlbmNlOiB0cnVlLAogICAgbGVuZ3RoOiB7IG1heGltdW06IDUwMDAgfSwKICAgIGZvcm1hdDogeyB3aXRoOiAvXEEoc3NofGVjZHNhKS0uKlxaLyB9CgogIHZhbGlkYXRlcyA6ZmluZ2VycHJpbnQsCiAgICB1bmlxdWVuZXNzOiB0cnVlLAogICAgcHJlc2VuY2U6IHsgbWVzc2FnZTogJ2Nhbm5vdCBiZSBnZW5lcmF0ZWQnIH0KCiAgdmFsaWRhdGUgOmtleV9tZWV0c19yZXN0cmljdGlvbnMKCiAgZGVsZWdhdGUgOm5hbWUsIDplbWFpbCwgdG86IDp1c2VyLCBwcmVmaXg6IHRydWUKCiAgYWZ0ZXJfY29tbWl0IDphZGRfdG9fc2hlbGwsIG9uOiA6Y3JlYXRlCiAgYWZ0ZXJfY3JlYXRlIDpwb3N0X2NyZWF0ZV9ob29rCiAgYWZ0ZXJfY3JlYXRlIDpyZWZyZXNoX3VzZXJfY2FjaGUKICBhZnRlcl9jb21taXQgOnJlbW92ZV9mcm9tX3NoZWxsLCBvbjogOmRlc3Ryb3kKICBhZnRlcl9kZXN0cm95IDpwb3N0X2Rlc3Ryb3lfaG9vawogIGFmdGVyX2Rlc3Ryb3kgOnJlZnJlc2hfdXNlcl9jYWNoZQoKICBkZWYga2V5PSh2YWx1ZSkKICAgIHZhbHVlJi5kZWxldGUhKCJcblxyIikKICAgIHZhbHVlLnN0cmlwISB1bmxlc3MgdmFsdWUuYmxhbms=", - "Sha": "d5a3ff139356ce33e37e73add446f16869741b50", + "Sha": "570e7b2abdd848b95f2f578043fc23bd6f6fd24d", "BlobID": "79f7bbd25901e8334750839545a9bd021f0e4c83" } \ No newline at end of file From 5aefd358cc7eac029eed7594d51ade36fe0403b9 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Thu, 15 Apr 2021 09:08:10 +0100 Subject: [PATCH 018/282] Update changelog for 1.13.1 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 465d56a30..a48688243 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.13.1 +### Fixed +- gitlab, content.find return last_commit_id not commit_id, from [@tphoney](https://github.com/tphoney). See [#104](https://github.com/drone/go-scm/pull/104). + ## 1.13.0 ### Added - Create branch functionality, from [@tphoney](https://github.com/tphoney). See [#103](https://github.com/drone/go-scm/pull/103). From 12ba5110872a7d2d52d6fdc5256646edc5adb55e Mon Sep 17 00:00:00 2001 From: Aleksandar Radisavljevic Date: Tue, 11 May 2021 12:36:31 +0200 Subject: [PATCH 019/282] Added ListCommits in pull request api --- go.mod | 2 +- go.sum | 3 +++ scm/driver/bitbucket/pr.go | 7 +++++++ scm/driver/gitea/pr.go | 4 ++++ scm/driver/github/pr.go | 7 +++++++ scm/driver/gitlab/pr.go | 7 +++++++ scm/driver/gogs/pr.go | 4 ++++ scm/driver/stash/pr.go | 12 ++++++++++++ scm/pr.go | 3 +++ 9 files changed, 48 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index cd3f85a78..3cf3b35ed 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/drone/go-scm require ( - github.com/google/go-cmp v0.2.0 + github.com/google/go-cmp v0.5.5 github.com/h2non/gock v1.0.9 ) diff --git a/go.sum b/go.sum index 7dbe62ae1..a97dec57d 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,7 @@ github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/h2non/gock v1.0.9 h1:17gCehSo8ZOgEsFKpQgqHiR7VLyjxdAG3lkhVvO9QZU= github.com/h2non/gock v1.0.9/go.mod h1:CZMcB0Lg5IWnr9bF79pPMg9WeV6WumxQiUJ1UvdO1iE= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/scm/driver/bitbucket/pr.go b/scm/driver/bitbucket/pr.go index 854fa0803..f00ed163c 100644 --- a/scm/driver/bitbucket/pr.go +++ b/scm/driver/bitbucket/pr.go @@ -39,6 +39,13 @@ func (s *pullService) ListChanges(ctx context.Context, repo string, number int, return convertDiffstats(out), res, err } +func (s *pullService) ListCommits(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Commit, *scm.Response, error) { + path := fmt.Sprintf("2.0/repositories/%s/pullrequests/%d/commits?%s", repo, number, encodeListOptions(opts)) + out := new(commits) + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertCommitList(out), res, err +} + func (s *pullService) Merge(ctx context.Context, repo string, number int) (*scm.Response, error) { path := fmt.Sprintf("2.0/repositories/%s/pullrequests/%d/merge", repo, number) res, err := s.client.do(ctx, "POST", path, nil, nil) diff --git a/scm/driver/gitea/pr.go b/scm/driver/gitea/pr.go index ab7fc4142..754f46240 100644 --- a/scm/driver/gitea/pr.go +++ b/scm/driver/gitea/pr.go @@ -38,6 +38,10 @@ func (s *pullService) ListComments(context.Context, string, int, scm.ListOptions return nil, nil, scm.ErrNotSupported } +func (s *pullService) ListCommits(context.Context, string, int, scm.ListOptions) ([]*scm.Commit, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + func (s *pullService) ListChanges(context.Context, string, int, scm.ListOptions) ([]*scm.Change, *scm.Response, error) { return nil, nil, scm.ErrNotSupported } diff --git a/scm/driver/github/pr.go b/scm/driver/github/pr.go index af332f00e..3b396ca82 100644 --- a/scm/driver/github/pr.go +++ b/scm/driver/github/pr.go @@ -38,6 +38,13 @@ func (s *pullService) ListChanges(ctx context.Context, repo string, number int, return convertChangeList(out), res, err } +func (s *pullService) ListCommits(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Commit, *scm.Response, error) { + path := fmt.Sprintf("/repos/%s/pulls/%dcommits?%s", repo, number, encodeListOptions(opts)) + out := []*commit{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertCommitList(out), res, err +} + func (s *pullService) Merge(ctx context.Context, repo string, number int) (*scm.Response, error) { path := fmt.Sprintf("repos/%s/pulls/%d/merge", repo, number) res, err := s.client.do(ctx, "PUT", path, nil, nil) diff --git a/scm/driver/gitlab/pr.go b/scm/driver/gitlab/pr.go index 9a6ca0d6e..aee0cffd7 100644 --- a/scm/driver/gitlab/pr.go +++ b/scm/driver/gitlab/pr.go @@ -52,6 +52,13 @@ func (s *pullService) ListComments(ctx context.Context, repo string, index int, return convertIssueCommentList(out), res, err } +func (s *pullService) ListCommits(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Commit, *scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/merge_requests/%d/commits%s", repo, number, encodeListOptions(opts)) + out := []*commit{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertCommitList(out), res, err +} + func (s *pullService) Create(ctx context.Context, repo string, input *scm.PullRequestInput) (*scm.PullRequest, *scm.Response, error) { in := url.Values{} in.Set("title", input.Title) diff --git a/scm/driver/gogs/pr.go b/scm/driver/gogs/pr.go index 1e851fdea..c2556ceb1 100644 --- a/scm/driver/gogs/pr.go +++ b/scm/driver/gogs/pr.go @@ -34,6 +34,10 @@ func (s *pullService) ListChanges(context.Context, string, int, scm.ListOptions) return nil, nil, scm.ErrNotSupported } +func (s *pullService) ListCommits(context.Context, string, int, scm.ListOptions) ([]*scm.Commit, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + func (s *pullService) Create(context.Context, string, *scm.PullRequestInput) (*scm.PullRequest, *scm.Response, error) { return nil, nil, scm.ErrNotSupported } diff --git a/scm/driver/stash/pr.go b/scm/driver/stash/pr.go index a404c7acc..061b27b3a 100644 --- a/scm/driver/stash/pr.go +++ b/scm/driver/stash/pr.go @@ -65,6 +65,18 @@ func (s *pullService) ListComments(context.Context, string, int, scm.ListOptions return nil, nil, scm.ErrNotSupported } +func (s *pullService) ListCommits(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Commit, *scm.Response, error) { + namespace, name := scm.Split(repo) + path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/pull-requests/%d/commits", namespace, name, number) + out := new(commits) + res, err := s.client.do(ctx, "GET", path, nil, out) + if !out.pagination.LastPage.Bool { + res.Page.First = 1 + res.Page.Next = opts.Page + 1 + } + return convertCommitList(out), res, err +} + func (s *pullService) Merge(ctx context.Context, repo string, number int) (*scm.Response, error) { namespace, name := scm.Split(repo) path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/pull-requests/%d/merge", namespace, name, number) diff --git a/scm/pr.go b/scm/pr.go index 8c049e93e..6f00a93c5 100644 --- a/scm/pr.go +++ b/scm/pr.go @@ -81,6 +81,9 @@ type ( // ListComments returns the pull request comment list. ListComments(context.Context, string, int, ListOptions) ([]*Comment, *Response, error) + // ListComments returns the pull request commit list. + ListCommits(context.Context, string, int, ListOptions) ([]*Commit, *Response, error) + // Merge merges the repository pull request. Merge(context.Context, string, int) (*Response, error) From 6cab798d501c435795f74e7d3b43b39d1d21719a Mon Sep 17 00:00:00 2001 From: Aleksandar Radisavljevic Date: Tue, 11 May 2021 13:50:35 +0200 Subject: [PATCH 020/282] added unittests --- go.mod | 2 +- go.sum | 3 --- scm/driver/bitbucket/pr_test.go | 26 ++++++++++++++++++++++++++ scm/driver/gitea/pr_test.go | 8 ++++++++ scm/driver/github/pr.go | 2 +- scm/driver/github/pr_test.go | 32 ++++++++++++++++++++++++++++++++ scm/driver/gitlab/pr.go | 2 +- scm/driver/gitlab/pr_test.go | 29 +++++++++++++++++++++++++++++ scm/driver/gogs/pr_test.go | 8 ++++++++ scm/driver/stash/pr_test.go | 25 +++++++++++++++++++++++++ 10 files changed, 131 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 3cf3b35ed..cd3f85a78 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/drone/go-scm require ( - github.com/google/go-cmp v0.5.5 + github.com/google/go-cmp v0.2.0 github.com/h2non/gock v1.0.9 ) diff --git a/go.sum b/go.sum index a97dec57d..7dbe62ae1 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,4 @@ github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/h2non/gock v1.0.9 h1:17gCehSo8ZOgEsFKpQgqHiR7VLyjxdAG3lkhVvO9QZU= github.com/h2non/gock v1.0.9/go.mod h1:CZMcB0Lg5IWnr9bF79pPMg9WeV6WumxQiUJ1UvdO1iE= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/scm/driver/bitbucket/pr_test.go b/scm/driver/bitbucket/pr_test.go index 90d8648d6..00f112f75 100644 --- a/scm/driver/bitbucket/pr_test.go +++ b/scm/driver/bitbucket/pr_test.go @@ -149,3 +149,29 @@ func TestPullCreate(t *testing.T) { t.Log(diff) } } +func TestPullListCommits(t *testing.T) { + defer gock.Off() + + gock.New("https://api.bitbucket.org"). + Get("/2.0/repositories/atlassian/atlaskit/pullrequests/1/commits"). + MatchParam("pagelen", "30"). + MatchParam("page", "1"). + Reply(200). + Type("application/json"). + File("testdata/commits.json") + + client, _ := New("https://api.bitbucket.org") + got, _, err := client.PullRequests.ListCommits(context.Background(), "atlassian/atlaskit", 1, scm.ListOptions{Size: 30, Page: 1}) + if err != nil { + t.Error(err) + } + + want := []*scm.Commit{} + raw, _ := ioutil.ReadFile("testdata/commits.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} diff --git a/scm/driver/gitea/pr_test.go b/scm/driver/gitea/pr_test.go index 6bff3bb3c..fc2d88e97 100644 --- a/scm/driver/gitea/pr_test.go +++ b/scm/driver/gitea/pr_test.go @@ -171,3 +171,11 @@ func TestPullRequestCommentDelete(t *testing.T) { t.Errorf("Expect Not Supported error") } } + +func TestPullListCommits(t *testing.T) { + client, _ := New("https://try.gitea.io") + _, _, err := client.PullRequests.ListCommits(context.Background(), "go-gitea/gitea", 1, scm.ListOptions{}) + if err != scm.ErrNotSupported { + t.Errorf("Expect Not Supported error") + } +} diff --git a/scm/driver/github/pr.go b/scm/driver/github/pr.go index 3b396ca82..749d73585 100644 --- a/scm/driver/github/pr.go +++ b/scm/driver/github/pr.go @@ -39,7 +39,7 @@ func (s *pullService) ListChanges(ctx context.Context, repo string, number int, } func (s *pullService) ListCommits(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Commit, *scm.Response, error) { - path := fmt.Sprintf("/repos/%s/pulls/%dcommits?%s", repo, number, encodeListOptions(opts)) + path := fmt.Sprintf("/repos/%s/pulls/%d/commits?%s", repo, number, encodeListOptions(opts)) out := []*commit{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertCommitList(out), res, err diff --git a/scm/driver/github/pr_test.go b/scm/driver/github/pr_test.go index e239fc3b1..9bf7b5337 100644 --- a/scm/driver/github/pr_test.go +++ b/scm/driver/github/pr_test.go @@ -189,3 +189,35 @@ func TestPullCreate(t *testing.T) { t.Run("Request", testRequest(res)) t.Run("rate", testRate(res)) } + +func TestPullListCommits(t *testing.T) { + gock.New("https://api.github.com"). + Get("/repos/octocat/hello-world/pulls/1347/commits"). + MatchParam("page", "1"). + MatchParam("per_page", "30"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + SetHeaders(mockPageHeaders). + File("testdata/commits.json") + + client := NewDefault() + got, res, err := client.PullRequests.ListCommits(context.Background(), "octocat/hello-world", 1347, scm.ListOptions{Page: 1, Size: 30}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Commit{} + raw, _ := ioutil.ReadFile("testdata/commits.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) + t.Run("Page", testPage(res)) +} diff --git a/scm/driver/gitlab/pr.go b/scm/driver/gitlab/pr.go index aee0cffd7..0d942188c 100644 --- a/scm/driver/gitlab/pr.go +++ b/scm/driver/gitlab/pr.go @@ -53,7 +53,7 @@ func (s *pullService) ListComments(ctx context.Context, repo string, index int, } func (s *pullService) ListCommits(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Commit, *scm.Response, error) { - path := fmt.Sprintf("api/v4/projects/%s/merge_requests/%d/commits%s", repo, number, encodeListOptions(opts)) + path := fmt.Sprintf("api/v4/projects/%s/merge_requests/%d/commits?%s", repo, number, encodeListOptions(opts)) out := []*commit{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertCommitList(out), res, err diff --git a/scm/driver/gitlab/pr_test.go b/scm/driver/gitlab/pr_test.go index 032e9a382..fe35f1e8d 100644 --- a/scm/driver/gitlab/pr_test.go +++ b/scm/driver/gitlab/pr_test.go @@ -309,3 +309,32 @@ func TestPullCommentDelete(t *testing.T) { t.Run("Request", testRequest(res)) t.Run("Rate", testRate(res)) } + +func TestPullListCommits(t *testing.T) { + gock.New("https://gitlab.com"). + Get("/api/v4/projects/diaspora/diaspora/merge_requests/1347/commits"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + SetHeaders(mockPageHeaders). + File("testdata/commits.json") + + client := NewDefault() + got, res, err := client.PullRequests.ListCommits(context.Background(), "diaspora/diaspora", 1347, scm.ListOptions{Page: 1, Size: 30}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Commit{} + raw, _ := ioutil.ReadFile("testdata/commits.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} diff --git a/scm/driver/gogs/pr_test.go b/scm/driver/gogs/pr_test.go index 3495ae165..88a4ae0a3 100644 --- a/scm/driver/gogs/pr_test.go +++ b/scm/driver/gogs/pr_test.go @@ -102,3 +102,11 @@ func TestPullRequestCommentDelete(t *testing.T) { t.Errorf("Expect Not Supported error") } } + +func TestPullRequestCommits(t *testing.T) { + client, _ := New("https://try.gogs.io") + _, _, err := client.PullRequests.ListCommits(context.Background(), "gogits/gogs", 1, scm.ListOptions{}) + if err != scm.ErrNotSupported { + t.Errorf("Expect Not Supported error") + } +} diff --git a/scm/driver/stash/pr_test.go b/scm/driver/stash/pr_test.go index b9695485e..4ed8d5932 100644 --- a/scm/driver/stash/pr_test.go +++ b/scm/driver/stash/pr_test.go @@ -208,3 +208,28 @@ func TestPullCreateComment(t *testing.T) { t.Log(diff) } } + +func TestPullListCommits(t *testing.T) { + defer gock.Off() + + gock.New("http://example.com:7990"). + Get("rest/api/1.0/projects/PRJ/repos/my-repo/pull-requests/1/commits"). + Reply(200). + Type("application/json"). + File("testdata/commits.json") + + client, _ := New("http://example.com:7990") + got, _, err := client.PullRequests.ListCommits(context.Background(), "PRJ/my-repo", 1, scm.ListOptions{Size: 30, Page: 1}) + if err != nil { + t.Error(err) + } + + want := []*scm.Commit{} + raw, _ := ioutil.ReadFile("testdata/commits.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} From 0b8c844ca356957e5c815e48b56b475759e0f111 Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Tue, 11 May 2021 12:54:15 -0400 Subject: [PATCH 021/282] Fix ListCommits typo --- scm/pr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/pr.go b/scm/pr.go index 6f00a93c5..c2902baea 100644 --- a/scm/pr.go +++ b/scm/pr.go @@ -81,7 +81,7 @@ type ( // ListComments returns the pull request comment list. ListComments(context.Context, string, int, ListOptions) ([]*Comment, *Response, error) - // ListComments returns the pull request commit list. + // ListCommits returns the pull request commit list. ListCommits(context.Context, string, int, ListOptions) ([]*Commit, *Response, error) // Merge merges the repository pull request. From a9bd38606b23c4aaec15a3d13faa9ae2c48e4208 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Wed, 12 May 2021 12:21:50 +0100 Subject: [PATCH 022/282] Update changelog for 1.14.0 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a48688243..9ee6b4f68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.14.0 +### Added +- Added ListCommits in pull request api, from [@aradisavljevic](https://github.com/aradisavljevic). See [#106](https://github.com/drone/go-scm/pull/106). + ## 1.13.1 ### Fixed - gitlab, content.find return last_commit_id not commit_id, from [@tphoney](https://github.com/tphoney). See [#104](https://github.com/drone/go-scm/pull/104). From 369b89ee15a01d36daac15455333651926cc9718 Mon Sep 17 00:00:00 2001 From: Troy Sornson Date: Sat, 15 May 2021 10:33:49 -0600 Subject: [PATCH 023/282] Fixing Gitea commit API in case `ref/heads/` prefix is added to ref --- scm/driver/gitea/git.go | 1 + 1 file changed, 1 insertion(+) diff --git a/scm/driver/gitea/git.go b/scm/driver/gitea/git.go index 21d4c100d..8382b8cad 100644 --- a/scm/driver/gitea/git.go +++ b/scm/driver/gitea/git.go @@ -29,6 +29,7 @@ func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Re } func (s *gitService) FindCommit(ctx context.Context, repo, ref string) (*scm.Commit, *scm.Response, error) { + ref = scm.TrimRef(ref) path := fmt.Sprintf("api/v1/repos/%s/git/commits/%s", repo, url.PathEscape(ref)) out := new(commitInfo) res, err := s.client.do(ctx, "GET", path, nil, out) From 47199438ca5f6faab00863a215e2338948142786 Mon Sep 17 00:00:00 2001 From: Aleksandar Radisavljevic Date: Tue, 18 May 2021 22:18:52 +0200 Subject: [PATCH 024/282] fix gitlab repo encoding in commits from pr request --- scm/driver/gitlab/integration/pr_test.go | 46 ++++++++++++++++++++++++ scm/driver/gitlab/pr.go | 2 +- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/scm/driver/gitlab/integration/pr_test.go b/scm/driver/gitlab/integration/pr_test.go index c11623066..64c64d05b 100644 --- a/scm/driver/gitlab/integration/pr_test.go +++ b/scm/driver/gitlab/integration/pr_test.go @@ -22,6 +22,7 @@ func testPullRequests(client *scm.Client) func(t *testing.T) { t.Run("Find", testPullRequestFind(client)) t.Run("Changes", testPullRequestChanges(client)) t.Run("Comments", testPullRequestComments(client)) + t.Run("Commits", testPullRequestCommitList(client)) } } @@ -120,6 +121,22 @@ func testPullRequestChanges(client *scm.Client) func(t *testing.T) { } } +func testPullRequestCommitList(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + opts := scm.ListOptions{} + result, _, err := client.PullRequests.ListCommits(context.Background(), "gitlab-org/testme", 1, opts) + if err != nil { + t.Error(err) + } + if len(result) == 0 { + t.Errorf("Got empty pull request commit list") + return + } + t.Run("Commit", testPullRequestCommit(result[0])) + } +} + // // struct sub-tests // @@ -216,3 +233,32 @@ func testChange(change *scm.Change) func(t *testing.T) { } } } + +func testPullRequestCommit(commit *scm.Commit) func(t *testing.T) { + return func(t *testing.T) { + if got, want := commit.Message, "JS fix\n\nSigned-off-by: Dmitriy Zaporozhets \n"; got != want { + t.Errorf("Want commit Message %q, got %q", want, got) + } + if got, want := commit.Sha, "12d65c8dd2b2676fa3ac47d955accc085a37a9c1"; got != want { + t.Errorf("Want commit Sha %q, got %q", want, got) + } + if got, want := commit.Author.Name, "Dmitriy Zaporozhets"; got != want { + t.Errorf("Want commit author Name %q, got %q", want, got) + } + if got, want := commit.Author.Email, "dmitriy.zaporozhets@gmail.com"; got != want { + t.Errorf("Want commit author Email %q, got %q", want, got) + } + if got, want := commit.Author.Date.Unix(), int64(1393489620); got != want { + t.Errorf("Want commit author Date %d, got %d", want, got) + } + if got, want := commit.Committer.Name, "Dmitriy Zaporozhets"; got != want { + t.Errorf("Want commit author Name %q, got %q", want, got) + } + if got, want := commit.Committer.Email, "dmitriy.zaporozhets@gmail.com"; got != want { + t.Errorf("Want commit author Email %q, got %q", want, got) + } + if got, want := commit.Committer.Date.Unix(), int64(1393489620); got != want { + t.Errorf("Want commit author Date %d, got %d", want, got) + } + } +} diff --git a/scm/driver/gitlab/pr.go b/scm/driver/gitlab/pr.go index 0d942188c..b82951d4c 100644 --- a/scm/driver/gitlab/pr.go +++ b/scm/driver/gitlab/pr.go @@ -53,7 +53,7 @@ func (s *pullService) ListComments(ctx context.Context, repo string, index int, } func (s *pullService) ListCommits(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Commit, *scm.Response, error) { - path := fmt.Sprintf("api/v4/projects/%s/merge_requests/%d/commits?%s", repo, number, encodeListOptions(opts)) + path := fmt.Sprintf("api/v4/projects/%s/merge_requests/%d/commits?%s", encode(repo), number, encodeListOptions(opts)) out := []*commit{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertCommitList(out), res, err From 2fd608ed36b65169f20f8dd9296d701a0e3bc202 Mon Sep 17 00:00:00 2001 From: Aleksandar Radisavljevic Date: Wed, 19 May 2021 13:33:37 +0200 Subject: [PATCH 025/282] added more integration unit tests --- scm/driver/bitbucket/pr.go | 1 + scm/driver/github/integration/issue_test.go | 2 +- scm/driver/github/integration/org_test.go | 2 +- scm/driver/github/integration/pr_test.go | 54 ++++++++++++++++++++- scm/driver/github/integration/user_test.go | 2 +- 5 files changed, 56 insertions(+), 5 deletions(-) diff --git a/scm/driver/bitbucket/pr.go b/scm/driver/bitbucket/pr.go index f00ed163c..20dc31441 100644 --- a/scm/driver/bitbucket/pr.go +++ b/scm/driver/bitbucket/pr.go @@ -43,6 +43,7 @@ func (s *pullService) ListCommits(ctx context.Context, repo string, number int, path := fmt.Sprintf("2.0/repositories/%s/pullrequests/%d/commits?%s", repo, number, encodeListOptions(opts)) out := new(commits) res, err := s.client.do(ctx, "GET", path, nil, &out) + copyPagination(out.pagination, res) return convertCommitList(out), res, err } diff --git a/scm/driver/github/integration/issue_test.go b/scm/driver/github/integration/issue_test.go index 3b28d3aee..5ed080102 100644 --- a/scm/driver/github/integration/issue_test.go +++ b/scm/driver/github/integration/issue_test.go @@ -112,7 +112,7 @@ func testIssue(issue *scm.Issue) func(t *testing.T) { if got, want := issue.Author.Login, "octocat"; got != want { t.Errorf("Want issue Author Login %q, got %q", want, got) } - if got, want := issue.Author.Avatar, "https://avatars3.githubusercontent.com/u/583231?v=4"; got != want { + if got, want := issue.Author.Avatar, "https://avatars.githubusercontent.com/u/583231?v=4"; got != want { t.Errorf("Want issue Author Avatar %q, got %q", want, got) } if got, want := issue.Closed, false; got != want { diff --git a/scm/driver/github/integration/org_test.go b/scm/driver/github/integration/org_test.go index 8f72d968d..d58114449 100644 --- a/scm/driver/github/integration/org_test.go +++ b/scm/driver/github/integration/org_test.go @@ -44,7 +44,7 @@ func testOrg(organization *scm.Organization) func(t *testing.T) { if got, want := organization.Name, "github"; got != want { t.Errorf("Want organization Name %q, got %q", want, got) } - if got, want := organization.Avatar, "https://avatars1.githubusercontent.com/u/9919?v=4"; got != want { + if got, want := organization.Avatar, "https://avatars.githubusercontent.com/u/9919?v=4"; got != want { t.Errorf("Want organization Avatar %q, got %q", want, got) } } diff --git a/scm/driver/github/integration/pr_test.go b/scm/driver/github/integration/pr_test.go index c4ec31cbf..293aa4c33 100644 --- a/scm/driver/github/integration/pr_test.go +++ b/scm/driver/github/integration/pr_test.go @@ -22,6 +22,7 @@ func testPullRequests(client *scm.Client) func(t *testing.T) { t.Run("Find", testPullRequestFind(client)) t.Run("Changes", testPullRequestChanges(client)) t.Run("Comments", testPullRequestComments(client)) + t.Run("Commits", testPullRequestCommits(client)) } } @@ -120,6 +121,26 @@ func testPullRequestChanges(client *scm.Client) func(t *testing.T) { } } +// +// pull request commits sub-tests +// + +func testPullRequestCommits(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + opts := scm.ListOptions{} + result, _, err := client.PullRequests.ListCommits(context.Background(), "octocat/Hello-World", 140, opts) + if err != nil { + t.Error(err) + } + if len(result) == 0 { + t.Errorf("Got empty pull request change list") + return + } + t.Run("Commit", testPullRequestCommit(result[0])) + } +} + // // struct sub-tests // @@ -147,13 +168,13 @@ func testPullRequest(pr *scm.PullRequest) func(t *testing.T) { if got, want := pr.Sha, "b3cbd5bbd7e81436d2eee04537ea2b4c0cad4cdf"; got != want { t.Errorf("Want pr Sha %q, got %q", want, got) } - if got, want := pr.Link, "https://github.com/octocat/Hello-World/pull/140.diff"; got != want { + if got, want := pr.Link, "https://github.com/octocat/Hello-World/pull/140"; got != want { t.Errorf("Want pr Link %q, got %q", want, got) } if got, want := pr.Author.Login, "octocat"; got != want { t.Errorf("Want pr Author Login %q, got %q", want, got) } - if got, want := pr.Author.Avatar, "https://avatars3.githubusercontent.com/u/583231?v=4"; got != want { + if got, want := pr.Author.Avatar, "https://avatars.githubusercontent.com/u/583231?v=4"; got != want { t.Errorf("Want pr Author Avatar %q, got %q", want, got) } if got, want := pr.Closed, true; got != want { @@ -210,3 +231,32 @@ func testChange(change *scm.Change) func(t *testing.T) { } } } + +func testPullRequestCommit(commit *scm.Commit) func(t *testing.T) { + return func(t *testing.T) { + if got, want := commit.Message, "Create CONTRIBUTING.md"; got != want { + t.Errorf("Want commit Message %q, got %q", want, got) + } + if got, want := commit.Sha, "b3cbd5bbd7e81436d2eee04537ea2b4c0cad4cdf"; got != want { + t.Errorf("Want commit Sha %q, got %q", want, got) + } + if got, want := commit.Author.Name, "The Octocat"; got != want { + t.Errorf("Want commit author Name %q, got %q", want, got) + } + if got, want := commit.Author.Email, "octocat@nowhere.com"; got != want { + t.Errorf("Want commit author Email %q, got %q", want, got) + } + if got, want := commit.Author.Date.Unix(), int64(1402438946); got != want { + t.Errorf("Want commit author Date %d, got %d", want, got) + } + if got, want := commit.Committer.Name, "The Octocat"; got != want { + t.Errorf("Want commit author Name %q, got %q", want, got) + } + if got, want := commit.Committer.Email, "octocat@nowhere.com"; got != want { + t.Errorf("Want commit author Email %q, got %q", want, got) + } + if got, want := commit.Committer.Date.Unix(), int64(1402438946); got != want { + t.Errorf("Want commit author Date %d, got %d", want, got) + } + } +} diff --git a/scm/driver/github/integration/user_test.go b/scm/driver/github/integration/user_test.go index 0a5b77770..a290b22c6 100644 --- a/scm/driver/github/integration/user_test.go +++ b/scm/driver/github/integration/user_test.go @@ -47,7 +47,7 @@ func testUser(user *scm.User) func(t *testing.T) { if got, want := user.Name, "The Octocat"; got != want { t.Errorf("Want user Name %q, got %q", want, got) } - if got, want := user.Avatar, "https://avatars3.githubusercontent.com/u/583231?v=4"; got != want { + if got, want := user.Avatar, "https://avatars.githubusercontent.com/u/583231?v=4"; got != want { t.Errorf("Want user Avatar %q, got %q", want, got) } } From 609b30dd07c753c58fcac50064dbddbcfc0797f6 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Wed, 19 May 2021 16:36:38 +0100 Subject: [PATCH 026/282] Update changelog for 1.14.0 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ee6b4f68..10250a31a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.14.1 +### Fixed +- fix gitlab repo encoding in commits from pr request, from [@aradisavljevic](https://github.com/aradisavljevic). See [#109](https://github.com/drone/go-scm/pull/109). + ## 1.14.0 ### Added - Added ListCommits in pull request api, from [@aradisavljevic](https://github.com/aradisavljevic). See [#106](https://github.com/drone/go-scm/pull/106). From 1d0ee4a2d8a68813348f8754cc8c479c43ab9dcf Mon Sep 17 00:00:00 2001 From: TP Honey Date: Fri, 21 May 2021 14:13:53 +0100 Subject: [PATCH 027/282] (feat) add delete file for github and gitlab --- scm/content.go | 2 +- scm/driver/bitbucket/content.go | 2 +- scm/driver/bitbucket/content_test.go | 2 +- scm/driver/gitea/content.go | 2 +- scm/driver/gitea/content_test.go | 2 +- scm/driver/github/content.go | 20 ++++++++- scm/driver/github/content_test.go | 41 ++++++++++++++++--- scm/driver/github/git_test.go | 16 ++++---- scm/driver/github/issue_test.go | 12 +++--- scm/driver/github/org_test.go | 6 +-- scm/driver/github/pr_test.go | 10 ++--- scm/driver/github/repo_test.go | 20 ++++----- scm/driver/github/review_test.go | 6 +-- .../github/testdata/content_delete.json | 37 +++++++++++++++++ scm/driver/github/user_test.go | 6 +-- scm/driver/github/webhook_test.go | 2 +- scm/driver/gitlab/content.go | 14 ++++++- scm/driver/gitlab/content_test.go | 29 +++++++++++-- scm/driver/gogs/content.go | 2 +- scm/driver/gogs/content_test.go | 2 +- scm/driver/stash/content.go | 2 +- scm/driver/stash/content_test.go | 6 +-- scm/driver/stash/git_test.go | 16 ++++---- scm/driver/stash/pr_test.go | 14 +++---- scm/driver/stash/repo_test.go | 12 +++--- scm/driver/stash/user.go | 2 +- scm/driver/stash/user_test.go | 6 +-- scm/driver/stash/webhook_test.go | 2 +- 28 files changed, 203 insertions(+), 90 deletions(-) create mode 100644 scm/driver/github/testdata/content_delete.json diff --git a/scm/content.go b/scm/content.go index ce2cef31d..4f5e4a0e9 100644 --- a/scm/content.go +++ b/scm/content.go @@ -47,7 +47,7 @@ type ( Update(ctx context.Context, repo, path string, params *ContentParams) (*Response, error) // Delete deletes a reository file. - Delete(ctx context.Context, repo, path, ref string) (*Response, error) + Delete(ctx context.Context, repo, path string, params *ContentParams) (*Response, error) // List returns a list of contents in a repository directory by path. It is // up to the driver to list the directory recursively or non-recursively, diff --git a/scm/driver/bitbucket/content.go b/scm/driver/bitbucket/content.go index 8dac19c64..73f91d79e 100644 --- a/scm/driver/bitbucket/content.go +++ b/scm/driver/bitbucket/content.go @@ -67,7 +67,7 @@ func (s *contentService) Update(ctx context.Context, repo, path string, params * return res, err } -func (s *contentService) Delete(ctx context.Context, repo, path, ref string) (*scm.Response, error) { +func (s *contentService) Delete(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { return nil, scm.ErrNotSupported } diff --git a/scm/driver/bitbucket/content_test.go b/scm/driver/bitbucket/content_test.go index 54aa977ac..3336f8cd2 100644 --- a/scm/driver/bitbucket/content_test.go +++ b/scm/driver/bitbucket/content_test.go @@ -184,7 +184,7 @@ func TestContentUpdateBadCommitID(t *testing.T) { func TestContentDelete(t *testing.T) { content := new(contentService) - _, err := content.Delete(context.Background(), "atlassian/atlaskit", "README", "master") + _, err := content.Delete(context.Background(), "atlassian/atlaskit", "README", &scm.ContentParams{}) if err != scm.ErrNotSupported { t.Errorf("Expect Not Supported error") } diff --git a/scm/driver/gitea/content.go b/scm/driver/gitea/content.go index 07945a48a..06b3db195 100644 --- a/scm/driver/gitea/content.go +++ b/scm/driver/gitea/content.go @@ -34,7 +34,7 @@ func (s *contentService) Update(ctx context.Context, repo, path string, params * return nil, scm.ErrNotSupported } -func (s *contentService) Delete(ctx context.Context, repo, path, ref string) (*scm.Response, error) { +func (s *contentService) Delete(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { return nil, scm.ErrNotSupported } diff --git a/scm/driver/gitea/content_test.go b/scm/driver/gitea/content_test.go index 4e73acfc5..5a276da4c 100644 --- a/scm/driver/gitea/content_test.go +++ b/scm/driver/gitea/content_test.go @@ -61,7 +61,7 @@ func TestContentUpdate(t *testing.T) { func TestContentDelete(t *testing.T) { client, _ := New("https://try.gitea.io") - _, err := client.Contents.Delete(context.Background(), "go-gitea/gitea", "README.md", "master") + _, err := client.Contents.Delete(context.Background(), "go-gitea/gitea", "README.md", &scm.ContentParams{}) if err != scm.ErrNotSupported { t.Errorf("Expect Not Supported error") } diff --git a/scm/driver/github/content.go b/scm/driver/github/content.go index 58fc17698..709cf705f 100644 --- a/scm/driver/github/content.go +++ b/scm/driver/github/content.go @@ -70,8 +70,24 @@ func (s *contentService) Update(ctx context.Context, repo, path string, params * return res, err } -func (s *contentService) Delete(ctx context.Context, repo, path, ref string) (*scm.Response, error) { - return nil, scm.ErrNotSupported +func (s *contentService) Delete(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { + endpoint := fmt.Sprintf("repos/%s/contents/%s", repo, path) + in := &contentCreateUpdate{ + Message: params.Message, + Branch: params.Branch, + // NB the sha passed to github rest api is the blob sha, not the commit sha + Sha: params.BlobID, + Committer: commitAuthor{ + Name: params.Signature.Name, + Email: params.Signature.Email, + }, + Author: commitAuthor{ + Name: params.Signature.Name, + Email: params.Signature.Email, + }, + } + res, err := s.client.do(ctx, "DELETE", endpoint, in, nil) + return res, err } func (s *contentService) List(ctx context.Context, repo, path, ref string, _ scm.ListOptions) ([]*scm.ContentInfo, *scm.Response, error) { diff --git a/scm/driver/github/content_test.go b/scm/driver/github/content_test.go index 1c8692812..06923bf74 100644 --- a/scm/driver/github/content_test.go +++ b/scm/driver/github/content_test.go @@ -40,7 +40,7 @@ func TestContentFind(t *testing.T) { want := new(scm.Content) raw, _ := ioutil.ReadFile("testdata/content.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -159,10 +159,39 @@ func TestContentUpdateBadBlobID(t *testing.T) { } func TestContentDelete(t *testing.T) { - content := new(contentService) - _, err := content.Delete(context.Background(), "octocat/hello-world", "README", "master") - if err != scm.ErrNotSupported { - t.Errorf("Expect Not Supported error") + defer gock.Off() + + gock.New("https://api.github.com"). + Delete("/repos/octocat/hello-world/contents/test/hello"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/content_delete.json") + + params := &scm.ContentParams{ + Message: "a new commit message", + BlobID: "95b966ae1c166bd92f8ae7d1c313e738c731dfc3", + Signature: scm.Signature{ + Name: "Monalisa Octocat", + Email: "octocat@github.com", + }, + } + + client := NewDefault() + res, err := client.Contents.Delete( + context.Background(), + "octocat/hello-world", + "test/hello", + params, + ) + + if err != nil { + t.Error(err) + return + } + + if res.Status != 200 { + t.Errorf("Unexpected Results") } } @@ -192,7 +221,7 @@ func TestContentList(t *testing.T) { want := []*scm.ContentInfo{} raw, _ := ioutil.ReadFile("testdata/content_list.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") diff --git a/scm/driver/github/git_test.go b/scm/driver/github/git_test.go index e708c67cd..9c0a6c530 100644 --- a/scm/driver/github/git_test.go +++ b/scm/driver/github/git_test.go @@ -35,7 +35,7 @@ func TestGitFindCommit(t *testing.T) { want := new(scm.Commit) raw, _ := ioutil.ReadFile("testdata/commit.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -65,7 +65,7 @@ func TestGitFindBranch(t *testing.T) { want := new(scm.Reference) raw, _ := ioutil.ReadFile("testdata/branch.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -95,7 +95,7 @@ func TestGitFindTag(t *testing.T) { want := new(scm.Reference) raw, _ := ioutil.ReadFile("testdata/tag.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -161,7 +161,7 @@ func TestGitListCommits(t *testing.T) { want := []*scm.Commit{} raw, _ := ioutil.ReadFile("testdata/commits.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -195,7 +195,7 @@ func TestGitListBranches(t *testing.T) { want := []*scm.Reference{} raw, _ := ioutil.ReadFile("testdata/branches.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -229,7 +229,7 @@ func TestGitListTags(t *testing.T) { want := []*scm.Reference{} raw, _ := ioutil.ReadFile("testdata/tags.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -260,7 +260,7 @@ func TestGitListChanges(t *testing.T) { want := []*scm.Change{} raw, _ := ioutil.ReadFile("testdata/changes.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -290,7 +290,7 @@ func TestGitCompareChanges(t *testing.T) { want := []*scm.Change{} raw, _ := ioutil.ReadFile("testdata/compare.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") diff --git a/scm/driver/github/issue_test.go b/scm/driver/github/issue_test.go index d6ff16f2e..af44e9bbd 100644 --- a/scm/driver/github/issue_test.go +++ b/scm/driver/github/issue_test.go @@ -35,7 +35,7 @@ func TestIssueFind(t *testing.T) { want := new(scm.Issue) raw, _ := ioutil.ReadFile("testdata/issue.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -65,7 +65,7 @@ func TestIssueCommentFind(t *testing.T) { want := new(scm.Comment) raw, _ := ioutil.ReadFile("testdata/issue_comment.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -99,7 +99,7 @@ func TestIssueList(t *testing.T) { want := []*scm.Issue{} raw, _ := ioutil.ReadFile("testdata/issues.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -133,7 +133,7 @@ func TestIssueListComments(t *testing.T) { want := []*scm.Comment{} raw, _ := ioutil.ReadFile("testdata/issue_comments.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -169,7 +169,7 @@ func TestIssueCreate(t *testing.T) { want := new(scm.Issue) raw, _ := ioutil.ReadFile("testdata/issue.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -203,7 +203,7 @@ func TestIssueCreateComment(t *testing.T) { want := new(scm.Comment) raw, _ := ioutil.ReadFile("testdata/issue_comment.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") diff --git a/scm/driver/github/org_test.go b/scm/driver/github/org_test.go index b36c00d8e..eaa9b22f4 100644 --- a/scm/driver/github/org_test.go +++ b/scm/driver/github/org_test.go @@ -35,7 +35,7 @@ func TestOrganizationFind(t *testing.T) { want := new(scm.Organization) raw, _ := ioutil.ReadFile("testdata/org.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -65,7 +65,7 @@ func TestOrganizationFindMembership(t *testing.T) { want := new(scm.Membership) raw, _ := ioutil.ReadFile("testdata/membership.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -98,7 +98,7 @@ func TestOrganizationList(t *testing.T) { want := []*scm.Organization{} raw, _ := ioutil.ReadFile("testdata/orgs.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") diff --git a/scm/driver/github/pr_test.go b/scm/driver/github/pr_test.go index 9bf7b5337..d49d5cef3 100644 --- a/scm/driver/github/pr_test.go +++ b/scm/driver/github/pr_test.go @@ -35,7 +35,7 @@ func TestPullFind(t *testing.T) { want := new(scm.PullRequest) raw, _ := ioutil.ReadFile("testdata/pr.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -69,7 +69,7 @@ func TestPullList(t *testing.T) { want := []*scm.PullRequest{} raw, _ := ioutil.ReadFile("testdata/pulls.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -101,7 +101,7 @@ func TestPullListChanges(t *testing.T) { want := []*scm.Change{} raw, _ := ioutil.ReadFile("testdata/pr_files.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -179,7 +179,7 @@ func TestPullCreate(t *testing.T) { want := new(scm.PullRequest) raw, _ := ioutil.ReadFile("testdata/pr.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -210,7 +210,7 @@ func TestPullListCommits(t *testing.T) { want := []*scm.Commit{} raw, _ := ioutil.ReadFile("testdata/commits.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") diff --git a/scm/driver/github/repo_test.go b/scm/driver/github/repo_test.go index 731f960fe..7fd992eac 100644 --- a/scm/driver/github/repo_test.go +++ b/scm/driver/github/repo_test.go @@ -34,7 +34,7 @@ func TestRepositoryFind(t *testing.T) { want := new(scm.Repository) raw, _ := ioutil.ReadFile("testdata/repo.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -64,7 +64,7 @@ func TestRepositoryPerms(t *testing.T) { want := new(scm.Repository) raw, _ := ioutil.ReadFile("testdata/repo.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want.Perm); diff != "" { t.Errorf("Unexpected Results") @@ -118,7 +118,7 @@ func TestRepositoryList(t *testing.T) { want := []*scm.Repository{} raw, _ := ioutil.ReadFile("testdata/repos.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -152,7 +152,7 @@ func TestStatusList(t *testing.T) { want := []*scm.Status{} raw, _ := ioutil.ReadFile("testdata/statuses.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -190,7 +190,7 @@ func TestStatusCreate(t *testing.T) { want := new(scm.Status) raw, _ := ioutil.ReadFile("testdata/status.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -229,7 +229,7 @@ func TestDeployStatusCreate(t *testing.T) { want := new(scm.DeployStatus) raw, _ := ioutil.ReadFile("testdata/deployment.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -259,7 +259,7 @@ func TestRepositoryHookFind(t *testing.T) { want := new(scm.Hook) raw, _ := ioutil.ReadFile("testdata/hook.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -292,7 +292,7 @@ func TestRepositoryHookList(t *testing.T) { want := []*scm.Hook{} raw, _ := ioutil.ReadFile("testdata/hooks.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -330,7 +330,7 @@ func TestRepositoryHookCreate(t *testing.T) { want := new(scm.Hook) raw, _ := ioutil.ReadFile("testdata/hook.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -367,7 +367,7 @@ func TestRepositoryHookUpdate(t *testing.T) { want := new(scm.Hook) raw, _ := ioutil.ReadFile("testdata/hook.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") diff --git a/scm/driver/github/review_test.go b/scm/driver/github/review_test.go index 3aaf08ba5..4d12b7947 100644 --- a/scm/driver/github/review_test.go +++ b/scm/driver/github/review_test.go @@ -34,7 +34,7 @@ func TestReviewFind(t *testing.T) { want := new(scm.Review) raw, _ := ioutil.ReadFile("testdata/pr_comment.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -67,7 +67,7 @@ func TestReviewList(t *testing.T) { want := []*scm.Review{} raw, _ := ioutil.ReadFile("testdata/pr_comments.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -105,7 +105,7 @@ func TestReviewCreate(t *testing.T) { want := new(scm.Review) raw, _ := ioutil.ReadFile("testdata/pr_comment.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") diff --git a/scm/driver/github/testdata/content_delete.json b/scm/driver/github/testdata/content_delete.json new file mode 100644 index 000000000..eeefc02b8 --- /dev/null +++ b/scm/driver/github/testdata/content_delete.json @@ -0,0 +1,37 @@ +{ + "content": null, + "commit": { + "sha": "7638417db6d59f3c431d3e1f261cc637155684cd", + "node_id": "MDY6Q29tbWl0NzYzODQxN2RiNmQ1OWYzYzQzMWQzZTFmMjYxY2M2MzcxNTU2ODRjZA==", + "url": "https://api.github.com/repos/octocat/Hello-World/git/commits/7638417db6d59f3c431d3e1f261cc637155684cd", + "html_url": "https://github.com/octocat/Hello-World/git/commit/7638417db6d59f3c431d3e1f261cc637155684cd", + "author": { + "date": "2014-11-07T22:01:45Z", + "name": "Monalisa Octocat", + "email": "octocat@github.com" + }, + "committer": { + "date": "2014-11-07T22:01:45Z", + "name": "Monalisa Octocat", + "email": "octocat@github.com" + }, + "message": "my commit message", + "tree": { + "url": "https://api.github.com/repos/octocat/Hello-World/git/trees/691272480426f78a0138979dd3ce63b77f706feb", + "sha": "691272480426f78a0138979dd3ce63b77f706feb" + }, + "parents": [ + { + "url": "https://api.github.com/repos/octocat/Hello-World/git/commits/1acc419d4d6a9ce985db7be48c6349a0475975b5", + "html_url": "https://github.com/octocat/Hello-World/git/commit/1acc419d4d6a9ce985db7be48c6349a0475975b5", + "sha": "1acc419d4d6a9ce985db7be48c6349a0475975b5" + } + ], + "verification": { + "verified": false, + "reason": "unsigned", + "signature": null, + "payload": null + } + } +} \ No newline at end of file diff --git a/scm/driver/github/user_test.go b/scm/driver/github/user_test.go index 86e5b709d..2eb6fea8e 100644 --- a/scm/driver/github/user_test.go +++ b/scm/driver/github/user_test.go @@ -39,7 +39,7 @@ func TestUserFind(t *testing.T) { want := new(scm.User) raw, _ := ioutil.ReadFile("testdata/user.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -71,12 +71,12 @@ func TestUserLoginFind(t *testing.T) { want := new(scm.User) raw, _ := ioutil.ReadFile("testdata/user.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) - json.NewEncoder(os.Stdout).Encode(got) + _ = json.NewEncoder(os.Stdout).Encode(got) } t.Run("Request", testRequest(res)) diff --git a/scm/driver/github/webhook_test.go b/scm/driver/github/webhook_test.go index 3f62cb8c6..99ba0d327 100644 --- a/scm/driver/github/webhook_test.go +++ b/scm/driver/github/webhook_test.go @@ -223,7 +223,7 @@ func TestWebhooks(t *testing.T) { t.Log(diff) // debug only. remove once implemented - json.NewEncoder(os.Stdout).Encode(o) + _ = json.NewEncoder(os.Stdout).Encode(o) } switch event := o.(type) { diff --git a/scm/driver/gitlab/content.go b/scm/driver/gitlab/content.go index 4c8fd8218..feef351f1 100644 --- a/scm/driver/gitlab/content.go +++ b/scm/driver/gitlab/content.go @@ -69,8 +69,18 @@ func (s *contentService) Update(ctx context.Context, repo, path string, params * return res, err } -func (s *contentService) Delete(ctx context.Context, repo, path, ref string) (*scm.Response, error) { - return nil, scm.ErrNotSupported +func (s *contentService) Delete(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { + endpoint := fmt.Sprintf("api/v4/projects/%s/repository/files/%s", encode(repo), encodePath(path)) + in := &createUpdateContent{ + Branch: params.Branch, + CommitMessage: params.Message, + Encoding: "base64", + AuthorName: params.Signature.Name, + AuthorEmail: params.Signature.Email, + LastCommitID: params.Sha, + } + res, err := s.client.do(ctx, "DELETE", endpoint, in, nil) + return res, err } func (s *contentService) List(ctx context.Context, repo, path, ref string, opts scm.ListOptions) ([]*scm.ContentInfo, *scm.Response, error) { diff --git a/scm/driver/gitlab/content_test.go b/scm/driver/gitlab/content_test.go index 29349fa95..d7baa5bbe 100644 --- a/scm/driver/gitlab/content_test.go +++ b/scm/driver/gitlab/content_test.go @@ -142,10 +142,31 @@ func TestContentUpdateBadCommitID(t *testing.T) { } func TestContentDelete(t *testing.T) { - content := new(contentService) - _, err := content.Delete(context.Background(), "octocat/hello-world", "README", "master") - if err != scm.ErrNotSupported { - t.Errorf("Expect Not Supported error") + defer gock.Off() + + gock.New("https://gitlab.com"). + Delete("/api/v4/projects/diaspora/diaspora/repository/files/app/project.rb"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders) + + client := NewDefault() + params := &scm.ContentParams{ + Message: "update file", + Signature: scm.Signature{ + Name: "Firstname Lastname", + Email: "kubesphere@example.com", + }, + } + + res, err := client.Contents.Delete(context.Background(), "diaspora/diaspora", "app/project.rb", params) + if err != nil { + t.Error(err) + return + } + + if res.Status != 200 { + t.Errorf("Unexpected Results") } } diff --git a/scm/driver/gogs/content.go b/scm/driver/gogs/content.go index b6ebe830a..44918ccab 100644 --- a/scm/driver/gogs/content.go +++ b/scm/driver/gogs/content.go @@ -34,7 +34,7 @@ func (s *contentService) Update(ctx context.Context, repo, path string, params * return nil, scm.ErrNotSupported } -func (s *contentService) Delete(ctx context.Context, repo, path, ref string) (*scm.Response, error) { +func (s *contentService) Delete(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { return nil, scm.ErrNotSupported } diff --git a/scm/driver/gogs/content_test.go b/scm/driver/gogs/content_test.go index 0e3745703..8dd95de41 100644 --- a/scm/driver/gogs/content_test.go +++ b/scm/driver/gogs/content_test.go @@ -58,7 +58,7 @@ func TestContentUpdate(t *testing.T) { func TestContentDelete(t *testing.T) { client, _ := New("https://try.gogs.io") - _, err := client.Contents.Delete(context.Background(), "gogits/gogs", "README.md", "master") + _, err := client.Contents.Delete(context.Background(), "gogits/gogs", "README.md", &scm.ContentParams{}) if err != scm.ErrNotSupported { t.Errorf("Expect Not Supported error") } diff --git a/scm/driver/stash/content.go b/scm/driver/stash/content.go index b067825ec..52e2ef425 100644 --- a/scm/driver/stash/content.go +++ b/scm/driver/stash/content.go @@ -35,7 +35,7 @@ func (s *contentService) Update(ctx context.Context, repo, path string, params * return nil, scm.ErrNotSupported } -func (s *contentService) Delete(ctx context.Context, repo, path, ref string) (*scm.Response, error) { +func (s *contentService) Delete(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { return nil, scm.ErrNotSupported } diff --git a/scm/driver/stash/content_test.go b/scm/driver/stash/content_test.go index e958df5c1..43ca8c15c 100644 --- a/scm/driver/stash/content_test.go +++ b/scm/driver/stash/content_test.go @@ -34,7 +34,7 @@ func TestContentFind(t *testing.T) { want := new(scm.Content) raw, _ := ioutil.ReadFile("testdata/content.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -60,7 +60,7 @@ func TestContentUpdate(t *testing.T) { func TestContentDelete(t *testing.T) { content := new(contentService) - _, err := content.Delete(context.Background(), "atlassian/atlaskit", "README", "master") + _, err := content.Delete(context.Background(), "atlassian/atlaskit", "README", &scm.ContentParams{}) if err != scm.ErrNotSupported { t.Errorf("Expect Not Supported error") } @@ -90,7 +90,7 @@ func TestContentList(t *testing.T) { want := []*scm.ContentInfo{} raw, _ := ioutil.ReadFile("testdata/content_list.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") diff --git a/scm/driver/stash/git_test.go b/scm/driver/stash/git_test.go index 4ce37595e..04ad8b8d3 100644 --- a/scm/driver/stash/git_test.go +++ b/scm/driver/stash/git_test.go @@ -33,7 +33,7 @@ func TestGitFindCommit(t *testing.T) { want := new(scm.Commit) raw, _ := ioutil.ReadFile("testdata/commit.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -59,7 +59,7 @@ func TestGitFindBranch(t *testing.T) { want := new(scm.Reference) raw, _ := ioutil.ReadFile("testdata/branch.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -85,7 +85,7 @@ func TestGitFindTag(t *testing.T) { want := new(scm.Reference) raw, _ := ioutil.ReadFile("testdata/tag.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -110,7 +110,7 @@ func TestGitListCommits(t *testing.T) { want := []*scm.Commit{} raw, _ := ioutil.ReadFile("testdata/commits.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -136,7 +136,7 @@ func TestGitListBranches(t *testing.T) { want := []*scm.Reference{} raw, _ := ioutil.ReadFile("testdata/branches.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -164,7 +164,7 @@ func TestGitListTags(t *testing.T) { want := []*scm.Reference{} raw, _ := ioutil.ReadFile("testdata/tags.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -192,7 +192,7 @@ func TestGitListChanges(t *testing.T) { want := []*scm.Change{} raw, _ := ioutil.ReadFile("testdata/changes.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -220,7 +220,7 @@ func TestGitCompareChanges(t *testing.T) { want := []*scm.Change{} raw, _ := ioutil.ReadFile("testdata/compare.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") diff --git a/scm/driver/stash/pr_test.go b/scm/driver/stash/pr_test.go index 4ed8d5932..4710f4867 100644 --- a/scm/driver/stash/pr_test.go +++ b/scm/driver/stash/pr_test.go @@ -33,7 +33,7 @@ func TestPullFind(t *testing.T) { want := new(scm.PullRequest) raw, _ := ioutil.ReadFile("testdata/pr.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -58,7 +58,7 @@ func TestPullFindComment(t *testing.T) { want := new(scm.Comment) raw, _ := ioutil.ReadFile("testdata/pr_comment.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -83,7 +83,7 @@ func TestPullList(t *testing.T) { want := []*scm.PullRequest{} raw, _ := ioutil.ReadFile("testdata/prs.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -110,7 +110,7 @@ func TestPullListChanges(t *testing.T) { want := []*scm.Change{} raw, _ := ioutil.ReadFile("testdata/pr_change.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -174,7 +174,7 @@ func TestPullCreate(t *testing.T) { want := new(scm.PullRequest) raw, _ := ioutil.ReadFile("testdata/pr.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -201,7 +201,7 @@ func TestPullCreateComment(t *testing.T) { want := new(scm.Comment) raw, _ := ioutil.ReadFile("testdata/pr_comment.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -226,7 +226,7 @@ func TestPullListCommits(t *testing.T) { want := []*scm.Commit{} raw, _ := ioutil.ReadFile("testdata/commits.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") diff --git a/scm/driver/stash/repo_test.go b/scm/driver/stash/repo_test.go index 57c6fdb1d..dff71f07a 100644 --- a/scm/driver/stash/repo_test.go +++ b/scm/driver/stash/repo_test.go @@ -33,7 +33,7 @@ func TestRepositoryFind(t *testing.T) { want := new(scm.Repository) raw, _ := ioutil.ReadFile("testdata/repo.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -237,7 +237,7 @@ func TestRepositoryList(t *testing.T) { want := []*scm.Repository{} raw, _ := ioutil.ReadFile("testdata/repos.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -293,7 +293,7 @@ func TestRepositoryHookFind(t *testing.T) { want := new(scm.Hook) raw, _ := ioutil.ReadFile("testdata/webhook.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -320,7 +320,7 @@ func TestRepositoryHookList(t *testing.T) { want := []*scm.Hook{} raw, _ := ioutil.ReadFile("testdata/webhooks.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -357,7 +357,7 @@ func TestRepositoryHookCreate(t *testing.T) { want := new(scm.Hook) raw, _ := ioutil.ReadFile("testdata/webhook.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -394,7 +394,7 @@ func TestRepositoryHookUpdate(t *testing.T) { want := new(scm.Hook) raw, _ := ioutil.ReadFile("testdata/webhook.json.golden") - json.Unmarshal(raw, want) + _ = json.Unmarshal(raw, want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") diff --git a/scm/driver/stash/user.go b/scm/driver/stash/user.go index 4b7fa5b8a..3bcade3e1 100644 --- a/scm/driver/stash/user.go +++ b/scm/driver/stash/user.go @@ -20,7 +20,7 @@ type userService struct { } func (s *userService) Find(ctx context.Context) (*scm.User, *scm.Response, error) { - path := fmt.Sprintf("plugins/servlet/applinks/whoami") + path := "plugins/servlet/applinks/whoami" out := new(bytes.Buffer) res, err := s.client.do(ctx, "GET", path, nil, out) if err != nil { diff --git a/scm/driver/stash/user_test.go b/scm/driver/stash/user_test.go index 9e05e4d31..ac4df21ad 100644 --- a/scm/driver/stash/user_test.go +++ b/scm/driver/stash/user_test.go @@ -39,7 +39,7 @@ func TestUserFind(t *testing.T) { want := new(scm.User) raw, _ := ioutil.ReadFile("testdata/user.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -82,7 +82,7 @@ func TestUserLoginFind(t *testing.T) { want := new(scm.User) raw, _ := ioutil.ReadFile("testdata/user.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") @@ -117,7 +117,7 @@ func TestUserLoginFind_ViaSearch(t *testing.T) { want := new(scm.User) raw, _ := ioutil.ReadFile("testdata/user_search.json.golden") - json.Unmarshal(raw, &want) + _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") diff --git a/scm/driver/stash/webhook_test.go b/scm/driver/stash/webhook_test.go index e7f162185..eb0486ef1 100644 --- a/scm/driver/stash/webhook_test.go +++ b/scm/driver/stash/webhook_test.go @@ -144,7 +144,7 @@ func TestWebhooks(t *testing.T) { t.Log(diff) // debug only. remove once implemented - json.NewEncoder(os.Stdout).Encode(o) + _ = json.NewEncoder(os.Stdout).Encode(o) } switch event := o.(type) { From adbb881e5b452abf123e7dfef22d5e3592cec0e7 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Thu, 27 May 2021 11:13:44 +0100 Subject: [PATCH 028/282] Update changelog for 1.15.0 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10250a31a..ae5872ed4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.15.0 +### Added +- add delete file for github and gitlab, from [@tphoney](https://github.com/tphoney). See [#110](https://github.com/drone/go-scm/pull/110). +- ## 1.14.1 ### Fixed - fix gitlab repo encoding in commits from pr request, from [@aradisavljevic](https://github.com/aradisavljevic). See [#109](https://github.com/drone/go-scm/pull/109). From 84b3706efd4ab32d031f6c774d993388eec4d7e1 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Thu, 27 May 2021 11:14:47 +0100 Subject: [PATCH 029/282] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae5872ed4..57f10ca42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## 1.15.0 ### Added - add delete file for github and gitlab, from [@tphoney](https://github.com/tphoney). See [#110](https://github.com/drone/go-scm/pull/110). -- + ## 1.14.1 ### Fixed - fix gitlab repo encoding in commits from pr request, from [@aradisavljevic](https://github.com/aradisavljevic). See [#109](https://github.com/drone/go-scm/pull/109). From 49273135b1378b84a7c3419741e51868416f1d4f Mon Sep 17 00:00:00 2001 From: TP Honey Date: Wed, 16 Jun 2021 15:29:40 +0100 Subject: [PATCH 030/282] (DRON-88) github fix pr ListChanges deleted/renamed status --- scm/driver/github/pr.go | 4 +- scm/driver/github/testdata/pr_files.json | 54 +++++++++++++++---- .../github/testdata/pr_files.json.golden | 25 ++++++++- 3 files changed, 70 insertions(+), 13 deletions(-) diff --git a/scm/driver/github/pr.go b/scm/driver/github/pr.go index 749d73585..39c5d20e2 100644 --- a/scm/driver/github/pr.go +++ b/scm/driver/github/pr.go @@ -187,8 +187,8 @@ func convertChange(from *file) *scm.Change { return &scm.Change{ Path: from.Filename, Added: from.Status == "added", - Deleted: from.Status == "deleted", - Renamed: from.Status == "moved", + Deleted: from.Status == "removed", + Renamed: from.Status == "renamed", BlobID: from.BlobID, } } diff --git a/scm/driver/github/testdata/pr_files.json b/scm/driver/github/testdata/pr_files.json index d3ca75649..18488635a 100644 --- a/scm/driver/github/testdata/pr_files.json +++ b/scm/driver/github/testdata/pr_files.json @@ -1,14 +1,50 @@ [ { - "sha": "bbcd538c8e72b8c175046e27cc8f907076331401", - "filename": "file1.txt", + "sha": "291b15982c4926705f5639abffe96b2b6c419ce7", + "filename": "asda2", + "status": "modified", + "additions": 1, + "deletions": 1, + "changes": 2, + "blob_url": "https://github.com/tphoney/scm-test/blob/ad442ec8e99589912117c7d1e689f56b32356868/asda2", + "raw_url": "https://github.com/tphoney/scm-test/raw/ad442ec8e99589912117c7d1e689f56b32356868/asda2", + "contents_url": "https://api.github.com/repos/tphoney/scm-test/contents/asda2?ref=ad442ec8e99589912117c7d1e689f56b32356868", + "patch": "@@ -1,2 +1,2 @@n-n+asdasdn asdasdasd" + }, + { + "sha": "ce013625030ba8dba906f756967f9e9ca394464a", + "filename": "remove_me", "status": "added", - "additions": 103, - "deletions": 21, - "changes": 124, - "blob_url": "https://github.com/octocat/Hello-World/blob/6dcb09b5b57875f334f61aebed695e2e4193db5e/file1.txt", - "raw_url": "https://github.com/octocat/Hello-World/raw/6dcb09b5b57875f334f61aebed695e2e4193db5e/file1.txt", - "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/file1.txt?ref=6dcb09b5b57875f334f61aebed695e2e4193db5e", - "patch": "@@ -132,7 +132,7 @@ module Test @@ -1000,7 +1000,7 @@ module Test" + "additions": 1, + "deletions": 0, + "changes": 1, + "blob_url": "https://github.com/tphoney/scm-test/blob/ad442ec8e99589912117c7d1e689f56b32356868/remove_me", + "raw_url": "https://github.com/tphoney/scm-test/raw/ad442ec8e99589912117c7d1e689f56b32356868/remove_me", + "contents_url": "https://api.github.com/repos/tphoney/scm-test/contents/remove_me?ref=ad442ec8e99589912117c7d1e689f56b32356868", + "patch": "@@ -0,0 +1 @@n+hello" + }, + { + "sha": "70c379b63ffa0795fdbfbc128e5a2818397b7ef8", + "filename": "tp", + "status": "renamed", + "additions": 0, + "deletions": 0, + "changes": 0, + "blob_url": "https://github.com/tphoney/scm-test/blob/ad442ec8e99589912117c7d1e689f56b32356868/tp", + "raw_url": "https://github.com/tphoney/scm-test/raw/ad442ec8e99589912117c7d1e689f56b32356868/tp", + "contents_url": "https://api.github.com/repos/tphoney/scm-test/contents/tp?ref=ad442ec8e99589912117c7d1e689f56b32356868", + "previous_filename": "abhinav" + }, + { + "sha": "0f9282d7e71e0f8cb748bfe00e52d7ed13dad036", + "filename": "upsert", + "status": "removed", + "additions": 0, + "deletions": 1, + "changes": 1, + "blob_url": "https://github.com/tphoney/scm-test/blob/6a86c7aca4425c8781876c31ffb6e4284fb07d56/upsert", + "raw_url": "https://github.com/tphoney/scm-test/raw/6a86c7aca4425c8781876c31ffb6e4284fb07d56/upsert", + "contents_url": "https://api.github.com/repos/tphoney/scm-test/contents/upsert?ref=6a86c7aca4425c8781876c31ffb6e4284fb07d56", + "patch": "@@ -1 +0,0 @@n-asdasn No newline at end of file" } ] \ No newline at end of file diff --git a/scm/driver/github/testdata/pr_files.json.golden b/scm/driver/github/testdata/pr_files.json.golden index b5034d7cf..2add0e0b7 100644 --- a/scm/driver/github/testdata/pr_files.json.golden +++ b/scm/driver/github/testdata/pr_files.json.golden @@ -1,9 +1,30 @@ [ { - "Path": "file1.txt", + "Path": "asda2", + "Added": false, + "Renamed": false, + "Deleted": false, + "BlobID": "291b15982c4926705f5639abffe96b2b6c419ce7" + }, + { + "Path": "remove_me", "Added": true, "Renamed": false, "Deleted": false, - "BlobID": "bbcd538c8e72b8c175046e27cc8f907076331401" + "BlobID": "ce013625030ba8dba906f756967f9e9ca394464a" + }, + { + "Path": "tp", + "Added": false, + "Renamed": true, + "Deleted": false, + "BlobID": "70c379b63ffa0795fdbfbc128e5a2818397b7ef8" + }, + { + "Path": "upsert", + "Added": false, + "Renamed": false, + "Deleted": true, + "BlobID": "0f9282d7e71e0f8cb748bfe00e52d7ed13dad036" } ] \ No newline at end of file From d1bdb2e3598b2db3d5cc732d7fc86da6ea6ae333 Mon Sep 17 00:00:00 2001 From: Eoin McAfee Date: Wed, 16 Jun 2021 18:10:25 +0100 Subject: [PATCH 031/282] fix issue where write permission on bitbucket server wasn't working at repo level add unit test --- scm/driver/stash/repo.go | 8 ++-- scm/driver/stash/repo_test.go | 46 ++++++++++++++++++++- scm/driver/stash/testdata/repos.json | 41 ++++++++++++++++++ scm/driver/stash/testdata/repos.json.golden | 13 ++++++ 4 files changed, 103 insertions(+), 5 deletions(-) diff --git a/scm/driver/stash/repo.go b/scm/driver/stash/repo.go index 17e17362e..e7754b459 100644 --- a/scm/driver/stash/repo.go +++ b/scm/driver/stash/repo.go @@ -137,10 +137,10 @@ func (s *repositoryService) FindPerms(ctx context.Context, repo string) (*scm.Pe }, nil, nil } // HACK: test if the user has write access to the repository. - _, name := scm.Split(repo) + namespace, _ := scm.Split(repo) repos, _, _ := s.listWrite(ctx, repo) for _, repo := range repos { - if repo.Name == name { + if repo.Namespace == namespace { return &scm.Perm{ Pull: true, Push: true, @@ -170,8 +170,8 @@ func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* // listWrite returns the user repository list. func (s *repositoryService) listWrite(ctx context.Context, repo string) ([]*scm.Repository, *scm.Response, error) { - namespace, name := scm.Split(repo) - path := fmt.Sprintf("rest/api/1.0/repos?size=1000&permission=REPO_WRITE&projectname=%s&name=%s", namespace, name) + _, name := scm.Split(repo) + path := fmt.Sprintf("rest/api/1.0/repos?size=1000&permission=REPO_WRITE&name=%s", name) out := new(repositories) res, err := s.client.do(ctx, "GET", path, nil, out) return convertRepositoryList(out), res, err diff --git a/scm/driver/stash/repo_test.go b/scm/driver/stash/repo_test.go index dff71f07a..83924a8ba 100644 --- a/scm/driver/stash/repo_test.go +++ b/scm/driver/stash/repo_test.go @@ -157,7 +157,6 @@ func TestRepositoryPerms_Write(t *testing.T) { Get("/rest/api/1.0/repos"). MatchParam("size", "1000"). MatchParam("permission", "REPO_WRITE"). - MatchParam("projectname", "PRJ"). MatchParam("name", "my-repo"). Reply(200). Type("application/json"). @@ -185,6 +184,51 @@ func TestRepositoryPerms_Write(t *testing.T) { } } +func TestRepositoryPermsDifferentProjectName_Write(t *testing.T) { + defer gock.Off() + + gock.New("http://example.com:7990"). + Get("/rest/api/1.0/projects/PRJ/repos/quux"). + Reply(200). + Type("application/json"). + File("testdata/repo.json") + + gock.New("http://example.com:7990"). + Get("/rest/api/1.0/projects/PRJ/repos/quux/webhooks"). + Reply(404). + Type("application/json") + + gock.New("http://example.com:7990"). + Get("/rest/api/1.0/repos"). + MatchParam("size", "1000"). + MatchParam("permission", "REPO_WRITE"). + MatchParam("name", "quux"). + Reply(200). + Type("application/json"). + File("testdata/repos.json") + + client, _ := New("http://example.com:7990") + got, _, err := client.Repositories.FindPerms(context.Background(), "PRJ/quux") + if err != nil { + t.Error(err) + } + + want := &scm.Perm{ + Pull: true, + Push: true, + Admin: false, + } + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + if gock.IsPending() { + t.Errorf("pending API requests") + } +} + func TestRepositoryPerms_Forbidden(t *testing.T) { defer gock.Off() diff --git a/scm/driver/stash/testdata/repos.json b/scm/driver/stash/testdata/repos.json index 46f119c9b..68bc40157 100644 --- a/scm/driver/stash/testdata/repos.json +++ b/scm/driver/stash/testdata/repos.json @@ -43,6 +43,47 @@ } ] } + }, + { + "slug": "quux", + "id": 2, + "name": "quux", + "scmId": "git", + "state": "AVAILABLE", + "statusMessage": "Available", + "forkable": true, + "project": { + "key": "PRJ", + "id": 2, + "name": "different_name", + "public": false, + "type": "NORMAL", + "links": { + "self": [ + { + "href": "http://example.com:7990/projects/PRJ" + } + ] + } + }, + "public": false, + "links": { + "clone": [ + { + "href": "ssh://git@example.com:7999/prj/quux.git", + "name": "ssh" + }, + { + "href": "http://jcitizen@example.com:7990/scm/prj/quux.git", + "name": "http" + } + ], + "self": [ + { + "href": "http://example.com:7990/projects/PRJ/repos/quux/browse" + } + ] + } } ], "start": 0 diff --git a/scm/driver/stash/testdata/repos.json.golden b/scm/driver/stash/testdata/repos.json.golden index ef009866b..18e4d4018 100644 --- a/scm/driver/stash/testdata/repos.json.golden +++ b/scm/driver/stash/testdata/repos.json.golden @@ -11,5 +11,18 @@ "Link": "http://example.com:7990/projects/PRJ/repos/my-repo/browse", "Created": "0001-01-01T00:00:00Z", "Updated": "0001-01-01T00:00:00Z" + }, + { + "ID": "2", + "Namespace": "PRJ", + "Name": "quux", + "Perm": null, + "Branch": "master", + "Private": true, + "Clone": "http://example.com:7990/scm/prj/quux.git", + "CloneSSH": "ssh://git@example.com:7999/prj/quux.git", + "Link": "http://example.com:7990/projects/PRJ/repos/quux/browse", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" } ] \ No newline at end of file From d256ead79e50f74fd0df515b854071bdbf5453c2 Mon Sep 17 00:00:00 2001 From: Eoin McAfee <83226740+eoinmcafee00@users.noreply.github.com> Date: Thu, 17 Jun 2021 12:12:52 +0100 Subject: [PATCH 032/282] update changelog for 1.15.1 --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57f10ca42..2bcfdc061 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.15.1 +### Added +- (DRON-88) github fix pr ListChanges deleted/renamed status, from [@tphoney](https://github.com/tphoney). See [#113](https://github.com/drone/go-scm/pull/113). +- (DRON-84) github fix pr write permission issue with bitbucket server, from [@eoinmcafee0](https://github.com/eoinmcafee00). See [#114](https://github.com/drone/go-scm/pull/114). + ## 1.15.0 ### Added - add delete file for github and gitlab, from [@tphoney](https://github.com/tphoney). See [#110](https://github.com/drone/go-scm/pull/110). From 510145d05751f7c066ef45281895568e12449513 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Tue, 20 Jul 2021 14:21:38 +0100 Subject: [PATCH 033/282] (maint) prep for v.1.15.2 release --- .github_changelog_generator | 1 + CHANGELOG.md | 21 ++++++ HISTORY.md | 125 ++++++++++++++++++++++++++++++++++++ README.md | 26 +++++++- 4 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 .github_changelog_generator create mode 100644 HISTORY.md diff --git a/.github_changelog_generator b/.github_changelog_generator new file mode 100644 index 000000000..3051fa60c --- /dev/null +++ b/.github_changelog_generator @@ -0,0 +1 @@ +since-tag=v1.15.1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bcfdc061..c9dd93640 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,22 @@ # Changelog + +## [v1.15.2](https://github.com/drone/go-scm/tree/v1.15.2) (2021-07-20) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.15.1...v1.15.2) + +**Fixed bugs:** + +- Fixing Gitea commit API in case `ref/heads/` prefix is added to ref [\#108](https://github.com/drone/go-scm/pull/108) ([Vici37](https://github.com/Vici37)) +- use access json header / extend error message parsing for stash [\#89](https://github.com/drone/go-scm/pull/89) ([bakito](https://github.com/bakito)) + +**Closed issues:** + +- Drone and Bitbucket broken for write permission detection for drone build restart permission. [\#87](https://github.com/drone/go-scm/issues/87) + +**Merged pull requests:** + +- Add a vet step to drone config [\#83](https://github.com/drone/go-scm/pull/83) ([tboerger](https://github.com/tboerger)) + All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), @@ -123,3 +141,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix missing avatar in Gitea commit from [@jgeek1011](https://github.com/geek1011). - Implement GET commit endpoint for Gogs from [@ogarcia](https://github.com/ogarcia). + + +\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* diff --git a/HISTORY.md b/HISTORY.md new file mode 100644 index 000000000..2bcfdc061 --- /dev/null +++ b/HISTORY.md @@ -0,0 +1,125 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## 1.15.1 +### Added +- (DRON-88) github fix pr ListChanges deleted/renamed status, from [@tphoney](https://github.com/tphoney). See [#113](https://github.com/drone/go-scm/pull/113). +- (DRON-84) github fix pr write permission issue with bitbucket server, from [@eoinmcafee0](https://github.com/eoinmcafee00). See [#114](https://github.com/drone/go-scm/pull/114). + +## 1.15.0 +### Added +- add delete file for github and gitlab, from [@tphoney](https://github.com/tphoney). See [#110](https://github.com/drone/go-scm/pull/110). + +## 1.14.1 +### Fixed +- fix gitlab repo encoding in commits from pr request, from [@aradisavljevic](https://github.com/aradisavljevic). See [#109](https://github.com/drone/go-scm/pull/109). + +## 1.14.0 +### Added +- Added ListCommits in pull request api, from [@aradisavljevic](https://github.com/aradisavljevic). See [#106](https://github.com/drone/go-scm/pull/106). + +## 1.13.1 +### Fixed +- gitlab, content.find return last_commit_id not commit_id, from [@tphoney](https://github.com/tphoney). See [#104](https://github.com/drone/go-scm/pull/104). + +## 1.13.0 +### Added +- Create branch functionality, from [@tphoney](https://github.com/tphoney). See [#103](https://github.com/drone/go-scm/pull/103). + +## 1.12.0 +### Added +- return sha/blob_id for content.list, from [@tphoney](https://github.com/tphoney). See [#102](https://github.com/drone/go-scm/pull/102). + +## 1.11.0 +### Added +- normalise sha in content, add bitbucket create/update, from [@tphoney](https://github.com/tphoney). See [#101](https://github.com/drone/go-scm/pull/101). + +## 1.10.0 +### Added +- return hash/object_id for files changed in github, from [@tphoney](https://github.com/tphoney). See [#99](https://github.com/drone/go-scm/pull/99). + +## 1.9.0 +### Added +- Added issue_comment parsing for github webhook, from [@aman-harness](https://github.com/aman-harness). See [#91](https://github.com/drone/go-scm/pull/91). +- Added Pr in issue, from [@aman-harness](https://github.com/aman-harness). See [#93](https://github.com/drone/go-scm/pull/93). +- gitlab contents. Find returns hash/blob, from [@tphoney](https://github.com/tphoney). See [#97](https://github.com/drone/go-scm/pull/97). +- add ListCommits for gitea and stash, from [@tphoney](https://github.com/tphoney). See [#98](https://github.com/drone/go-scm/pull/98). + +### Changed +- retry with event subset for legacy stash versions, from [@bakito](https://github.com/bakito). See [#90](https://github.com/drone/go-scm/pull/90). + +## 1.8.0 +### Added +- Support for GitLab visibility attribute, from [@bradrydzewski](https://github.com/bradrydzewski). See [79951ad](https://github.com/drone/go-scm/commit/79951ad7a0d0b1989ea84d99be31fcb9320ae348). +- Support for GitHub visibility attribute, from [@bradrydzewski](https://github.com/bradrydzewski). See [5141b8e](https://github.com/drone/go-scm/commit/5141b8e1db921fe2101c12594c5159b9ffffebc3). + +### Changed +- Support for parsing unknown pull request events, from [@bradrydzewski](https://github.com/bradrydzewski). See [ffa46d9](https://github.com/drone/go-scm/commit/ffa46d955454baa609975eebbe9fdfc4b0a9f7e9). + +## 1.7.2 +### Added +- Support for finding and listing repository tags in GitHub driver, from [@chhsia0](https://github.com/chhsia0). See [#79](https://github.com/drone/go-scm/pull/79). +- Support for finding and listing repository tags in Gitea driver, from [@bradyrdzewski](https://github.com/bradyrdzewski). See [427b8a8](https://github.com/drone/go-scm/commit/427b8a85897c892148801824760bc66d3a3cdcdb). +- Support for git object hashes in GitHub, from from [@bradyrdzewski](https://github.com/bradyrdzewski). See [5230330](https://github.com/drone/go-scm/commit/523033025a7ee875fcfb156f4c660b37e269b1a8). +- Support for before and after commit sha in Stash driver, from [@jlehtimaki](https://github.com/jlehtimaki). See [#82](https://github.com/drone/go-scm/pull/82). +- Support for before and after commit sha in GitLab and Bitbucket driver, from [@shubhag](https://github.com/shubhag). See [#85](https://github.com/drone/go-scm/pull/85). + +## 1.7.1 +### Added +- Support for skip verification in Bitbucket webhook creation, from [@chhsia0](https://github.com/chhsia0). See [#63](https://github.com/drone/go-scm/pull/63). +- Support for Gitea pagination, from [@CirnoT](https://github.com/CirnoT). See [#66](https://github.com/drone/go-scm/pull/66). +- Support for labels in pull request resources, from [@takirala](https://github.com/takirala). See [#67](https://github.com/drone/go-scm/pull/67). +- Support for updating webhooks, from [@chhsia0](https://github.com/chhsia0). See [#71](https://github.com/drone/go-scm/pull/71). + +### Fixed +- Populate diff links in pull request resources, from [@shubhag](https://github.com/shubhag). See [#75](https://github.com/drone/go-scm/pull/75). +- Filter Bitbucket repository search by project, from [@bradrydzewski](https://github.com/bradrydzewski). + +## 1.7.0 +### Added +- Improve status display text in new bitbucket pull request screen, from [@bradrydzewski](https://github.com/bradrydzewski). See [#27](https://github.com/drone/go-scm/issues/27). +- Implement timestamp value for GitHub push webhooks, from [@bradrydzewski](https://github.com/bradrydzewski). +- Implement deep link to branch. +- Implement git compare function to compare two separate commits, from [@chhsia0](https://github.com/chhsia0). +- Implement support for creating and updating GitLab and GitHub repository contents, from [@zhuxiaoyang](https://github.com/zhuxiaoyang). +- Capture Repository link for Gitea, Gogs and Gitlab, from [@chhsia0](https://github.com/chhsia0). + +### Fixed +- Fix issue with GitHub enterprise deep link including API prefix, from [@bradrydzewski](https://github.com/bradrydzewski). +- Fix issue with GitHub deploy hooks for commits having an invalid reference, from [@bradrydzewski](https://github.com/bradrydzewski). +- Support for Skipping SSL verification for GitLab webhooks. See [#40](https://github.com/drone/go-scm/pull/40). +- Support for Skipping SSL verification for GitHub webhooks. See [#44](https://github.com/drone/go-scm/pull/40). +- Fix issue with handling slashes in Bitbucket branch names. See [#7](https://github.com/drone/go-scm/pull/47). +- Fix incorrect Gitea tag link. See [#52](https://github.com/drone/go-scm/pull/52). +- Encode ref when making Gitea API calls. See [#61](https://github.com/drone/go-scm/pull/61). + +## [1.6.0] +### Added +- Support Head and Base sha for GitHub pull request, from [@bradrydzewski](https://github.com/bradrydzewski). +- Support Before sha for Bitbucket, from [@jkdev81](https://github.com/jkdev81). +- Support for creating GitHub deployment hooks, from [@bradrydzewski](https://github.com/bradrydzewski). +- Endpoint to get organization membership for GitHub, from [@bradrydzewski](https://github.com/bradrydzewski). +- Functions to generate deep links to git resources, from [@bradrydzewski](https://github.com/bradrydzewski). + +### Fixed +- Fix issue getting a GitLab commit by ref, from [@bradrydzewski](https://github.com/bradrydzewski). + +## [1.5.0] +### Added + +- Fix missing sha for Gitea tag hooks, from [@techknowlogick](https://github.com/techknowlogick). See [#22](https://github.com/drone/go-scm/pull/22). +- Support for Gitea webhook signature verification, from [@techknowlogick](https://github.com/techknowlogick). + +## [1.4.0] +### Added + +- Fix issues base64 decoding GitLab content, from [@bradrydzewski](https://github.com/bradrydzewski). + +## [1.3.0] +### Added + +- Fix missing avatar in Gitea commit from [@jgeek1011](https://github.com/geek1011). +- Implement GET commit endpoint for Gogs from [@ogarcia](https://github.com/ogarcia). diff --git a/README.md b/README.md index 66349fb6c..856fb2e21 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ +# go-scm + [![Go Doc](https://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/drone/go-scm/scm) Package scm provides a unified interface to multiple source code management systems including GitHub, GitHub Enterprise, Bitbucket, Bitbucket Server, Gitea and Gogs. -# Getting Started +## Getting Started Create a GitHub client: @@ -71,7 +73,7 @@ func main() { } ``` -# Authentication +## Authentication The scm client does not directly handle authentication. Instead, when creating a new client, provide a `http.Client` that can handle authentication for you. For convenience, this library includes oauth1 and oauth2 implementations that can be used to authenticate requests. @@ -109,3 +111,23 @@ func main() { } } ``` + +## Release procedure + +Run the changelog generator. + +```BASH +docker run -it --rm -v "$(pwd)":/usr/local/src/your-app githubchangeloggenerator/github-changelog-generator -u drone -p go-scm -t +``` + +You can generate a token by logging into your GitHub account and going to Settings -> Personal access tokens. + +Next we tag the PR's with the fixes or enhancements labels. If the PR does not fufil the requirements, do not add a label. + +Run the changelog generator again with the future version according to semver. + +```BASH +docker run -it --rm -v "$(pwd)":/usr/local/src/your-app githubchangeloggenerator/github-changelog-generator -u drone -p go-scm -t --future-release v1.15.2 +``` + +Create your pull request for the release. Get it merged then tag the release. From 8ce6b18ce66d4ade2ae8072b18fe8add93cb822e Mon Sep 17 00:00:00 2001 From: Eoin McAfee Date: Fri, 24 Sep 2021 15:30:42 +0100 Subject: [PATCH 034/282] add release & milestone functionality --- go.mod | 2 + go.sum | 13 + scm/client.go | 10 +- scm/const.go | 2 + scm/driver/bitbucket/bitbucket.go | 2 + scm/driver/bitbucket/milestone.go | 31 ++ scm/driver/bitbucket/release.go | 43 +++ scm/driver/gitea/git.go | 6 +- scm/driver/gitea/gitea.go | 2 + scm/driver/gitea/gitea_test.go | 22 +- scm/driver/gitea/issue.go | 12 +- scm/driver/gitea/milestone.go | 130 +++++++ scm/driver/gitea/milestone_test.go | 178 +++++++++ scm/driver/gitea/org.go | 2 +- scm/driver/gitea/org_test.go | 2 +- scm/driver/gitea/pr.go | 6 +- scm/driver/gitea/release.go | 150 ++++++++ scm/driver/gitea/release_test.go | 342 ++++++++++++++++++ scm/driver/gitea/repo.go | 8 +- scm/driver/gitea/repo_test.go | 2 +- scm/driver/gitea/testdata/milestone.json | 12 + .../gitea/testdata/milestone.json.golden | 8 + .../gitea/testdata/milestone_create.json | 6 + scm/driver/gitea/testdata/milestones.json | 14 + .../gitea/testdata/milestones.json.golden | 10 + scm/driver/gitea/testdata/release.json | 10 + scm/driver/gitea/testdata/release.json.golden | 10 + scm/driver/gitea/testdata/release_create.json | 8 + scm/driver/gitea/testdata/release_update.json | 8 + scm/driver/gitea/testdata/releases.json | 12 + .../gitea/testdata/releases.json.golden | 12 + scm/driver/gitea/user.go | 12 +- scm/driver/gitea/user_test.go | 14 +- scm/driver/gitea/util.go | 52 +++ scm/driver/gitea/webhook.go | 16 +- scm/driver/github/github.go | 2 + scm/driver/github/milestone.go | 111 ++++++ scm/driver/github/milestone_test.go | 177 +++++++++ scm/driver/github/release.go | 131 +++++++ scm/driver/github/release_test.go | 186 ++++++++++ scm/driver/github/testdata/milestone.json | 37 ++ .../github/testdata/milestone.json.golden | 9 + .../github/testdata/milestone_create.json | 6 + scm/driver/github/testdata/milestones.json | 39 ++ .../github/testdata/milestones.json.golden | 11 + scm/driver/github/testdata/release.json | 74 ++++ .../github/testdata/release.json.golden | 12 + scm/driver/github/testdata/releases.json | 76 ++++ .../github/testdata/releases.json.golden | 14 + scm/driver/github/util.go | 32 ++ scm/driver/gitlab/gitlab.go | 2 + scm/driver/gitlab/milestone.go | 166 +++++++++ scm/driver/gitlab/milestone_test.go | 186 ++++++++++ scm/driver/gitlab/release.go | 111 ++++++ scm/driver/gitlab/release_test.go | 184 ++++++++++ scm/driver/gitlab/testdata/milestone.json | 13 + .../gitlab/testdata/milestone.json.golden | 8 + .../gitlab/testdata/milestone_create.json | 5 + .../gitlab/testdata/milestone_update.json | 6 + scm/driver/gitlab/testdata/milestones.json | 15 + .../gitlab/testdata/milestones.json.golden | 10 + scm/driver/gitlab/testdata/release.json | 100 +++++ .../gitlab/testdata/release.json.golden | 10 + scm/driver/gitlab/testdata/releases.json | 167 +++++++++ .../gitlab/testdata/releases.json.golden | 14 + scm/driver/gitlab/util.go | 16 + scm/driver/gogs/gogs.go | 2 + scm/driver/gogs/milestone.go | 31 ++ scm/driver/gogs/release.go | 42 +++ scm/driver/stash/milestone.go | 31 ++ scm/driver/stash/release.go | 43 +++ scm/driver/stash/stash.go | 2 + scm/milestone.go | 42 +++ scm/pr.go | 11 + scm/release.go | 67 ++++ scm/util.go | 1 + 76 files changed, 3327 insertions(+), 44 deletions(-) create mode 100644 scm/driver/bitbucket/milestone.go create mode 100644 scm/driver/bitbucket/release.go create mode 100644 scm/driver/gitea/milestone.go create mode 100644 scm/driver/gitea/milestone_test.go create mode 100644 scm/driver/gitea/release.go create mode 100644 scm/driver/gitea/release_test.go create mode 100644 scm/driver/gitea/testdata/milestone.json create mode 100644 scm/driver/gitea/testdata/milestone.json.golden create mode 100644 scm/driver/gitea/testdata/milestone_create.json create mode 100644 scm/driver/gitea/testdata/milestones.json create mode 100644 scm/driver/gitea/testdata/milestones.json.golden create mode 100644 scm/driver/gitea/testdata/release.json create mode 100644 scm/driver/gitea/testdata/release.json.golden create mode 100644 scm/driver/gitea/testdata/release_create.json create mode 100644 scm/driver/gitea/testdata/release_update.json create mode 100644 scm/driver/gitea/testdata/releases.json create mode 100644 scm/driver/gitea/testdata/releases.json.golden create mode 100644 scm/driver/github/milestone.go create mode 100644 scm/driver/github/milestone_test.go create mode 100644 scm/driver/github/release.go create mode 100644 scm/driver/github/release_test.go create mode 100644 scm/driver/github/testdata/milestone.json create mode 100644 scm/driver/github/testdata/milestone.json.golden create mode 100644 scm/driver/github/testdata/milestone_create.json create mode 100644 scm/driver/github/testdata/milestones.json create mode 100644 scm/driver/github/testdata/milestones.json.golden create mode 100644 scm/driver/github/testdata/release.json create mode 100644 scm/driver/github/testdata/release.json.golden create mode 100644 scm/driver/github/testdata/releases.json create mode 100644 scm/driver/github/testdata/releases.json.golden create mode 100644 scm/driver/gitlab/milestone.go create mode 100644 scm/driver/gitlab/milestone_test.go create mode 100644 scm/driver/gitlab/release.go create mode 100644 scm/driver/gitlab/release_test.go create mode 100644 scm/driver/gitlab/testdata/milestone.json create mode 100644 scm/driver/gitlab/testdata/milestone.json.golden create mode 100644 scm/driver/gitlab/testdata/milestone_create.json create mode 100644 scm/driver/gitlab/testdata/milestone_update.json create mode 100644 scm/driver/gitlab/testdata/milestones.json create mode 100644 scm/driver/gitlab/testdata/milestones.json.golden create mode 100644 scm/driver/gitlab/testdata/release.json create mode 100644 scm/driver/gitlab/testdata/release.json.golden create mode 100644 scm/driver/gitlab/testdata/releases.json create mode 100644 scm/driver/gitlab/testdata/releases.json.golden create mode 100644 scm/driver/gogs/milestone.go create mode 100644 scm/driver/gogs/release.go create mode 100644 scm/driver/stash/milestone.go create mode 100644 scm/driver/stash/release.go create mode 100644 scm/milestone.go create mode 100644 scm/release.go diff --git a/go.mod b/go.mod index cd3f85a78..6cce62b48 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,8 @@ module github.com/drone/go-scm require ( github.com/google/go-cmp v0.2.0 github.com/h2non/gock v1.0.9 + github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 // indirect + github.com/stretchr/testify v1.7.0 ) go 1.13 diff --git a/go.sum b/go.sum index 7dbe62ae1..00f0342cb 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,17 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/h2non/gock v1.0.9 h1:17gCehSo8ZOgEsFKpQgqHiR7VLyjxdAG3lkhVvO9QZU= github.com/h2non/gock v1.0.9/go.mod h1:CZMcB0Lg5IWnr9bF79pPMg9WeV6WumxQiUJ1UvdO1iE= +github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4= +github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/scm/client.go b/scm/client.go index e6cbc5ae9..c89fe89a3 100644 --- a/scm/client.go +++ b/scm/client.go @@ -70,9 +70,11 @@ type ( // ListOptions specifies optional pagination // parameters. ListOptions struct { - URL string - Page int - Size int + URL string + Page int + Size int + Open bool + Closed bool } // Client manages communication with a version control @@ -93,8 +95,10 @@ type ( Git GitService Organizations OrganizationService Issues IssueService + Milestones MilestoneService PullRequests PullRequestService Repositories RepositoryService + Releases ReleaseService Reviews ReviewService Users UserService Webhooks WebhookService diff --git a/scm/const.go b/scm/const.go index ac81da919..638560da3 100644 --- a/scm/const.go +++ b/scm/const.go @@ -240,3 +240,5 @@ func (v Visibility) String() (s string) { return "unknown" } } + +const SearchTimeFormat = "2006-01-02T15:04:05Z" diff --git a/scm/driver/bitbucket/bitbucket.go b/scm/driver/bitbucket/bitbucket.go index f02f5e9b2..1b8a1af77 100644 --- a/scm/driver/bitbucket/bitbucket.go +++ b/scm/driver/bitbucket/bitbucket.go @@ -34,9 +34,11 @@ func New(uri string) (*scm.Client, error) { client.Contents = &contentService{client} client.Git = &gitService{client} client.Issues = &issueService{client} + client.Milestones = &milestoneService{client} client.Organizations = &organizationService{client} client.PullRequests = &pullService{&issueService{client}} client.Repositories = &repositoryService{client} + client.Releases = &releaseService{client} client.Reviews = &reviewService{client} client.Users = &userService{client} client.Webhooks = &webhookService{client} diff --git a/scm/driver/bitbucket/milestone.go b/scm/driver/bitbucket/milestone.go new file mode 100644 index 000000000..7e18430ae --- /dev/null +++ b/scm/driver/bitbucket/milestone.go @@ -0,0 +1,31 @@ +package bitbucket + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type milestoneService struct { + client *wrapper +} + +func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *milestoneService) List(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *milestoneService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *milestoneService) Update(ctx context.Context, repo string, id int, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} diff --git a/scm/driver/bitbucket/release.go b/scm/driver/bitbucket/release.go new file mode 100644 index 000000000..c38d0b40a --- /dev/null +++ b/scm/driver/bitbucket/release.go @@ -0,0 +1,43 @@ +package bitbucket + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type releaseService struct { + client *wrapper +} + +func (s *releaseService) Find(ctx context.Context, repo string, id int) (*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *releaseService) FindByTag(ctx context.Context, repo string, tag string) (*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *releaseService) List(ctx context.Context, repo string, opts scm.ReleaseListOptions) ([]*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *releaseService) Create(ctx context.Context, repo string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *releaseService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *releaseService) DeleteByTag(ctx context.Context, repo string, tag string) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *releaseService) Update(ctx context.Context, repo string, id int, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *releaseService) UpdateByTag(ctx context.Context, repo string, tag string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} diff --git a/scm/driver/gitea/git.go b/scm/driver/gitea/git.go index 8382b8cad..d1b2223e2 100644 --- a/scm/driver/gitea/git.go +++ b/scm/driver/gitea/git.go @@ -107,8 +107,8 @@ type ( commitInfo struct { Sha string `json:"sha"` Commit commit `json:"commit"` - Author user `json:"author"` - Committer user `json:"committer"` + Author User `json:"author"` + Committer User `json:"committer"` } // gitea signature object. @@ -176,7 +176,7 @@ func convertSignature(src signature) scm.Signature { } } -func convertUserSignature(src user) scm.Signature { +func convertUserSignature(src User) scm.Signature { return scm.Signature{ Login: userLogin(&src), Email: src.Email, diff --git a/scm/driver/gitea/gitea.go b/scm/driver/gitea/gitea.go index e52900189..3e8031cbd 100644 --- a/scm/driver/gitea/gitea.go +++ b/scm/driver/gitea/gitea.go @@ -35,9 +35,11 @@ func New(uri string) (*scm.Client, error) { client.Contents = &contentService{client} client.Git = &gitService{client} client.Issues = &issueService{client} + client.Milestones = & milestoneService{client} client.Organizations = &organizationService{client} client.PullRequests = &pullService{client} client.Repositories = &repositoryService{client} + client.Releases = &releaseService{client} client.Reviews = &reviewService{client} client.Users = &userService{client} client.Webhooks = &webhookService{client} diff --git a/scm/driver/gitea/gitea_test.go b/scm/driver/gitea/gitea_test.go index 79f0573da..658aef0c5 100644 --- a/scm/driver/gitea/gitea_test.go +++ b/scm/driver/gitea/gitea_test.go @@ -5,7 +5,10 @@ // package gitea implements a Gogs client. package gitea -import "testing" +import ( + "github.com/drone/go-scm/scm" + "testing" +) func TestClient(t *testing.T) { client, err := New("https://try.gitea.io") @@ -33,3 +36,20 @@ func TestClient_Error(t *testing.T) { t.Errorf("Expect error when invalid URL") } } + +func testPage(res *scm.Response) func(t *testing.T) { + return func(t *testing.T) { + if got, want := res.Page.Next, 2; got != want { + t.Errorf("Want next page %d, got %d", want, got) + } + if got, want := res.Page.Prev, 1; got != want { + t.Errorf("Want prev page %d, got %d", want, got) + } + if got, want := res.Page.First, 1; got != want { + t.Errorf("Want first page %d, got %d", want, got) + } + if got, want := res.Page.Last, 5; got != want { + t.Errorf("Want last page %d, got %d", want, got) + } + } +} \ No newline at end of file diff --git a/scm/driver/gitea/issue.go b/scm/driver/gitea/issue.go index e006920c8..b80524a62 100644 --- a/scm/driver/gitea/issue.go +++ b/scm/driver/gitea/issue.go @@ -87,9 +87,9 @@ type ( // gitea issue response object. issue struct { ID int `json:"id"` - Number int `json:"number"` - User user `json:"user"` - Title string `json:"title"` + Number int `json:"number"` + User User `json:"User"` + Title string `json:"title"` Body string `json:"body"` State string `json:"state"` Labels []string `json:"labels"` @@ -111,9 +111,9 @@ type ( // gitea issue comment response object. issueComment struct { ID int `json:"id"` - HTMLURL string `json:"html_url"` - User user `json:"user"` - Body string `json:"body"` + HTMLURL string `json:"html_url"` + User User `json:"User"` + Body string `json:"body"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } diff --git a/scm/driver/gitea/milestone.go b/scm/driver/gitea/milestone.go new file mode 100644 index 000000000..bec60a56e --- /dev/null +++ b/scm/driver/gitea/milestone.go @@ -0,0 +1,130 @@ +package gitea + +import ( + "context" + "fmt" + "time" + + "github.com/drone/go-scm/scm" +) + +type milestoneService struct { + client *wrapper +} + +func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) { + namespace, name := scm.Split(repo) + path := fmt.Sprintf("api/v1/repos/%s/%s/milestones/%d", namespace, name, id) + out := new(milestone) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertMilestone(out), res, err +} + +func (s *milestoneService) List(ctx context.Context, repo string, opts scm.MilestoneListOptions) ([]*scm.Milestone, *scm.Response, error) { + namespace, name := scm.Split(repo) + path := fmt.Sprintf("api/v1/repos/%s/%s/milestones%s", namespace, name, encodeMilestoneListOptions(opts)) + out := []*milestone{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertMilestoneList(out), res, err +} + +func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + namespace, name := scm.Split(repo) + path := fmt.Sprintf("api/v1/repos/%s/%s/milestones", namespace, name) + in := &milestoneInput{ + Title: input.Title, + Description: input.Description, + State: StateOpen, + Deadline: input.DueDate, + } + if input.State == "closed" { + in.State = StateClosed + } + out := new(milestone) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertMilestone(out), res, err +} + +func (s *milestoneService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + namespace, name := scm.Split(repo) + path := fmt.Sprintf("api/v1/repos/%s/%s/milestones/%d", namespace, name, id) + return s.client.do(ctx, "DELETE", path, nil, nil) +} + +func (s *milestoneService) Update(ctx context.Context, repo string, id int, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + namespace, name := scm.Split(repo) + path := fmt.Sprintf("api/v1/repos/%s/%s/milestones/%d", namespace, name, id) + in := milestoneInput{} + if input.Title != "" { + in.Title = input.Title + } + switch input.State { + case "open": + in.State = StateOpen + case "close", "closed": + in.State = StateClosed + } + if input.Description != "" { + in.Description = input.Description + } + if input.DueDate != nil { + in.Deadline = input.DueDate + } + out := new(milestone) + res, err := s.client.do(ctx, "PATCH", path, in, out) + return convertMilestone(out), res, err +} + +// StateType issue state type +type StateType string + +const ( + // StateOpen pr/issue is open + StateOpen StateType = "open" + // StateClosed pr/issue is closed + StateClosed StateType = "closed" + // StateAll is all + StateAll StateType = "all" +) + +type milestone struct { + ID int64 `json:"id"` + Title string `json:"title"` + Description string `json:"description"` + State StateType `json:"state"` + OpenIssues int `json:"open_issues"` + ClosedIssues int `json:"closed_issues"` + Created time.Time `json:"created_at"` + Updated *time.Time `json:"updated_at"` + Closed *time.Time `json:"closed_at"` + Deadline *time.Time `json:"due_on"` +} + +type milestoneInput struct { + Title string `json:"title"` + Description string `json:"description"` + State StateType `json:"state"` + Deadline *time.Time `json:"due_on"` +} + +func convertMilestoneList(src []*milestone) []*scm.Milestone { + var dst []*scm.Milestone + for _, v := range src { + dst = append(dst, convertMilestone(v)) + } + return dst +} + +func convertMilestone(src *milestone) *scm.Milestone { + if src == nil || src.Deadline == nil { + return nil + } + return &scm.Milestone{ + Number: int(src.ID), + ID: int(src.ID), + Title: src.Title, + Description: src.Description, + State: string(src.State), + DueDate: src.Deadline, + } +} diff --git a/scm/driver/gitea/milestone_test.go b/scm/driver/gitea/milestone_test.go new file mode 100644 index 000000000..5472f9738 --- /dev/null +++ b/scm/driver/gitea/milestone_test.go @@ -0,0 +1,178 @@ +package gitea + +import ( + "context" + "encoding/json" + "io/ioutil" + "testing" + "time" + + "github.com/drone/go-scm/scm" + + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" + "github.com/stretchr/testify/assert" +) + +func TestMilestoneFind(t *testing.T) { + defer gock.Off() + + mockServerVersion() + + gock.New("https://try.gitea.io"). + Get("/api/v1/repos/jcitizen/my-repo/milestones/1"). + Reply(200). + Type("application/json"). + File("testdata/milestone.json") + + client, _ := New("https://try.gitea.io") + got, _, err := client.Milestones.Find(context.Background(), "jcitizen/my-repo", 1) + if err != nil { + t.Error(err) + } + + want := new(scm.Milestone) + raw, _ := ioutil.ReadFile("testdata/milestone.json.golden") + err = json.Unmarshal(raw, want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + +func TestMilestoneList(t *testing.T) { + defer gock.Off() + + mockServerVersion() + + gock.New("https://try.gitea.io"). + Get("/api/v1/repos/jcitizen/my-repo/milestones"). + Reply(200). + Type("application/json"). + SetHeaders(mockPageHeaders). + File("testdata/milestones.json") + + client, _ := New("https://try.gitea.io") + got, res, err := client.Milestones.List(context.Background(), "jcitizen/my-repo", scm.MilestoneListOptions{}) + if err != nil { + t.Error(err) + } + + want := []*scm.Milestone{} + raw, _ := ioutil.ReadFile("testdata/milestones.json.golden") + err = json.Unmarshal(raw, &want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Page", testPage(res)) +} + +func TestMilestoneCreate(t *testing.T) { + defer gock.Off() + + mockServerVersion() + + gock.New("https://try.gitea.io"). + Post("/api/v1/repos/jcitizen/my-repo/milestones"). + File("testdata/milestone_create.json"). + Reply(200). + Type("application/json"). + File("testdata/milestone.json") + + client, _ := New("https://try.gitea.io") + dueDate, _ := time.Parse(scm.SearchTimeFormat, "2012-10-09T23:39:01Z") + input := &scm.MilestoneInput{ + Title: "v1.0", + Description: "Tracking milestone for version 1.0", + State: "open", + DueDate: &dueDate, + } + got, _, err := client.Milestones.Create(context.Background(), "jcitizen/my-repo", input) + if err != nil { + t.Error(err) + } + + want := new(scm.Milestone) + raw, _ := ioutil.ReadFile("testdata/milestone.json.golden") + err = json.Unmarshal(raw, want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + +func TestMilestoneUpdate(t *testing.T) { + defer gock.Off() + + mockServerVersion() + + gock.New("https://try.gitea.io"). + Patch("/api/v1/repos/jcitizen/my-repo/milestones"). + File("testdata/milestone_create.json"). + Reply(200). + Type("application/json"). + File("testdata/milestone.json") + + client, _ := New("https://try.gitea.io") + dueDate, _ := time.Parse(scm.SearchTimeFormat, "2012-10-09T23:39:01Z") + input := &scm.MilestoneInput{ + Title: "v1.0", + Description: "Tracking milestone for version 1.0", + State: "open", + DueDate: &dueDate, + } + got, _, err := client.Milestones.Update(context.Background(), "jcitizen/my-repo", 1, input) + if err != nil { + t.Error(err) + } + + want := new(scm.Milestone) + raw, _ := ioutil.ReadFile("testdata/milestone.json.golden") + err = json.Unmarshal(raw, want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + +func TestMilestoneDelete(t *testing.T) { + defer gock.Off() + + mockServerVersion() + + gock.New("https://try.gitea.io"). + Delete("/api/v1/repos/jcitizen/my-repo/milestones/1"). + Reply(200). + Type("application/json") + + client, _ := New("https://try.gitea.io") + _, err := client.Milestones.Delete(context.Background(), "jcitizen/my-repo", 1) + if err != nil { + t.Error(err) + } +} + +var mockPageHeaders = map[string]string{ + "Link": `; rel="next",` + + `; rel="prev",` + + `; rel="first",` + + `; rel="last"`, +} + +func mockServerVersion() { + gock.New("https://try.gitea.io"). + Get("/api/v1/version"). + Reply(200). + Type("application/json"). + File("testdata/version.json") +} diff --git a/scm/driver/gitea/org.go b/scm/driver/gitea/org.go index c7c7efc03..25d9b4c8b 100644 --- a/scm/driver/gitea/org.go +++ b/scm/driver/gitea/org.go @@ -27,7 +27,7 @@ func (s *organizationService) FindMembership(ctx context.Context, name, username } func (s *organizationService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Organization, *scm.Response, error) { - path := fmt.Sprintf("api/v1/user/orgs?%s", encodeListOptions(opts)) + path := fmt.Sprintf("api/v1/User/orgs?%s", encodeListOptions(opts)) out := []*org{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertOrgList(out), res, err diff --git a/scm/driver/gitea/org_test.go b/scm/driver/gitea/org_test.go index 90a0a193c..1515faaf1 100644 --- a/scm/driver/gitea/org_test.go +++ b/scm/driver/gitea/org_test.go @@ -53,7 +53,7 @@ func TestOrgList(t *testing.T) { defer gock.Off() gock.New("https://try.gitea.io"). - Get("/api/v1/user/orgs"). + Get("/api/v1/User/orgs"). Reply(200). Type("application/json"). File("testdata/organizations.json") diff --git a/scm/driver/gitea/pr.go b/scm/driver/gitea/pr.go index 754f46240..890aac0ad 100644 --- a/scm/driver/gitea/pr.go +++ b/scm/driver/gitea/pr.go @@ -83,9 +83,9 @@ func (s *pullService) Close(context.Context, string, int) (*scm.Response, error) type pr struct { ID int `json:"id"` - Number int `json:"number"` - User user `json:"user"` - Title string `json:"title"` + Number int `json:"number"` + User User `json:"User"` + Title string `json:"title"` Body string `json:"body"` State string `json:"state"` HeadBranch string `json:"head_branch"` diff --git a/scm/driver/gitea/release.go b/scm/driver/gitea/release.go new file mode 100644 index 000000000..e00e6e8e7 --- /dev/null +++ b/scm/driver/gitea/release.go @@ -0,0 +1,150 @@ +package gitea + +import ( + "context" + "fmt" + "time" + + "github.com/drone/go-scm/scm" +) + +type releaseService struct { + client *wrapper +} + +func (s *releaseService) Find(ctx context.Context, repo string, id int) (*scm.Release, *scm.Response, error) { + namespace, name := scm.Split(repo) + path := fmt.Sprintf("api/v1/repos/%s/%s/releases/%d", namespace, name, id) + out := new(release) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertRelease(out), res, err +} + +func (s *releaseService) FindByTag(ctx context.Context, repo string, tag string) (*scm.Release, *scm.Response, error) { + namespace, name := scm.Split(repo) + path := fmt.Sprintf("api/v1/repos/%s/%s/releases/tags/%s", namespace, name, tag) + out := new(release) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertRelease(out), res, err +} + +func (s *releaseService) List(ctx context.Context, repo string, opts scm.ReleaseListOptions) ([]*scm.Release, *scm.Response, error) { + namespace, name := scm.Split(repo) + path := fmt.Sprintf("api/v1/repos/%s/%s/releases?%s", namespace, name, encodeReleaseListOptions(opts)) + out := []*release{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertReleaseList(out), res, err +} + +func (s *releaseService) Create(ctx context.Context, repo string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + namespace, name := scm.Split(repo) + path := fmt.Sprintf("api/v1/repos/%s/%s/releases", namespace, name) + in := &ReleaseInput{ + TagName: input.Tag, + Target: input.Commitish, + Title: input.Title, + Note: input.Description, + IsDraft: input.Draft, + IsPrerelease: input.Prerelease, + } + out := new(release) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertRelease(out), res, err +} + +func (s *releaseService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + namespace, name := scm.Split(repo) + path := fmt.Sprintf("api/v1/repos/%s/%s/releases/%d", namespace, name, id) + return s.client.do(ctx, "DELETE", path, nil, nil) +} + +func (s *releaseService) DeleteByTag(ctx context.Context, repo string, tag string) (*scm.Response, error) { + namespace, name := scm.Split(repo) + path := fmt.Sprintf("api/v1/repos/%s/%s/releases/tags/%s", namespace, name, tag) + return s.client.do(ctx, "DELETE", path, nil, nil) +} + +func (s *releaseService) Update(ctx context.Context, repo string, id int, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + namespace, name := scm.Split(repo) + path := fmt.Sprintf("api/v1/repos/%s/%s/releases/%d", namespace, name, id) + in := &ReleaseInput{ + TagName: input.Tag, + Target: input.Commitish, + Title: input.Title, + Note: input.Description, + IsDraft: input.Draft, + IsPrerelease: input.Prerelease, + } + out := new(release) + res, err := s.client.do(ctx, "PATCH", path, in, out) + return convertRelease(out), res, err +} + +func (s *releaseService) UpdateByTag(ctx context.Context, repo string, tag string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + rel, _, err := s.FindByTag(ctx, repo, tag) + if err != nil { + return nil, nil, err + } + return s.Update(ctx, repo, rel.ID, input) +} + +type ReleaseInput struct { + TagName string `json:"tag_name"` + Target string `json:"target_commitish"` + Title string `json:"name"` + Note string `json:"body"` + IsDraft bool `json:"draft"` + IsPrerelease bool `json:"prerelease"` +} + +// release represents a repository release +type release struct { + ID int64 `json:"id"` + TagName string `json:"tag_name"` + Target string `json:"target_commitish"` + Title string `json:"name"` + Note string `json:"body"` + URL string `json:"url"` + HTMLURL string `json:"html_url"` + TarURL string `json:"tarball_url"` + ZipURL string `json:"zipball_url"` + IsDraft bool `json:"draft"` + IsPrerelease bool `json:"prerelease"` + CreatedAt time.Time `json:"created_at"` + PublishedAt time.Time `json:"published_at"` + Publisher *User `json:"author"` + Attachments []*Attachment `json:"assets"` +} + +type Attachment struct { + ID int64 `json:"id"` + Name string `json:"name"` + Size int64 `json:"size"` + DownloadCount int64 `json:"download_count"` + Created time.Time `json:"created_at"` + UUID string `json:"uuid"` + DownloadURL string `json:"browser_download_url"` +} + +func convertRelease(src *release) *scm.Release { + return &scm.Release{ + ID: int(src.ID), + Title: src.Title, + Description: src.Note, + Link: ConvertAPIURLToHTMLURL(src.URL, src.TagName), + Tag: src.TagName, + Commitish: src.Target, + Draft: src.IsDraft, + Prerelease: src.IsPrerelease, + Created: src.CreatedAt, + Published: src.PublishedAt, + } +} + +func convertReleaseList(src []*release) []*scm.Release { + var dst []*scm.Release + for _, v := range src { + dst = append(dst, convertRelease(v)) + } + return dst +} diff --git a/scm/driver/gitea/release_test.go b/scm/driver/gitea/release_test.go new file mode 100644 index 000000000..762b944bd --- /dev/null +++ b/scm/driver/gitea/release_test.go @@ -0,0 +1,342 @@ +package gitea + +import ( + "context" + "encoding/json" + "io/ioutil" + "testing" + + "github.com/drone/go-scm/scm" + + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" + "github.com/stretchr/testify/assert" +) + +func TestConvertAPIURLToHTMLURL(t *testing.T) { + + got := ConvertAPIURLToHTMLURL("https://try.gitea.com/api/v1/repos/octocat/Hello-World/123", "v1.0.0") + want := "https://try.gitea.com/octocat/Hello-World/releases/tag/v1.0.0" + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + + t.Log("got:") + t.Log(string(got)) + } + +} + +func TestConvertAPIURLToHTMLURLEmptyLinkWhenURLParseFails(t *testing.T) { + + broken := []string{"http s://try.gitea.com/api/v1/repos/octocat/Hello-World/123", "https://try.gitea.com/api/v1/repos/octocat/Hello-World"} + for _, url := range broken { + + got := ConvertAPIURLToHTMLURL(url, "v1.0.0") + want := "" + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + + t.Log("got:") + t.Log(string(got)) + } + } + +} + +func TestReleaseFind(t *testing.T) { + defer gock.Off() + + mockServerVersion() + + gock.New("https://try.gitea.io"). + Get("/repos/octocat/hello-world/releases/1"). + Reply(200). + Type("application/json"). + File("testdata/release.json") + + client, err := New("https://try.gitea.io") + if err != nil { + t.Error(err) + return + } + got, _, err := client.Releases.Find(context.Background(), "octocat/hello-world", 1) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Release) + raw, _ := ioutil.ReadFile("testdata/release.json.golden") + err = json.Unmarshal(raw, want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + + data, _ := json.Marshal(got) + t.Log("got JSON:") + t.Log(string(data)) + } +} + +func TestReleaseFindByTag(t *testing.T) { + defer gock.Off() + + mockServerVersion() + + gock.New("https://try.gitea.io"). + Get("/repos/octocat/hello-world/releases/tags/v1.0.0"). + Reply(200). + Type("application/json"). + File("testdata/release.json") + + client, err := New("https://try.gitea.io") + if err != nil { + t.Error(err) + return + } + got, _, err := client.Releases.FindByTag(context.Background(), "octocat/hello-world", "v1.0.0") + if err != nil { + t.Error(err) + return + } + + want := new(scm.Release) + raw, _ := ioutil.ReadFile("testdata/release.json.golden") + err = json.Unmarshal(raw, want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + + data, _ := json.Marshal(got) + t.Log("got JSON:") + t.Log(string(data)) + } +} + +func TestReleaseList(t *testing.T) { + defer gock.Off() + + mockServerVersion() + + gock.New("https://try.gitea.io"). + Get("/repos/octocat/hello-world/releases"). + MatchParam("page", "1"). + MatchParam("limit", "30"). + Reply(200). + Type("application/json"). + File("testdata/releases.json") + + client, err := New("https://try.gitea.io") + if err != nil { + t.Error(err) + return + } + + got, _, err := client.Releases.List(context.Background(), "octocat/hello-world", scm.ReleaseListOptions{Page: 1, Size: 30, Open: true, Closed: true}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Release{} + raw, _ := ioutil.ReadFile("testdata/releases.json.golden") + err = json.Unmarshal(raw, &want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + + data, _ := json.Marshal(got) + t.Log("got JSON:") + t.Log(string(data)) + } + +} + +func TestReleaseCreate(t *testing.T) { + defer gock.Off() + + mockServerVersion() + + gock.New("https://try.gitea.io"). + Post("/repos/octocat/hello-world/releases"). + File("testdata/release_create.json"). + Reply(200). + Type("application/json"). + File("testdata/release.json") + + client, err := New("https://try.gitea.io") + if err != nil { + t.Error(err) + return + } + input := &scm.ReleaseInput{ + Title: "v1.0.0", + Description: "Description of the release", + Tag: "v1.0.0", + Commitish: "master", + Draft: false, + Prerelease: false, + } + + got, _, err := client.Releases.Create(context.Background(), "octocat/hello-world", input) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Release) + raw, _ := ioutil.ReadFile("testdata/release.json.golden") + err = json.Unmarshal(raw, want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + + data, _ := json.Marshal(got) + t.Log("got JSON:") + t.Log(string(data)) + } + +} + +func TestReleaseUpdate(t *testing.T) { + defer gock.Off() + + mockServerVersion() + + gock.New("https://try.gitea.io"). + Patch("/repos/octocat/hello-world/releases/1"). + File("testdata/release_update.json"). + Reply(200). + Type("application/json"). + File("testdata/release.json") + + client, err := New("https://try.gitea.io") + if err != nil { + t.Error(err) + return + } + input := &scm.ReleaseInput{ + Title: "v1.0.0", + Description: "Description of the release", + Tag: "v1.0.0", + Commitish: "master", + Draft: false, + Prerelease: false, + } + got, _, err := client.Releases.Update(context.Background(), "octocat/hello-world", 1, input) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Release) + raw, _ := ioutil.ReadFile("testdata/release.json.golden") + err = json.Unmarshal(raw, want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + +} + +func TestReleaseUpdateByTag(t *testing.T) { + defer gock.Off() + + mockServerVersion() + + gock.New("https://try.gitea.io"). + Get("/repos/octocat/hello-world/releases/tags/v1.0.0"). + Reply(200). + Type("application/json"). + File("testdata/release.json") + + gock.New("https://try.gitea.io"). + Patch("/repos/octocat/hello-world/releases/1"). + File("testdata/release_update.json"). + Reply(200). + Type("application/json"). + File("testdata/release.json") + + client, err := New("https://try.gitea.io") + if err != nil { + t.Error(err) + return + } + input := &scm.ReleaseInput{ + Title: "v1.0.0", + Description: "Description of the release", + Tag: "v1.0.0", + Commitish: "master", + Draft: false, + Prerelease: false, + } + got, _, err := client.Releases.UpdateByTag(context.Background(), "octocat/hello-world", "v1.0.0", input) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Release) + raw, _ := ioutil.ReadFile("testdata/release.json.golden") + err = json.Unmarshal(raw, want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + +} + + +func TestReleaseDelete(t *testing.T) { + defer gock.Off() + + mockServerVersion() + + gock.New("https://try.gitea.io"). + Delete("/repos/octocat/hello-world/releases/1"). + Reply(200). + Type("application/json") + + client, err := New("https://try.gitea.io") + _, err = client.Releases.Delete(context.Background(), "octocat/hello-world", 1) + if err != nil { + t.Error(err) + return + } + +} + +func TestReleaseDeleteByTag(t *testing.T) { + defer gock.Off() + + mockServerVersion() + + gock.New("https://try.gitea.io"). + Delete("/repos/octocat/hello-world/releases/tags/v1.0.0"). + Reply(200). + Type("application/json") + + client, err := New("https://try.gitea.io") + _, err = client.Releases.DeleteByTag(context.Background(), "octocat/hello-world", "v1.0.0") + if err != nil { + t.Error(err) + return + } + +} \ No newline at end of file diff --git a/scm/driver/gitea/repo.go b/scm/driver/gitea/repo.go index 154c7f322..7a2ca2fea 100644 --- a/scm/driver/gitea/repo.go +++ b/scm/driver/gitea/repo.go @@ -40,7 +40,7 @@ func (s *repositoryService) FindPerms(ctx context.Context, repo string) (*scm.Pe } func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { - path := fmt.Sprintf("api/v1/user/repos?%s", encodeListOptions(opts)) + path := fmt.Sprintf("api/v1/User/repos?%s", encodeListOptions(opts)) out := []*repository{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertRepositoryList(out), res, err @@ -135,9 +135,9 @@ func (s *repositoryService) DeleteHook(ctx context.Context, repo string, id stri type ( // gitea repository resource. repository struct { - ID int `json:"id"` - Owner user `json:"owner"` - Name string `json:"name"` + ID int `json:"id"` + Owner User `json:"owner"` + Name string `json:"name"` FullName string `json:"full_name"` Private bool `json:"private"` Fork bool `json:"fork"` diff --git a/scm/driver/gitea/repo_test.go b/scm/driver/gitea/repo_test.go index bf9da32ae..e252b32f6 100644 --- a/scm/driver/gitea/repo_test.go +++ b/scm/driver/gitea/repo_test.go @@ -73,7 +73,7 @@ func TestRepoList(t *testing.T) { defer gock.Off() gock.New("https://try.gitea.io"). - Get("/api/v1/user/repos"). + Get("/api/v1/User/repos"). Reply(200). Type("application/json"). File("testdata/repos.json") diff --git a/scm/driver/gitea/testdata/milestone.json b/scm/driver/gitea/testdata/milestone.json new file mode 100644 index 000000000..9d69fb31c --- /dev/null +++ b/scm/driver/gitea/testdata/milestone.json @@ -0,0 +1,12 @@ +{ + "closed_at": "2020-09-11T19:32:38.046Z", + "closed_issues": 0, + "created_at": "2020-09-11T19:32:38.046Z", + "description": "string", + "due_on": "2020-09-11T19:32:38.046Z", + "id": 1, + "open_issues": 0, + "state": "open", + "title": "string", + "updated_at": "2020-09-11T19:32:38.046Z" +} diff --git a/scm/driver/gitea/testdata/milestone.json.golden b/scm/driver/gitea/testdata/milestone.json.golden new file mode 100644 index 000000000..be885236a --- /dev/null +++ b/scm/driver/gitea/testdata/milestone.json.golden @@ -0,0 +1,8 @@ +{ + "Description": "string", + "DueDate": "2020-09-11T19:32:38.046Z", + "ID": 1, + "Number": 1, + "State": "open", + "Title": "string" +} diff --git a/scm/driver/gitea/testdata/milestone_create.json b/scm/driver/gitea/testdata/milestone_create.json new file mode 100644 index 000000000..ca4130241 --- /dev/null +++ b/scm/driver/gitea/testdata/milestone_create.json @@ -0,0 +1,6 @@ +{ + "title": "v1.0", + "description": "Tracking milestone for version 1.0", + "state": "open", + "due_on": "2012-10-09T23:39:01Z" +} diff --git a/scm/driver/gitea/testdata/milestones.json b/scm/driver/gitea/testdata/milestones.json new file mode 100644 index 000000000..90cb3ed92 --- /dev/null +++ b/scm/driver/gitea/testdata/milestones.json @@ -0,0 +1,14 @@ +[ + { + "closed_at": "2020-09-11T19:32:38.046Z", + "closed_issues": 0, + "created_at": "2020-09-11T19:32:38.046Z", + "description": "string", + "due_on": "2020-09-11T19:32:38.046Z", + "id": 1, + "open_issues": 0, + "state": "open", + "title": "string", + "updated_at": "2020-09-11T19:32:38.046Z" + } +] diff --git a/scm/driver/gitea/testdata/milestones.json.golden b/scm/driver/gitea/testdata/milestones.json.golden new file mode 100644 index 000000000..23ce5fd75 --- /dev/null +++ b/scm/driver/gitea/testdata/milestones.json.golden @@ -0,0 +1,10 @@ +[ + { + "Description": "string", + "DueDate": "2020-09-11T19:32:38.046Z", + "ID": 1, + "Number": 1, + "State": "open", + "Title": "string" + } +] diff --git a/scm/driver/gitea/testdata/release.json b/scm/driver/gitea/testdata/release.json new file mode 100644 index 000000000..02eeed341 --- /dev/null +++ b/scm/driver/gitea/testdata/release.json @@ -0,0 +1,10 @@ +{ + "id": 1, + "name": "v1.0.0", + "body": "Description of the release", + "url": "https://try.gitea.com/api/v1/repos/octocat/Hello-World/123", + "tag_name": "v1.0.0", + "target_commitish": "master", + "draft": false, + "prerelease": false +} \ No newline at end of file diff --git a/scm/driver/gitea/testdata/release.json.golden b/scm/driver/gitea/testdata/release.json.golden new file mode 100644 index 000000000..5ebc0ddf8 --- /dev/null +++ b/scm/driver/gitea/testdata/release.json.golden @@ -0,0 +1,10 @@ +{ + "ID": 1, + "Title": "v1.0.0", + "Description": "Description of the release", + "Link": "https://try.gitea.com/octocat/Hello-World/releases/tag/v1.0.0", + "Tag": "v1.0.0", + "Commitish": "master", + "Draft": false, + "Prerelease": false +} \ No newline at end of file diff --git a/scm/driver/gitea/testdata/release_create.json b/scm/driver/gitea/testdata/release_create.json new file mode 100644 index 000000000..37e53d251 --- /dev/null +++ b/scm/driver/gitea/testdata/release_create.json @@ -0,0 +1,8 @@ +{ + "tag_name": "v1.0.0", + "target_commitish": "master", + "name": "v1.0.0", + "body": "Description of the release", + "draft": false, + "prerelease": false +} \ No newline at end of file diff --git a/scm/driver/gitea/testdata/release_update.json b/scm/driver/gitea/testdata/release_update.json new file mode 100644 index 000000000..37e53d251 --- /dev/null +++ b/scm/driver/gitea/testdata/release_update.json @@ -0,0 +1,8 @@ +{ + "tag_name": "v1.0.0", + "target_commitish": "master", + "name": "v1.0.0", + "body": "Description of the release", + "draft": false, + "prerelease": false +} \ No newline at end of file diff --git a/scm/driver/gitea/testdata/releases.json b/scm/driver/gitea/testdata/releases.json new file mode 100644 index 000000000..252ace560 --- /dev/null +++ b/scm/driver/gitea/testdata/releases.json @@ -0,0 +1,12 @@ +[ + { + "id": 1, + "name": "v1.0.0", + "body": "Description of the release", + "url": "https://try.gitea.com/api/v1/repos/octocat/Hello-World/123", + "tag_name": "v1.0.0", + "target_commitish": "master", + "draft": false, + "prerelease": false + } +] \ No newline at end of file diff --git a/scm/driver/gitea/testdata/releases.json.golden b/scm/driver/gitea/testdata/releases.json.golden new file mode 100644 index 000000000..51a6b244a --- /dev/null +++ b/scm/driver/gitea/testdata/releases.json.golden @@ -0,0 +1,12 @@ +[ + { + "ID": 1, + "Title": "v1.0.0", + "Description": "Description of the release", + "Link": "https://try.gitea.com/octocat/Hello-World/releases/tag/v1.0.0", + "Tag": "v1.0.0", + "Commitish": "master", + "Draft": false, + "Prerelease": false + } +] \ No newline at end of file diff --git a/scm/driver/gitea/user.go b/scm/driver/gitea/user.go index 09b9e9399..623cbbdb4 100644 --- a/scm/driver/gitea/user.go +++ b/scm/driver/gitea/user.go @@ -16,14 +16,14 @@ type userService struct { } func (s *userService) Find(ctx context.Context) (*scm.User, *scm.Response, error) { - out := new(user) - res, err := s.client.do(ctx, "GET", "api/v1/user", nil, out) + out := new(User) + res, err := s.client.do(ctx, "GET", "api/v1/User", nil, out) return convertUser(out), res, err } func (s *userService) FindLogin(ctx context.Context, login string) (*scm.User, *scm.Response, error) { path := fmt.Sprintf("api/v1/users/%s", login) - out := new(user) + out := new(User) res, err := s.client.do(ctx, "GET", path, nil, out) return convertUser(out), res, err } @@ -37,7 +37,7 @@ func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, err // native data structures // -type user struct { +type User struct { ID int `json:"id"` Login string `json:"login"` Username string `json:"username"` @@ -50,7 +50,7 @@ type user struct { // native data structure conversion // -func convertUser(src *user) *scm.User { +func convertUser(src *User) *scm.User { return &scm.User{ Login: userLogin(src), Avatar: src.Avatar, @@ -59,7 +59,7 @@ func convertUser(src *user) *scm.User { } } -func userLogin(src *user) string { +func userLogin(src *User) string { if src.Username != "" { return src.Username } diff --git a/scm/driver/gitea/user_test.go b/scm/driver/gitea/user_test.go index 64d1eaaa6..24d9f9e3e 100644 --- a/scm/driver/gitea/user_test.go +++ b/scm/driver/gitea/user_test.go @@ -20,10 +20,10 @@ func TestUserFind(t *testing.T) { defer gock.Off() gock.New("https://try.gitea.io"). - Get("/api/v1/user"). + Get("/api/v1/User"). Reply(200). Type("application/json"). - File("testdata/user.json") + File("testdata/User.json") client, _ := New("https://try.gitea.io") got, _, err := client.Users.Find(context.Background()) @@ -32,7 +32,7 @@ func TestUserFind(t *testing.T) { } want := new(scm.User) - raw, _ := ioutil.ReadFile("testdata/user.json.golden") + raw, _ := ioutil.ReadFile("testdata/User.json.golden") json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { @@ -48,7 +48,7 @@ func TestUserLoginFind(t *testing.T) { Get("/api/v1/users/jcitizen"). Reply(200). Type("application/json"). - File("testdata/user.json") + File("testdata/User.json") client, _ := New("https://try.gitea.io") got, _, err := client.Users.FindLogin(context.Background(), "jcitizen") @@ -57,7 +57,7 @@ func TestUserLoginFind(t *testing.T) { } want := new(scm.User) - raw, _ := ioutil.ReadFile("testdata/user.json.golden") + raw, _ := ioutil.ReadFile("testdata/User.json.golden") json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { @@ -70,10 +70,10 @@ func TestUserFindEmail(t *testing.T) { defer gock.Off() gock.New("https://try.gitea.io"). - Get("/api/v1/user"). + Get("/api/v1/User"). Reply(200). Type("application/json"). - File("testdata/user.json") + File("testdata/User.json") client, _ := New("https://try.gitea.io") email, _, err := client.Users.FindEmail(context.Background()) diff --git a/scm/driver/gitea/util.go b/scm/driver/gitea/util.go index 1179ddaeb..e88ed4c66 100644 --- a/scm/driver/gitea/util.go +++ b/scm/driver/gitea/util.go @@ -5,8 +5,10 @@ package gitea import ( + "fmt" "net/url" "strconv" + "strings" "github.com/drone/go-scm/scm" ) @@ -53,3 +55,53 @@ func encodePullRequestListOptions(opts scm.PullRequestListOptions) string { } return params.Encode() } + +// ConvertAPIURLToHTMLURL converts an release API endpoint into a html endpoint +func ConvertAPIURLToHTMLURL(apiURL string, tagName string) string { + // "url": "https://try.gitea.com/api/v1/repos/octocat/Hello-World/123", + // "html_url": "https://try.gitea.com/octocat/Hello-World/releases/tag/v1.0.0", + // the url field is the API url, not the html url, so until go-sdk v0.13.3, build it ourselves + link, err := url.Parse(apiURL) + if err != nil { + return "" + } + + pathParts := strings.Split(link.Path, "/") + if len(pathParts) != 7 { + return "" + } + link.Path = fmt.Sprintf("/%s/%s/releases/tag/%s", pathParts[4], pathParts[5], tagName) + return link.String() +} + +func encodeMilestoneListOptions(opts scm.MilestoneListOptions) string { + params := url.Values{} + if opts.Page != 0 { + params.Set("page", strconv.Itoa(opts.Page)) + } + if opts.Size != 0 { + params.Set("per_page", strconv.Itoa(opts.Size)) + } + if opts.Open && opts.Closed { + params.Set("state", "all") + } else if opts.Closed { + params.Set("state", "closed") + } + return params.Encode() +} + +func encodeReleaseListOptions(opts scm.ReleaseListOptions) string { + params := url.Values{} + if opts.Page != 0 { + params.Set("page", strconv.Itoa(opts.Page)) + } + if opts.Size != 0 { + params.Set("per_page", strconv.Itoa(opts.Size)) + } + if opts.Open && opts.Closed { + params.Set("state", "all") + } else if opts.Closed { + params.Set("state", "closed") + } + return params.Encode() +} \ No newline at end of file diff --git a/scm/driver/gitea/webhook.go b/scm/driver/gitea/webhook.go index 30dc4e38e..22e07bfda 100644 --- a/scm/driver/gitea/webhook.go +++ b/scm/driver/gitea/webhook.go @@ -146,8 +146,8 @@ type ( Compare string `json:"compare_url"` Commits []commit `json:"commits"` Repository repository `json:"repository"` - Pusher user `json:"pusher"` - Sender user `json:"sender"` + Pusher User `json:"pusher"` + Sender User `json:"sender"` } // gitea create webhook payload @@ -156,8 +156,8 @@ type ( RefType string `json:"ref_type"` Sha string `json:"sha"` DefaultBranch string `json:"default_branch"` - Repository repository `json:"repository"` - Sender user `json:"sender"` + Repository repository `json:"repository"` + Sender User `json:"sender"` } // gitea issue webhook payload @@ -165,8 +165,8 @@ type ( Action string `json:"action"` Issue issue `json:"issue"` Comment issueComment `json:"comment"` - Repository repository `json:"repository"` - Sender user `json:"sender"` + Repository repository `json:"repository"` + Sender User `json:"sender"` } // gitea pull request webhook payload @@ -174,8 +174,8 @@ type ( Action string `json:"action"` Number int `json:"number"` PullRequest pr `json:"pull_request"` - Repository repository `json:"repository"` - Sender user `json:"sender"` + Repository repository `json:"repository"` + Sender User `json:"sender"` } ) diff --git a/scm/driver/github/github.go b/scm/driver/github/github.go index 82f315112..8464b3e2f 100644 --- a/scm/driver/github/github.go +++ b/scm/driver/github/github.go @@ -38,9 +38,11 @@ func New(uri string) (*scm.Client, error) { client.Contents = &contentService{client} client.Git = &gitService{client} client.Issues = &issueService{client} + client.Milestones = &milestoneService{client} client.Organizations = &organizationService{client} client.PullRequests = &pullService{&issueService{client}} client.Repositories = &RepositoryService{client} + client.Releases = &releaseService{client} client.Reviews = &reviewService{client} client.Users = &userService{client} client.Webhooks = &webhookService{client} diff --git a/scm/driver/github/milestone.go b/scm/driver/github/milestone.go new file mode 100644 index 000000000..beb8847e7 --- /dev/null +++ b/scm/driver/github/milestone.go @@ -0,0 +1,111 @@ +package github + +import ( + "context" + "fmt" + "time" + + "github.com/drone/go-scm/scm" +) + +type milestoneService struct { + client *wrapper +} + +type milestone struct { + ID int `json:"id"` + Number int `json:"number"` + Title string `json:"title"` + Description string `json:"description"` + State string `json:"state"` + DueOn time.Time `json:"due_on"` + URL string `json:"url"` + HTMLURL string `json:"html_url"` + LabelsURL string `json:"labels_url"` + Creator user `json:"creator"` + OpenIssues int `json:"open_issues"` + ClosedIssues int `json:"closed_issues"` + NodeID string `json:"node_id"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + ClosedAt time.Time `json:"closed_at"` +} + +type milestoneInput struct { + Title string `json:"title"` + State string `json:"state"` + Description string `json:"description"` + DueOn time.Time `json:"due_on"` +} + +func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/milestones/%d", repo, id) + out := new(milestone) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertMilestone(out), res, err +} + +func (s *milestoneService) List(ctx context.Context, repo string, opts scm.MilestoneListOptions) ([]*scm.Milestone, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/milestones?%s", repo, encodeMilestoneListOptions(opts)) + out := []*milestone{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertMilestoneList(out), res, err +} + +func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/milestones", repo) + in := &milestoneInput{ + Title: input.Title, + State: input.State, + Description: input.Description, + DueOn: *input.DueDate, + } + out := new(milestone) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertMilestone(out), res, err +} + +func (s *milestoneService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + path := fmt.Sprintf("repos/%s/milestones/%d", repo, id) + return s.client.do(ctx, "DELETE", path, nil, nil) +} + +func (s *milestoneService) Update(ctx context.Context, repo string, id int, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/milestones/%d", repo, id) + in := &milestoneInput{} + if input.Title != "" { + in.Title = input.Title + } + if input.State != "" { + in.State = input.State + } + if input.Description != "" { + in.Description = input.Description + } + if input.DueDate != nil { + in.DueOn = *input.DueDate + } + out := new(milestone) + res, err := s.client.do(ctx, "PATCH", path, in, out) + return convertMilestone(out), res, err +} + +func convertMilestoneList(from []*milestone) []*scm.Milestone { + var to []*scm.Milestone + for _, m := range from { + to = append(to, convertMilestone(m)) + } + return to +} + +func convertMilestone(from *milestone) *scm.Milestone { + return &scm.Milestone{ + Number: from.Number, + ID: from.ID, + Title: from.Title, + Description: from.Description, + Link: from.HTMLURL, + State: from.State, + DueDate: &from.DueOn, + } +} diff --git a/scm/driver/github/milestone_test.go b/scm/driver/github/milestone_test.go new file mode 100644 index 000000000..a9d28d05c --- /dev/null +++ b/scm/driver/github/milestone_test.go @@ -0,0 +1,177 @@ +package github + +import ( + "context" + "encoding/json" + "github.com/drone/go-scm/scm" + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" + "github.com/stretchr/testify/assert" + "io/ioutil" + "testing" + "time" +) + +func TestMilestoneFind(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Get("/repos/octocat/hello-world/milestones/1"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/milestone.json") + + client := NewDefault() + got, res, err := client.Milestones.Find(context.Background(), "octocat/hello-world", 1) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Milestone) + raw, _ := ioutil.ReadFile("testdata/milestone.json.golden") + err = json.Unmarshal(raw, want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} + +func TestMilestoneList(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Get("/repos/octocat/hello-world/milestones"). + MatchParam("page", "1"). + MatchParam("per_page", "30"). + MatchParam("state", "all"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/milestones.json") + client := NewDefault() + got, res, err := client.Milestones.List(context.Background(), "octocat/hello-world", scm.MilestoneListOptions{Page: 1, Size: 30, Open: true, Closed: true}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Milestone{} + raw, _ := ioutil.ReadFile("testdata/milestones.json.golden") + err = json.Unmarshal(raw, &want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} + +func TestMilestoneCreate(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Post("/repos/octocat/hello-world/milestones"). + File("testdata/milestone_create.json"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/milestone.json") + + client := NewDefault() + dueDate, _ := time.Parse(scm.SearchTimeFormat, "2012-10-09T23:39:01Z") + input := &scm.MilestoneInput{ + Title: "v1.0", + Description: "Tracking milestone for version 1.0", + State: "open", + DueDate: &dueDate, + } + + got, res, err := client.Milestones.Create(context.Background(), "octocat/hello-world", input) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Milestone) + raw, _ := ioutil.ReadFile("testdata/milestone.json.golden") + err = json.Unmarshal(raw, want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} + +func TestMilestoneUpdate(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Patch("/repos/octocat/hello-world/milestones/1"). + File("testdata/milestone_create.json"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/milestone.json") + + client := NewDefault() + dueDate, _ := time.Parse(scm.SearchTimeFormat, "2012-10-09T23:39:01Z") + input := &scm.MilestoneInput{ + Title: "v1.0", + Description: "Tracking milestone for version 1.0", + State: "open", + DueDate: &dueDate, + } + + got, res, err := client.Milestones.Update(context.Background(), "octocat/hello-world", 1, input) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Milestone) + raw, _ := ioutil.ReadFile("testdata/milestone.json.golden") + err = json.Unmarshal(raw, want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} + +func TestMilestoneDelete(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Delete("/repos/octocat/hello-world/milestones/1"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders) + + client := NewDefault() + res, err := client.Milestones.Delete(context.Background(), "octocat/hello-world", 1) + if err != nil { + t.Error(err) + return + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} diff --git a/scm/driver/github/release.go b/scm/driver/github/release.go new file mode 100644 index 000000000..add064d27 --- /dev/null +++ b/scm/driver/github/release.go @@ -0,0 +1,131 @@ +package github + +import ( + "context" + "fmt" + "time" + + "github.com/drone/go-scm/scm" +) + +type releaseService struct { + client *wrapper +} + +type release struct { + ID int `json:"id"` + Title string `json:"name"` + Description string `json:"body"` + Link string `json:"html_url,omitempty"` + Tag string `json:"tag_name,omitempty"` + Commitish string `json:"target_commitish,omitempty"` + Draft bool `json:"draft"` + Prerelease bool `json:"prerelease"` + Created time.Time `json:"created_at"` + Published time.Time `json:"published_at"` +} + +type releaseInput struct { + Title string `json:"name"` + Description string `json:"body"` + Tag string `json:"tag_name"` + Commitish string `json:"target_commitish"` + Draft bool `json:"draft"` + Prerelease bool `json:"prerelease"` +} + +func (s *releaseService) Find(ctx context.Context, repo string, id int) (*scm.Release, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/releases/%d", repo, id) + out := new(release) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertRelease(out), res, err +} + +func (s *releaseService) FindByTag(ctx context.Context, repo string, tag string) (*scm.Release, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/releases/tags/%s", repo, tag) + out := new(release) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertRelease(out), res, err +} + +func (s *releaseService) List(ctx context.Context, repo string, opts scm.ReleaseListOptions) ([]*scm.Release, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/releases?%s", repo, encodeReleaseListOptions(opts)) + out := []*release{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertReleaseList(out), res, err +} + +func (s *releaseService) Create(ctx context.Context, repo string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/releases", repo) + in := &releaseInput{ + Title: input.Title, + Commitish: input.Commitish, + Description: input.Description, + Draft: input.Draft, + Prerelease: input.Prerelease, + Tag: input.Tag, + } + out := new(release) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertRelease(out), res, err +} + +func (s *releaseService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + path := fmt.Sprintf("repos/%s/releases/%d", repo, id) + return s.client.do(ctx, "DELETE", path, nil, nil) +} + +func (s *releaseService) DeleteByTag(ctx context.Context, repo string, tag string) (*scm.Response, error) { + rel, _, _ := s.FindByTag(ctx, repo, tag) + return s.Delete(ctx, repo, rel.ID) +} + +func (s *releaseService) Update(ctx context.Context, repo string, id int, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/releases/%d", repo, id) + in := &releaseInput{} + if input.Title != "" { + in.Title = input.Title + } + if input.Description != "" { + in.Description = input.Description + } + if input.Commitish != "" { + in.Commitish = input.Commitish + } + if input.Tag != "" { + in.Tag = input.Tag + } + in.Draft = input.Draft + in.Prerelease = input.Prerelease + out := new(release) + res, err := s.client.do(ctx, "PATCH", path, in, out) + return convertRelease(out), res, err +} + +func (s *releaseService) UpdateByTag(ctx context.Context, repo string, tag string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + rel, _, _ := s.FindByTag(ctx, repo, tag) + return s.Update(ctx, repo, rel.ID, input) +} + +func convertReleaseList(from []*release) []*scm.Release { + var to []*scm.Release + for _, m := range from { + to = append(to, convertRelease(m)) + } + return to +} + +func convertRelease(from *release) *scm.Release { + return &scm.Release{ + ID: from.ID, + Title: from.Title, + Description: from.Description, + Link: from.Link, + Tag: from.Tag, + Commitish: from.Commitish, + Draft: from.Draft, + Prerelease: from.Prerelease, + Created: from.Created, + Published: from.Published, + } +} diff --git a/scm/driver/github/release_test.go b/scm/driver/github/release_test.go new file mode 100644 index 000000000..a42cb8021 --- /dev/null +++ b/scm/driver/github/release_test.go @@ -0,0 +1,186 @@ +package github + +import ( + "context" + "encoding/json" + "github.com/drone/go-scm/scm" + "github.com/h2non/gock" + "io/ioutil" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/assert" +) + +func TestReleaseFind(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Get("/repos/octocat/hello-world/releases/1"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/release.json") + + client := NewDefault() + got, res, err := client.Releases.Find(context.Background(), "octocat/hello-world", 1) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Release) + raw, _ := ioutil.ReadFile("testdata/release.json.golden") + err = json.Unmarshal(raw, want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + + data, _ := json.Marshal(got) + t.Log("got JSON:") + t.Log(string(data)) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} + +func TestReleaseList(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Get("/repos/octocat/hello-world/releases"). + MatchParam("page", "1"). + MatchParam("per_page", "30"). + MatchParam("state", "all"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/releases.json") + + client := NewDefault() + got, res, err := client.Releases.List(context.Background(), "octocat/hello-world", scm.ReleaseListOptions{Page: 1, Size: 30, Open: true, Closed: true}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Release{} + raw, _ := ioutil.ReadFile("testdata/releases.json.golden") + err = json.Unmarshal(raw, &want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + + data, _ := json.Marshal(got) + t.Log("got JSON:") + t.Log(string(data)) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} + +func TestReleaseCreate(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Post("/repos/octocat/hello-world/releases"). + File("testdata/release_create.json"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/release.json") + + client := NewDefault() + input := &scm.ReleaseInput{ + Title: "v1.0", + Description: "Tracking release for version 1.0", + Tag: "v1.0", + } + + got, res, err := client.Releases.Create(context.Background(), "octocat/hello-world", input) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Release) + raw, _ := ioutil.ReadFile("testdata/release.json.golden") + err = json.Unmarshal(raw, want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + + data, _ := json.Marshal(got) + t.Log("got JSON:") + t.Log(string(data)) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} + +func TestReleaseUpdate(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Patch("/repos/octocat/hello-world/releases/1"). + File("testdata/release_create.json"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/release.json") + + client := NewDefault() + input := &scm.ReleaseInput{ + Title: "v1.0", + Description: "Tracking release for version 1.0", + Tag: "v1.0", + } + + got, res, err := client.Releases.Update(context.Background(), "octocat/hello-world", 1, input) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Release) + raw, _ := ioutil.ReadFile("testdata/release.json.golden") + err = json.Unmarshal(raw, want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} + +func TestReleaseDelete(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Delete("/repos/octocat/hello-world/releases/1"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders) + + client := NewDefault() + res, err := client.Releases.Delete(context.Background(), "octocat/hello-world", 1) + if err != nil { + t.Error(err) + return + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} diff --git a/scm/driver/github/testdata/milestone.json b/scm/driver/github/testdata/milestone.json new file mode 100644 index 000000000..cabb83865 --- /dev/null +++ b/scm/driver/github/testdata/milestone.json @@ -0,0 +1,37 @@ +{ + "url": "https://api.github.com/repos/octocat/Hello-World/milestones/1", + "html_url": "https://github.com/octocat/Hello-World/milestones/v1.0", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/milestones/1/labels", + "id": 1002604, + "node_id": "MDk6TWlsZXN0b25lMTAwMjYwNA==", + "number": 1, + "state": "open", + "title": "v1.0", + "description": "Tracking milestone for version 1.0", + "creator": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "open_issues": 4, + "closed_issues": 8, + "created_at": "2011-04-10T20:09:31Z", + "updated_at": "2014-03-03T18:58:10Z", + "closed_at": "2013-02-12T13:22:01Z", + "due_on": "2012-10-09T23:39:01Z" +} diff --git a/scm/driver/github/testdata/milestone.json.golden b/scm/driver/github/testdata/milestone.json.golden new file mode 100644 index 000000000..ccab27361 --- /dev/null +++ b/scm/driver/github/testdata/milestone.json.golden @@ -0,0 +1,9 @@ +{ + "Link": "https://github.com/octocat/Hello-World/milestones/v1.0", + "ID": 1002604, + "Number": 1, + "State": "open", + "Title": "v1.0", + "Description": "Tracking milestone for version 1.0", + "DueDate": "2012-10-09T23:39:01Z" +} diff --git a/scm/driver/github/testdata/milestone_create.json b/scm/driver/github/testdata/milestone_create.json new file mode 100644 index 000000000..c89bac2bc --- /dev/null +++ b/scm/driver/github/testdata/milestone_create.json @@ -0,0 +1,6 @@ +{ + "state": "open", + "title": "v1.0", + "description": "Tracking milestone for version 1.0", + "due_on": "2012-10-09T23:39:01Z" +} diff --git a/scm/driver/github/testdata/milestones.json b/scm/driver/github/testdata/milestones.json new file mode 100644 index 000000000..6a4e96bb0 --- /dev/null +++ b/scm/driver/github/testdata/milestones.json @@ -0,0 +1,39 @@ +[ + { + "url": "https://api.github.com/repos/octocat/Hello-World/milestones/1", + "html_url": "https://github.com/octocat/Hello-World/milestones/v1.0", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/milestones/1/labels", + "id": 1002604, + "node_id": "MDk6TWlsZXN0b25lMTAwMjYwNA==", + "number": 1, + "state": "open", + "title": "v1.0", + "description": "Tracking milestone for version 1.0", + "creator": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "open_issues": 4, + "closed_issues": 8, + "created_at": "2011-04-10T20:09:31Z", + "updated_at": "2014-03-03T18:58:10Z", + "closed_at": "2013-02-12T13:22:01Z", + "due_on": "2012-10-09T23:39:01Z" + } +] diff --git a/scm/driver/github/testdata/milestones.json.golden b/scm/driver/github/testdata/milestones.json.golden new file mode 100644 index 000000000..4d3a51459 --- /dev/null +++ b/scm/driver/github/testdata/milestones.json.golden @@ -0,0 +1,11 @@ +[ + { + "Link": "https://github.com/octocat/Hello-World/milestones/v1.0", + "ID": 1002604, + "Number": 1, + "State": "open", + "Title": "v1.0", + "Description": "Tracking milestone for version 1.0", + "DueDate": "2012-10-09T23:39:01Z" + } +] diff --git a/scm/driver/github/testdata/release.json b/scm/driver/github/testdata/release.json new file mode 100644 index 000000000..b85892dbf --- /dev/null +++ b/scm/driver/github/testdata/release.json @@ -0,0 +1,74 @@ +{ + "url": "https://api.github.com/repos/octocat/Hello-World/releases/1", + "html_url": "https://github.com/octocat/Hello-World/releases/v1.0.0", + "assets_url": "https://api.github.com/repos/octocat/Hello-World/releases/1/assets", + "upload_url": "https://uploads.github.com/repos/octocat/Hello-World/releases/1/assets{?name,label}", + "tarball_url": "https://api.github.com/repos/octocat/Hello-World/tarball/v1.0.0", + "zipball_url": "https://api.github.com/repos/octocat/Hello-World/zipball/v1.0.0", + "id": 1, + "node_id": "MDc6UmVsZWFzZTE=", + "tag_name": "v1.0.0", + "target_commitish": "master", + "name": "v1.0.0", + "body": "Description of the release", + "draft": false, + "prerelease": false, + "created_at": "2013-02-27T19:35:32Z", + "published_at": "2013-02-27T19:35:32Z", + "author": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "assets": [ + { + "url": "https://api.github.com/repos/octocat/Hello-World/releases/assets/1", + "browser_download_url": "https://github.com/octocat/Hello-World/releases/download/v1.0.0/example.zip", + "id": 1, + "node_id": "MDEyOlJlbGVhc2VBc3NldDE=", + "name": "example.zip", + "label": "short description", + "state": "uploaded", + "content_type": "application/zip", + "size": 1024, + "download_count": 42, + "created_at": "2013-02-27T19:35:32Z", + "updated_at": "2013-02-27T19:35:32Z", + "uploader": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + } + } + ] +} \ No newline at end of file diff --git a/scm/driver/github/testdata/release.json.golden b/scm/driver/github/testdata/release.json.golden new file mode 100644 index 000000000..f199eca60 --- /dev/null +++ b/scm/driver/github/testdata/release.json.golden @@ -0,0 +1,12 @@ +{ + "ID": 1, + "Title": "v1.0.0", + "Description": "Description of the release", + "Link": "https://github.com/octocat/Hello-World/releases/v1.0.0", + "Tag": "v1.0.0", + "Commitish": "master", + "Draft": false, + "Prerelease": false, + "Created": "2013-02-27T19:35:32Z", + "Published": "2013-02-27T19:35:32Z" +} \ No newline at end of file diff --git a/scm/driver/github/testdata/releases.json b/scm/driver/github/testdata/releases.json new file mode 100644 index 000000000..e544c30b4 --- /dev/null +++ b/scm/driver/github/testdata/releases.json @@ -0,0 +1,76 @@ +[ + { + "url": "https://api.github.com/repos/octocat/Hello-World/releases/1", + "html_url": "https://github.com/octocat/Hello-World/releases/v1.0.0", + "assets_url": "https://api.github.com/repos/octocat/Hello-World/releases/1/assets", + "upload_url": "https://uploads.github.com/repos/octocat/Hello-World/releases/1/assets{?name,label}", + "tarball_url": "https://api.github.com/repos/octocat/Hello-World/tarball/v1.0.0", + "zipball_url": "https://api.github.com/repos/octocat/Hello-World/zipball/v1.0.0", + "id": 1, + "node_id": "MDc6UmVsZWFzZTE=", + "tag_name": "v1.0.0", + "target_commitish": "master", + "name": "v1.0.0", + "body": "Description of the release", + "draft": false, + "prerelease": false, + "created_at": "2013-02-27T19:35:32Z", + "published_at": "2013-02-27T19:35:32Z", + "author": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "assets": [ + { + "url": "https://api.github.com/repos/octocat/Hello-World/releases/assets/1", + "browser_download_url": "https://github.com/octocat/Hello-World/releases/download/v1.0.0/example.zip", + "id": 1, + "node_id": "MDEyOlJlbGVhc2VBc3NldDE=", + "name": "example.zip", + "label": "short description", + "state": "uploaded", + "content_type": "application/zip", + "size": 1024, + "download_count": 42, + "created_at": "2013-02-27T19:35:32Z", + "updated_at": "2013-02-27T19:35:32Z", + "uploader": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + } + } + ] + } +] \ No newline at end of file diff --git a/scm/driver/github/testdata/releases.json.golden b/scm/driver/github/testdata/releases.json.golden new file mode 100644 index 000000000..db9d598a5 --- /dev/null +++ b/scm/driver/github/testdata/releases.json.golden @@ -0,0 +1,14 @@ +[ + { + "ID": 1, + "Title": "v1.0.0", + "Description": "Description of the release", + "Link": "https://github.com/octocat/Hello-World/releases/v1.0.0", + "Tag": "v1.0.0", + "Commitish": "master", + "Draft": false, + "Prerelease": false, + "Created": "2013-02-27T19:35:32Z", + "Published": "2013-02-27T19:35:32Z" + } +] \ No newline at end of file diff --git a/scm/driver/github/util.go b/scm/driver/github/util.go index a6b3c55a7..e92b63c88 100644 --- a/scm/driver/github/util.go +++ b/scm/driver/github/util.go @@ -67,3 +67,35 @@ func encodePullRequestListOptions(opts scm.PullRequestListOptions) string { } return params.Encode() } + +func encodeMilestoneListOptions(opts scm.MilestoneListOptions) string { + params := url.Values{} + if opts.Page != 0 { + params.Set("page", strconv.Itoa(opts.Page)) + } + if opts.Size != 0 { + params.Set("per_page", strconv.Itoa(opts.Size)) + } + if opts.Open && opts.Closed { + params.Set("state", "all") + } else if opts.Closed { + params.Set("state", "closed") + } + return params.Encode() +} + +func encodeReleaseListOptions(opts scm.ReleaseListOptions) string { + params := url.Values{} + if opts.Page != 0 { + params.Set("page", strconv.Itoa(opts.Page)) + } + if opts.Size != 0 { + params.Set("per_page", strconv.Itoa(opts.Size)) + } + if opts.Open && opts.Closed { + params.Set("state", "all") + } else if opts.Closed { + params.Set("state", "closed") + } + return params.Encode() +} \ No newline at end of file diff --git a/scm/driver/gitlab/gitlab.go b/scm/driver/gitlab/gitlab.go index 1a907e511..4d92016cd 100644 --- a/scm/driver/gitlab/gitlab.go +++ b/scm/driver/gitlab/gitlab.go @@ -34,8 +34,10 @@ func New(uri string) (*scm.Client, error) { client.Git = &gitService{client} client.Issues = &issueService{client} client.Organizations = &organizationService{client} + client.Milestones = &milestoneService{client} client.PullRequests = &pullService{client} client.Repositories = &repositoryService{client} + client.Releases = &releaseService{client} client.Reviews = &reviewService{client} client.Users = &userService{client} client.Webhooks = &webhookService{client} diff --git a/scm/driver/gitlab/milestone.go b/scm/driver/gitlab/milestone.go new file mode 100644 index 000000000..7cdf8e56a --- /dev/null +++ b/scm/driver/gitlab/milestone.go @@ -0,0 +1,166 @@ +package gitlab + +import ( + "context" + "errors" + "fmt" + "net/url" + "time" + + "github.com/drone/go-scm/scm" +) + +type milestoneService struct { + client *wrapper +} + +// isoTime represents an ISO 8601 formatted date +type isoTime time.Time + +// ISO 8601 date format +const iso8601 = "2006-01-02" + +// MarshalJSON implements the json.Marshaler interface +func (t isoTime) MarshalJSON() ([]byte, error) { + if y := time.Time(t).Year(); y < 0 || y >= 10000 { + // ISO 8901 uses 4 digits for the years + return nil, errors.New("json: ISOTime year outside of range [0,9999]") + } + + b := make([]byte, 0, len(iso8601)+2) + b = append(b, '"') + b = time.Time(t).AppendFormat(b, iso8601) + b = append(b, '"') + + return b, nil +} + +// UnmarshalJSON implements the json.Unmarshaler interface +func (t *isoTime) UnmarshalJSON(data []byte) error { + // Ignore null, like in the main JSON package + if string(data) == "null" { + return nil + } + + isotime, err := time.Parse(`"`+iso8601+`"`, string(data)) + *t = isoTime(isotime) + + return err +} + +// EncodeValues implements the query.Encoder interface +func (t *isoTime) EncodeValues(key string, v *url.Values) error { + if t == nil || (time.Time(*t)).IsZero() { + return nil + } + v.Add(key, t.String()) + return nil +} + +// String implements the Stringer interface +func (t isoTime) String() string { + return time.Time(t).Format(iso8601) +} + +type milestone struct { + ID int `json:"id"` + IID int `json:"iid"` + ProjectID int `json:"project_id"` + Title string `json:"title"` + Description string `json:"description"` + State string `json:"state"` + DueDate isoTime `json:"due_date"` + StartDate isoTime `json:"start_date"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + Expired bool `json:"expired"` +} + +type milestoneInput struct { + Title *string `json:"title"` + StateEvent *string `json:"state_event,omitempty"` + Description *string `json:"description"` + DueDate *isoTime `json:"due_date"` +} + +func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/milestones/%d", encode(repo), id) + out := new(milestone) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertMilestone(out), res, err +} + +func (s *milestoneService) List(ctx context.Context, repo string, opts scm.MilestoneListOptions) ([]*scm.Milestone, *scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/milestones?%s", encode(repo), encodeMilestoneListOptions(opts)) + out := []*milestone{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertMilestoneList(out), res, err +} + +func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/milestones", encode(repo)) + dueDateIso := isoTime(*input.DueDate) + in := &milestoneInput{ + Title: &input.Title, + Description: &input.Description, + DueDate: &dueDateIso, + } + out := new(milestone) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertMilestone(out), res, err +} + +func (s *milestoneService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/milestones/%d", encode(repo), id) + res, err := s.client.do(ctx, "DELETE", path, nil, nil) + return res, err +} + +func (s *milestoneService) Update(ctx context.Context, repo string, id int, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/milestones/%d", encode(repo), id) + in := &milestoneInput{} + if input.Title != "" { + in.Title = &input.Title + } + if input.State != "" { + if input.State == "open" { + activate := "activate" + in.StateEvent = &activate + } else { + in.StateEvent = &input.State + } + } + if input.Description != "" { + in.Description = &input.Description + } + if input.DueDate != nil { + dueDateIso := isoTime(*input.DueDate) + in.DueDate = &dueDateIso + } + out := new(milestone) + res, err := s.client.do(ctx, "PATCH", path, in, out) + return convertMilestone(out), res, err +} + +func convertMilestoneList(from []*milestone) []*scm.Milestone { + var to []*scm.Milestone + for _, m := range from { + to = append(to, convertMilestone(m)) + } + return to +} + +func convertMilestone(from *milestone) *scm.Milestone { + if from == nil || from.Title == "" { + return nil + } + dueDate := time.Time(from.DueDate) + return &scm.Milestone{ + Number: from.ID, + ID: from.ID, + Title: from.Title, + Description: from.Description, + State: from.State, + DueDate: &dueDate, + } +} diff --git a/scm/driver/gitlab/milestone_test.go b/scm/driver/gitlab/milestone_test.go new file mode 100644 index 000000000..f8e02794c --- /dev/null +++ b/scm/driver/gitlab/milestone_test.go @@ -0,0 +1,186 @@ +package gitlab + +import ( + "context" + "encoding/json" + "github.com/drone/go-scm/scm" + "github.com/h2non/gock" + "io/ioutil" + "testing" + "time" + + "github.com/google/go-cmp/cmp" +) + +func TestMilestoneFind(t *testing.T) { + defer gock.Off() + + gock.New("https://gitlab.com"). + Get("/api/v4/projects/diaspora/diaspora/milestones/1"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/milestone.json") + + client := NewDefault() + got, res, err := client.Milestones.Find(context.Background(), "diaspora/diaspora", 1) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Milestone) + raw, err := ioutil.ReadFile("testdata/milestone.json.golden") + if err != nil { + t.Fatalf("ioutil.ReadFile: %v", err) + } + if err := json.Unmarshal(raw, want); err != nil { + t.Fatalf("json.Unmarshal: %v", err) + } + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} + +func TestMilestoneList(t *testing.T) { + defer gock.Off() + + gock.New("https://gitlab.com"). + Get("/api/v4/projects/diaspora/diaspora/milestones"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/milestones.json") + + client := NewDefault() + got, res, err := client.Milestones.List(context.Background(), "diaspora/diaspora", scm.MilestoneListOptions{}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Milestone{} + raw, err := ioutil.ReadFile("testdata/milestones.json.golden") + if err != nil { + t.Fatalf("ioutil.ReadFile: %v", err) + } + if err := json.Unmarshal(raw, &want); err != nil { + t.Fatalf("json.Unmarshal: %v", err) + } + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} + +func TestMilestoneCreate(t *testing.T) { + defer gock.Off() + + gock.New("https://gitlab.com"). + Post("/api/v4/projects/diaspora/diaspora/milestones"). + File("testdata/milestone_create.json"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/milestone.json") + + client := NewDefault() + dueDate, _ := time.Parse(scm.SearchTimeFormat, "2012-10-09T23:39:01Z") + input := &scm.MilestoneInput{ + Title: "v1.0", + Description: "Tracking milestone for version 1.0", + State: "open", + DueDate: &dueDate, + } + got, res, err := client.Milestones.Create(context.Background(), "diaspora/diaspora", input) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Milestone) + raw, err := ioutil.ReadFile("testdata/milestone.json.golden") + if err != nil { + t.Fatalf("ioutil.ReadFile: %v", err) + } + if err := json.Unmarshal(raw, &want); err != nil { + t.Fatalf("json.Unmarshal: %v", err) + } + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} + +func TestMilestoneUpdate(t *testing.T) { + defer gock.Off() + + gock.New("https://gitlab.com"). + Patch("/api/v4/projects/diaspora/diaspora/milestones/1"). + File("testdata/milestone_update.json"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/milestone.json") + + client := NewDefault() + dueDate, _ := time.Parse(scm.SearchTimeFormat, "2012-10-09T23:39:01Z") + input := &scm.MilestoneInput{ + Title: "v1.0", + Description: "Tracking milestone for version 1.0", + State: "close", + DueDate: &dueDate, + } + got, res, err := client.Milestones.Update(context.Background(), "diaspora/diaspora", 1, input) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Milestone) + raw, err := ioutil.ReadFile("testdata/milestone.json.golden") + if err != nil { + t.Fatalf("ioutil.ReadFile: %v", err) + } + if err := json.Unmarshal(raw, &want); err != nil { + t.Fatalf("json.Unmarshal: %v", err) + } + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} + +func TestMilestoneDelete(t *testing.T) { + defer gock.Off() + + gock.New("https://gitlab.com"). + Delete("/api/v4/projects/diaspora/diaspora/milestones/1"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders) + + client := NewDefault() + _, err := client.Milestones.Delete(context.Background(), "diaspora/diaspora", 1) + if err != nil { + t.Error(err) + return + } +} diff --git a/scm/driver/gitlab/release.go b/scm/driver/gitlab/release.go new file mode 100644 index 000000000..625404870 --- /dev/null +++ b/scm/driver/gitlab/release.go @@ -0,0 +1,111 @@ +package gitlab + +import ( + "context" + "fmt" + + "github.com/drone/go-scm/scm" +) + +type releaseService struct { + client *wrapper +} + +type release struct { + Title string `json:"name"` + Description string `json:"description"` + Tag string `json:"tag_name"` + Commit struct { + ID string `json:"id"` + } `json:"commit"` +} + +type releaseInput struct { + Title string `json:"name"` + Description string `json:"description"` + Tag string `json:"tag_name"` +} + +func (s *releaseService) Find(ctx context.Context, repo string, id int) (*scm.Release, *scm.Response, error) { + // this could be implemented by List and filter but would be to expensive + panic("gitlab only allows to find a release by tag") +} + +func (s *releaseService) FindByTag(ctx context.Context, repo string, tag string) (*scm.Release, *scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/releases/%s", encode(repo), tag) + out := new(release) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertRelease(out), res, err +} + +func (s *releaseService) List(ctx context.Context, repo string, opts scm.ReleaseListOptions) ([]*scm.Release, *scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/releases", encode(repo)) + out := []*release{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertReleaseList(out), res, err +} + +func (s *releaseService) Create(ctx context.Context, repo string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/releases", encode(repo)) + in := &releaseInput{ + Title: input.Title, + Description: input.Description, + Tag: input.Tag, + } + out := new(release) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertRelease(out), res, err +} + +func (s *releaseService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + // this could be implemented by List and filter but would be to expensive + panic("gitlab only allows to delete a release by tag") +} + +func (s *releaseService) DeleteByTag(ctx context.Context, repo string, tag string) (*scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/releases/%s", encode(repo), tag) + return s.client.do(ctx, "DELETE", path, nil, nil) +} + +func (s *releaseService) Update(ctx context.Context, repo string, id int, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + // this could be implemented by List and filter but would be to expensive + panic("gitlab only allows to update a release by tag") +} + +func (s *releaseService) UpdateByTag(ctx context.Context, repo string, tag string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/releases/%s", encode(repo), tag) + in := &releaseInput{} + if input.Title != "" { + in.Title = input.Title + } + if input.Description != "" { + in.Description = input.Description + } + if input.Tag != "" { + in.Tag = input.Tag + } + out := new(release) + res, err := s.client.do(ctx, "PUT", path, in, out) + return convertRelease(out), res, err +} + +func convertReleaseList(from []*release) []*scm.Release { + var to []*scm.Release + for _, m := range from { + to = append(to, convertRelease(m)) + } + return to +} + +func convertRelease(from *release) *scm.Release { + return &scm.Release{ + ID: 0, + Title: from.Title, + Description: from.Description, + Link: "", + Tag: from.Tag, + Commitish: from.Commit.ID, + Draft: false, // not supported by gitlab + Prerelease: false, // not supported by gitlab + } +} diff --git a/scm/driver/gitlab/release_test.go b/scm/driver/gitlab/release_test.go new file mode 100644 index 000000000..1c3fda899 --- /dev/null +++ b/scm/driver/gitlab/release_test.go @@ -0,0 +1,184 @@ +package gitlab + +import ( + "context" + "encoding/json" + "io/ioutil" + "testing" + + "github.com/drone/go-scm/scm" + + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" + "github.com/stretchr/testify/assert" +) + +func TestReleaseFindByTag(t *testing.T) { + defer gock.Off() + + gock.New("https://gitlab.com"). + Get("/api/v4/projects/diaspora/diaspora/releases/v1.0.1"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/release.json") + + client := NewDefault() + got, res, err := client.Releases.FindByTag(context.Background(), "diaspora/diaspora", "v1.0.1") + if err != nil { + t.Error(err) + return + } + + want := new(scm.Release) + raw, _ := ioutil.ReadFile("testdata/release.json.golden") + err = json.Unmarshal(raw, want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + + data, _ := json.Marshal(got) + t.Log("got JSON:") + t.Log(string(data)) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} + +func TestReleaseList(t *testing.T) { + defer gock.Off() + + gock.New("https://gitlab.com"). + Get("/api/v4/projects/diaspora/diaspora/releases"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/releases.json") + + client := NewDefault() + got, res, err := client.Releases.List(context.Background(), "diaspora/diaspora", scm.ReleaseListOptions{}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Release{} + raw, _ := ioutil.ReadFile("testdata/releases.json.golden") + err = json.Unmarshal(raw, &want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + + data, _ := json.Marshal(got) + t.Log("got JSON:") + t.Log(string(data)) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} + +func TestReleaseCreate(t *testing.T) { + defer gock.Off() + + gock.New("https://gitlab.com"). + Post("/api/v4/projects/diaspora/diaspora/releases"). + File("testdata/release_create.json"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/release.json") + + client := NewDefault() + input := &scm.ReleaseInput{ + Title: "v1.0", + Description: "Tracking release for version 1.0", + Tag: "v1.0", + } + + got, res, err := client.Releases.Create(context.Background(), "diaspora/diaspora", input) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Release) + raw, _ := ioutil.ReadFile("testdata/release.json.golden") + err = json.Unmarshal(raw, want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + + data, _ := json.Marshal(got) + t.Log("got JSON:") + t.Log(string(data)) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} + +func TestReleaseUpdateByTag(t *testing.T) { + defer gock.Off() + + gock.New("https://gitlab.com"). + Put("/api/v4/projects/diaspora/diaspora/releases/v1.0"). + File("testdata/release_create.json"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/release.json") + + client := NewDefault() + input := &scm.ReleaseInput{ + Title: "v1.0", + Description: "Tracking release for version 1.0", + Tag: "v1.0", + } + + got, res, err := client.Releases.UpdateByTag(context.Background(), "diaspora/diaspora", "v1.0", input) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Release) + raw, _ := ioutil.ReadFile("testdata/release.json.golden") + err = json.Unmarshal(raw, want) + assert.NoError(t, err) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} + +func TestReleaseDeleteByTag(t *testing.T) { + defer gock.Off() + + gock.New("https://gitlab.com"). + Delete("/api/v4/projects/diaspora/diaspora/releases/v1.0"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders) + + client := NewDefault() + res, err := client.Releases.DeleteByTag(context.Background(), "diaspora/diaspora", "v1.0") + if err != nil { + t.Error(err) + return + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) +} diff --git a/scm/driver/gitlab/testdata/milestone.json b/scm/driver/gitlab/testdata/milestone.json new file mode 100644 index 000000000..0cbf520b3 --- /dev/null +++ b/scm/driver/gitlab/testdata/milestone.json @@ -0,0 +1,13 @@ +{ + "id": 12, + "iid": 3, + "project_id": 16, + "title": "10.0", + "description": "Version", + "due_date": "2013-11-29", + "start_date": "2013-11-10", + "state": "active", + "updated_at": "2013-10-02T09:24:18Z", + "created_at": "2013-10-02T09:24:18Z", + "expired": false +} diff --git a/scm/driver/gitlab/testdata/milestone.json.golden b/scm/driver/gitlab/testdata/milestone.json.golden new file mode 100644 index 000000000..186481374 --- /dev/null +++ b/scm/driver/gitlab/testdata/milestone.json.golden @@ -0,0 +1,8 @@ +{ + "ID": 12, + "Number": 12, + "Title": "10.0", + "Description": "Version", + "DueDate": "2013-11-29T00:00:00Z", + "State": "active" +} diff --git a/scm/driver/gitlab/testdata/milestone_create.json b/scm/driver/gitlab/testdata/milestone_create.json new file mode 100644 index 000000000..efb5309fd --- /dev/null +++ b/scm/driver/gitlab/testdata/milestone_create.json @@ -0,0 +1,5 @@ +{ + "title": "v1.0", + "description": "Tracking milestone for version 1.0", + "due_date": "2012-10-09" +} diff --git a/scm/driver/gitlab/testdata/milestone_update.json b/scm/driver/gitlab/testdata/milestone_update.json new file mode 100644 index 000000000..a91bbbd16 --- /dev/null +++ b/scm/driver/gitlab/testdata/milestone_update.json @@ -0,0 +1,6 @@ +{ + "title": "v1.0", + "description": "Tracking milestone for version 1.0", + "state_event": "close", + "due_date": "2012-10-09" +} diff --git a/scm/driver/gitlab/testdata/milestones.json b/scm/driver/gitlab/testdata/milestones.json new file mode 100644 index 000000000..f6c9e76cf --- /dev/null +++ b/scm/driver/gitlab/testdata/milestones.json @@ -0,0 +1,15 @@ +[ + { + "id": 12, + "iid": 3, + "project_id": 16, + "title": "10.0", + "description": "Version", + "due_date": "2013-11-29", + "start_date": "2013-11-10", + "state": "active", + "updated_at": "2013-10-02T09:24:18Z", + "created_at": "2013-10-02T09:24:18Z", + "expired": false + } +] diff --git a/scm/driver/gitlab/testdata/milestones.json.golden b/scm/driver/gitlab/testdata/milestones.json.golden new file mode 100644 index 000000000..9fd157cca --- /dev/null +++ b/scm/driver/gitlab/testdata/milestones.json.golden @@ -0,0 +1,10 @@ +[ + { + "ID": 12, + "Number": 12, + "Title": "10.0", + "Description": "Version", + "DueDate": "2013-11-29T00:00:00Z", + "State": "active" + } +] diff --git a/scm/driver/gitlab/testdata/release.json b/scm/driver/gitlab/testdata/release.json new file mode 100644 index 000000000..2f32681eb --- /dev/null +++ b/scm/driver/gitlab/testdata/release.json @@ -0,0 +1,100 @@ +{ + "tag_name":"v0.1", + "description":"## CHANGELOG\r\n\r\n- Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn't respected. !22516", + "name":"Awesome app v0.1 alpha", + "description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eRemove limit of 100 when searching repository code. !8671\u003c/li\u003e\n\u003cli\u003eShow error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\u003c/li\u003e\n\u003cli\u003eFix a bug where internal email pattern wasn't respected. !22516\u003c/li\u003e\n\u003c/ul\u003e", + "created_at":"2019-01-03T01:55:18.203Z", + "released_at":"2019-01-03T01:55:18.203Z", + "author":{ + "id":1, + "name":"Administrator", + "username":"root", + "state":"active", + "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", + "web_url":"https://gitlab.example.com/root" + }, + "commit":{ + "id":"f8d3d94cbd347e924aa7b715845e439d00e80ca4", + "short_id":"f8d3d94c", + "title":"Initial commit", + "created_at":"2019-01-03T01:53:28.000Z", + "parent_ids":[ + + ], + "message":"Initial commit", + "author_name":"Administrator", + "author_email":"admin@example.com", + "authored_date":"2019-01-03T01:53:28.000Z", + "committer_name":"Administrator", + "committer_email":"admin@example.com", + "committed_date":"2019-01-03T01:53:28.000Z" + }, + "milestones": [ + { + "id":51, + "iid":1, + "project_id":24, + "title":"v1.0-rc", + "description":"Voluptate fugiat possimus quis quod aliquam expedita.", + "state":"closed", + "created_at":"2019-07-12T19:45:44.256Z", + "updated_at":"2019-07-12T19:45:44.256Z", + "due_date":"2019-08-16T11:00:00.256Z", + "start_date":"2019-07-30T12:00:00.256Z", + "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/1", + "issue_stats": { + "total": 98, + "closed": 76 + } + }, + { + "id":52, + "iid":2, + "project_id":24, + "title":"v1.0", + "description":"Voluptate fugiat possimus quis quod aliquam expedita.", + "state":"closed", + "created_at":"2019-07-16T14:00:12.256Z", + "updated_at":"2019-07-16T14:00:12.256Z", + "due_date":"2019-08-16T11:00:00.256Z", + "start_date":"2019-07-30T12:00:00.256Z", + "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/2", + "issue_stats": { + "total": 24, + "closed": 21 + } + } + ], + "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", + "tag_path":"/root/awesome-app/-/tags/v0.11.1", + "assets":{ + "count":5, + "sources":[ + { + "format":"zip", + "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.zip" + }, + { + "format":"tar.gz", + "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.gz" + }, + { + "format":"tar.bz2", + "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.bz2" + }, + { + "format":"tar", + "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar" + } + ], + "links":[ + { + "id":3, + "name":"hoge", + "url":"https://gitlab.example.com/root/awesome-app/-/tags/v0.11.1/binaries/linux-amd64", + "external":true, + "link_type":"other" + } + ] + } +} diff --git a/scm/driver/gitlab/testdata/release.json.golden b/scm/driver/gitlab/testdata/release.json.golden new file mode 100644 index 000000000..3ac087ded --- /dev/null +++ b/scm/driver/gitlab/testdata/release.json.golden @@ -0,0 +1,10 @@ +{ + "ID": 0, + "Title": "Awesome app v0.1 alpha", + "Description": "## CHANGELOG\r\n\r\n- Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn't respected. !22516", + "Link": "", + "Tag": "v0.1", + "Commitish": "f8d3d94cbd347e924aa7b715845e439d00e80ca4", + "Draft": false, + "Prerelease": false +} diff --git a/scm/driver/gitlab/testdata/releases.json b/scm/driver/gitlab/testdata/releases.json new file mode 100644 index 000000000..c0a708965 --- /dev/null +++ b/scm/driver/gitlab/testdata/releases.json @@ -0,0 +1,167 @@ +[ + { + "tag_name":"v0.2", + "description":"## CHANGELOG\r\n\r\n- Escape label and milestone titles to prevent XSS in GFM autocomplete. !2740\r\n- Prevent private snippets from being embeddable.\r\n- Add subresources removal to member destroy service.", + "name":"Awesome app v0.2 beta", + "description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eEscape label and milestone titles to prevent XSS in GFM autocomplete. !2740\u003c/li\u003e\n\u003cli\u003ePrevent private snippets from being embeddable.\u003c/li\u003e\n\u003cli\u003eAdd subresources removal to member destroy service.\u003c/li\u003e\n\u003c/ul\u003e", + "created_at":"2019-01-03T01:56:19.539Z", + "released_at":"2019-01-03T01:56:19.539Z", + "author":{ + "id":1, + "name":"Administrator", + "username":"root", + "state":"active", + "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", + "web_url":"https://gitlab.example.com/root" + }, + "commit":{ + "id":"079e90101242458910cccd35eab0e211dfc359c0", + "short_id":"079e9010", + "title":"Update README.md", + "created_at":"2019-01-03T01:55:38.000Z", + "parent_ids":[ + "f8d3d94cbd347e924aa7b715845e439d00e80ca4" + ], + "message":"Update README.md", + "author_name":"Administrator", + "author_email":"admin@example.com", + "authored_date":"2019-01-03T01:55:38.000Z", + "committer_name":"Administrator", + "committer_email":"admin@example.com", + "committed_date":"2019-01-03T01:55:38.000Z" + }, + "milestones": [ + { + "id":51, + "iid":1, + "project_id":24, + "title":"v1.0-rc", + "description":"Voluptate fugiat possimus quis quod aliquam expedita.", + "state":"closed", + "created_at":"2019-07-12T19:45:44.256Z", + "updated_at":"2019-07-12T19:45:44.256Z", + "due_date":"2019-08-16T11:00:00.256Z", + "start_date":"2019-07-30T12:00:00.256Z", + "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/1", + "issue_stats": { + "total": 98, + "closed": 76 + } + }, + { + "id":52, + "iid":2, + "project_id":24, + "title":"v1.0", + "description":"Voluptate fugiat possimus quis quod aliquam expedita.", + "state":"closed", + "created_at":"2019-07-16T14:00:12.256Z", + "updated_at":"2019-07-16T14:00:12.256Z", + "due_date":"2019-08-16T11:00:00.256Z", + "start_date":"2019-07-30T12:00:00.256Z", + "web_url":"https://gitlab.example.com/root/awesome-app/-/milestones/2", + "issue_stats": { + "total": 24, + "closed": 21 + } + } + ], + "commit_path":"/root/awesome-app/commit/588440f66559714280628a4f9799f0c4eb880a4a", + "tag_path":"/root/awesome-app/-/tags/v0.11.1", + "assets":{ + "count":6, + "sources":[ + { + "format":"zip", + "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.2/awesome-app-v0.2.zip" + }, + { + "format":"tar.gz", + "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.2/awesome-app-v0.2.tar.gz" + }, + { + "format":"tar.bz2", + "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.2/awesome-app-v0.2.tar.bz2" + }, + { + "format":"tar", + "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.2/awesome-app-v0.2.tar" + } + ], + "links":[ + { + "id":2, + "name":"awesome-v0.2.msi", + "url":"http://192.168.10.15:3000/msi", + "external":true, + "link_type":"other" + }, + { + "id":1, + "name":"awesome-v0.2.dmg", + "url":"http://192.168.10.15:3000", + "external":true, + "link_type":"other" + } + ], + "evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.2/evidence.json" + } + }, + { + "tag_name":"v0.1", + "description":"## CHANGELOG\r\n\r\n-Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn't respected. !22516", + "name":"Awesome app v0.1 alpha", + "description_html":"\u003ch2 dir=\"auto\"\u003e\n\u003ca id=\"user-content-changelog\" class=\"anchor\" href=\"#changelog\" aria-hidden=\"true\"\u003e\u003c/a\u003eCHANGELOG\u003c/h2\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003eRemove limit of 100 when searching repository code. !8671\u003c/li\u003e\n\u003cli\u003eShow error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\u003c/li\u003e\n\u003cli\u003eFix a bug where internal email pattern wasn't respected. !22516\u003c/li\u003e\n\u003c/ul\u003e", + "created_at":"2019-01-03T01:55:18.203Z", + "released_at":"2019-01-03T01:55:18.203Z", + "author":{ + "id":1, + "name":"Administrator", + "username":"root", + "state":"active", + "avatar_url":"https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", + "web_url":"https://gitlab.example.com/root" + }, + "commit":{ + "id":"f8d3d94cbd347e924aa7b715845e439d00e80ca4", + "short_id":"f8d3d94c", + "title":"Initial commit", + "created_at":"2019-01-03T01:53:28.000Z", + "parent_ids":[ + + ], + "message":"Initial commit", + "author_name":"Administrator", + "author_email":"admin@example.com", + "authored_date":"2019-01-03T01:53:28.000Z", + "committer_name":"Administrator", + "committer_email":"admin@example.com", + "committed_date":"2019-01-03T01:53:28.000Z" + }, + "assets":{ + "count":4, + "sources":[ + { + "format":"zip", + "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.zip" + }, + { + "format":"tar.gz", + "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.gz" + }, + { + "format":"tar.bz2", + "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar.bz2" + }, + { + "format":"tar", + "url":"https://gitlab.example.com/root/awesome-app/-/archive/v0.1/awesome-app-v0.1.tar" + } + ], + "links":[ + + ], + "evidence_file_path":"https://gitlab.example.com/root/awesome-app/-/releases/v0.1/evidence.json" + } + } +] diff --git a/scm/driver/gitlab/testdata/releases.json.golden b/scm/driver/gitlab/testdata/releases.json.golden new file mode 100644 index 000000000..640ae4b7f --- /dev/null +++ b/scm/driver/gitlab/testdata/releases.json.golden @@ -0,0 +1,14 @@ +[ + { + "Title": "Awesome app v0.2 beta", + "Description": "## CHANGELOG\r\n\r\n- Escape label and milestone titles to prevent XSS in GFM autocomplete. !2740\r\n- Prevent private snippets from being embeddable.\r\n- Add subresources removal to member destroy service.", + "Tag": "v0.2", + "Commitish": "079e90101242458910cccd35eab0e211dfc359c0" + }, + { + "Title": "Awesome app v0.1 alpha", + "Description": "## CHANGELOG\r\n\r\n-Remove limit of 100 when searching repository code. !8671\r\n- Show error message when attempting to reopen an MR and there is an open MR for the same branch. !16447 (Akos Gyimesi)\r\n- Fix a bug where internal email pattern wasn't respected. !22516", + "Tag": "v0.1", + "Commitish": "f8d3d94cbd347e924aa7b715845e439d00e80ca4" + } +] diff --git a/scm/driver/gitlab/util.go b/scm/driver/gitlab/util.go index adc28ae30..6228e4759 100644 --- a/scm/driver/gitlab/util.go +++ b/scm/driver/gitlab/util.go @@ -96,3 +96,19 @@ func encodePullRequestListOptions(opts scm.PullRequestListOptions) string { } return params.Encode() } + +func encodeMilestoneListOptions(opts scm.MilestoneListOptions) string { + params := url.Values{} + if opts.Page != 0 { + params.Set("page", strconv.Itoa(opts.Page)) + } + if opts.Size != 0 { + params.Set("per_page", strconv.Itoa(opts.Size)) + } + if opts.Open && opts.Closed { + params.Set("state", "all") + } else if opts.Closed { + params.Set("state", "closed") + } + return params.Encode() +} \ No newline at end of file diff --git a/scm/driver/gogs/gogs.go b/scm/driver/gogs/gogs.go index 073dc5e0c..41e3f429b 100644 --- a/scm/driver/gogs/gogs.go +++ b/scm/driver/gogs/gogs.go @@ -36,8 +36,10 @@ func New(uri string) (*scm.Client, error) { client.Git = &gitService{client} client.Issues = &issueService{client} client.Organizations = &organizationService{client} + client.Milestones = &milestoneService{client} client.PullRequests = &pullService{client} client.Repositories = &repositoryService{client} + client.Releases = &releaseService{client} client.Reviews = &reviewService{client} client.Users = &userService{client} client.Webhooks = &webhookService{client} diff --git a/scm/driver/gogs/milestone.go b/scm/driver/gogs/milestone.go new file mode 100644 index 000000000..71a78794b --- /dev/null +++ b/scm/driver/gogs/milestone.go @@ -0,0 +1,31 @@ +package gogs + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type milestoneService struct { + client *wrapper +} + +func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *milestoneService) List(ctx context.Context, repo string, opts scm.MilestoneListOptions) ([]*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *milestoneService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *milestoneService) Update(ctx context.Context, repo string, id int, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} diff --git a/scm/driver/gogs/release.go b/scm/driver/gogs/release.go new file mode 100644 index 000000000..cf8ce092a --- /dev/null +++ b/scm/driver/gogs/release.go @@ -0,0 +1,42 @@ +package gogs + +import ( + "context" + "github.com/drone/go-scm/scm" +) + +type releaseService struct { + client *wrapper +} + +func (s *releaseService) Find(ctx context.Context, repo string, id int) (*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *releaseService) FindByTag(ctx context.Context, repo string, tag string) (*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *releaseService) List(ctx context.Context, repo string, opts scm.ReleaseListOptions) ([]*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *releaseService) Create(ctx context.Context, repo string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *releaseService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *releaseService) DeleteByTag(ctx context.Context, repo string, tag string) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *releaseService) Update(ctx context.Context, repo string, id int, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *releaseService) UpdateByTag(ctx context.Context, repo string, tag string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} diff --git a/scm/driver/stash/milestone.go b/scm/driver/stash/milestone.go new file mode 100644 index 000000000..e873f7b4e --- /dev/null +++ b/scm/driver/stash/milestone.go @@ -0,0 +1,31 @@ +package stash + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type milestoneService struct { + client *wrapper +} + +func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *milestoneService) List(ctx context.Context, repo string, opts scm.MilestoneListOptions) ([]*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *milestoneService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *milestoneService) Update(ctx context.Context, repo string, id int, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} diff --git a/scm/driver/stash/release.go b/scm/driver/stash/release.go new file mode 100644 index 000000000..8376200bb --- /dev/null +++ b/scm/driver/stash/release.go @@ -0,0 +1,43 @@ +package stash + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type releaseService struct { + client *wrapper +} + +func (s *releaseService) Find(ctx context.Context, repo string, id int) (*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *releaseService) FindByTag(ctx context.Context, repo string, tag string) (*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *releaseService) List(ctx context.Context, repo string, opts scm.ReleaseListOptions) ([]*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *releaseService) Create(ctx context.Context, repo string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *releaseService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *releaseService) DeleteByTag(ctx context.Context, repo string, tag string) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *releaseService) Update(ctx context.Context, repo string, id int, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *releaseService) UpdateByTag(ctx context.Context, repo string, tag string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} diff --git a/scm/driver/stash/stash.go b/scm/driver/stash/stash.go index 363ac64d8..17244d456 100644 --- a/scm/driver/stash/stash.go +++ b/scm/driver/stash/stash.go @@ -38,9 +38,11 @@ func New(uri string) (*scm.Client, error) { client.Contents = &contentService{client} client.Git = &gitService{client} client.Issues = &issueService{client} + client.Milestones = &milestoneService{client} client.Organizations = &organizationService{client} client.PullRequests = &pullService{client} client.Repositories = &repositoryService{client} + client.Releases = &releaseService{client} client.Reviews = &reviewService{client} client.Users = &userService{client} client.Webhooks = &webhookService{client} diff --git a/scm/milestone.go b/scm/milestone.go new file mode 100644 index 000000000..54ed9683b --- /dev/null +++ b/scm/milestone.go @@ -0,0 +1,42 @@ +package scm + +import ( + "context" + "time" +) + +type ( + // MilestoneInput contains the information needed to create a milestone + MilestoneInput struct { + Title string + Description string + State string + DueDate *time.Time + } + + // MilestoneListOptions provides options for querying a list of repository milestones. + MilestoneListOptions struct { + Page int + Size int + Open bool + Closed bool + } + + // MilestoneService provides access to creating, listing, updating, and deleting milestones + MilestoneService interface { + // Find returns the milestone for the given number in the given repository + Find(context.Context, string, int) (*Milestone, *Response, error) + + // List returns a list of milestones in the given repository + List(context.Context, string, MilestoneListOptions) ([]*Milestone, *Response, error) + + // Create creates a milestone in the given repository + Create(context.Context, string, *MilestoneInput) (*Milestone, *Response, error) + + // Update updates a milestone in the given repository + Update(context.Context, string, int, *MilestoneInput) (*Milestone, *Response, error) + + // Delete deletes a milestone in the given repository + Delete(context.Context, string, int) (*Response, error) + } +) diff --git a/scm/pr.go b/scm/pr.go index c2902baea..49d4e3543 100644 --- a/scm/pr.go +++ b/scm/pr.go @@ -64,6 +64,17 @@ type ( Color string } + // Milestone the milestone + Milestone struct { + Number int + ID int + Title string + Description string + Link string + State string + DueDate *time.Time + } + // PullRequestService provides access to pull request resources. PullRequestService interface { // Find returns the repository pull request by number. diff --git a/scm/release.go b/scm/release.go new file mode 100644 index 000000000..68d6a058d --- /dev/null +++ b/scm/release.go @@ -0,0 +1,67 @@ +package scm + +import ( + "context" + "time" +) + +type ( + // Release the release + Release struct { + ID int + Title string + Description string + Link string + Tag string + Commitish string + Draft bool + Prerelease bool + Created time.Time + Published time.Time + } + + // ReleaseInput contains the information needed to create a release + ReleaseInput struct { + Title string + Description string + Tag string + Commitish string + Draft bool + Prerelease bool + } + + // ReleaseListOptions provides options for querying a list of repository releases. + ReleaseListOptions struct { + Page int + Size int + Open bool + Closed bool + } + + // ReleaseService provides access to creating, listing, updating, and deleting releases + ReleaseService interface { + // Find returns the release for the given number in the given repository + Find(context.Context, string, int) (*Release, *Response, error) + + // FindByTag returns the release for the given tag in the given repository + FindByTag(context.Context, string, string) (*Release, *Response, error) + + // List returns a list of releases in the given repository + List(context.Context, string, ReleaseListOptions) ([]*Release, *Response, error) + + // Create creates a release in the given repository + Create(context.Context, string, *ReleaseInput) (*Release, *Response, error) + + // Update updates a release in the given repository + Update(context.Context, string, int, *ReleaseInput) (*Release, *Response, error) + + // UpdateByTag deletes a release in the given repository by tag + UpdateByTag(context.Context, string, string, *ReleaseInput) (*Release, *Response, error) + + // Delete deletes a release in the given repository + Delete(context.Context, string, int) (*Response, error) + + // DeleteByTag deletes a release in the given repository by tag + DeleteByTag(context.Context, string, string) (*Response, error) + } +) diff --git a/scm/util.go b/scm/util.go index 6108feee8..02da73a65 100644 --- a/scm/util.go +++ b/scm/util.go @@ -77,3 +77,4 @@ func IsPullRequest(ref string) bool { strings.HasPrefix(ref, "refs/pull-request/") || strings.HasPrefix(ref, "refs/merge-requests/") } + From fb675e09daf47bd21f851afa2ccd7608e9f660ad Mon Sep 17 00:00:00 2001 From: Eoin McAfee Date: Fri, 24 Sep 2021 16:08:40 +0100 Subject: [PATCH 035/282] remove assert package lib --- go.mod | 1 - scm/driver/gitea/milestone_test.go | 25 +++++++++++------- scm/driver/gitea/release_test.go | 40 ++++++++++++++++++----------- scm/driver/github/milestone_test.go | 33 +++++++++++++++--------- scm/driver/github/release_test.go | 30 ++++++++++++++-------- scm/driver/gitlab/release_test.go | 25 +++++++++++------- 6 files changed, 97 insertions(+), 57 deletions(-) diff --git a/go.mod b/go.mod index 6cce62b48..1a7e7c5ea 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ require ( github.com/google/go-cmp v0.2.0 github.com/h2non/gock v1.0.9 github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 // indirect - github.com/stretchr/testify v1.7.0 ) go 1.13 diff --git a/scm/driver/gitea/milestone_test.go b/scm/driver/gitea/milestone_test.go index 5472f9738..f825ae161 100644 --- a/scm/driver/gitea/milestone_test.go +++ b/scm/driver/gitea/milestone_test.go @@ -11,7 +11,6 @@ import ( "github.com/google/go-cmp/cmp" "github.com/h2non/gock" - "github.com/stretchr/testify/assert" ) func TestMilestoneFind(t *testing.T) { @@ -34,8 +33,10 @@ func TestMilestoneFind(t *testing.T) { want := new(scm.Milestone) raw, _ := ioutil.ReadFile("testdata/milestone.json.golden") err = json.Unmarshal(raw, want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) @@ -63,8 +64,10 @@ func TestMilestoneList(t *testing.T) { want := []*scm.Milestone{} raw, _ := ioutil.ReadFile("testdata/milestones.json.golden") err = json.Unmarshal(raw, &want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) @@ -101,8 +104,10 @@ func TestMilestoneCreate(t *testing.T) { want := new(scm.Milestone) raw, _ := ioutil.ReadFile("testdata/milestone.json.golden") err = json.Unmarshal(raw, want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) @@ -137,8 +142,10 @@ func TestMilestoneUpdate(t *testing.T) { want := new(scm.Milestone) raw, _ := ioutil.ReadFile("testdata/milestone.json.golden") err = json.Unmarshal(raw, want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) diff --git a/scm/driver/gitea/release_test.go b/scm/driver/gitea/release_test.go index 762b944bd..ecd6458e7 100644 --- a/scm/driver/gitea/release_test.go +++ b/scm/driver/gitea/release_test.go @@ -10,7 +10,6 @@ import ( "github.com/google/go-cmp/cmp" "github.com/h2non/gock" - "github.com/stretchr/testify/assert" ) func TestConvertAPIURLToHTMLURL(t *testing.T) { @@ -72,8 +71,10 @@ func TestReleaseFind(t *testing.T) { want := new(scm.Release) raw, _ := ioutil.ReadFile("testdata/release.json.golden") err = json.Unmarshal(raw, want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) @@ -109,8 +110,10 @@ func TestReleaseFindByTag(t *testing.T) { want := new(scm.Release) raw, _ := ioutil.ReadFile("testdata/release.json.golden") err = json.Unmarshal(raw, want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) @@ -149,8 +152,10 @@ func TestReleaseList(t *testing.T) { want := []*scm.Release{} raw, _ := ioutil.ReadFile("testdata/releases.json.golden") err = json.Unmarshal(raw, &want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) @@ -197,8 +202,10 @@ func TestReleaseCreate(t *testing.T) { want := new(scm.Release) raw, _ := ioutil.ReadFile("testdata/release.json.golden") err = json.Unmarshal(raw, want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) @@ -244,8 +251,10 @@ func TestReleaseUpdate(t *testing.T) { want := new(scm.Release) raw, _ := ioutil.ReadFile("testdata/release.json.golden") err = json.Unmarshal(raw, want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) @@ -293,8 +302,10 @@ func TestReleaseUpdateByTag(t *testing.T) { want := new(scm.Release) raw, _ := ioutil.ReadFile("testdata/release.json.golden") err = json.Unmarshal(raw, want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) @@ -302,7 +313,6 @@ func TestReleaseUpdateByTag(t *testing.T) { } - func TestReleaseDelete(t *testing.T) { defer gock.Off() @@ -339,4 +349,4 @@ func TestReleaseDeleteByTag(t *testing.T) { return } -} \ No newline at end of file +} diff --git a/scm/driver/github/milestone_test.go b/scm/driver/github/milestone_test.go index a9d28d05c..e3546b36d 100644 --- a/scm/driver/github/milestone_test.go +++ b/scm/driver/github/milestone_test.go @@ -3,13 +3,14 @@ package github import ( "context" "encoding/json" - "github.com/drone/go-scm/scm" - "github.com/google/go-cmp/cmp" - "github.com/h2non/gock" - "github.com/stretchr/testify/assert" "io/ioutil" "testing" "time" + + "github.com/drone/go-scm/scm" + + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" ) func TestMilestoneFind(t *testing.T) { @@ -32,8 +33,10 @@ func TestMilestoneFind(t *testing.T) { want := new(scm.Milestone) raw, _ := ioutil.ReadFile("testdata/milestone.json.golden") err = json.Unmarshal(raw, want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) @@ -65,8 +68,10 @@ func TestMilestoneList(t *testing.T) { want := []*scm.Milestone{} raw, _ := ioutil.ReadFile("testdata/milestones.json.golden") err = json.Unmarshal(raw, &want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) @@ -105,8 +110,10 @@ func TestMilestoneCreate(t *testing.T) { want := new(scm.Milestone) raw, _ := ioutil.ReadFile("testdata/milestone.json.golden") err = json.Unmarshal(raw, want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) @@ -145,8 +152,10 @@ func TestMilestoneUpdate(t *testing.T) { want := new(scm.Milestone) raw, _ := ioutil.ReadFile("testdata/milestone.json.golden") err = json.Unmarshal(raw, want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) diff --git a/scm/driver/github/release_test.go b/scm/driver/github/release_test.go index a42cb8021..20ebd2ffb 100644 --- a/scm/driver/github/release_test.go +++ b/scm/driver/github/release_test.go @@ -3,13 +3,13 @@ package github import ( "context" "encoding/json" - "github.com/drone/go-scm/scm" - "github.com/h2non/gock" "io/ioutil" "testing" + "github.com/drone/go-scm/scm" + "github.com/google/go-cmp/cmp" - "github.com/stretchr/testify/assert" + "github.com/h2non/gock" ) func TestReleaseFind(t *testing.T) { @@ -32,8 +32,10 @@ func TestReleaseFind(t *testing.T) { want := new(scm.Release) raw, _ := ioutil.ReadFile("testdata/release.json.golden") err = json.Unmarshal(raw, want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) @@ -70,8 +72,10 @@ func TestReleaseList(t *testing.T) { want := []*scm.Release{} raw, _ := ioutil.ReadFile("testdata/releases.json.golden") err = json.Unmarshal(raw, &want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) @@ -112,8 +116,10 @@ func TestReleaseCreate(t *testing.T) { want := new(scm.Release) raw, _ := ioutil.ReadFile("testdata/release.json.golden") err = json.Unmarshal(raw, want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) @@ -154,8 +160,10 @@ func TestReleaseUpdate(t *testing.T) { want := new(scm.Release) raw, _ := ioutil.ReadFile("testdata/release.json.golden") err = json.Unmarshal(raw, want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) diff --git a/scm/driver/gitlab/release_test.go b/scm/driver/gitlab/release_test.go index 1c3fda899..998654923 100644 --- a/scm/driver/gitlab/release_test.go +++ b/scm/driver/gitlab/release_test.go @@ -10,7 +10,6 @@ import ( "github.com/google/go-cmp/cmp" "github.com/h2non/gock" - "github.com/stretchr/testify/assert" ) func TestReleaseFindByTag(t *testing.T) { @@ -33,8 +32,10 @@ func TestReleaseFindByTag(t *testing.T) { want := new(scm.Release) raw, _ := ioutil.ReadFile("testdata/release.json.golden") err = json.Unmarshal(raw, want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) @@ -68,8 +69,10 @@ func TestReleaseList(t *testing.T) { want := []*scm.Release{} raw, _ := ioutil.ReadFile("testdata/releases.json.golden") err = json.Unmarshal(raw, &want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) @@ -110,8 +113,10 @@ func TestReleaseCreate(t *testing.T) { want := new(scm.Release) raw, _ := ioutil.ReadFile("testdata/release.json.golden") err = json.Unmarshal(raw, want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) @@ -152,8 +157,10 @@ func TestReleaseUpdateByTag(t *testing.T) { want := new(scm.Release) raw, _ := ioutil.ReadFile("testdata/release.json.golden") err = json.Unmarshal(raw, want) - assert.NoError(t, err) - + if err != nil { + t.Error(err) + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) From 9bedabec2fbe704b3b438cfb01fee88aab8e9686 Mon Sep 17 00:00:00 2001 From: Eoin McAfee Date: Fri, 24 Sep 2021 16:43:22 +0100 Subject: [PATCH 036/282] revert user back to private --- scm/driver/gitea/git.go | 6 +++--- scm/driver/gitea/issue.go | 4 ++-- scm/driver/gitea/org.go | 2 +- scm/driver/gitea/org_test.go | 2 +- scm/driver/gitea/pr.go | 2 +- scm/driver/gitea/release.go | 2 +- scm/driver/gitea/repo.go | 4 ++-- scm/driver/gitea/repo_test.go | 2 +- scm/driver/gitea/user.go | 12 ++++++------ scm/driver/gitea/user_test.go | 14 +++++++------- scm/driver/gitea/webhook.go | 10 +++++----- 11 files changed, 30 insertions(+), 30 deletions(-) diff --git a/scm/driver/gitea/git.go b/scm/driver/gitea/git.go index d1b2223e2..8382b8cad 100644 --- a/scm/driver/gitea/git.go +++ b/scm/driver/gitea/git.go @@ -107,8 +107,8 @@ type ( commitInfo struct { Sha string `json:"sha"` Commit commit `json:"commit"` - Author User `json:"author"` - Committer User `json:"committer"` + Author user `json:"author"` + Committer user `json:"committer"` } // gitea signature object. @@ -176,7 +176,7 @@ func convertSignature(src signature) scm.Signature { } } -func convertUserSignature(src User) scm.Signature { +func convertUserSignature(src user) scm.Signature { return scm.Signature{ Login: userLogin(&src), Email: src.Email, diff --git a/scm/driver/gitea/issue.go b/scm/driver/gitea/issue.go index b80524a62..d5e322a4b 100644 --- a/scm/driver/gitea/issue.go +++ b/scm/driver/gitea/issue.go @@ -88,7 +88,7 @@ type ( issue struct { ID int `json:"id"` Number int `json:"number"` - User User `json:"User"` + User user `json:"user"` Title string `json:"title"` Body string `json:"body"` State string `json:"state"` @@ -112,7 +112,7 @@ type ( issueComment struct { ID int `json:"id"` HTMLURL string `json:"html_url"` - User User `json:"User"` + User user `json:"user"` Body string `json:"body"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` diff --git a/scm/driver/gitea/org.go b/scm/driver/gitea/org.go index 25d9b4c8b..c7c7efc03 100644 --- a/scm/driver/gitea/org.go +++ b/scm/driver/gitea/org.go @@ -27,7 +27,7 @@ func (s *organizationService) FindMembership(ctx context.Context, name, username } func (s *organizationService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Organization, *scm.Response, error) { - path := fmt.Sprintf("api/v1/User/orgs?%s", encodeListOptions(opts)) + path := fmt.Sprintf("api/v1/user/orgs?%s", encodeListOptions(opts)) out := []*org{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertOrgList(out), res, err diff --git a/scm/driver/gitea/org_test.go b/scm/driver/gitea/org_test.go index 1515faaf1..90a0a193c 100644 --- a/scm/driver/gitea/org_test.go +++ b/scm/driver/gitea/org_test.go @@ -53,7 +53,7 @@ func TestOrgList(t *testing.T) { defer gock.Off() gock.New("https://try.gitea.io"). - Get("/api/v1/User/orgs"). + Get("/api/v1/user/orgs"). Reply(200). Type("application/json"). File("testdata/organizations.json") diff --git a/scm/driver/gitea/pr.go b/scm/driver/gitea/pr.go index 890aac0ad..efea1f6e4 100644 --- a/scm/driver/gitea/pr.go +++ b/scm/driver/gitea/pr.go @@ -84,7 +84,7 @@ func (s *pullService) Close(context.Context, string, int) (*scm.Response, error) type pr struct { ID int `json:"id"` Number int `json:"number"` - User User `json:"User"` + User user `json:"user"` Title string `json:"title"` Body string `json:"body"` State string `json:"state"` diff --git a/scm/driver/gitea/release.go b/scm/driver/gitea/release.go index e00e6e8e7..7658fb7c3 100644 --- a/scm/driver/gitea/release.go +++ b/scm/driver/gitea/release.go @@ -112,7 +112,7 @@ type release struct { IsPrerelease bool `json:"prerelease"` CreatedAt time.Time `json:"created_at"` PublishedAt time.Time `json:"published_at"` - Publisher *User `json:"author"` + Publisher *user `json:"author"` Attachments []*Attachment `json:"assets"` } diff --git a/scm/driver/gitea/repo.go b/scm/driver/gitea/repo.go index 7a2ca2fea..ef2b441bd 100644 --- a/scm/driver/gitea/repo.go +++ b/scm/driver/gitea/repo.go @@ -40,7 +40,7 @@ func (s *repositoryService) FindPerms(ctx context.Context, repo string) (*scm.Pe } func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { - path := fmt.Sprintf("api/v1/User/repos?%s", encodeListOptions(opts)) + path := fmt.Sprintf("api/v1/user/repos?%s", encodeListOptions(opts)) out := []*repository{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertRepositoryList(out), res, err @@ -136,7 +136,7 @@ type ( // gitea repository resource. repository struct { ID int `json:"id"` - Owner User `json:"owner"` + Owner user `json:"owner"` Name string `json:"name"` FullName string `json:"full_name"` Private bool `json:"private"` diff --git a/scm/driver/gitea/repo_test.go b/scm/driver/gitea/repo_test.go index e252b32f6..bf9da32ae 100644 --- a/scm/driver/gitea/repo_test.go +++ b/scm/driver/gitea/repo_test.go @@ -73,7 +73,7 @@ func TestRepoList(t *testing.T) { defer gock.Off() gock.New("https://try.gitea.io"). - Get("/api/v1/User/repos"). + Get("/api/v1/user/repos"). Reply(200). Type("application/json"). File("testdata/repos.json") diff --git a/scm/driver/gitea/user.go b/scm/driver/gitea/user.go index 623cbbdb4..09b9e9399 100644 --- a/scm/driver/gitea/user.go +++ b/scm/driver/gitea/user.go @@ -16,14 +16,14 @@ type userService struct { } func (s *userService) Find(ctx context.Context) (*scm.User, *scm.Response, error) { - out := new(User) - res, err := s.client.do(ctx, "GET", "api/v1/User", nil, out) + out := new(user) + res, err := s.client.do(ctx, "GET", "api/v1/user", nil, out) return convertUser(out), res, err } func (s *userService) FindLogin(ctx context.Context, login string) (*scm.User, *scm.Response, error) { path := fmt.Sprintf("api/v1/users/%s", login) - out := new(User) + out := new(user) res, err := s.client.do(ctx, "GET", path, nil, out) return convertUser(out), res, err } @@ -37,7 +37,7 @@ func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, err // native data structures // -type User struct { +type user struct { ID int `json:"id"` Login string `json:"login"` Username string `json:"username"` @@ -50,7 +50,7 @@ type User struct { // native data structure conversion // -func convertUser(src *User) *scm.User { +func convertUser(src *user) *scm.User { return &scm.User{ Login: userLogin(src), Avatar: src.Avatar, @@ -59,7 +59,7 @@ func convertUser(src *User) *scm.User { } } -func userLogin(src *User) string { +func userLogin(src *user) string { if src.Username != "" { return src.Username } diff --git a/scm/driver/gitea/user_test.go b/scm/driver/gitea/user_test.go index 24d9f9e3e..64d1eaaa6 100644 --- a/scm/driver/gitea/user_test.go +++ b/scm/driver/gitea/user_test.go @@ -20,10 +20,10 @@ func TestUserFind(t *testing.T) { defer gock.Off() gock.New("https://try.gitea.io"). - Get("/api/v1/User"). + Get("/api/v1/user"). Reply(200). Type("application/json"). - File("testdata/User.json") + File("testdata/user.json") client, _ := New("https://try.gitea.io") got, _, err := client.Users.Find(context.Background()) @@ -32,7 +32,7 @@ func TestUserFind(t *testing.T) { } want := new(scm.User) - raw, _ := ioutil.ReadFile("testdata/User.json.golden") + raw, _ := ioutil.ReadFile("testdata/user.json.golden") json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { @@ -48,7 +48,7 @@ func TestUserLoginFind(t *testing.T) { Get("/api/v1/users/jcitizen"). Reply(200). Type("application/json"). - File("testdata/User.json") + File("testdata/user.json") client, _ := New("https://try.gitea.io") got, _, err := client.Users.FindLogin(context.Background(), "jcitizen") @@ -57,7 +57,7 @@ func TestUserLoginFind(t *testing.T) { } want := new(scm.User) - raw, _ := ioutil.ReadFile("testdata/User.json.golden") + raw, _ := ioutil.ReadFile("testdata/user.json.golden") json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { @@ -70,10 +70,10 @@ func TestUserFindEmail(t *testing.T) { defer gock.Off() gock.New("https://try.gitea.io"). - Get("/api/v1/User"). + Get("/api/v1/user"). Reply(200). Type("application/json"). - File("testdata/User.json") + File("testdata/user.json") client, _ := New("https://try.gitea.io") email, _, err := client.Users.FindEmail(context.Background()) diff --git a/scm/driver/gitea/webhook.go b/scm/driver/gitea/webhook.go index 22e07bfda..5f02bc5db 100644 --- a/scm/driver/gitea/webhook.go +++ b/scm/driver/gitea/webhook.go @@ -146,8 +146,8 @@ type ( Compare string `json:"compare_url"` Commits []commit `json:"commits"` Repository repository `json:"repository"` - Pusher User `json:"pusher"` - Sender User `json:"sender"` + Pusher user `json:"pusher"` + Sender user `json:"sender"` } // gitea create webhook payload @@ -157,7 +157,7 @@ type ( Sha string `json:"sha"` DefaultBranch string `json:"default_branch"` Repository repository `json:"repository"` - Sender User `json:"sender"` + Sender user `json:"sender"` } // gitea issue webhook payload @@ -166,7 +166,7 @@ type ( Issue issue `json:"issue"` Comment issueComment `json:"comment"` Repository repository `json:"repository"` - Sender User `json:"sender"` + Sender user `json:"sender"` } // gitea pull request webhook payload @@ -175,7 +175,7 @@ type ( Number int `json:"number"` PullRequest pr `json:"pull_request"` Repository repository `json:"repository"` - Sender User `json:"sender"` + Sender user `json:"sender"` } ) From 00597ec59d9196687e7a6a822fe0bbb7aedfba54 Mon Sep 17 00:00:00 2001 From: Eoin McAfee Date: Mon, 27 Sep 2021 10:33:33 +0100 Subject: [PATCH 037/282] techqa feedback --- scm/driver/bitbucket/milestone.go | 2 +- scm/driver/gitea/milestone.go | 32 ++++++++++++++--------------- scm/driver/gitea/milestone_test.go | 4 ++-- scm/driver/gitea/release.go | 9 +++++++- scm/driver/gitea/repo.go | 6 +++--- scm/driver/gitea/util.go | 24 +++++++++------------- scm/driver/github/milestone.go | 8 ++++---- scm/driver/github/milestone_test.go | 4 ++-- scm/driver/gitlab/milestone.go | 20 +++++++++--------- scm/driver/gitlab/milestone_test.go | 4 ++-- scm/driver/gitlab/release.go | 6 ++---- scm/milestone.go | 2 +- scm/pr.go | 2 +- 13 files changed, 62 insertions(+), 61 deletions(-) diff --git a/scm/driver/bitbucket/milestone.go b/scm/driver/bitbucket/milestone.go index 7e18430ae..7c2624dc6 100644 --- a/scm/driver/bitbucket/milestone.go +++ b/scm/driver/bitbucket/milestone.go @@ -14,7 +14,7 @@ func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm. return nil, nil, scm.ErrNotSupported } -func (s *milestoneService) List(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Milestone, *scm.Response, error) { +func (s *milestoneService) List(ctx context.Context, repo string, opts scm.MilestoneListOptions) ([]*scm.Milestone, *scm.Response, error) { return nil, nil, scm.ErrNotSupported } diff --git a/scm/driver/gitea/milestone.go b/scm/driver/gitea/milestone.go index bec60a56e..545a54775 100644 --- a/scm/driver/gitea/milestone.go +++ b/scm/driver/gitea/milestone.go @@ -67,7 +67,7 @@ func (s *milestoneService) Update(ctx context.Context, repo string, id int, inpu if input.Description != "" { in.Description = input.Description } - if input.DueDate != nil { + if !input.DueDate.IsZero() { in.Deadline = input.DueDate } out := new(milestone) @@ -88,23 +88,23 @@ const ( ) type milestone struct { - ID int64 `json:"id"` - Title string `json:"title"` - Description string `json:"description"` - State StateType `json:"state"` - OpenIssues int `json:"open_issues"` - ClosedIssues int `json:"closed_issues"` - Created time.Time `json:"created_at"` - Updated *time.Time `json:"updated_at"` - Closed *time.Time `json:"closed_at"` - Deadline *time.Time `json:"due_on"` + ID int64 `json:"id"` + Title string `json:"title"` + Description string `json:"description"` + State StateType `json:"state"` + OpenIssues int `json:"open_issues"` + ClosedIssues int `json:"closed_issues"` + Created time.Time `json:"created_at"` + Updated time.Time `json:"updated_at"` + Closed time.Time `json:"closed_at"` + Deadline time.Time `json:"due_on"` } type milestoneInput struct { - Title string `json:"title"` - Description string `json:"description"` - State StateType `json:"state"` - Deadline *time.Time `json:"due_on"` + Title string `json:"title"` + Description string `json:"description"` + State StateType `json:"state"` + Deadline time.Time `json:"due_on"` } func convertMilestoneList(src []*milestone) []*scm.Milestone { @@ -116,7 +116,7 @@ func convertMilestoneList(src []*milestone) []*scm.Milestone { } func convertMilestone(src *milestone) *scm.Milestone { - if src == nil || src.Deadline == nil { + if src == nil || src.Deadline.IsZero() { return nil } return &scm.Milestone{ diff --git a/scm/driver/gitea/milestone_test.go b/scm/driver/gitea/milestone_test.go index f825ae161..93d9f185e 100644 --- a/scm/driver/gitea/milestone_test.go +++ b/scm/driver/gitea/milestone_test.go @@ -94,7 +94,7 @@ func TestMilestoneCreate(t *testing.T) { Title: "v1.0", Description: "Tracking milestone for version 1.0", State: "open", - DueDate: &dueDate, + DueDate: dueDate, } got, _, err := client.Milestones.Create(context.Background(), "jcitizen/my-repo", input) if err != nil { @@ -132,7 +132,7 @@ func TestMilestoneUpdate(t *testing.T) { Title: "v1.0", Description: "Tracking milestone for version 1.0", State: "open", - DueDate: &dueDate, + DueDate: dueDate, } got, _, err := client.Milestones.Update(context.Background(), "jcitizen/my-repo", 1, input) if err != nil { diff --git a/scm/driver/gitea/release.go b/scm/driver/gitea/release.go index 7658fb7c3..a85b57cb0 100644 --- a/scm/driver/gitea/release.go +++ b/scm/driver/gitea/release.go @@ -30,7 +30,7 @@ func (s *releaseService) FindByTag(ctx context.Context, repo string, tag string) func (s *releaseService) List(ctx context.Context, repo string, opts scm.ReleaseListOptions) ([]*scm.Release, *scm.Response, error) { namespace, name := scm.Split(repo) - path := fmt.Sprintf("api/v1/repos/%s/%s/releases?%s", namespace, name, encodeReleaseListOptions(opts)) + path := fmt.Sprintf("api/v1/repos/%s/%s/releases?%s", namespace, name, encodeReleaseListOptions(releaseListOptionsToGiteaListOptions(opts))) out := []*release{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertReleaseList(out), res, err @@ -148,3 +148,10 @@ func convertReleaseList(src []*release) []*scm.Release { } return dst } + +func releaseListOptionsToGiteaListOptions(in scm.ReleaseListOptions) ListOptions { + return ListOptions{ + Page: in.Page, + PageSize: in.Size, + } +} \ No newline at end of file diff --git a/scm/driver/gitea/repo.go b/scm/driver/gitea/repo.go index ef2b441bd..154c7f322 100644 --- a/scm/driver/gitea/repo.go +++ b/scm/driver/gitea/repo.go @@ -135,9 +135,9 @@ func (s *repositoryService) DeleteHook(ctx context.Context, repo string, id stri type ( // gitea repository resource. repository struct { - ID int `json:"id"` - Owner user `json:"owner"` - Name string `json:"name"` + ID int `json:"id"` + Owner user `json:"owner"` + Name string `json:"name"` FullName string `json:"full_name"` Private bool `json:"private"` Fork bool `json:"fork"` diff --git a/scm/driver/gitea/util.go b/scm/driver/gitea/util.go index e88ed4c66..3404b1b0c 100644 --- a/scm/driver/gitea/util.go +++ b/scm/driver/gitea/util.go @@ -90,18 +90,14 @@ func encodeMilestoneListOptions(opts scm.MilestoneListOptions) string { return params.Encode() } -func encodeReleaseListOptions(opts scm.ReleaseListOptions) string { - params := url.Values{} - if opts.Page != 0 { - params.Set("page", strconv.Itoa(opts.Page)) - } - if opts.Size != 0 { - params.Set("per_page", strconv.Itoa(opts.Size)) - } - if opts.Open && opts.Closed { - params.Set("state", "all") - } else if opts.Closed { - params.Set("state", "closed") - } - return params.Encode() +type ListOptions struct { + Page int + PageSize int +} + +func encodeReleaseListOptions(o ListOptions) string { + query := make(url.Values) + query.Add("page", fmt.Sprintf("%d", o.Page)) + query.Add("limit", fmt.Sprintf("%d", o.PageSize)) + return query.Encode() } \ No newline at end of file diff --git a/scm/driver/github/milestone.go b/scm/driver/github/milestone.go index beb8847e7..b01c0e1c5 100644 --- a/scm/driver/github/milestone.go +++ b/scm/driver/github/milestone.go @@ -58,7 +58,7 @@ func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.M Title: input.Title, State: input.State, Description: input.Description, - DueOn: *input.DueDate, + DueOn: input.DueDate, } out := new(milestone) res, err := s.client.do(ctx, "POST", path, in, out) @@ -82,8 +82,8 @@ func (s *milestoneService) Update(ctx context.Context, repo string, id int, inpu if input.Description != "" { in.Description = input.Description } - if input.DueDate != nil { - in.DueOn = *input.DueDate + if !input.DueDate.IsZero() { + in.DueOn = input.DueDate } out := new(milestone) res, err := s.client.do(ctx, "PATCH", path, in, out) @@ -106,6 +106,6 @@ func convertMilestone(from *milestone) *scm.Milestone { Description: from.Description, Link: from.HTMLURL, State: from.State, - DueDate: &from.DueOn, + DueDate: from.DueOn, } } diff --git a/scm/driver/github/milestone_test.go b/scm/driver/github/milestone_test.go index e3546b36d..0d9c72d7a 100644 --- a/scm/driver/github/milestone_test.go +++ b/scm/driver/github/milestone_test.go @@ -98,7 +98,7 @@ func TestMilestoneCreate(t *testing.T) { Title: "v1.0", Description: "Tracking milestone for version 1.0", State: "open", - DueDate: &dueDate, + DueDate: dueDate, } got, res, err := client.Milestones.Create(context.Background(), "octocat/hello-world", input) @@ -140,7 +140,7 @@ func TestMilestoneUpdate(t *testing.T) { Title: "v1.0", Description: "Tracking milestone for version 1.0", State: "open", - DueDate: &dueDate, + DueDate: dueDate, } got, res, err := client.Milestones.Update(context.Background(), "octocat/hello-world", 1, input) diff --git a/scm/driver/gitlab/milestone.go b/scm/driver/gitlab/milestone.go index 7cdf8e56a..0995a5ebf 100644 --- a/scm/driver/gitlab/milestone.go +++ b/scm/driver/gitlab/milestone.go @@ -77,10 +77,10 @@ type milestone struct { } type milestoneInput struct { - Title *string `json:"title"` - StateEvent *string `json:"state_event,omitempty"` - Description *string `json:"description"` - DueDate *isoTime `json:"due_date"` + Title *string `json:"title"` + StateEvent *string `json:"state_event,omitempty"` + Description *string `json:"description"` + DueDate isoTime `json:"due_date"` } func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) { @@ -99,11 +99,11 @@ func (s *milestoneService) List(ctx context.Context, repo string, opts scm.Miles func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { path := fmt.Sprintf("api/v4/projects/%s/milestones", encode(repo)) - dueDateIso := isoTime(*input.DueDate) + dueDateIso := isoTime(input.DueDate) in := &milestoneInput{ Title: &input.Title, Description: &input.Description, - DueDate: &dueDateIso, + DueDate: dueDateIso, } out := new(milestone) res, err := s.client.do(ctx, "POST", path, in, out) @@ -133,9 +133,9 @@ func (s *milestoneService) Update(ctx context.Context, repo string, id int, inpu if input.Description != "" { in.Description = &input.Description } - if input.DueDate != nil { - dueDateIso := isoTime(*input.DueDate) - in.DueDate = &dueDateIso + if !input.DueDate.IsZero() { + dueDateIso := isoTime(input.DueDate) + in.DueDate = dueDateIso } out := new(milestone) res, err := s.client.do(ctx, "PATCH", path, in, out) @@ -161,6 +161,6 @@ func convertMilestone(from *milestone) *scm.Milestone { Title: from.Title, Description: from.Description, State: from.State, - DueDate: &dueDate, + DueDate: dueDate, } } diff --git a/scm/driver/gitlab/milestone_test.go b/scm/driver/gitlab/milestone_test.go index f8e02794c..58d578638 100644 --- a/scm/driver/gitlab/milestone_test.go +++ b/scm/driver/gitlab/milestone_test.go @@ -99,7 +99,7 @@ func TestMilestoneCreate(t *testing.T) { Title: "v1.0", Description: "Tracking milestone for version 1.0", State: "open", - DueDate: &dueDate, + DueDate: dueDate, } got, res, err := client.Milestones.Create(context.Background(), "diaspora/diaspora", input) if err != nil { @@ -142,7 +142,7 @@ func TestMilestoneUpdate(t *testing.T) { Title: "v1.0", Description: "Tracking milestone for version 1.0", State: "close", - DueDate: &dueDate, + DueDate: dueDate, } got, res, err := client.Milestones.Update(context.Background(), "diaspora/diaspora", 1, input) if err != nil { diff --git a/scm/driver/gitlab/release.go b/scm/driver/gitlab/release.go index 625404870..874c728ee 100644 --- a/scm/driver/gitlab/release.go +++ b/scm/driver/gitlab/release.go @@ -27,8 +27,7 @@ type releaseInput struct { } func (s *releaseService) Find(ctx context.Context, repo string, id int) (*scm.Release, *scm.Response, error) { - // this could be implemented by List and filter but would be to expensive - panic("gitlab only allows to find a release by tag") + return nil, nil, scm.ErrNotSupported } func (s *releaseService) FindByTag(ctx context.Context, repo string, tag string) (*scm.Release, *scm.Response, error) { @@ -58,8 +57,7 @@ func (s *releaseService) Create(ctx context.Context, repo string, input *scm.Rel } func (s *releaseService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { - // this could be implemented by List and filter but would be to expensive - panic("gitlab only allows to delete a release by tag") + return nil, scm.ErrNotSupported } func (s *releaseService) DeleteByTag(ctx context.Context, repo string, tag string) (*scm.Response, error) { diff --git a/scm/milestone.go b/scm/milestone.go index 54ed9683b..a251c9dba 100644 --- a/scm/milestone.go +++ b/scm/milestone.go @@ -11,7 +11,7 @@ type ( Title string Description string State string - DueDate *time.Time + DueDate time.Time } // MilestoneListOptions provides options for querying a list of repository milestones. diff --git a/scm/pr.go b/scm/pr.go index 49d4e3543..f08147bae 100644 --- a/scm/pr.go +++ b/scm/pr.go @@ -72,7 +72,7 @@ type ( Description string Link string State string - DueDate *time.Time + DueDate time.Time } // PullRequestService provides access to pull request resources. From 725ce808d2d483010378621b5cf082b68e7cb5b4 Mon Sep 17 00:00:00 2001 From: Eoin McAfee Date: Tue, 28 Sep 2021 16:56:01 +0100 Subject: [PATCH 038/282] change time.Time to null.Time package --- scm/client.go | 2 -- scm/driver/github/milestone.go | 32 ++++++++++++++++---------------- scm/driver/github/release.go | 11 +++++------ 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/scm/client.go b/scm/client.go index c89fe89a3..462be89bd 100644 --- a/scm/client.go +++ b/scm/client.go @@ -73,8 +73,6 @@ type ( URL string Page int Size int - Open bool - Closed bool } // Client manages communication with a version control diff --git a/scm/driver/github/milestone.go b/scm/driver/github/milestone.go index b01c0e1c5..89231623a 100644 --- a/scm/driver/github/milestone.go +++ b/scm/driver/github/milestone.go @@ -3,9 +3,9 @@ package github import ( "context" "fmt" - "time" "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/internal/null" ) type milestoneService struct { @@ -18,7 +18,7 @@ type milestone struct { Title string `json:"title"` Description string `json:"description"` State string `json:"state"` - DueOn time.Time `json:"due_on"` + DueOn null.Time `json:"due_on"` URL string `json:"url"` HTMLURL string `json:"html_url"` LabelsURL string `json:"labels_url"` @@ -26,16 +26,16 @@ type milestone struct { OpenIssues int `json:"open_issues"` ClosedIssues int `json:"closed_issues"` NodeID string `json:"node_id"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - ClosedAt time.Time `json:"closed_at"` + CreatedAt null.Time `json:"created_at"` + UpdatedAt null.Time `json:"updated_at"` + ClosedAt null.Time `json:"closed_at"` } type milestoneInput struct { Title string `json:"title"` State string `json:"state"` Description string `json:"description"` - DueOn time.Time `json:"due_on"` + DueOn null.Time `json:"due_on"` } func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) { @@ -58,7 +58,7 @@ func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.M Title: input.Title, State: input.State, Description: input.Description, - DueOn: input.DueDate, + DueOn: null.Time{Time: input.DueDate, Valid: true}, } out := new(milestone) res, err := s.client.do(ctx, "POST", path, in, out) @@ -83,7 +83,7 @@ func (s *milestoneService) Update(ctx context.Context, repo string, id int, inpu in.Description = input.Description } if !input.DueDate.IsZero() { - in.DueOn = input.DueDate + in.DueOn = null.Time{Time: input.DueDate, Valid: true} } out := new(milestone) res, err := s.client.do(ctx, "PATCH", path, in, out) @@ -98,14 +98,14 @@ func convertMilestoneList(from []*milestone) []*scm.Milestone { return to } -func convertMilestone(from *milestone) *scm.Milestone { +func convertMilestone(src *milestone) *scm.Milestone { return &scm.Milestone{ - Number: from.Number, - ID: from.ID, - Title: from.Title, - Description: from.Description, - Link: from.HTMLURL, - State: from.State, - DueDate: from.DueOn, + Number: src.Number, + ID: src.ID, + Title: src.Title, + Description: src.Description, + Link: src.HTMLURL, + State: src.State, + DueDate: src.DueOn.ValueOrZero(), } } diff --git a/scm/driver/github/release.go b/scm/driver/github/release.go index add064d27..9be09e686 100644 --- a/scm/driver/github/release.go +++ b/scm/driver/github/release.go @@ -3,9 +3,8 @@ package github import ( "context" "fmt" - "time" - "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/internal/null" ) type releaseService struct { @@ -21,8 +20,8 @@ type release struct { Commitish string `json:"target_commitish,omitempty"` Draft bool `json:"draft"` Prerelease bool `json:"prerelease"` - Created time.Time `json:"created_at"` - Published time.Time `json:"published_at"` + Created null.Time `json:"created_at"` + Published null.Time `json:"published_at"` } type releaseInput struct { @@ -125,7 +124,7 @@ func convertRelease(from *release) *scm.Release { Commitish: from.Commitish, Draft: from.Draft, Prerelease: from.Prerelease, - Created: from.Created, - Published: from.Published, + Created: from.Created.ValueOrZero(), + Published: from.Published.ValueOrZero(), } } From 9184b690ac0dd2c59820f7036b710588c9bf9519 Mon Sep 17 00:00:00 2001 From: Eoin McAfee Date: Wed, 29 Sep 2021 09:59:35 +0100 Subject: [PATCH 039/282] update milestone/release to use null.time instead of time.Time --- scm/driver/gitea/milestone.go | 19 +++++++++---------- scm/driver/gitea/release.go | 13 ++++++------- scm/driver/github/milestone.go | 4 ++-- scm/driver/gitlab/milestone.go | 5 +++-- scm/driver/internal/null/time.go | 22 ++++++++++++++++++++++ 5 files changed, 42 insertions(+), 21 deletions(-) diff --git a/scm/driver/gitea/milestone.go b/scm/driver/gitea/milestone.go index 545a54775..b0a983539 100644 --- a/scm/driver/gitea/milestone.go +++ b/scm/driver/gitea/milestone.go @@ -3,9 +3,8 @@ package gitea import ( "context" "fmt" - "time" - "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/internal/null" ) type milestoneService struct { @@ -35,7 +34,7 @@ func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.M Title: input.Title, Description: input.Description, State: StateOpen, - Deadline: input.DueDate, + Deadline: null.NewTime(input.DueDate, true), } if input.State == "closed" { in.State = StateClosed @@ -68,7 +67,7 @@ func (s *milestoneService) Update(ctx context.Context, repo string, id int, inpu in.Description = input.Description } if !input.DueDate.IsZero() { - in.Deadline = input.DueDate + in.Deadline = null.NewTime(input.DueDate, true) } out := new(milestone) res, err := s.client.do(ctx, "PATCH", path, in, out) @@ -94,17 +93,17 @@ type milestone struct { State StateType `json:"state"` OpenIssues int `json:"open_issues"` ClosedIssues int `json:"closed_issues"` - Created time.Time `json:"created_at"` - Updated time.Time `json:"updated_at"` - Closed time.Time `json:"closed_at"` - Deadline time.Time `json:"due_on"` + Created null.Time `json:"created_at"` + Updated null.Time `json:"updated_at"` + Closed null.Time `json:"closed_at"` + Deadline null.Time `json:"due_on"` } type milestoneInput struct { Title string `json:"title"` Description string `json:"description"` State StateType `json:"state"` - Deadline time.Time `json:"due_on"` + Deadline null.Time `json:"due_on"` } func convertMilestoneList(src []*milestone) []*scm.Milestone { @@ -125,6 +124,6 @@ func convertMilestone(src *milestone) *scm.Milestone { Title: src.Title, Description: src.Description, State: string(src.State), - DueDate: src.Deadline, + DueDate: src.Deadline.ValueOrZero(), } } diff --git a/scm/driver/gitea/release.go b/scm/driver/gitea/release.go index a85b57cb0..dab325964 100644 --- a/scm/driver/gitea/release.go +++ b/scm/driver/gitea/release.go @@ -3,9 +3,8 @@ package gitea import ( "context" "fmt" - "time" - "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/internal/null" ) type releaseService struct { @@ -110,8 +109,8 @@ type release struct { ZipURL string `json:"zipball_url"` IsDraft bool `json:"draft"` IsPrerelease bool `json:"prerelease"` - CreatedAt time.Time `json:"created_at"` - PublishedAt time.Time `json:"published_at"` + CreatedAt null.Time `json:"created_at"` + PublishedAt null.Time `json:"published_at"` Publisher *user `json:"author"` Attachments []*Attachment `json:"assets"` } @@ -121,7 +120,7 @@ type Attachment struct { Name string `json:"name"` Size int64 `json:"size"` DownloadCount int64 `json:"download_count"` - Created time.Time `json:"created_at"` + Created null.Time `json:"created_at"` UUID string `json:"uuid"` DownloadURL string `json:"browser_download_url"` } @@ -136,8 +135,8 @@ func convertRelease(src *release) *scm.Release { Commitish: src.Target, Draft: src.IsDraft, Prerelease: src.IsPrerelease, - Created: src.CreatedAt, - Published: src.PublishedAt, + Created: src.CreatedAt.ValueOrZero(), + Published: src.PublishedAt.ValueOrZero(), } } diff --git a/scm/driver/github/milestone.go b/scm/driver/github/milestone.go index 89231623a..0209870a0 100644 --- a/scm/driver/github/milestone.go +++ b/scm/driver/github/milestone.go @@ -58,7 +58,7 @@ func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.M Title: input.Title, State: input.State, Description: input.Description, - DueOn: null.Time{Time: input.DueDate, Valid: true}, + DueOn: null.NewTime(input.DueDate, true), } out := new(milestone) res, err := s.client.do(ctx, "POST", path, in, out) @@ -83,7 +83,7 @@ func (s *milestoneService) Update(ctx context.Context, repo string, id int, inpu in.Description = input.Description } if !input.DueDate.IsZero() { - in.DueOn = null.Time{Time: input.DueDate, Valid: true} + in.DueOn = null.NewTime(input.DueDate, true) } out := new(milestone) res, err := s.client.do(ctx, "PATCH", path, in, out) diff --git a/scm/driver/gitlab/milestone.go b/scm/driver/gitlab/milestone.go index 0995a5ebf..111897508 100644 --- a/scm/driver/gitlab/milestone.go +++ b/scm/driver/gitlab/milestone.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "github.com/drone/go-scm/scm/driver/internal/null" "net/url" "time" @@ -71,8 +72,8 @@ type milestone struct { State string `json:"state"` DueDate isoTime `json:"due_date"` StartDate isoTime `json:"start_date"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` + CreatedAt null.Time `json:"created_at"` + UpdatedAt null.Time `json:"updated_at"` Expired bool `json:"expired"` } diff --git a/scm/driver/internal/null/time.go b/scm/driver/internal/null/time.go index 574209ad0..71f64c3f9 100644 --- a/scm/driver/internal/null/time.go +++ b/scm/driver/internal/null/time.go @@ -63,3 +63,25 @@ func (t Time) ValueOrZero() time.Time { func (t Time) IsZero() bool { return !t.Valid || t.Time.IsZero() } + +// Ptr returns a pointer to this Time's value, +// or a nil pointer if this Time is zero. +func (t Time) Ptr() *time.Time { + if !t.Valid { + return nil + } + return &t.Time +} + +// NewTime creates a new Time. +func NewTime(t time.Time, valid bool) Time { + return Time{ + Time: t, + Valid: valid, + } +} + +// TimeFrom creates a new Time that will always be valid. +func TimeFrom(t time.Time) Time { + return NewTime(t, true) +} \ No newline at end of file From 44e08911f44e2ef3e9b5652e5f7b3049631ff7f1 Mon Sep 17 00:00:00 2001 From: Eoin McAfee Date: Wed, 29 Sep 2021 10:01:38 +0100 Subject: [PATCH 040/282] go fmt import --- scm/driver/gitea/milestone.go | 1 + scm/driver/gitea/release.go | 7 ++++--- scm/driver/github/release.go | 1 + scm/driver/gitlab/milestone_test.go | 5 +++-- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/scm/driver/gitea/milestone.go b/scm/driver/gitea/milestone.go index b0a983539..ee4683ba4 100644 --- a/scm/driver/gitea/milestone.go +++ b/scm/driver/gitea/milestone.go @@ -3,6 +3,7 @@ package gitea import ( "context" "fmt" + "github.com/drone/go-scm/scm" "github.com/drone/go-scm/scm/driver/internal/null" ) diff --git a/scm/driver/gitea/release.go b/scm/driver/gitea/release.go index dab325964..10483c770 100644 --- a/scm/driver/gitea/release.go +++ b/scm/driver/gitea/release.go @@ -3,6 +3,7 @@ package gitea import ( "context" "fmt" + "github.com/drone/go-scm/scm" "github.com/drone/go-scm/scm/driver/internal/null" ) @@ -21,7 +22,7 @@ func (s *releaseService) Find(ctx context.Context, repo string, id int) (*scm.Re func (s *releaseService) FindByTag(ctx context.Context, repo string, tag string) (*scm.Release, *scm.Response, error) { namespace, name := scm.Split(repo) - path := fmt.Sprintf("api/v1/repos/%s/%s/releases/tags/%s", namespace, name, tag) + path := fmt.Sprintf("api/v1/repos/%s/%s/releases/tags/%s", namespace, name, tag) out := new(release) res, err := s.client.do(ctx, "GET", path, nil, out) return convertRelease(out), res, err @@ -59,7 +60,7 @@ func (s *releaseService) Delete(ctx context.Context, repo string, id int) (*scm. func (s *releaseService) DeleteByTag(ctx context.Context, repo string, tag string) (*scm.Response, error) { namespace, name := scm.Split(repo) - path := fmt.Sprintf("api/v1/repos/%s/%s/releases/tags/%s", namespace, name, tag) + path := fmt.Sprintf("api/v1/repos/%s/%s/releases/tags/%s", namespace, name, tag) return s.client.do(ctx, "DELETE", path, nil, nil) } @@ -153,4 +154,4 @@ func releaseListOptionsToGiteaListOptions(in scm.ReleaseListOptions) ListOptions Page: in.Page, PageSize: in.Size, } -} \ No newline at end of file +} diff --git a/scm/driver/github/release.go b/scm/driver/github/release.go index 9be09e686..afc848c79 100644 --- a/scm/driver/github/release.go +++ b/scm/driver/github/release.go @@ -3,6 +3,7 @@ package github import ( "context" "fmt" + "github.com/drone/go-scm/scm" "github.com/drone/go-scm/scm/driver/internal/null" ) diff --git a/scm/driver/gitlab/milestone_test.go b/scm/driver/gitlab/milestone_test.go index 58d578638..98dfaa65e 100644 --- a/scm/driver/gitlab/milestone_test.go +++ b/scm/driver/gitlab/milestone_test.go @@ -3,13 +3,14 @@ package gitlab import ( "context" "encoding/json" - "github.com/drone/go-scm/scm" - "github.com/h2non/gock" "io/ioutil" "testing" "time" + "github.com/drone/go-scm/scm" + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" ) func TestMilestoneFind(t *testing.T) { From 44f7ab1871813a1861e5fcfa50e53ae3da479d23 Mon Sep 17 00:00:00 2001 From: Eoin McAfee Date: Wed, 29 Sep 2021 17:03:06 +0100 Subject: [PATCH 041/282] more techqa --- scm/driver/gitea/issue.go | 12 ++++++------ scm/driver/gitea/milestone.go | 32 ++++++++++++++++---------------- scm/driver/gitea/pr.go | 6 +++--- scm/driver/gitea/release.go | 2 +- scm/driver/gitea/release_test.go | 4 ++-- scm/driver/gitea/util.go | 4 ++-- scm/driver/github/milestone.go | 4 ++-- scm/driver/internal/null/time.go | 2 +- 8 files changed, 33 insertions(+), 33 deletions(-) diff --git a/scm/driver/gitea/issue.go b/scm/driver/gitea/issue.go index d5e322a4b..e006920c8 100644 --- a/scm/driver/gitea/issue.go +++ b/scm/driver/gitea/issue.go @@ -87,9 +87,9 @@ type ( // gitea issue response object. issue struct { ID int `json:"id"` - Number int `json:"number"` - User user `json:"user"` - Title string `json:"title"` + Number int `json:"number"` + User user `json:"user"` + Title string `json:"title"` Body string `json:"body"` State string `json:"state"` Labels []string `json:"labels"` @@ -111,9 +111,9 @@ type ( // gitea issue comment response object. issueComment struct { ID int `json:"id"` - HTMLURL string `json:"html_url"` - User user `json:"user"` - Body string `json:"body"` + HTMLURL string `json:"html_url"` + User user `json:"user"` + Body string `json:"body"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } diff --git a/scm/driver/gitea/milestone.go b/scm/driver/gitea/milestone.go index ee4683ba4..921a8ae69 100644 --- a/scm/driver/gitea/milestone.go +++ b/scm/driver/gitea/milestone.go @@ -34,11 +34,11 @@ func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.M in := &milestoneInput{ Title: input.Title, Description: input.Description, - State: StateOpen, + State: stateOpen, Deadline: null.NewTime(input.DueDate, true), } if input.State == "closed" { - in.State = StateClosed + in.State = stateClosed } out := new(milestone) res, err := s.client.do(ctx, "POST", path, in, out) @@ -60,39 +60,39 @@ func (s *milestoneService) Update(ctx context.Context, repo string, id int, inpu } switch input.State { case "open": - in.State = StateOpen + in.State = stateOpen case "close", "closed": - in.State = StateClosed + in.State = stateClosed } if input.Description != "" { in.Description = input.Description } if !input.DueDate.IsZero() { - in.Deadline = null.NewTime(input.DueDate, true) + in.Deadline = null.TimeFrom(input.DueDate) } out := new(milestone) res, err := s.client.do(ctx, "PATCH", path, in, out) return convertMilestone(out), res, err } -// StateType issue state type -type StateType string +// stateType issue state type +type stateType string const ( - // StateOpen pr/issue is open - StateOpen StateType = "open" - // StateClosed pr/issue is closed - StateClosed StateType = "closed" + // stateOpen pr/issue is open + stateOpen stateType = "open" + // stateClosed pr/issue is closed + stateClosed stateType = "closed" // StateAll is all - StateAll StateType = "all" + StateAll stateType = "all" ) type milestone struct { ID int64 `json:"id"` Title string `json:"title"` - Description string `json:"description"` - State StateType `json:"state"` - OpenIssues int `json:"open_issues"` + Description string `json:"description"` + State stateType `json:"state"` + OpenIssues int `json:"open_issues"` ClosedIssues int `json:"closed_issues"` Created null.Time `json:"created_at"` Updated null.Time `json:"updated_at"` @@ -103,7 +103,7 @@ type milestone struct { type milestoneInput struct { Title string `json:"title"` Description string `json:"description"` - State StateType `json:"state"` + State stateType `json:"state"` Deadline null.Time `json:"due_on"` } diff --git a/scm/driver/gitea/pr.go b/scm/driver/gitea/pr.go index efea1f6e4..754f46240 100644 --- a/scm/driver/gitea/pr.go +++ b/scm/driver/gitea/pr.go @@ -83,9 +83,9 @@ func (s *pullService) Close(context.Context, string, int) (*scm.Response, error) type pr struct { ID int `json:"id"` - Number int `json:"number"` - User user `json:"user"` - Title string `json:"title"` + Number int `json:"number"` + User user `json:"user"` + Title string `json:"title"` Body string `json:"body"` State string `json:"state"` HeadBranch string `json:"head_branch"` diff --git a/scm/driver/gitea/release.go b/scm/driver/gitea/release.go index 10483c770..f64eab834 100644 --- a/scm/driver/gitea/release.go +++ b/scm/driver/gitea/release.go @@ -131,7 +131,7 @@ func convertRelease(src *release) *scm.Release { ID: int(src.ID), Title: src.Title, Description: src.Note, - Link: ConvertAPIURLToHTMLURL(src.URL, src.TagName), + Link: convertAPIURLToHTMLURL(src.URL, src.TagName), Tag: src.TagName, Commitish: src.Target, Draft: src.IsDraft, diff --git a/scm/driver/gitea/release_test.go b/scm/driver/gitea/release_test.go index ecd6458e7..4cf491890 100644 --- a/scm/driver/gitea/release_test.go +++ b/scm/driver/gitea/release_test.go @@ -14,7 +14,7 @@ import ( func TestConvertAPIURLToHTMLURL(t *testing.T) { - got := ConvertAPIURLToHTMLURL("https://try.gitea.com/api/v1/repos/octocat/Hello-World/123", "v1.0.0") + got := convertAPIURLToHTMLURL("https://try.gitea.com/api/v1/repos/octocat/Hello-World/123", "v1.0.0") want := "https://try.gitea.com/octocat/Hello-World/releases/tag/v1.0.0" if diff := cmp.Diff(got, want); diff != "" { @@ -32,7 +32,7 @@ func TestConvertAPIURLToHTMLURLEmptyLinkWhenURLParseFails(t *testing.T) { broken := []string{"http s://try.gitea.com/api/v1/repos/octocat/Hello-World/123", "https://try.gitea.com/api/v1/repos/octocat/Hello-World"} for _, url := range broken { - got := ConvertAPIURLToHTMLURL(url, "v1.0.0") + got := convertAPIURLToHTMLURL(url, "v1.0.0") want := "" if diff := cmp.Diff(got, want); diff != "" { diff --git a/scm/driver/gitea/util.go b/scm/driver/gitea/util.go index 3404b1b0c..29915e910 100644 --- a/scm/driver/gitea/util.go +++ b/scm/driver/gitea/util.go @@ -56,8 +56,8 @@ func encodePullRequestListOptions(opts scm.PullRequestListOptions) string { return params.Encode() } -// ConvertAPIURLToHTMLURL converts an release API endpoint into a html endpoint -func ConvertAPIURLToHTMLURL(apiURL string, tagName string) string { +// convertAPIURLToHTMLURL converts an release API endpoint into a html endpoint +func convertAPIURLToHTMLURL(apiURL string, tagName string) string { // "url": "https://try.gitea.com/api/v1/repos/octocat/Hello-World/123", // "html_url": "https://try.gitea.com/octocat/Hello-World/releases/tag/v1.0.0", // the url field is the API url, not the html url, so until go-sdk v0.13.3, build it ourselves diff --git a/scm/driver/github/milestone.go b/scm/driver/github/milestone.go index 0209870a0..2ff382138 100644 --- a/scm/driver/github/milestone.go +++ b/scm/driver/github/milestone.go @@ -58,7 +58,7 @@ func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.M Title: input.Title, State: input.State, Description: input.Description, - DueOn: null.NewTime(input.DueDate, true), + DueOn: null.TimeFrom(input.DueDate), } out := new(milestone) res, err := s.client.do(ctx, "POST", path, in, out) @@ -83,7 +83,7 @@ func (s *milestoneService) Update(ctx context.Context, repo string, id int, inpu in.Description = input.Description } if !input.DueDate.IsZero() { - in.DueOn = null.NewTime(input.DueDate, true) + in.DueOn = null.TimeFrom(input.DueDate) } out := new(milestone) res, err := s.client.do(ctx, "PATCH", path, in, out) diff --git a/scm/driver/internal/null/time.go b/scm/driver/internal/null/time.go index 71f64c3f9..3182ce71f 100644 --- a/scm/driver/internal/null/time.go +++ b/scm/driver/internal/null/time.go @@ -83,5 +83,5 @@ func NewTime(t time.Time, valid bool) Time { // TimeFrom creates a new Time that will always be valid. func TimeFrom(t time.Time) Time { - return NewTime(t, true) + return NewTime(t, !t.IsZero()) } \ No newline at end of file From bba8ab12113d08f1914428b3c8e593cde041337c Mon Sep 17 00:00:00 2001 From: Eoin McAfee Date: Fri, 1 Oct 2021 16:04:44 +0100 Subject: [PATCH 042/282] go fmt --- scm/client.go | 6 +++--- scm/driver/gitea/milestone.go | 8 ++++---- scm/driver/gitea/webhook.go | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/scm/client.go b/scm/client.go index 462be89bd..20ece1f21 100644 --- a/scm/client.go +++ b/scm/client.go @@ -70,9 +70,9 @@ type ( // ListOptions specifies optional pagination // parameters. ListOptions struct { - URL string - Page int - Size int + URL string + Page int + Size int } // Client manages communication with a version control diff --git a/scm/driver/gitea/milestone.go b/scm/driver/gitea/milestone.go index 921a8ae69..3c19faec1 100644 --- a/scm/driver/gitea/milestone.go +++ b/scm/driver/gitea/milestone.go @@ -35,7 +35,7 @@ func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.M Title: input.Title, Description: input.Description, State: stateOpen, - Deadline: null.NewTime(input.DueDate, true), + Deadline: null.TimeFrom(input.DueDate), } if input.State == "closed" { in.State = stateClosed @@ -90,9 +90,9 @@ const ( type milestone struct { ID int64 `json:"id"` Title string `json:"title"` - Description string `json:"description"` - State stateType `json:"state"` - OpenIssues int `json:"open_issues"` + Description string `json:"description"` + State stateType `json:"state"` + OpenIssues int `json:"open_issues"` ClosedIssues int `json:"closed_issues"` Created null.Time `json:"created_at"` Updated null.Time `json:"updated_at"` diff --git a/scm/driver/gitea/webhook.go b/scm/driver/gitea/webhook.go index 5f02bc5db..30dc4e38e 100644 --- a/scm/driver/gitea/webhook.go +++ b/scm/driver/gitea/webhook.go @@ -156,8 +156,8 @@ type ( RefType string `json:"ref_type"` Sha string `json:"sha"` DefaultBranch string `json:"default_branch"` - Repository repository `json:"repository"` - Sender user `json:"sender"` + Repository repository `json:"repository"` + Sender user `json:"sender"` } // gitea issue webhook payload @@ -165,8 +165,8 @@ type ( Action string `json:"action"` Issue issue `json:"issue"` Comment issueComment `json:"comment"` - Repository repository `json:"repository"` - Sender user `json:"sender"` + Repository repository `json:"repository"` + Sender user `json:"sender"` } // gitea pull request webhook payload @@ -174,8 +174,8 @@ type ( Action string `json:"action"` Number int `json:"number"` PullRequest pr `json:"pull_request"` - Repository repository `json:"repository"` - Sender user `json:"sender"` + Repository repository `json:"repository"` + Sender user `json:"sender"` } ) From 793da1e44b7ae61b1550604578627cd965a7d643 Mon Sep 17 00:00:00 2001 From: Eoin McAfee Date: Fri, 1 Oct 2021 16:06:17 +0100 Subject: [PATCH 043/282] lowercase state' --- scm/driver/gitea/milestone.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scm/driver/gitea/milestone.go b/scm/driver/gitea/milestone.go index 3c19faec1..73c69bccd 100644 --- a/scm/driver/gitea/milestone.go +++ b/scm/driver/gitea/milestone.go @@ -83,8 +83,8 @@ const ( stateOpen stateType = "open" // stateClosed pr/issue is closed stateClosed stateType = "closed" - // StateAll is all - StateAll stateType = "all" + // stateAll is all + stateAll stateType = "all" ) type milestone struct { From 42f44c1d2518ebcfdbef60fd2c2f2fce18ad0c5b Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 28 Oct 2021 11:46:52 +0800 Subject: [PATCH 044/282] Fix Gitea example code on README.md As title. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 856fb2e21..571c1722f 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ Create a Gitea client: ```Go import ( "github.com/drone/go-scm/scm" - "github.com/drone/go-scm/scm/driver/github" + "github.com/drone/go-scm/scm/driver/gitea" ) func main() { From 7f0aaa82db815f4688f97e8079f3adbb264c8959 Mon Sep 17 00:00:00 2001 From: kit101 Date: Fri, 19 Nov 2021 00:28:07 +0800 Subject: [PATCH 045/282] Feat: implemented gitee provider (#124) * Feat: implemented gitee provider (#1) --- README.md | 13 + scm/const.go | 3 + scm/driver/gitee/content.go | 142 +++ scm/driver/gitee/content_test.go | 200 +++++ scm/driver/gitee/git.go | 302 +++++++ scm/driver/gitee/git_test.go | 279 ++++++ scm/driver/gitee/gitee.go | 154 ++++ scm/driver/gitee/gitee_test.go | 97 ++ scm/driver/gitee/integration/content_test.go | 54 ++ scm/driver/gitee/integration/git_test.go | 214 +++++ scm/driver/gitee/integration/gitee_test.go | 37 + scm/driver/gitee/integration/integration.go | 5 + scm/driver/gitee/integration/issue_test.go | 145 +++ scm/driver/gitee/integration/org_test.go | 51 ++ scm/driver/gitee/integration/pr_test.go | 212 +++++ scm/driver/gitee/integration/repo_test.go | 85 ++ scm/driver/gitee/integration/user_test.go | 54 ++ scm/driver/gitee/issue.go | 336 +++++++ scm/driver/gitee/issue_test.go | 280 ++++++ scm/driver/gitee/linker.go | 50 ++ scm/driver/gitee/linker_test.go | 103 +++ scm/driver/gitee/org.go | 97 ++ scm/driver/gitee/org_test.go | 108 +++ scm/driver/gitee/pr.go | 413 +++++++++ scm/driver/gitee/pr_test.go | 320 +++++++ scm/driver/gitee/repo.go | 233 +++++ scm/driver/gitee/repo_test.go | 359 ++++++++ scm/driver/gitee/review.go | 31 + scm/driver/gitee/review_test.go | 44 + scm/driver/gitee/testdata/branch.json | 49 + scm/driver/gitee/testdata/branch.json.golden | 5 + scm/driver/gitee/testdata/branches.json | 11 + .../gitee/testdata/branches.json.golden | 7 + scm/driver/gitee/testdata/changes.json | 87 ++ scm/driver/gitee/testdata/changes.json.golden | 9 + scm/driver/gitee/testdata/commit.json | 123 +++ scm/driver/gitee/testdata/commit.json.golden | 19 + scm/driver/gitee/testdata/commits.json | 203 +++++ scm/driver/gitee/testdata/commits.json.golden | 59 ++ scm/driver/gitee/testdata/compare.json | 201 +++++ scm/driver/gitee/testdata/compare.json.golden | 9 + scm/driver/gitee/testdata/content.json | 16 + scm/driver/gitee/testdata/content.json.golden | 5 + scm/driver/gitee/testdata/content_create.json | 40 + scm/driver/gitee/testdata/content_delete.json | 27 + scm/driver/gitee/testdata/content_list.json | 44 + .../gitee/testdata/content_list.json.golden | 14 + scm/driver/gitee/testdata/content_update.json | 40 + scm/driver/gitee/testdata/error.json | 3 + scm/driver/gitee/testdata/hook.json | 14 + scm/driver/gitee/testdata/hook.json.golden | 14 + scm/driver/gitee/testdata/hooks.json | 16 + scm/driver/gitee/testdata/hooks.json.golden | 16 + scm/driver/gitee/testdata/issue.json | 235 +++++ scm/driver/gitee/testdata/issue.json.golden | 16 + scm/driver/gitee/testdata/issue_comment.json | 34 + .../gitee/testdata/issue_comment.json.golden | 10 + scm/driver/gitee/testdata/issue_comments.json | 36 + .../gitee/testdata/issue_comments.json.golden | 12 + scm/driver/gitee/testdata/issues.json | 468 ++++++++++ scm/driver/gitee/testdata/issues.json.golden | 34 + scm/driver/gitee/testdata/membership.json | 28 + .../gitee/testdata/membership.json.golden | 4 + scm/driver/gitee/testdata/org.json | 12 + scm/driver/gitee/testdata/org.json.golden | 4 + scm/driver/gitee/testdata/orgs.json | 15 + scm/driver/gitee/testdata/orgs.json.golden | 6 + scm/driver/gitee/testdata/pr.json | 239 +++++ scm/driver/gitee/testdata/pr.json.golden | 30 + scm/driver/gitee/testdata/pr_comment.json | 44 + .../gitee/testdata/pr_comment.json.golden | 11 + scm/driver/gitee/testdata/pr_comments.json | 46 + .../gitee/testdata/pr_comments.json.golden | 13 + scm/driver/gitee/testdata/pr_commits.json | 65 ++ .../gitee/testdata/pr_commits.json.golden | 21 + scm/driver/gitee/testdata/pr_files.json | 82 ++ .../gitee/testdata/pr_files.json.golden | 30 + scm/driver/gitee/testdata/pulls.json | 839 ++++++++++++++++++ scm/driver/gitee/testdata/pulls.json.golden | 92 ++ scm/driver/gitee/testdata/repo.json | 160 ++++ scm/driver/gitee/testdata/repo.json.golden | 17 + scm/driver/gitee/testdata/repos.json | 162 ++++ scm/driver/gitee/testdata/repos.json.golden | 19 + scm/driver/gitee/testdata/tag.json | 8 + scm/driver/gitee/testdata/tag.json.golden | 5 + scm/driver/gitee/testdata/tags.json | 34 + scm/driver/gitee/testdata/tags.json.golden | 22 + scm/driver/gitee/testdata/user.json | 30 + scm/driver/gitee/testdata/user.json.golden | 8 + .../testdata/webhooks/issue_hook_assign.json | 223 +++++ .../webhooks/issue_hook_assign.json.golden | 37 + .../testdata/webhooks/issue_hook_delete.json | 235 +++++ .../webhooks/issue_hook_delete.json.golden | 37 + .../testdata/webhooks/issue_hook_open.json | 192 ++++ .../webhooks/issue_hook_open.json.golden | 34 + .../webhooks/issue_hook_state_change.json | 235 +++++ .../issue_hook_state_change.json.golden | 37 + .../webhooks/note_hook_issue_comment.json | 217 +++++ .../note_hook_issue_comment.json.golden | 49 + .../webhooks/note_hook_pr_comment.json | 394 ++++++++ .../webhooks/note_hook_pr_comment.json.golden | 63 ++ .../gitee/testdata/webhooks/pr_close.json | 601 +++++++++++++ .../testdata/webhooks/pr_close.json.golden | 57 ++ .../gitee/testdata/webhooks/pr_labeled.json | 601 +++++++++++++ .../testdata/webhooks/pr_labeled.json.golden | 57 ++ .../gitee/testdata/webhooks/pr_merge.json | 596 +++++++++++++ .../testdata/webhooks/pr_merge.json.golden | 51 ++ .../gitee/testdata/webhooks/pr_open.json | 596 +++++++++++++ .../testdata/webhooks/pr_open.json.golden | 51 ++ .../gitee/testdata/webhooks/pr_unlabeled.json | 596 +++++++++++++ .../webhooks/pr_unlabeled.json.golden | 51 ++ .../gitee/testdata/webhooks/pr_update.json | 596 +++++++++++++ .../testdata/webhooks/pr_update.json.golden | 51 ++ scm/driver/gitee/testdata/webhooks/push.json | 230 +++++ .../gitee/testdata/webhooks/push.json.golden | 60 ++ .../testdata/webhooks/push_branch_create.json | 189 ++++ .../webhooks/push_branch_create.json.golden | 41 + .../testdata/webhooks/push_branch_delete.json | 151 ++++ .../webhooks/push_branch_delete.json.golden | 28 + .../gitee/testdata/webhooks/tag_create.json | 189 ++++ .../testdata/webhooks/tag_create.json.golden | 25 + .../gitee/testdata/webhooks/tag_delete.json | 151 ++++ .../testdata/webhooks/tag_delete.json.golden | 25 + scm/driver/gitee/user.go | 81 ++ scm/driver/gitee/user_test.go | 106 +++ scm/driver/gitee/util.go | 75 ++ scm/driver/gitee/util_test.go | 94 ++ scm/driver/gitee/webhook.go | 463 ++++++++++ scm/driver/gitee/webhook_test.go | 265 ++++++ 129 files changed, 16173 insertions(+) create mode 100644 scm/driver/gitee/content.go create mode 100644 scm/driver/gitee/content_test.go create mode 100644 scm/driver/gitee/git.go create mode 100644 scm/driver/gitee/git_test.go create mode 100644 scm/driver/gitee/gitee.go create mode 100644 scm/driver/gitee/gitee_test.go create mode 100644 scm/driver/gitee/integration/content_test.go create mode 100644 scm/driver/gitee/integration/git_test.go create mode 100644 scm/driver/gitee/integration/gitee_test.go create mode 100644 scm/driver/gitee/integration/integration.go create mode 100644 scm/driver/gitee/integration/issue_test.go create mode 100644 scm/driver/gitee/integration/org_test.go create mode 100644 scm/driver/gitee/integration/pr_test.go create mode 100644 scm/driver/gitee/integration/repo_test.go create mode 100644 scm/driver/gitee/integration/user_test.go create mode 100644 scm/driver/gitee/issue.go create mode 100644 scm/driver/gitee/issue_test.go create mode 100644 scm/driver/gitee/linker.go create mode 100644 scm/driver/gitee/linker_test.go create mode 100644 scm/driver/gitee/org.go create mode 100644 scm/driver/gitee/org_test.go create mode 100644 scm/driver/gitee/pr.go create mode 100644 scm/driver/gitee/pr_test.go create mode 100644 scm/driver/gitee/repo.go create mode 100644 scm/driver/gitee/repo_test.go create mode 100644 scm/driver/gitee/review.go create mode 100644 scm/driver/gitee/review_test.go create mode 100644 scm/driver/gitee/testdata/branch.json create mode 100644 scm/driver/gitee/testdata/branch.json.golden create mode 100644 scm/driver/gitee/testdata/branches.json create mode 100644 scm/driver/gitee/testdata/branches.json.golden create mode 100644 scm/driver/gitee/testdata/changes.json create mode 100644 scm/driver/gitee/testdata/changes.json.golden create mode 100644 scm/driver/gitee/testdata/commit.json create mode 100644 scm/driver/gitee/testdata/commit.json.golden create mode 100644 scm/driver/gitee/testdata/commits.json create mode 100644 scm/driver/gitee/testdata/commits.json.golden create mode 100644 scm/driver/gitee/testdata/compare.json create mode 100644 scm/driver/gitee/testdata/compare.json.golden create mode 100644 scm/driver/gitee/testdata/content.json create mode 100644 scm/driver/gitee/testdata/content.json.golden create mode 100644 scm/driver/gitee/testdata/content_create.json create mode 100644 scm/driver/gitee/testdata/content_delete.json create mode 100644 scm/driver/gitee/testdata/content_list.json create mode 100644 scm/driver/gitee/testdata/content_list.json.golden create mode 100644 scm/driver/gitee/testdata/content_update.json create mode 100644 scm/driver/gitee/testdata/error.json create mode 100644 scm/driver/gitee/testdata/hook.json create mode 100644 scm/driver/gitee/testdata/hook.json.golden create mode 100644 scm/driver/gitee/testdata/hooks.json create mode 100644 scm/driver/gitee/testdata/hooks.json.golden create mode 100644 scm/driver/gitee/testdata/issue.json create mode 100644 scm/driver/gitee/testdata/issue.json.golden create mode 100644 scm/driver/gitee/testdata/issue_comment.json create mode 100644 scm/driver/gitee/testdata/issue_comment.json.golden create mode 100644 scm/driver/gitee/testdata/issue_comments.json create mode 100644 scm/driver/gitee/testdata/issue_comments.json.golden create mode 100644 scm/driver/gitee/testdata/issues.json create mode 100644 scm/driver/gitee/testdata/issues.json.golden create mode 100644 scm/driver/gitee/testdata/membership.json create mode 100644 scm/driver/gitee/testdata/membership.json.golden create mode 100644 scm/driver/gitee/testdata/org.json create mode 100644 scm/driver/gitee/testdata/org.json.golden create mode 100644 scm/driver/gitee/testdata/orgs.json create mode 100644 scm/driver/gitee/testdata/orgs.json.golden create mode 100644 scm/driver/gitee/testdata/pr.json create mode 100644 scm/driver/gitee/testdata/pr.json.golden create mode 100644 scm/driver/gitee/testdata/pr_comment.json create mode 100644 scm/driver/gitee/testdata/pr_comment.json.golden create mode 100644 scm/driver/gitee/testdata/pr_comments.json create mode 100644 scm/driver/gitee/testdata/pr_comments.json.golden create mode 100644 scm/driver/gitee/testdata/pr_commits.json create mode 100644 scm/driver/gitee/testdata/pr_commits.json.golden create mode 100644 scm/driver/gitee/testdata/pr_files.json create mode 100644 scm/driver/gitee/testdata/pr_files.json.golden create mode 100644 scm/driver/gitee/testdata/pulls.json create mode 100644 scm/driver/gitee/testdata/pulls.json.golden create mode 100644 scm/driver/gitee/testdata/repo.json create mode 100644 scm/driver/gitee/testdata/repo.json.golden create mode 100644 scm/driver/gitee/testdata/repos.json create mode 100644 scm/driver/gitee/testdata/repos.json.golden create mode 100644 scm/driver/gitee/testdata/tag.json create mode 100644 scm/driver/gitee/testdata/tag.json.golden create mode 100644 scm/driver/gitee/testdata/tags.json create mode 100644 scm/driver/gitee/testdata/tags.json.golden create mode 100644 scm/driver/gitee/testdata/user.json create mode 100644 scm/driver/gitee/testdata/user.json.golden create mode 100644 scm/driver/gitee/testdata/webhooks/issue_hook_assign.json create mode 100644 scm/driver/gitee/testdata/webhooks/issue_hook_assign.json.golden create mode 100644 scm/driver/gitee/testdata/webhooks/issue_hook_delete.json create mode 100644 scm/driver/gitee/testdata/webhooks/issue_hook_delete.json.golden create mode 100644 scm/driver/gitee/testdata/webhooks/issue_hook_open.json create mode 100644 scm/driver/gitee/testdata/webhooks/issue_hook_open.json.golden create mode 100644 scm/driver/gitee/testdata/webhooks/issue_hook_state_change.json create mode 100644 scm/driver/gitee/testdata/webhooks/issue_hook_state_change.json.golden create mode 100644 scm/driver/gitee/testdata/webhooks/note_hook_issue_comment.json create mode 100644 scm/driver/gitee/testdata/webhooks/note_hook_issue_comment.json.golden create mode 100644 scm/driver/gitee/testdata/webhooks/note_hook_pr_comment.json create mode 100644 scm/driver/gitee/testdata/webhooks/note_hook_pr_comment.json.golden create mode 100644 scm/driver/gitee/testdata/webhooks/pr_close.json create mode 100644 scm/driver/gitee/testdata/webhooks/pr_close.json.golden create mode 100644 scm/driver/gitee/testdata/webhooks/pr_labeled.json create mode 100644 scm/driver/gitee/testdata/webhooks/pr_labeled.json.golden create mode 100644 scm/driver/gitee/testdata/webhooks/pr_merge.json create mode 100644 scm/driver/gitee/testdata/webhooks/pr_merge.json.golden create mode 100644 scm/driver/gitee/testdata/webhooks/pr_open.json create mode 100644 scm/driver/gitee/testdata/webhooks/pr_open.json.golden create mode 100644 scm/driver/gitee/testdata/webhooks/pr_unlabeled.json create mode 100644 scm/driver/gitee/testdata/webhooks/pr_unlabeled.json.golden create mode 100644 scm/driver/gitee/testdata/webhooks/pr_update.json create mode 100644 scm/driver/gitee/testdata/webhooks/pr_update.json.golden create mode 100644 scm/driver/gitee/testdata/webhooks/push.json create mode 100644 scm/driver/gitee/testdata/webhooks/push.json.golden create mode 100644 scm/driver/gitee/testdata/webhooks/push_branch_create.json create mode 100644 scm/driver/gitee/testdata/webhooks/push_branch_create.json.golden create mode 100644 scm/driver/gitee/testdata/webhooks/push_branch_delete.json create mode 100644 scm/driver/gitee/testdata/webhooks/push_branch_delete.json.golden create mode 100644 scm/driver/gitee/testdata/webhooks/tag_create.json create mode 100644 scm/driver/gitee/testdata/webhooks/tag_create.json.golden create mode 100644 scm/driver/gitee/testdata/webhooks/tag_delete.json create mode 100644 scm/driver/gitee/testdata/webhooks/tag_delete.json.golden create mode 100644 scm/driver/gitee/user.go create mode 100644 scm/driver/gitee/user_test.go create mode 100644 scm/driver/gitee/util.go create mode 100644 scm/driver/gitee/util_test.go create mode 100644 scm/driver/gitee/webhook.go create mode 100644 scm/driver/gitee/webhook_test.go diff --git a/README.md b/README.md index 571c1722f..c149e22e3 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,19 @@ func main() { } ``` +Create a Gitee client: + +```Go +import ( + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/gitee" +) + +func main() { + client, err := gitee.New("https://gitee.com/api/v5") +} +``` + ## Authentication The scm client does not directly handle authentication. Instead, when creating a new client, provide a `http.Client` that can handle authentication for you. For convenience, this library includes oauth1 and oauth2 implementations that can be used to authenticate requests. diff --git a/scm/const.go b/scm/const.go index 638560da3..66551e2ac 100644 --- a/scm/const.go +++ b/scm/const.go @@ -121,6 +121,7 @@ const ( DriverBitbucket DriverStash DriverCoding + DriverGitee ) // String returns the string representation of Driver. @@ -140,6 +141,8 @@ func (d Driver) String() (s string) { return "stash" case DriverCoding: return "coding" + case DriverGitee: + return "gitee" default: return "unknown" } diff --git a/scm/driver/gitee/content.go b/scm/driver/gitee/content.go new file mode 100644 index 000000000..7ac8d6445 --- /dev/null +++ b/scm/driver/gitee/content.go @@ -0,0 +1,142 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "context" + "encoding/base64" + "fmt" + + "github.com/drone/go-scm/scm" +) + +type contentService struct { + client *wrapper +} + +func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm.Content, *scm.Response, error) { + endpoint := fmt.Sprintf("repos/%s/contents/%s?ref=%s", repo, path, ref) + out := new(content) + res, err := s.client.do(ctx, "GET", endpoint, nil, out) + raw, _ := base64.StdEncoding.DecodeString(out.Content) + return &scm.Content{ + Path: out.Path, + Data: raw, + Sha: out.Sha, + }, res, err +} + +func (s *contentService) Create(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { + endpoint := fmt.Sprintf("repos/%s/contents/%s", repo, path) + in := &contentCreateUpdate{ + Message: params.Message, + Branch: params.Branch, + Content: params.Data, + Committer: commitAuthor{ + Name: params.Signature.Name, + Email: params.Signature.Email, + }, + Author: commitAuthor{ + Name: params.Signature.Name, + Email: params.Signature.Email, + }, + } + + res, err := s.client.do(ctx, "POST", endpoint, in, nil) + return res, err +} + +func (s *contentService) Update(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { + endpoint := fmt.Sprintf("repos/%s/contents/%s", repo, path) + in := &contentCreateUpdate{ + Message: params.Message, + Branch: params.Branch, + Content: params.Data, + Sha: params.Sha, + Committer: commitAuthor{ + Name: params.Signature.Name, + Email: params.Signature.Email, + }, + Author: commitAuthor{ + Name: params.Signature.Name, + Email: params.Signature.Email, + }, + } + res, err := s.client.do(ctx, "PUT", endpoint, in, nil) + return res, err +} + +func (s *contentService) Delete(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { + endpoint := fmt.Sprintf("repos/%s/contents/%s", repo, path) + in := &contentCreateUpdate{ + Message: params.Message, + Branch: params.Branch, + Sha: params.Sha, + Committer: commitAuthor{ + Name: params.Signature.Name, + Email: params.Signature.Email, + }, + Author: commitAuthor{ + Name: params.Signature.Name, + Email: params.Signature.Email, + }, + } + res, err := s.client.do(ctx, "DELETE", endpoint, in, nil) + return res, err +} + +func (s *contentService) List(ctx context.Context, repo, path, ref string, _ scm.ListOptions) ([]*scm.ContentInfo, *scm.Response, error) { + endpoint := fmt.Sprintf("repos/%s/contents/%s?ref=%s", repo, path, ref) + out := []*content{} + res, err := s.client.do(ctx, "GET", endpoint, nil, &out) + return convertContentInfoList(out), res, err +} + +type content struct { + Name string `json:"name"` + Path string `json:"path"` + Sha string `json:"sha"` + Content string `json:"content"` + Type string `json:"type"` +} + +type contentCreateUpdate struct { + Branch string `json:"branch"` + Message string `json:"message"` + Content []byte `json:"content"` + Sha string `json:"sha"` + Author commitAuthor `json:"author"` + Committer commitAuthor `json:"committer"` +} + +type commitAuthor struct { + Name string `json:"name"` + Date string `json:"date"` + Email string `json:"email"` +} + +func convertContentInfoList(from []*content) []*scm.ContentInfo { + to := []*scm.ContentInfo{} + for _, v := range from { + to = append(to, convertContentInfo(v)) + } + return to +} +func convertContentInfo(from *content) *scm.ContentInfo { + to := &scm.ContentInfo{Path: from.Path} + switch from.Type { + case "file": + to.Kind = scm.ContentKindFile + case "dir": + to.Kind = scm.ContentKindDirectory + case "symlink": + to.Kind = scm.ContentKindSymlink + case "submodule": + to.Kind = scm.ContentKindGitlink + default: + to.Kind = scm.ContentKindUnsupported + } + return to +} diff --git a/scm/driver/gitee/content_test.go b/scm/driver/gitee/content_test.go new file mode 100644 index 000000000..0ded74af6 --- /dev/null +++ b/scm/driver/gitee/content_test.go @@ -0,0 +1,200 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "context" + "encoding/json" + "io/ioutil" + "testing" + + "github.com/drone/go-scm/scm" + + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" +) + +func TestContentFind(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test/contents/README.md"). + MatchParam("ref", "d295a4c616d46fbcdfa3dfd1473c1337a1ec6f83"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/content.json") + + client := NewDefault() + got, res, err := client.Contents.Find( + context.Background(), + "kit101/drone-yml-test", + "README.md", + "d295a4c616d46fbcdfa3dfd1473c1337a1ec6f83", + ) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Content) + raw, _ := ioutil.ReadFile("testdata/content.json.golden") + json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestContentCreate(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Post("/repos/kit101/drone-yml-test/contents/apitest/CreateByDroneGiteeProvider.md"). + Reply(201). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/content_create.json") + + params := &scm.ContentParams{ + Message: "my commit message", + Data: []byte("bY3JlYXRlIGJ5IGRyb25lLXNjbSBnaXRlZSBwcm92aWRlci4gMjAyMS0wOC0xNyAyMzowNToxNi4="), + Signature: scm.Signature{ + Name: "kit101", + Email: "kit101@gitee.com", + }, + } + + client := NewDefault() + res, err := client.Contents.Create( + context.Background(), + "kit101/drone-yml-test", + "apitest/CreateByDroneGiteeProvider.md", + params, + ) + + if err != nil { + t.Error(err) + return + } + + if res.Status != 201 { + t.Errorf("Unexpected Results") + } +} + +func TestContentUpdate(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Put("/repos/kit101/drone-yml-test/contents/apitest/UpdateByDroneGiteeProvider.md"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/content_update.json") + + params := &scm.ContentParams{ + Message: "my commit message by update", + Data: []byte("bdXBkYXRlIGJ5IGRyb25lLXNjbSBnaXRlZSBwcm92aWRlci4gMjAyMS0wOC0xNyAyMzozMDozNy4="), + Sha: "9de0cf94e1e3c1cbe0a25c3865de4cc9ede7ad3e", + Signature: scm.Signature{ + Name: "kit101", + Email: "kit101@gitee.com", + }, + } + + client := NewDefault() + res, err := client.Contents.Update( + context.Background(), + "kit101/drone-yml-test", + "apitest/UpdateByDroneGiteeProvider.md", + params, + ) + + if err != nil { + t.Error(err) + return + } + + if res.Status != 200 { + t.Errorf("Unexpected Results") + } +} + +func TestContentDelete(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Delete("/repos/kit101/drone-yml-test/contents/apitest/DeleteByDroneGiteeProvider.md"). + Reply(204). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/content_delete.json") + + contentParams := scm.ContentParams{ + Branch: "master", + Sha: "ae0653e4ab697cd77fc559cd798bdb30e8bb4d7e", + Message: "delete commit message", + Signature: scm.Signature{ + Name: "kit101", + Email: "kit101@gitee.com", + }, + } + client := NewDefault() + res, err := client.Contents.Delete( + context.Background(), + "kit101/drone-yml-test", + "apitest/DeleteByDroneGiteeProvider.md", + &contentParams, + ) + if err != nil { + t.Error(err) + return + } + + if got, want := res.Status, 204; got != want { + t.Errorf("Want response status %d, got %d", want, got) + } + t.Run("Request", testRequest(res)) +} + +func TestContentList(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test/contents/apitest"). + MatchParam("ref", "master"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/content_list.json") + + client := NewDefault() + got, res, err := client.Contents.List( + context.Background(), + "kit101/drone-yml-test", + "apitest", + "master", + scm.ListOptions{}, + ) + if err != nil { + t.Error(err) + return + } + + want := []*scm.ContentInfo{} + raw, _ := ioutil.ReadFile("testdata/content_list.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} diff --git a/scm/driver/gitee/git.go b/scm/driver/gitee/git.go new file mode 100644 index 000000000..6b2933b67 --- /dev/null +++ b/scm/driver/gitee/git.go @@ -0,0 +1,302 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "context" + "fmt" + "time" + + "github.com/drone/go-scm/scm" +) + +type gitService struct { + client *wrapper +} + +func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.CreateBranch) (*scm.Response, error) { + path := fmt.Sprintf("repos/%s/branches", repo) + in := &branchCreate{ + Refs: params.Sha, + BranchName: params.Name, + } + res, err := s.client.do(ctx, "POST", path, in, nil) + return res, err +} + +func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/branches/%s", repo, name) + out := new(branch) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertBranch(out), res, err +} + +func (s *gitService) FindCommit(ctx context.Context, repo, ref string) (*scm.Commit, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/commits/%s", repo, ref) + out := new(commit) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertCommit(out), res, err +} + +func (s *gitService) FindTag(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { + tags, res, err := s.ListTags(ctx, repo, scm.ListOptions{}) + if err != nil { + return nil, nil, err + } + for _, tag := range tags { + if tag.Name == name { + return tag, res, err + } + } + return nil, res, err +} + +func (s *gitService) ListBranches(ctx context.Context, repo string, _ scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/branches", repo) + out := []*branch{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertBranchList(out), res, err +} + +func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/commits?%s", repo, encodeCommitListOptions(opts)) + out := []*commit{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertCommitList(out), res, err +} + +func (s *gitService) ListTags(ctx context.Context, repo string, _ scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/tags", repo) + out := []*releasesTags{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertTagList(out), res, err +} + +func (s *gitService) ListChanges(ctx context.Context, repo, ref string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/commits/%s", repo, ref) + out := new(commit) + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertChangeList(out.Files), res, err +} + +func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/compare/%s...%s", repo, source, target) + out := new(compare) + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertChangeList(out.Files), res, err +} + +type branchCreate struct { + Refs string `json:"refs"` + BranchName string `json:"branch_name"` +} + +type branch struct { + //Links string `json:"_links"` + Name string `json:"name"` + Commit tree `json:"commit"` + Protected bool `json:"protected"` + ProtectionURL string `json:"protection_url"` +} + +type commit struct { + URL string `json:"url"` + Sha string `json:"sha"` + HtmlURL string `json:"html_url"` + CommentsURL string `json:"comments_url"` + Commit struct { + Author committer `json:"author"` + Committer committer `json:"committer"` + Message string `json:"message"` + Tree tree `json:"tree"` + } `json:"commit"` + Author author `json:"author"` + Committer author `json:"committer"` + Parents []tree `json:"parents"` + Stats struct { + ID string `json:"id"` + Additions int64 `json:"additions"` + Deletions int64 `json:"deletions"` + Total int64 `json:"total"` + } `json:"stats"` + Files []*file `json:"files"` +} + +type committer struct { + Name string `json:"name"` + Date time.Time `json:"date"` + Email string `json:"email"` +} + +type tree struct { + Sha string `json:"sha"` + URL string `json:"url"` +} + +type file struct { + SHA string `json:"sha"` + Filename string `json:"filename"` + Status string `json:"status"` + Additions int64 `json:"additions"` + Deletions int64 `json:"deletions"` + Changes int64 `json:"changes"` + BlobURL string `json:"blob_url"` + RawURL string `json:"raw_url"` + ContentURL string `json:"content_url"` + Patch string `json:"patch"` +} + +type compare struct { + BaseCommit struct { + URL string `json:"url"` + Sha string `json:"sha"` + HTMLURL string `json:"html_url"` + CommentsURL string `json:"comments_url"` + Commit compareCommit `json:"commit"` + Author compareAuthor `json:"author"` + Committer committer `json:"committer"` + Parents []tree `json:"parents"` + } `json:"base_commit"` + MergeBaseCommit struct { + URL string `json:"url"` + Sha string `json:"sha"` + HTMLURL string `json:"html_url"` + CommentsURL string `json:"comments_url"` + Commit compareCommit `json:"commit"` + Author compareAuthor `json:"author"` + Committer committer `json:"committer"` + Parents []tree `json:"parents"` + } `json:"merge_base_commit"` + Commits []struct { + URL string `json:"url"` + Sha string `json:"sha"` + HTMLURL string `json:"html_url"` + CommentsURL string `json:"comments_url"` + Commit compareCommit `json:"commit"` + Author compareAuthor `json:"author"` + Committer committer `json:"committer"` + Parents []tree `json:"parents"` + } `json:"commits"` + Files []*file `json:"files"` +} +type compareAuthor struct { + Name string `json:"name"` + Date time.Time `json:"date"` + Email string `json:"email"` +} +type compareCommit struct { + Author compareAuthor `json:"author"` + Committer committer `json:"committer"` + Message string `json:"message"` + Tree tree `json:"tree"` +} + +type releasesTags struct { + Name string `json:"name"` + Message string `json:"message"` + Commit struct { + Sha string `json:"sha"` + Date time.Time `json:"date"` + } `json:"commit"` +} + +type author struct { + ID int `json:"id"` + Login string `json:"login"` + Name string `json:"name"` + AvatarURL string `json:"avatar_url"` + URL string `json:"url"` + HTMLURL string `json:"html_url"` + FollowersURL string `json:"followers_url"` + FollowingURL string `json:"following_url"` + GistsURL string `json:"gists_url"` + StarredURL string `json:"starred_url"` + SubscriptionsURL string `json:"subscriptions_url"` + OrganizationsURL string `json:"organizations_url"` + ReposURL string `json:"repos_url"` + EventsURL string `json:"events_url"` + ReceivedEventsURL string `json:"received_events_url"` + Type string `json:"type"` +} + +func convertCommitList(from []*commit) []*scm.Commit { + to := []*scm.Commit{} + for _, v := range from { + to = append(to, convertCommit(v)) + } + return to +} + +func convertCommit(from *commit) *scm.Commit { + return &scm.Commit{ + Message: from.Commit.Message, + Sha: from.Sha, + Link: from.HtmlURL, + Author: scm.Signature{ + Name: from.Commit.Author.Name, + Email: from.Commit.Author.Email, + Date: from.Commit.Author.Date, + Login: from.Author.Login, + Avatar: from.Author.AvatarURL, + }, + Committer: scm.Signature{ + Name: from.Commit.Committer.Name, + Email: from.Commit.Committer.Email, + Date: from.Commit.Committer.Date, + Login: from.Committer.Login, + Avatar: from.Committer.AvatarURL, + }, + } +} + +func convertBranchList(from []*branch) []*scm.Reference { + to := []*scm.Reference{} + for _, v := range from { + to = append(to, convertBranch(v)) + } + return to +} + +func convertBranch(from *branch) *scm.Reference { + return &scm.Reference{ + Name: scm.TrimRef(from.Name), + Path: scm.ExpandRef(from.Name, "refs/heads/"), + Sha: from.Commit.Sha, + } +} + +func convertTagList(from []*releasesTags) []*scm.Reference { + to := []*scm.Reference{} + for _, v := range from { + to = append(to, convertTag(v)) + } + return to +} + +func convertTag(from *releasesTags) *scm.Reference { + return &scm.Reference{ + Name: scm.TrimRef(from.Name), + Path: scm.ExpandRef(from.Name, "refs/tags/"), + Sha: from.Commit.Sha, + } +} + +func convertChangeList(from []*file) []*scm.Change { + to := []*scm.Change{} + for _, v := range from { + to = append(to, convertChange(v)) + } + return to +} + +func convertChange(from *file) *scm.Change { + return &scm.Change{ + Path: from.Filename, + Added: from.Status == "added", + Deleted: from.Status == "removed", + Renamed: from.Status == "modified" && from.Additions == 0 && from.Deletions == 0 && from.Changes == 0, + BlobID: from.SHA, + } +} diff --git a/scm/driver/gitee/git_test.go b/scm/driver/gitee/git_test.go new file mode 100644 index 000000000..b62cd951c --- /dev/null +++ b/scm/driver/gitee/git_test.go @@ -0,0 +1,279 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "context" + "encoding/json" + "io/ioutil" + "testing" + + "github.com/drone/go-scm/scm" + + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" +) + +func TestGitCreateBranch(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Post("/repos/kit101/drone-yml-test/branches"). + Reply(201). + Type("application/json"). + SetHeaders(mockHeaders) + + client := NewDefault() + input := scm.CreateBranch{ + Name: "create-by-api", + Sha: "b72a4c4a2d838d96a545a42d41d7776ae5566f4a", + } + res, err := client.Git.CreateBranch(context.Background(), "kit101/drone-yml-test", &input) + if err != nil { + t.Error(err) + return + } + + if got, want := res.Status, 201; got != want { + t.Errorf("Want response status %d, got %d", want, got) + } + t.Run("Request", testRequest(res)) +} + +func TestGitFindBranch(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test/branches/master"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/branch.json") + + client := NewDefault() + got, res, err := client.Git.FindBranch(context.Background(), "kit101/drone-yml-test", "master") + if err != nil { + t.Error(err) + return + } + + want := new(scm.Reference) + raw, _ := ioutil.ReadFile("testdata/branch.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestGitFindCommit(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test/commits/e3c0ff4d5cef439ea11b30866fb1ed79b420801d"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/commit.json") + + client := NewDefault() + got, res, err := client.Git.FindCommit(context.Background(), "kit101/drone-yml-test", "e3c0ff4d5cef439ea11b30866fb1ed79b420801d") + if err != nil { + t.Error(err) + return + } + + want := new(scm.Commit) + raw, _ := ioutil.ReadFile("testdata/commit.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestGitFindTag(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test/tags"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/tags.json") + + client := NewDefault() + got, res, err := client.Git.FindTag(context.Background(), "kit101/drone-yml-test", "1.0") + if err != nil { + t.Error(err) + return + } + + want := new(scm.Reference) + raw, _ := ioutil.ReadFile("testdata/tag.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestGitListBranches(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test/branches"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/branches.json") + + client := NewDefault() + got, res, err := client.Git.ListBranches(context.Background(), "kit101/drone-yml-test", scm.ListOptions{}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Reference{} + raw, _ := ioutil.ReadFile("testdata/branches.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestGitListCommits(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test/commits"). + MatchParam("sha", "master"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + SetHeaders(mockPageHeaders). + File("testdata/commits.json") + + client := NewDefault() + got, res, err := client.Git.ListCommits(context.Background(), "kit101/drone-yml-test", + scm.CommitListOptions{Ref: "master", Page: 1, Size: 3}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Commit{} + raw, _ := ioutil.ReadFile("testdata/commits.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Page", testPage(res)) +} + +func TestGitListTags(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test/tags"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/tags.json") + + client := NewDefault() + got, res, err := client.Git.ListTags(context.Background(), "kit101/drone-yml-test", scm.ListOptions{}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Reference{} + raw, _ := ioutil.ReadFile("testdata/tags.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestGitListChanges(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com"). + Get("/repos/kit101/drone-yml-test/commits/7e84b6f94b8d4bfaa051910cc4ce16b73bcffd51"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/changes.json") + + client := NewDefault() + got, res, err := client.Git.ListChanges(context.Background(), "kit101/drone-yml-test", "7e84b6f94b8d4bfaa051910cc4ce16b73bcffd51", scm.ListOptions{}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Change{} + raw, _ := ioutil.ReadFile("testdata/changes.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestGitCompareChanges(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test/compare/e3c0ff4d5cef439ea11b30866fb1ed79b420801d...2700445cd84c08546f4d003f8aa54d2099a006b7"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/compare.json") + + client := NewDefault() + got, res, err := client.Git.CompareChanges(context.Background(), "kit101/drone-yml-test", "e3c0ff4d5cef439ea11b30866fb1ed79b420801d", "2700445cd84c08546f4d003f8aa54d2099a006b7", scm.ListOptions{}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Change{} + raw, _ := ioutil.ReadFile("testdata/compare.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} diff --git a/scm/driver/gitee/gitee.go b/scm/driver/gitee/gitee.go new file mode 100644 index 000000000..1403a7fe4 --- /dev/null +++ b/scm/driver/gitee/gitee.go @@ -0,0 +1,154 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package gitee implements a Gitee client. +package gitee + +import ( + "bytes" + "context" + "encoding/json" + "net/url" + "strconv" + "strings" + + "github.com/drone/go-scm/scm" +) + +// New returns a new Gitee API client. +func New(uri string) (*scm.Client, error) { + base, err := url.Parse(uri) + if err != nil { + return nil, err + } + if !strings.HasSuffix(base.Path, "/") { + base.Path = base.Path + "/" + } + client := &wrapper{new(scm.Client)} + client.BaseURL = base + // initialize services + client.Driver = scm.DriverGitee + client.Linker = &linker{websiteAddress(base)} + client.Contents = &contentService{client} + client.Git = &gitService{client} + client.Issues = &issueService{client} + client.Organizations = &organizationService{client} + client.PullRequests = &pullService{client} + client.Repositories = &RepositoryService{client} + client.Reviews = &reviewService{client} + client.Users = &userService{client} + client.Webhooks = &webhookService{client} + return client.Client, nil +} + +// NewDefault returns a new Gitee API client using the +// default gitee.com/api/v5 address. +func NewDefault() *scm.Client { + client, _ := New("https://gitee.com/api/v5") + return client +} + +// wrapper wraps the Client to provide high level helper functions +// for making http requests and unmarshaling the response. +type wrapper struct { + *scm.Client +} + +// do wraps the Client.Do function by creating the Request and +// unmarshalling the response. +func (c *wrapper) do(ctx context.Context, method, path string, in, out interface{}) (*scm.Response, error) { + req := &scm.Request{ + Method: method, + Path: path, + } + // if we are posting or putting data, we need to + // write it to the body of the request. + if in != nil { + buf := new(bytes.Buffer) + json.NewEncoder(buf).Encode(in) + req.Header = map[string][]string{ + "Content-Type": {"application/json"}, + } + req.Body = buf + } + // execute the http request + res, err := c.Client.Do(ctx, req) + if err != nil { + return nil, err + } + defer res.Body.Close() + // parse the gitee request id. + res.ID = res.Header.Get("X-Request-Id") + + // gitee pageValues + populatePageValues(req, res) + + // if an error is encountered, unmarshal and return the + // error response. + if res.Status > 300 { + err := new(Error) + json.NewDecoder(res.Body).Decode(err) + return res, err + } + + if out == nil { + return res, nil + } + + // if a json response is expected, parse and return + // the json response. + return res, json.NewDecoder(res.Body).Decode(out) +} + +// Error represents a Gitee error. +type Error struct { + Message string `json:"message"` +} + +func (e *Error) Error() string { + return e.Message +} + +// helper function converts the Gitee API url to +// the website url. +func websiteAddress(u *url.URL) string { + host, proto := u.Host, u.Scheme + switch host { + case "gitee.com/api/v5": + return "https://gitee.com/" + } + return proto + "://" + host + "/" +} + +// populatePageValues parses the HTTP Link response headers +// and populates the various pagination link values in the +// Response. +// response header: total_page, total_count +func populatePageValues(req *scm.Request, resp *scm.Response) { + last, totalError := strconv.Atoi(resp.Header.Get("total_page")) + reqURL, err := url.Parse(req.Path) + if err != nil { + return + } + current, currentError := strconv.Atoi(reqURL.Query().Get("page")) + if totalError != nil && currentError != nil { + return + } + resp.Page.First = 1 + if last != 0 { + resp.Page.Last = last + } + if current != 0 { + if current < resp.Page.Last { + resp.Page.Next = current + 1 + } else { + resp.Page.Next = resp.Page.Last + } + if current > resp.Page.First { + resp.Page.Prev = current - 1 + } else { + resp.Page.Prev = resp.Page.First + } + } +} diff --git a/scm/driver/gitee/gitee_test.go b/scm/driver/gitee/gitee_test.go new file mode 100644 index 000000000..df990b06d --- /dev/null +++ b/scm/driver/gitee/gitee_test.go @@ -0,0 +1,97 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "net/url" + "testing" + + "github.com/drone/go-scm/scm" +) + +var mockHeaders = map[string]string{ + "X-Request-Id": "7cb049dbf1fafae67b4f0aa81ca7e870", +} + +var mockPageHeaders = map[string]string{ + "total_page": `3`, +} + +func TestClient(t *testing.T) { + client, err := New("https://gitee.com/api/v5") + if err != nil { + t.Error(err) + } + if got, want := client.BaseURL.String(), "https://gitee.com/api/v5/"; got != want { + t.Errorf("Want Client URL %q, got %q", want, got) + } +} + +func TestClient_Base(t *testing.T) { + client, err := New("https://gitee.com/api/v5") + if err != nil { + t.Error(err) + } + got, want := client.BaseURL.String(), "https://gitee.com/api/v5/" + if got != want { + t.Errorf("Want Client URL %q, got %q", want, got) + } +} + +func TestClient_Default(t *testing.T) { + client := NewDefault() + if got, want := client.BaseURL.String(), "https://gitee.com/api/v5/"; got != want { + t.Errorf("Want Client URL %q, got %q", want, got) + } +} + +func TestClient_Error(t *testing.T) { + _, err := New("http://a b.com/") + if err == nil { + t.Errorf("Expect error when invalid URL") + } +} + +func testPage(res *scm.Response) func(t *testing.T) { + return func(t *testing.T) { + if got, want := res.Page.Prev, 1; got != want { + t.Errorf("Want prev page %d, got %d", want, got) + } + if got, want := res.Page.Next, 2; got != want { + t.Errorf("Want next page %d, got %d", want, got) + } + if got, want := res.Page.Last, 3; got != want { + t.Errorf("Want last page %d, got %d", want, got) + } + if got, want := res.Page.First, 1; got != want { + t.Errorf("Want first page %d, got %d", want, got) + } + } +} + +func testRequest(res *scm.Response) func(t *testing.T) { + return func(t *testing.T) { + if got, want := res.ID, "7cb049dbf1fafae67b4f0aa81ca7e870"; got != want { + t.Errorf("Want X-Request-Id %q, got %q", want, got) + } + } +} + +func TestWebsiteAddress(t *testing.T) { + tests := []struct { + api string + web string + }{ + {"https://gitee.com/api/v5/", "https://gitee.com/"}, + } + + for _, test := range tests { + parsed, _ := url.Parse(test.api) + got, want := websiteAddress(parsed), test.web + if got != want { + t.Errorf("Want website address %q, got %q", want, got) + } + } +} diff --git a/scm/driver/gitee/integration/content_test.go b/scm/driver/gitee/integration/content_test.go new file mode 100644 index 000000000..8e0404906 --- /dev/null +++ b/scm/driver/gitee/integration/content_test.go @@ -0,0 +1,54 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package integration + +import ( + "context" + "testing" + + "github.com/drone/go-scm/scm" +) + +func testContents(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + t.Run("Find", testContentFind(client)) + t.Run("Find/Branch", testContentFindBranch(client)) + } +} + +func testContentFind(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + result, _, err := client.Contents.Find(context.Background(), "kit101/drone-yml-test", "main.py", "5e7876efb3468ff679410b82a72f7c002382d41e") + if err != nil { + t.Error(err) + return + } + if got, want := result.Path, "main.py"; got != want { + t.Errorf("Got file path %q, want %q", got, want) + } + if got, want := string(result.Data), "if __name__ == '__main__':\r\n print('Hello world.')"; got != want { + t.Errorf("Got file data %q, want %q", got, want) + } + } +} + +func testContentFindBranch(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + result, _, err := client.Contents.Find(context.Background(), "kit101/drone-yml-test", "main.py", "feat-4") + if err != nil { + t.Error(err) + return + } + if got, want := result.Path, "main.py"; got != want { + t.Errorf("Got file path %q, want %q", got, want) + } + if got, want := string(result.Data), "if __name__ == '__main__':\r\n print('Hello world.')"; got != want { + t.Errorf("Got file data %q, want %q", got, want) + } + } +} diff --git a/scm/driver/gitee/integration/git_test.go b/scm/driver/gitee/integration/git_test.go new file mode 100644 index 000000000..d7267fc60 --- /dev/null +++ b/scm/driver/gitee/integration/git_test.go @@ -0,0 +1,214 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package integration + +import ( + "context" + "testing" + + "github.com/drone/go-scm/scm" +) + +// +// git sub-tests +// + +func testGit(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + t.Run("Branches", testBranches(client)) + t.Run("Commits", testCommits(client)) + t.Run("Tags", testTags(client)) + } +} + +// +// branch sub-tests +// + +func testBranches(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + t.Run("Find", testBranchFind(client)) + t.Run("List", testBranchList(client)) + } +} + +func testBranchFind(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + result, _, err := client.Git.FindBranch(context.Background(), "kit101/drone-yml-test", "feat-4") + if err != nil { + t.Error(err) + return + } + t.Run("Branch", testBranch(result)) + } +} + +func testBranchList(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + opts := scm.ListOptions{} + result, _, err := client.Git.ListBranches(context.Background(), "kit101/drone-yml-test", opts) + if err != nil { + t.Error(err) + return + } + if len(result) == 0 { + t.Errorf("Want a non-empty branch list") + } + for _, branch := range result { + if branch.Name == "feat-4" { + t.Run("Branch", testBranch(branch)) + } + } + } +} + +// +// branch sub-tests +// + +func testTags(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + t.Run("Find", testTagFind(client)) + t.Run("List", testTagList(client)) + } +} + +func testTagFind(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + tag, _, err := client.Git.FindTag(context.Background(), "kit101/drone-yml-test", "1.1") + if err != nil { + t.Error(err) + return + } + t.Run("Tag", testTag(tag)) + } +} + +func testTagList(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + opts := scm.ListOptions{} + result, _, err := client.Git.ListTags(context.Background(), "kit101/drone-yml-test", opts) + if err != nil { + t.Error(err) + return + } + if len(result) == 0 { + t.Errorf("Want a non-empty tag list") + } + for _, tag := range result { + if tag.Name == "1.1" { + t.Run("Tag", testTag(tag)) + } + } + } +} + +// +// commit sub-tests +// + +func testCommits(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + t.Run("Find", testCommitFind(client)) + t.Run("List", testCommitList(client)) + } +} + +func testCommitFind(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + result, _, err := client.Git.FindCommit(context.Background(), "kit101/drone-yml-test", "e3c0ff4d5cef439ea11b30866fb1ed79b420801d") + if err != nil { + t.Error(err) + return + } + t.Run("Commit", testCommit(result)) + } +} + +func testCommitList(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + opts := scm.CommitListOptions{ + Ref: "feat-4", + } + result, _, err := client.Git.ListCommits(context.Background(), "kit101/drone-yml-test", opts) + if err != nil { + t.Error(err) + return + } + if len(result) == 0 { + t.Errorf("Want a non-empty commit list") + } + for _, commit := range result { + if commit.Sha == "e3c0ff4d5cef439ea11b30866fb1ed79b420801d" { + t.Run("Commit", testCommit(commit)) + } + } + } +} + +// +// struct sub-tests +// + +func testBranch(branch *scm.Reference) func(t *testing.T) { + return func(t *testing.T) { + if got, want := branch.Name, "feat-4"; got != want { + t.Errorf("Want branch Name %q, got %q", want, got) + } + if got, want := branch.Sha, "2eac1cac02c325058cf959725c45b0612d3e8177"; got != want { + t.Errorf("Want branch Avatar %q, got %q", want, got) + } + } +} + +func testTag(tag *scm.Reference) func(t *testing.T) { + return func(t *testing.T) { + if got, want := tag.Name, "1.1"; got != want { + t.Errorf("Want tag Name %q, got %q", want, got) + } + if got, want := tag.Sha, "5e7876efb3468ff679410b82a72f7c002382d41e"; got != want { + t.Errorf("Want tag Avatar %q, got %q", want, got) + } + } +} + +func testCommit(commit *scm.Commit) func(t *testing.T) { + return func(t *testing.T) { + if got, want := commit.Message, "add/update/delete/rename\n"; got != want { + t.Errorf("Want commit Message %q, got %q", want, got) + } + if got, want := commit.Sha, "e3c0ff4d5cef439ea11b30866fb1ed79b420801d"; got != want { + t.Errorf("Want commit Sha %q, got %q", want, got) + } + if got, want := commit.Author.Name, "kit101"; got != want { + t.Errorf("Want commit author Name %q, got %q", want, got) + } + if got, want := commit.Author.Email, "qkssk1711@163.com"; got != want { + t.Errorf("Want commit author Email %q, got %q", want, got) + } + if got, want := commit.Author.Date.Unix(), int64(1629733553); got != want { + t.Errorf("Want commit author Date %d, got %d", want, got) + } + if got, want := commit.Committer.Name, "kit101"; got != want { + t.Errorf("Want commit author Name %q, got %q", want, got) + } + if got, want := commit.Committer.Email, "qkssk1711@163.com"; got != want { + t.Errorf("Want commit author Email %q, got %q", want, got) + } + if got, want := commit.Committer.Date.Unix(), int64(1629733553); got != want { + t.Errorf("Want commit author Date %d, got %d", want, got) + } + } +} diff --git a/scm/driver/gitee/integration/gitee_test.go b/scm/driver/gitee/integration/gitee_test.go new file mode 100644 index 000000000..cb9918130 --- /dev/null +++ b/scm/driver/gitee/integration/gitee_test.go @@ -0,0 +1,37 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package integration + +import ( + "net/http" + "os" + "testing" + + "github.com/drone/go-scm/scm/driver/gitee" + "github.com/drone/go-scm/scm/transport" +) + +func TestGitee(t *testing.T) { + accessToken := os.Getenv("GITEE_TOKEN") + if accessToken == "" { + t.Skipf("missing GITEE_TOKEN environment variable") + return + } + + client := gitee.NewDefault() + client.Client = &http.Client{ + Transport: &transport.BearerToken{ + Token: accessToken, + }, + } + + t.Run("Contents", testContents(client)) + t.Run("Git", testGit(client)) + t.Run("Issues", testIssues(client)) + t.Run("Organizations", testOrgs(client)) + t.Run("PullRequests", testPullRequests(client)) + t.Run("Repositories", testRepos(client)) + t.Run("Users", testUsers(client)) +} diff --git a/scm/driver/gitee/integration/integration.go b/scm/driver/gitee/integration/integration.go new file mode 100644 index 000000000..acc0ad401 --- /dev/null +++ b/scm/driver/gitee/integration/integration.go @@ -0,0 +1,5 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package integration diff --git a/scm/driver/gitee/integration/issue_test.go b/scm/driver/gitee/integration/issue_test.go new file mode 100644 index 000000000..f2d6ca846 --- /dev/null +++ b/scm/driver/gitee/integration/issue_test.go @@ -0,0 +1,145 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package integration + +import ( + "context" + "testing" + + "github.com/drone/go-scm/scm" +) + +// +// issue sub-tests +// + +func testIssues(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + t.Run("List", testIssueList(client)) + t.Run("Find", testIssueFind(client)) + t.Run("Comments", testIssueComments(client)) + } +} + +func testIssueList(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + opts := scm.IssueListOptions{ + Open: true, + Closed: true, + } + result, _, err := client.Issues.List(context.Background(), "kit101/drone-yml-test", opts) + if err != nil { + t.Error(err) + } + if len(result) == 0 { + t.Errorf("Got empty issue list") + } + } +} + +func testIssueFind(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + result, _, err := client.Issues.Find(context.Background(), "kit101/drone-yml-test", 735267685380) + if err != nil { + t.Error(err) + } + t.Run("Issue", testIssue(result)) + } +} + +// +// issue comment sub-tests +// + +func testIssueComments(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Run("List", testIssueCommentList(client)) + t.Run("Find", testIssueCommentFind(client)) + } +} + +func testIssueCommentList(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + opts := scm.ListOptions{} + result, _, err := client.Issues.ListComments(context.Background(), "kit101/drone-yml-test", 735267685380, opts) + if err != nil { + t.Error(err) + } + if len(result) == 0 { + t.Errorf("Want a non-empty issue comment list") + } + for _, comment := range result { + if comment.ID == 6877445 { + t.Run("Comment", testIssueComment(comment)) + } + } + } +} + +func testIssueCommentFind(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + result, _, err := client.Issues.FindComment(context.Background(), "kit101/drone-yml-test", 735267685380, 6877445) + if err != nil { + t.Error(err) + } + t.Run("Comment", testIssueComment(result)) + } +} + +// +// struct sub-tests +// + +func testIssue(issue *scm.Issue) func(t *testing.T) { + return func(t *testing.T) { + if got, want := issue.Number, 735267685380; got != want { + t.Errorf("Want issue Number %d, got %d", want, got) + } + if got, want := issue.Title, "test issue 1"; got != want { + t.Errorf("Want issue Title %q, got %q", want, got) + } + if got, want := issue.Body, "test issue 1"; got != want { + t.Errorf("Want issue Body %q, got %q", want, got) + } + if got, want := issue.Link, "https://gitee.com/kit101/drone-yml-test/issues/I4CD5P"; got != want { + t.Errorf("Want issue Link %q, got %q", want, got) + } + if got, want := issue.Author.Login, "kit101"; got != want { + t.Errorf("Want issue Author Login %q, got %q", want, got) + } + if got, want := issue.Author.Avatar, "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png"; got != want { + t.Errorf("Want issue Author Avatar %q, got %q", want, got) + } + if got, want := issue.Closed, true; got != want { + t.Errorf("Want issue Closed %v, got %v", want, got) + } + if got, want := issue.Created.Unix(), int64(1632878488); got != want { + t.Errorf("Want issue Created %d, got %d", want, got) + } + } +} + +func testIssueComment(comment *scm.Comment) func(t *testing.T) { + return func(t *testing.T) { + if got, want := comment.ID, 6877445; got != want { + t.Errorf("Want issue comment ID %d, got %d", want, got) + } + if got, want := comment.Body, "it's ok."; got != want { + t.Errorf("Want issue comment Body %q, got %q", want, got) + } + if got, want := comment.Author.Login, "kit101"; got != want { + t.Errorf("Want issue comment Author Login %q, got %q", want, got) + } + if got, want := comment.Created.Unix(), int64(1632884450); got != want { + t.Errorf("Want issue comment Created %d, got %d", want, got) + } + if got, want := comment.Updated.Unix(), int64(1632884450); got != want { + t.Errorf("Want issue comment Updated %d, got %d", want, got) + } + } +} diff --git a/scm/driver/gitee/integration/org_test.go b/scm/driver/gitee/integration/org_test.go new file mode 100644 index 000000000..e25590a19 --- /dev/null +++ b/scm/driver/gitee/integration/org_test.go @@ -0,0 +1,51 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package integration + +import ( + "context" + "testing" + + "github.com/drone/go-scm/scm" +) + +// +// organization sub-tests +// + +func testOrgs(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + t.Run("Find", testOrgFind(client)) + } +} + +func testOrgFind(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + result, _, err := client.Organizations.Find(context.Background(), "gitee-community") + if err != nil { + t.Error(err) + return + } + t.Run("Organization", testOrg(result)) + } +} + +// +// struct sub-tests +// + +func testOrg(organization *scm.Organization) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + if got, want := organization.Name, "gitee-community"; got != want { + t.Errorf("Want organization Name %q, got %q", want, got) + } + if got, want := organization.Avatar, "https://portrait.gitee.com/uploads/avatars/namespace/1715/5146011_gitee-community_1607593452.png?is_link=true"; got != want { + t.Errorf("Want organization Avatar %q, got %q", want, got) + } + } +} diff --git a/scm/driver/gitee/integration/pr_test.go b/scm/driver/gitee/integration/pr_test.go new file mode 100644 index 000000000..99caee142 --- /dev/null +++ b/scm/driver/gitee/integration/pr_test.go @@ -0,0 +1,212 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package integration + +import ( + "context" + "testing" + + "github.com/drone/go-scm/scm" +) + +// +// pull request sub-tests +// + +func testPullRequests(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + t.Run("List", testPullRequestList(client)) + t.Run("Find", testPullRequestFind(client)) + t.Run("Changes", testPullRequestChanges(client)) + t.Run("Comments", testPullRequestComments(client)) + } +} + +func testPullRequestList(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + opts := scm.PullRequestListOptions{ + Open: true, + Closed: true, + } + result, _, err := client.PullRequests.List(context.Background(), "kit101/drone-yml-test", opts) + if err != nil { + t.Error(err) + } + if len(result) == 0 { + t.Errorf("Got empty pull request list") + } + for _, pr := range result { + if pr.Number == 7 { + t.Run("PullRequest", testPullRequest(pr)) + } + } + } +} + +func testPullRequestFind(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + result, _, err := client.PullRequests.Find(context.Background(), "kit101/drone-yml-test", 7) + if err != nil { + t.Error(err) + } + t.Run("PullRequest", testPullRequest(result)) + } +} + +// +// pull request comment sub-tests +// + +func testPullRequestComments(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + t.Run("List", testPullRequestCommentFind(client)) + t.Run("Find", testPullRequestCommentList(client)) + } +} + +func testPullRequestCommentFind(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + result, _, err := client.PullRequests.FindComment(context.Background(), "kit101/drone-yml-test", 7, 6922557) + if err != nil { + t.Error(err) + } + t.Run("Comment", testPullRequestComment(result)) + } +} + +func testPullRequestCommentList(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + opts := scm.ListOptions{} + result, _, err := client.PullRequests.ListComments(context.Background(), "kit101/drone-yml-test", 7, opts) + if err != nil { + t.Error(err) + } + if len(result) == 0 { + t.Errorf("Got empty pull request comment list") + } + for _, comment := range result { + if comment.ID == 6922557 { + t.Run("Comment", testPullRequestComment(comment)) + } + } + } +} + +// +// pull request changes sub-tests +// + +func testPullRequestChanges(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + opts := scm.ListOptions{} + result, _, err := client.PullRequests.ListChanges(context.Background(), "kit101/drone-yml-test", 7, opts) + if err != nil { + t.Error(err) + } + if len(result) == 0 { + t.Errorf("Got empty pull request change list") + return + } + t.Run("File", testChange(result[0])) + } +} + +// +// struct sub-tests +// + +func testPullRequest(pr *scm.PullRequest) func(t *testing.T) { + return func(t *testing.T) { + if got, want := pr.Number, 7; got != want { + t.Errorf("Want pr Number %d, got %d", want, got) + } + if got, want := pr.Title, "feat add 3"; got != want { + t.Errorf("Want pr Title %q, got %q", want, got) + } + if got, want := pr.Body, ""; got != want { + t.Errorf("Want pr Body %q, got %q", want, got) + } + if got, want := pr.Source, "feat-2"; got != want { + t.Errorf("Want pr Source %q, got %q", want, got) + } + if got, want := pr.Target, "master"; got != want { + t.Errorf("Want pr Target %q, got %q", want, got) + } + if got, want := pr.Ref, "refs/pull/7/head"; got != want { + t.Errorf("Want pr Ref %q, got %q", want, got) + } + if got, want := pr.Sha, "6168d9dae737b47f00c59fafca10c913a6850c3a"; got != want { + t.Errorf("Want pr Sha %q, got %q", want, got) + } + if got, want := pr.Link, "https://gitee.com/kit101/drone-yml-test/pulls/7"; got != want { + t.Errorf("Want pr Link %q, got %q", want, got) + } + if got, want := pr.Diff, "https://gitee.com/kit101/drone-yml-test/pulls/7.diff"; got != want { + t.Errorf("Want pr Diff %q, got %q", want, got) + } + if got, want := pr.Author.Login, "kit101"; got != want { + t.Errorf("Want pr Author Login %q, got %q", want, got) + } + if got, want := pr.Author.Avatar, "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png"; got != want { + t.Errorf("Want pr Author Avatar %q, got %q", want, got) + } + if got, want := pr.Closed, false; got != want { + t.Errorf("Want pr Closed %v, got %v", want, got) + } + if got, want := pr.Merged, false; got != want { + t.Errorf("Want pr Merged %v, got %v", want, got) + } + if got, want := pr.Created.Unix(), int64(1632996627); got != want { + t.Errorf("Want pr Created %d, got %d", want, got) + } + } +} + +func testPullRequestComment(comment *scm.Comment) func(t *testing.T) { + return func(t *testing.T) { + if got, want := comment.ID, 6922557; got != want { + t.Errorf("Want pr comment ID %d, got %d", want, got) + } + if got, want := comment.Body, "test comment 1"; got != want { + t.Errorf("Want pr comment Body %q, got %q", want, got) + } + if got, want := comment.Author.Login, "kit101"; got != want { + t.Errorf("Want pr comment Author Login %q, got %q", want, got) + } + if got, want := comment.Author.Name, "kit101"; got != want { + t.Errorf("Want pr comment Author Name %q, got %q", want, got) + } + if got, want := comment.Created.Unix(), int64(1633570005); got != want { + t.Errorf("Want pr comment Created %d, got %d", want, got) + } + if got, want := comment.Updated.Unix(), int64(1633570005); got != want { + t.Errorf("Want pr comment Updated %d, got %d", want, got) + } + } +} + +func testChange(change *scm.Change) func(t *testing.T) { + return func(t *testing.T) { + if got, want := change.Path, "change/add3.txt"; got != want { + t.Errorf("Want file change Path %q, got %q", want, got) + } + if got, want := change.Added, true; got != want { + t.Errorf("Want file Added %v, got %v", want, got) + } + if got, want := change.Deleted, false; got != want { + t.Errorf("Want file Deleted %v, got %v", want, got) + } + if got, want := change.Renamed, false; got != want { + t.Errorf("Want file Renamed %v, got %v", want, got) + } + } +} diff --git a/scm/driver/gitee/integration/repo_test.go b/scm/driver/gitee/integration/repo_test.go new file mode 100644 index 000000000..5ff0cef15 --- /dev/null +++ b/scm/driver/gitee/integration/repo_test.go @@ -0,0 +1,85 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package integration + +import ( + "context" + "testing" + + "github.com/drone/go-scm/scm" +) + +// +// repository sub-tests +// + +func testRepos(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + t.Run("Find", testRepoFind(client)) + } +} + +func testRepoFind(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + result, _, err := client.Repositories.Find(context.Background(), "kit101/drone-yml-test") + if err != nil { + t.Error(err) + return + } + t.Run("Repository", testRepo(result)) + t.Run("Permissions", testPerm(result.Perm)) + } +} + +// +// struct sub-tests +// + +func testRepo(repository *scm.Repository) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + if got, want := repository.Name, "drone-yml-test"; got != want { + t.Errorf("Want repository Name %q, got %q", want, got) + } + if got, want := repository.Namespace, "kit101"; got != want { + t.Errorf("Want repository Namespace %q, got %q", want, got) + } + if got, want := repository.Branch, "master"; got != want { + t.Errorf("Want repository Branch %q, got %q", want, got) + } + if got, want := repository.Clone, "https://gitee.com/kit101/drone-yml-test.git"; got != want { + t.Errorf("Want repository Clone URL %q, got %q", want, got) + } + if got, want := repository.CloneSSH, "git@gitee.com:kit101/drone-yml-test.git"; got != want { + t.Errorf("Want repository SSH URL %q, got %q", want, got) + } + if got, want := repository.Link, "https://gitee.com/kit101/drone-yml-test.git"; got != want { + t.Errorf("Want repository Link %q, got %q", want, got) + } + if got, want := repository.Created.Unix(), int64(1616556274); got != want { + t.Errorf("Want repository Created %d, got %d", want, got) + } + if got, want := repository.Private, false; got != want { + t.Errorf("Want repository Private %v, got %v", want, got) + } + } +} + +func testPerm(perms *scm.Perm) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + if got, want := perms.Pull, true; got != want { + t.Errorf("Want permission Pull %v, got %v", want, got) + } + if got, want := perms.Push, false; got != want { + t.Errorf("Want permission Push %v, got %v", want, got) + } + if got, want := perms.Admin, false; got != want { + t.Errorf("Want permission Admin %v, got %v", want, got) + } + } +} diff --git a/scm/driver/gitee/integration/user_test.go b/scm/driver/gitee/integration/user_test.go new file mode 100644 index 000000000..26c731e12 --- /dev/null +++ b/scm/driver/gitee/integration/user_test.go @@ -0,0 +1,54 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package integration + +import ( + "context" + "testing" + + "github.com/drone/go-scm/scm" +) + +// +// user sub-tests +// + +func testUsers(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + t.Run("Find", testUserFind(client)) + } +} + +func testUserFind(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + result, _, err := client.Users.FindLogin(context.Background(), "kit101") + if err != nil { + t.Error(err) + return + } + t.Run("User", testUser(result)) + } +} + +// +// struct sub-tests +// + +func testUser(user *scm.User) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + if got, want := user.Login, "kit101"; got != want { + t.Errorf("Want user Login %q, got %q", want, got) + } + if got, want := user.Name, "kit101"; got != want { + t.Errorf("Want user Name %q, got %q", want, got) + } + if got, want := user.Avatar, "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png"; got != want { + t.Errorf("Want user Avatar %q, got %q", want, got) + } + } +} diff --git a/scm/driver/gitee/issue.go b/scm/driver/gitee/issue.go new file mode 100644 index 000000000..a5fe52a3f --- /dev/null +++ b/scm/driver/gitee/issue.go @@ -0,0 +1,336 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "context" + "fmt" + "strconv" + "time" + + "github.com/drone/go-scm/scm" +) + +type issueService struct { + client *wrapper +} + +func (s *issueService) Find(ctx context.Context, repo string, number int) (*scm.Issue, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/issues/%s", repo, decodeNumber(number)) + out := new(issue) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertIssue(out), res, err +} + +func (s *issueService) FindComment(ctx context.Context, repo string, number, id int) (*scm.Comment, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/issues/comments/%d", repo, id) + out := new(issueComment) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertIssueComment(out), res, err +} + +func (s *issueService) List(ctx context.Context, repo string, opts scm.IssueListOptions) ([]*scm.Issue, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/issues?%s", repo, encodeIssueListOptions(opts)) + out := []*issue{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + if err != nil { + res.Page.First = 1 + if opts.Page-1 < 1 { + res.Page.Prev = 1 + } else { + res.Page.Prev = opts.Page - 1 + } + totalPage, perr := strconv.Atoi(res.Header.Get("total_page")) + if perr != nil { + res.Page.Last = totalPage + if opts.Page+1 > totalPage { + res.Page.Next = totalPage + } else { + res.Page.Next = opts.Page + 1 + } + } + } + return convertIssueList(out), res, err +} + +func (s *issueService) ListComments(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Comment, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/issues/%s/comments?%s", repo, decodeNumber(number), encodeListOptions(opts)) + out := []*issueComment{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertIssueCommentList(out), res, err +} + +func (s *issueService) Create(ctx context.Context, repo string, input *scm.IssueInput) (*scm.Issue, *scm.Response, error) { + owner, repoName := scm.Split(repo) + path := fmt.Sprintf("repos/%s/issues", owner) + in := &issueInput{ + Repo: repoName, + Title: input.Title, + Body: input.Body, + } + out := new(issue) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertIssue(out), res, err +} + +func (s *issueService) CreateComment(ctx context.Context, repo string, number int, input *scm.CommentInput) (*scm.Comment, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/issues/%s/comments", repo, decodeNumber(number)) + in := &issueCommentInput{ + Body: input.Body, + } + out := new(issueComment) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertIssueComment(out), res, err +} + +func (s *issueService) DeleteComment(ctx context.Context, repo string, number, id int) (*scm.Response, error) { + path := fmt.Sprintf("repos/%s/issues/comments/%d", repo, id) + return s.client.do(ctx, "DELETE", path, nil, nil) +} + +func (s *issueService) Close(ctx context.Context, repo string, number int) (*scm.Response, error) { + owner, repoName := scm.Split(repo) + path := fmt.Sprintf("repos/%s/issues/%s", owner, decodeNumber(number)) + data := map[string]string{ + "repo": repoName, + "state": "closed", + } + out := new(issue) + res, err := s.client.do(ctx, "PATCH", path, &data, out) + return res, err +} + +func (s *issueService) Lock(context.Context, string, int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *issueService) Unlock(context.Context, string, int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +type issue struct { + ID int `json:"id"` + URL string `json:"url"` + RepositoryURL string `json:"repository_url"` + LabelsURL string `json:"labels_url"` + CommentsURL string `json:"comments_url"` + HtmlURL string `json:"html_url"` + ParentURL interface{} `json:"parent_url"` + Number string `json:"number"` + ParentID int `json:"parent_id"` + Depth int `json:"depth"` + State string `json:"state"` + Title string `json:"title"` + Body string `json:"body"` + User user `json:"user"` + Labels []label `json:"labels"` + Assignee assignee `json:"assignee"` + Collaborators []interface{} `json:"collaborators"` + Repository issueRepository `json:"repository"` + Milestone milestone `json:"milestone"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + PlanStartedAt interface{} `json:"plan_started_at"` + Deadline interface{} `json:"deadline"` + FinishedAt interface{} `json:"finished_at"` + ScheduledTime float64 `json:"scheduled_time"` + Comments int `json:"comments"` + Priority int `json:"priority"` + IssueType string `json:"issue_type"` + SecurityHole bool `json:"security_hole"` + IssueState string `json:"issue_state"` + IssueTypeDetail issueTypeDetail `json:"issue_type_detail"` + IssueStateDetail issueStateDetail `json:"issue_state_detail"` +} +type issueRepository struct { + ID int `json:"id"` + FullName string `json:"full_name"` + HumanName string `json:"human_name"` + URL string `json:"url"` + Namespace namespace `json:"namespace"` + Path string `json:"path"` + Name string `json:"name"` + Owner user `json:"owner"` + Assigner assignee `json:"assigner"` + Description string `json:"description"` + Private bool `json:"private"` + Public bool `json:"public"` + Internal bool `json:"internal"` + Fork bool `json:"fork"` + HTMLURL string `json:"html_url"` + SSHURL string `json:"ssh_url"` + ForksURL string `json:"forks_url"` + KeysURL string `json:"keys_url"` + CollaboratorsURL string `json:"collaborators_url"` + HooksURL string `json:"hooks_url"` + BranchesURL string `json:"branches_url"` + TagsURL string `json:"tags_url"` + BlobsURL string `json:"blobs_url"` + StargazersURL string `json:"stargazers_url"` + ContributorsURL string `json:"contributors_url"` + CommitsURL string `json:"commits_url"` + CommentsURL string `json:"comments_url"` + IssueCommentURL string `json:"issue_comment_url"` + IssuesURL string `json:"issues_url"` + PullsURL string `json:"pulls_url"` + MilestonesURL string `json:"milestones_url"` + NotificationsURL string `json:"notifications_url"` + LabelsURL string `json:"labels_url"` + ReleasesURL string `json:"releases_url"` + Recommend bool `json:"recommend"` + Gvp bool `json:"gvp"` + Homepage string `json:"homepage"` + Language interface{} `json:"language"` + ForksCount int `json:"forks_count"` + StargazersCount int `json:"stargazers_count"` + WatchersCount int `json:"watchers_count"` + DefaultBranch string `json:"default_branch"` + OpenIssuesCount int `json:"open_issues_count"` + HasIssues bool `json:"has_issues"` + HasWiki bool `json:"has_wiki"` + IssueComment bool `json:"issue_comment"` + CanComment bool `json:"can_comment"` + PullRequestsEnabled bool `json:"pull_requests_enabled"` + HasPage bool `json:"has_page"` + License interface{} `json:"license"` + Outsourced bool `json:"outsourced"` + ProjectCreator string `json:"project_creator"` + Members []string `json:"members"` + PushedAt time.Time `json:"pushed_at"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + Parent interface{} `json:"parent"` + Paas interface{} `json:"paas"` + AssigneesNumber int `json:"assignees_number"` + TestersNumber int `json:"testers_number"` + Assignee []assignee `json:"assignee"` + Testers []tester `json:"testers"` + Status string `json:"status"` + EmptyRepo bool `json:"empty_repo"` + Programs []interface{} `json:"programs"` + Enterprise interface{} `json:"enterprise"` +} +type issueTypeDetail struct { + ID int `json:"id"` + Title string `json:"title"` + Template interface{} `json:"template"` + Ident string `json:"ident"` + Color string `json:"color"` + IsSystem bool `json:"is_system"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} +type issueStateDetail struct { + ID int `json:"id"` + Title string `json:"title"` + Color string `json:"color"` + Icon string `json:"icon"` + Command interface{} `json:"command"` + Serial int `json:"serial"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} + +type issueInput struct { + Repo string `json:"repo"` + Title string `json:"title"` + Body string `json:"body"` +} + +type issueComment struct { + ID int `json:"id"` + HTMLURL string `json:"html_url"` + User struct { + ID int `json:"id"` + Login string `json:"login"` + AvatarURL string `json:"avatar_url"` + } `json:"user"` + Body string `json:"body"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} + +type issueCommentInput struct { + Body string `json:"body"` +} + +func convertIssueList(from []*issue) []*scm.Issue { + to := []*scm.Issue{} + for _, v := range from { + to = append(to, convertIssue(v)) + } + return to +} +func convertIssue(from *issue) *scm.Issue { + return &scm.Issue{ + Number: encodeNumber(from.Number), + Title: from.Title, + Body: from.Body, + Link: from.HtmlURL, + Labels: convertLabels(from), + Closed: from.State == "closed", + Author: scm.User{ + Login: from.User.Login, + Avatar: from.User.AvatarURL, + }, + Created: from.CreatedAt, + Updated: from.UpdatedAt, + } +} + +func convertIssueCommentList(from []*issueComment) []*scm.Comment { + to := []*scm.Comment{} + for _, v := range from { + to = append(to, convertIssueComment(v)) + } + return to +} +func convertIssueComment(from *issueComment) *scm.Comment { + return &scm.Comment{ + ID: from.ID, + Body: from.Body, + Author: scm.User{ + Login: from.User.Login, + Avatar: from.User.AvatarURL, + }, + Created: from.CreatedAt, + Updated: from.UpdatedAt, + } +} + +func convertLabels(from *issue) []string { + var labels []string + for _, label := range from.Labels { + labels = append(labels, label.Name) + } + return labels +} + +// The issue number of gitee consists of 6 uppercase letters or numbers. +// The ASCII of uppercase letters or numbers is between 48 and 90, so encoded issue number(max:9090909090) less than the maximum value of int. +func encodeNumber(giteeIssueNumber string) int { + runes := []rune(giteeIssueNumber) + encodedNumber := "" + for i := 0; i < len(runes); i++ { + encodedNumber += strconv.Itoa(int(runes[i])) + } + scmNumber, err := strconv.Atoi(encodedNumber) + if err != nil { + return 0 + } + return scmNumber +} +func decodeNumber(scmIssueNumber int) string { + issueNumberStr := strconv.Itoa(scmIssueNumber) + giteeNumber := "" + for i := 0; i < len(issueNumberStr)-1; i += 2 { + numberStr, err := strconv.Atoi(issueNumberStr[i : i+2]) + if err != nil { + return "" + } + giteeNumber += string(rune(numberStr)) + } + return giteeNumber +} diff --git a/scm/driver/gitee/issue_test.go b/scm/driver/gitee/issue_test.go new file mode 100644 index 000000000..a59ea6b29 --- /dev/null +++ b/scm/driver/gitee/issue_test.go @@ -0,0 +1,280 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "context" + "encoding/json" + "io/ioutil" + "testing" + + "github.com/drone/go-scm/scm" + + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" +) + +func TestEncodeAndDecodeIssueNumber(t *testing.T) { + giteeIssueNumber := "I4CD5P" + scmIssueNumber := 735267685380 + encodedScmIssueNumber := encodeNumber(giteeIssueNumber) + if diff := cmp.Diff(encodedScmIssueNumber, scmIssueNumber); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + encodedGiteeIssueNumber := decodeNumber(scmIssueNumber) + if diff := cmp.Diff(encodedGiteeIssueNumber, giteeIssueNumber); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + +func TestIssueFind(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test/issues/I4CD5P"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/issue.json") + + client := NewDefault() + got, res, err := client.Issues.Find(context.Background(), "kit101/drone-yml-test", 735267685380) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Issue) + raw, _ := ioutil.ReadFile("testdata/issue.json.golden") + json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestIssueFindComment(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test/issues/comments/6877445"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/issue_comment.json") + + client := NewDefault() + got, res, err := client.Issues.FindComment(context.Background(), "kit101/drone-yml-test", 735267685380, 6877445) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Comment) + raw, _ := ioutil.ReadFile("testdata/issue_comment.json.golden") + json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestIssueList(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test/issues"). + MatchParam("page", "1"). + MatchParam("per_page", "3"). + MatchParam("state", "all"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + SetHeaders(mockPageHeaders). + File("testdata/issues.json") + + client := NewDefault() + got, res, err := client.Issues.List(context.Background(), "kit101/drone-yml-test", scm.IssueListOptions{Page: 1, Size: 3, Open: true, Closed: true}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Issue{} + raw, _ := ioutil.ReadFile("testdata/issues.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Page", testPage(res)) +} + +func TestIssueListComments(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml/issues/I4CD5P/comments"). + MatchParam("page", "1"). + MatchParam("per_page", "3"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + SetHeaders(mockPageHeaders). + File("testdata/issue_comments.json") + + client := NewDefault() + got, res, err := client.Issues.ListComments(context.Background(), "kit101/drone-yml", 735267685380, scm.ListOptions{Size: 3, Page: 1}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Comment{} + raw, _ := ioutil.ReadFile("testdata/issue_comments.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Page", testPage(res)) +} + +func TestIssueCreate(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Post("/repos/kit101/issues"). + Reply(201). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/issue.json") + + input := scm.IssueInput{ + Title: "test issue 1", + Body: "test issue 1", + } + + client := NewDefault() + got, res, err := client.Issues.Create(context.Background(), "kit101/drone-yml-test", &input) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Issue) + raw, _ := ioutil.ReadFile("testdata/issue.json.golden") + json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestIssueCreateComment(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com"). + Post("/repos/kit101/drone-yml-test/issues/I4CD5P/comments"). + Reply(201). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/issue_comment.json") + + input := &scm.CommentInput{ + Body: "it's ok.", + } + + client := NewDefault() + got, res, err := client.Issues.CreateComment(context.Background(), "kit101/drone-yml-test", 735267685380, input) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Comment) + raw, _ := ioutil.ReadFile("testdata/issue_comment.json.golden") + json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestIssueDeleteComment(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Delete("/repos/kit101/drone-yml-test/issues/comments/6879139"). + Reply(204). + Type("application/json"). + SetHeaders(mockHeaders) + + client := NewDefault() + res, err := client.Issues.DeleteComment(context.Background(), "kit101/drone-yml-test", 735267685380, 6879139) + if err != nil { + t.Error(err) + return + } + + if got, want := res.Status, 204; got != want { + t.Errorf("Want response status %d, got %d", want, got) + } + t.Run("Request", testRequest(res)) +} + +func TestIssueClose(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Patch("/repos/kit101/issues/I4CD5P"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/issue.json") + + client := NewDefault() + res, err := client.Issues.Close(context.Background(), "kit101/drone-yml-test", 735267685380) + if err != nil { + t.Error(err) + return + } + + t.Run("Request", testRequest(res)) +} + +func TestIssueLock(t *testing.T) { + _, err := NewDefault().Issues.Lock(context.Background(), "kit101/drone-yml-test", 735267685380) + if err != scm.ErrNotSupported { + t.Errorf("Expect Not Supported error") + } +} + +func TestIssueUnlock(t *testing.T) { + _, err := NewDefault().Issues.Unlock(context.Background(), "kit101/drone-yml-test", 735267685380) + if err != scm.ErrNotSupported { + t.Errorf("Expect Not Supported error") + } +} diff --git a/scm/driver/gitee/linker.go b/scm/driver/gitee/linker.go new file mode 100644 index 000000000..79b0beac5 --- /dev/null +++ b/scm/driver/gitee/linker.go @@ -0,0 +1,50 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "context" + "fmt" + + "github.com/drone/go-scm/scm" +) + +type linker struct { + base string +} + +func (l *linker) Resource(ctx context.Context, repo string, ref scm.Reference) (string, error) { + switch { + case scm.IsTag(ref.Path): + t := scm.TrimRef(ref.Path) + return fmt.Sprintf("%s%s/tree/%s", l.base, repo, t), nil + case scm.IsPullRequest(ref.Path): + d := scm.ExtractPullRequest(ref.Path) + return fmt.Sprintf("%s%s/pulls/%d", l.base, repo, d), nil + case ref.Sha == "": + t := scm.TrimRef(ref.Path) + return fmt.Sprintf("%s%s/tree/%s", l.base, repo, t), nil + default: + return fmt.Sprintf("%s%s/commit/%s", l.base, repo, ref.Sha), nil + } +} + +func (l *linker) Diff(ctx context.Context, repo string, source, target scm.Reference) (string, error) { + if scm.IsPullRequest(target.Path) { + pullRequestID := scm.ExtractPullRequest(target.Path) + return fmt.Sprintf("%s%s/pulls/%d/files", l.base, repo, pullRequestID), nil + } + + s := source.Sha + t := target.Sha + if s == "" { + s = scm.TrimRef(source.Path) + } + if t == "" { + t = scm.TrimRef(target.Path) + } + + return fmt.Sprintf("%s%s/compare/%s...%s", l.base, repo, s, t), nil +} diff --git a/scm/driver/gitee/linker_test.go b/scm/driver/gitee/linker_test.go new file mode 100644 index 000000000..55c9a84f2 --- /dev/null +++ b/scm/driver/gitee/linker_test.go @@ -0,0 +1,103 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "context" + "testing" + + "github.com/drone/go-scm/scm" +) + +func TestLink(t *testing.T) { + tests := []struct { + path string + sha string + want string + }{ + { + path: "refs/heads/master", + sha: "2eac1cac02c325058cf959725c45b0612d3e8177", + want: "https://gitee.com/kit101/drone-yml-test/commit/2eac1cac02c325058cf959725c45b0612d3e8177", + }, + { + path: "refs/pull/7/head", + sha: "00b76e8abd51ae6a96318b3450944b32995f9158", + want: "https://gitee.com/kit101/drone-yml-test/pulls/7", + }, + { + path: "refs/tags/1.1", + want: "https://gitee.com/kit101/drone-yml-test/tree/1.1", + }, + { + path: "refs/heads/master", + want: "https://gitee.com/kit101/drone-yml-test/tree/master", + }, + } + + for _, test := range tests { + client := NewDefault() + ref := scm.Reference{ + Path: test.path, + Sha: test.sha, + } + got, err := client.Linker.Resource(context.Background(), "kit101/drone-yml-test", ref) + if err != nil { + t.Error(err) + return + } + want := test.want + if got != want { + t.Errorf("Want link %q, got %q", want, got) + } + } +} + +func TestDiff(t *testing.T) { + tests := []struct { + source scm.Reference + target scm.Reference + want string + }{ + { + source: scm.Reference{Sha: "2eac1cac02c325058cf959725c45b0612d3e8177"}, + target: scm.Reference{Sha: "00b76e8abd51ae6a96318b3450944b32995f9158"}, + want: "https://gitee.com/kit101/drone-yml-test/compare/2eac1cac02c325058cf959725c45b0612d3e8177...00b76e8abd51ae6a96318b3450944b32995f9158", + }, + { + source: scm.Reference{Path: "refs/heads/master"}, + target: scm.Reference{Sha: "00b76e8abd51ae6a96318b3450944b32995f9158"}, + want: "https://gitee.com/kit101/drone-yml-test/compare/master...00b76e8abd51ae6a96318b3450944b32995f9158", + }, + { + source: scm.Reference{Sha: "00b76e8abd51ae6a96318b3450944b32995f9158"}, + target: scm.Reference{Path: "refs/heads/master"}, + want: "https://gitee.com/kit101/drone-yml-test/compare/00b76e8abd51ae6a96318b3450944b32995f9158...master", + }, + { + target: scm.Reference{Path: "refs/pull/7/head"}, + want: "https://gitee.com/kit101/drone-yml-test/pulls/7/files", + }, + } + + for _, test := range tests { + client := NewDefault() + got, err := client.Linker.Diff(context.Background(), "kit101/drone-yml-test", test.source, test.target) + if err != nil { + t.Error(err) + return + } + want := test.want + if got != want { + t.Errorf("Want link %q, got %q", want, got) + } + } +} + +func TestLinkBase(t *testing.T) { + if got, want := NewDefault().Linker.(*linker).base, "https://gitee.com/"; got != want { + t.Errorf("Want url %s, got %s", want, got) + } +} diff --git a/scm/driver/gitee/org.go b/scm/driver/gitee/org.go new file mode 100644 index 000000000..1a9e66947 --- /dev/null +++ b/scm/driver/gitee/org.go @@ -0,0 +1,97 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "context" + "fmt" + + "github.com/drone/go-scm/scm" +) + +type organizationService struct { + client *wrapper +} + +func (s *organizationService) Find(ctx context.Context, name string) (*scm.Organization, *scm.Response, error) { + path := fmt.Sprintf("orgs/%s", name) + out := new(organization) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertOrganization(out), res, err +} + +func (s *organizationService) FindMembership(ctx context.Context, name, username string) (*scm.Membership, *scm.Response, error) { + path := fmt.Sprintf("orgs/%s/memberships/%s", name, username) + out := new(membership) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertMembership(out), res, err +} + +func (s *organizationService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Organization, *scm.Response, error) { + path := fmt.Sprintf("user/orgs?%s", encodeListOptions(opts)) + out := []*organization{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertOrganizationList(out), res, err +} + +type organization struct { + ID int `json:"id"` + Login string `json:"login"` + Name string `json:"name"` + URL string `json:"url"` + AvatarURL string `json:"avatar_url"` + ReposURL string `json:"repos_url"` + EventsURL string `json:"events_url"` + MembersURL string `json:"members_url"` + Description string `json:"description"` + FollowCount int `json:"follow_count"` +} + +type membership struct { + URL string `json:"url"` + Active bool `json:"active"` + Remark string `json:"remark"` + Role string `json:"role"` + OrganizationURL string `json:"organization_url"` + Organization organization `json:"organization"` + User struct { + ID int `json:"id"` + Login string `json:"login"` + Name string `json:"name"` + AvatarURL string `json:"avatar_url"` + URL string `json:"url"` + HtmlURL string `json:"html_url"` + Remark string `json:"remark"` + } `json:"user"` +} + +func convertOrganizationList(from []*organization) []*scm.Organization { + to := []*scm.Organization{} + for _, v := range from { + to = append(to, convertOrganization(v)) + } + return to +} + +func convertOrganization(from *organization) *scm.Organization { + return &scm.Organization{ + Name: from.Login, + Avatar: from.AvatarURL, + } +} + +func convertMembership(from *membership) *scm.Membership { + to := new(scm.Membership) + to.Active = from.Active + switch from.Role { + case "admin": + to.Role = scm.RoleAdmin + case "member": + to.Role = scm.RoleMember + default: + to.Role = scm.RoleUndefined + } + return to +} diff --git a/scm/driver/gitee/org_test.go b/scm/driver/gitee/org_test.go new file mode 100644 index 000000000..fa08e8927 --- /dev/null +++ b/scm/driver/gitee/org_test.go @@ -0,0 +1,108 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "context" + "encoding/json" + "io/ioutil" + "testing" + + "github.com/drone/go-scm/scm" + + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" +) + +func TestOrganizationFind(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/orgs/kit101-personal"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/org.json") + + client := NewDefault() + got, res, err := client.Organizations.Find(context.Background(), "kit101-personal") + if err != nil { + t.Error(err) + return + } + + want := new(scm.Organization) + raw, _ := ioutil.ReadFile("testdata/org.json.golden") + json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestOrganizationFindMembership(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/orgs/kit101-personal/memberships/kit101"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/membership.json") + + client := NewDefault() + got, res, err := client.Organizations.FindMembership(context.Background(), "kit101-personal", "kit101") + if err != nil { + t.Error(err) + return + } + + want := new(scm.Membership) + raw, _ := ioutil.ReadFile("testdata/membership.json.golden") + json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestOrganizationList(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/user/orgs"). + MatchParam("page", "1"). + MatchParam("per_page", "3"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + SetHeaders(mockPageHeaders). + File("testdata/orgs.json") + + client := NewDefault() + got, res, err := client.Organizations.List(context.Background(), scm.ListOptions{Size: 3, Page: 1}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Organization{} + raw, _ := ioutil.ReadFile("testdata/orgs.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Page", testPage(res)) +} diff --git a/scm/driver/gitee/pr.go b/scm/driver/gitee/pr.go new file mode 100644 index 000000000..7a35768f9 --- /dev/null +++ b/scm/driver/gitee/pr.go @@ -0,0 +1,413 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "context" + "fmt" + "time" + + "github.com/drone/go-scm/scm" +) + +type pullService struct { + client *wrapper +} + +func (s *pullService) Find(ctx context.Context, repo string, number int) (*scm.PullRequest, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/pulls/%d", repo, number) + out := new(pr) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertPullRequest(out), res, err +} + +func (s *pullService) FindComment(ctx context.Context, repo string, _ int, id int) (*scm.Comment, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/pulls/comments/%d", repo, id) + out := new(prComment) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertPullRequestComment(out), res, err +} + +func (s *pullService) List(ctx context.Context, repo string, opts scm.PullRequestListOptions) ([]*scm.PullRequest, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/pulls?%s", repo, encodePullRequestListOptions(opts)) + out := []*pr{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertPullRequestList(out), res, err +} + +func (s *pullService) ListChanges(ctx context.Context, repo string, number int, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/pulls/%d/files", repo, number) + out := []*prFile{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertPrChangeList(out), res, err +} + +func (s *pullService) ListComments(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Comment, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/pulls/%d/comments/?%s", repo, number, encodeListOptions(opts)) + out := []*prComment{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertPullRequestComments(out), res, err +} + +func (s *pullService) ListCommits(ctx context.Context, repo string, number int, _ scm.ListOptions) ([]*scm.Commit, *scm.Response, error) { + path := fmt.Sprintf("/repos/%s/pulls/%d/commits", repo, number) + out := []*prCommit{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertPrCommitList(out), res, err +} + +func (s *pullService) Merge(ctx context.Context, repo string, number int) (*scm.Response, error) { + path := fmt.Sprintf("repos/%s/pulls/%d/merge", repo, number) + res, err := s.client.do(ctx, "PUT", path, nil, nil) + return res, err +} + +func (s *pullService) Close(ctx context.Context, repo string, number int) (*scm.Response, error) { + path := fmt.Sprintf("repos/%s/pulls/%d", repo, number) + data := map[string]string{"state": "closed"} + res, err := s.client.do(ctx, "PATCH", path, &data, nil) + return res, err +} + +func (s *pullService) Create(ctx context.Context, repo string, input *scm.PullRequestInput) (*scm.PullRequest, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/pulls", repo) + in := &prInput{ + Title: input.Title, + Body: input.Body, + Head: input.Source, + Base: input.Target, + } + out := new(pr) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertPullRequest(out), res, err +} + +func (s *pullService) CreateComment(ctx context.Context, repo string, number int, input *scm.CommentInput) (*scm.Comment, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/pulls/%d/comments", repo, number) + in := &prCommentInput{ + Body: input.Body, + } + out := new(prComment) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertPullRequestComment(out), res, err +} + +func (s *pullService) DeleteComment(ctx context.Context, repo string, _ int, id int) (*scm.Response, error) { + path := fmt.Sprintf("repos/%s/pulls/comments/%d", repo, id) + res, err := s.client.do(ctx, "DELETE", path, nil, nil) + return res, err +} + +type ( + pr struct { + ID int `json:"id"` + URL string `json:"url"` + HtmlURL string `json:"html_url"` + DiffURL string `json:"diff_url"` + PatchURL string `json:"patch_url"` + IssueURL string `json:"issue_url"` + CommitsURL string `json:"commits_url"` + ReviewCommentsURL string `json:"review_comments_url"` + ReviewCommentURL string `json:"review_comment_url"` + CommentsURL string `json:"comments_url"` + Number int `json:"number"` + State string `json:"state"` + Title string `json:"title"` + Body string `json:"body"` + AssigneesNumber int `json:"assignees_number"` + TestersNumber int `json:"testers_number"` + Assignees []assignee `json:"assignees"` + Testers []tester `json:"testers"` + Milestone milestone `json:"milestone"` + Labels []label `json:"labels"` + Locked bool `json:"locked"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + ClosedAt time.Time `json:"closed_at"` + MergedAt time.Time `json:"merged_at"` + Mergeable bool `json:"mergeable"` + CanMergeCheck bool `json:"can_merge_check"` + Head headOrBase `json:"head"` + Base headOrBase `json:"base"` + User user `json:"user"` + } + assignee struct { + ID int `json:"id"` + Login string `json:"login"` + Name string `json:"name"` + AvatarURL string `json:"avatar_url"` + URL string `json:"url"` + HtmlURL string `json:"html_url"` + Remark string `json:"remark"` + FollowersURL string `json:"followers_url"` + FollowingURL string `json:"following_url"` + GistsURL string `json:"gists_url"` + StarredURL string `json:"starred_url"` + SubscriptionsURL string `json:"subscriptions_url"` + OrganizationsURL string `json:"organizations_url"` + ReposURL string `json:"repos_url"` + EventsURL string `json:"events_url"` + ReceivedEventsURL string `json:"received_events_url"` + Type string `json:"type"` + } + tester struct { + ID int `json:"id"` + Login string `json:"login"` + Name string `json:"name"` + AvatarURL string `json:"avatar_url"` + URL string `json:"url"` + HtmlURL string `json:"html_url"` + Remark string `json:"remark"` + FollowersURL string `json:"followers_url"` + FollowingURL string `json:"following_url"` + GistsURL string `json:"gists_url"` + StarredURL string `json:"starred_url"` + SubscriptionsURL string `json:"subscriptions_url"` + OrganizationsURL string `json:"organizations_url"` + ReposURL string `json:"repos_url"` + EventsURL string `json:"events_url"` + ReceivedEventsURL string `json:"received_events_url"` + Type string `json:"type"` + } + milestone struct { + URL string `json:"url"` + HtmlURL string `json:"html_url"` + ID int `json:"id"` + Number int `json:"number"` + RepositoryID interface{} `json:"repository_id"` + State string `json:"state"` + Title string `json:"title"` + Description string `json:"description"` + UpdatedAt time.Time `json:"updated_at"` + CreatedAt time.Time `json:"created_at"` + OpenIssues int `json:"open_issues"` + ClosedIssues int `json:"closed_issues"` + DueOn string `json:"due_on"` + } + label struct { + ID int `json:"id"` + Name string `json:"name"` + Color string `json:"color"` + RepositoryID int `json:"repository_id"` + URL string `json:"url"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + } + prRepo struct { + ID int `json:"id"` + FullName string `json:"full_name"` + HumanName string `json:"human_name"` + URL string `json:"url"` + //Namespace namespace `json:"namespace"` + Path string `json:"path"` + Name string `json:"name"` + Owner user `json:"owner"` + Assigner assignee `json:"assigner"` + Description string `json:"description"` + Private bool `json:"private"` + Public bool `json:"public"` + Internal bool `json:"internal"` + Fork bool `json:"fork"` + HtmlURL string `json:"html_url"` + SshURL string `json:"ssh_url"` + } + headOrBase struct { + Label string `json:"label"` + Ref string `json:"ref"` + Sha string `json:"sha"` + User user `json:"user"` + Repo prRepo `json:"repo"` + } + + prComment struct { + URL string `json:"url"` + ID int `json:"id"` + User user `json:"user"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + Body string `json:"body"` + HtmlURL string `json:"html_url"` + PullRequestURL string `json:"pull_request_url"` + } + + prFile struct { + Sha string `json:"sha"` + Filename string `json:"filename"` + Status string `json:"status"` + Additions string `json:"additions"` + Deletions string `json:"deletions"` + BlobURL string `json:"blob_url"` + RawURL string `json:"raw_url"` + Patch struct { + Diff string `json:"diff"` + NewPath string `json:"new_path"` + OldPath string `json:"old_path"` + AMode string `json:"a_mode"` + BMode string `json:"b_mode"` + NewFile bool `json:"new_file"` + RenamedFile bool `json:"renamed_file"` + DeletedFile bool `json:"deleted_file"` + TooLarge bool `json:"too_large"` + } `json:"patch"` + } + + prCommit struct { + URL string `json:"url"` + Sha string `json:"sha"` + HtmlURL string `json:"html_url"` + CommentsURL string `json:"comments_url"` + Commit struct { + URL string `json:"url"` + Author struct { + Name string `json:"name"` + Date time.Time `json:"date"` + Email string `json:"email"` + } `json:"author"` + Committer struct { + Name string `json:"name"` + Date time.Time `json:"date"` + Email string `json:"email"` + } `json:"committer"` + Message string `json:"message"` + CommentCount int `json:"comment_count"` + } `json:"commit"` + Author author `json:"author"` + Committer author `json:"committer"` + Parents struct { + URL string `json:"url"` + Sha string `json:"sha"` + } `json:"parents"` + } +) + +type prInput struct { + Title string `json:"title"` + Body string `json:"body"` + Head string `json:"head"` + Base string `json:"base"` +} +type prCommentInput struct { + Body string `json:"body"` +} + +func convertPullRequestList(from []*pr) []*scm.PullRequest { + to := []*scm.PullRequest{} + for _, v := range from { + to = append(to, convertPullRequest(v)) + } + return to +} +func convertPullRequest(from *pr) *scm.PullRequest { + var labels []scm.Label + for _, label := range from.Labels { + labels = append(labels, scm.Label{ + Name: label.Name, + Color: label.Color, + }) + } + merged := from.State == "merged" + closed := from.State == "closed" + if merged { + closed = true + } + return &scm.PullRequest{ + Number: from.Number, + Title: from.Title, + Body: from.Body, + Sha: from.Head.Sha, + Ref: fmt.Sprintf("refs/pull/%d/head", from.Number), + Source: from.Head.Ref, + Target: from.Base.Ref, + Fork: from.Head.Repo.FullName, + Link: from.HtmlURL, + Diff: from.DiffURL, + Closed: closed, + Merged: merged, + Head: scm.Reference{ + Name: from.Head.Ref, + Path: scm.ExpandRef(from.Head.Ref, "refs/heads"), + Sha: from.Head.Sha, + }, + Base: scm.Reference{ + Name: from.Base.Ref, + Path: scm.ExpandRef(from.Base.Ref, "refs/heads"), + Sha: from.Base.Sha, + }, + Author: scm.User{ + Login: from.User.Login, + Avatar: from.User.AvatarURL, + }, + Created: from.CreatedAt, + Updated: from.UpdatedAt, + Labels: labels, + } +} + +func convertPullRequestComments(from []*prComment) []*scm.Comment { + to := []*scm.Comment{} + for _, v := range from { + to = append(to, convertPullRequestComment(v)) + } + return to +} +func convertPullRequestComment(from *prComment) *scm.Comment { + return &scm.Comment{ + ID: from.ID, + Body: from.Body, + Author: scm.User{ + Login: from.User.Login, + Name: from.User.Name, + Avatar: from.User.AvatarURL, + }, + Created: from.CreatedAt, + Updated: from.UpdatedAt, + } +} + +func convertPrChangeList(from []*prFile) []*scm.Change { + to := []*scm.Change{} + for _, v := range from { + to = append(to, convertPrChange(v)) + } + return to +} +func convertPrChange(from *prFile) *scm.Change { + return &scm.Change{ + Path: from.Filename, + Added: from.Status == "added", + Deleted: from.Status == "deleted", + Renamed: from.Status == "renamed", + BlobID: from.Sha, + } +} + +func convertPrCommitList(from []*prCommit) []*scm.Commit { + to := []*scm.Commit{} + for _, v := range from { + to = append(to, convertPrCommit(v)) + } + return to +} +func convertPrCommit(from *prCommit) *scm.Commit { + return &scm.Commit{ + Message: from.Commit.Message, + Sha: from.Sha, + Link: from.HtmlURL, + Author: scm.Signature{ + Name: from.Commit.Author.Name, + Email: from.Commit.Author.Email, + Date: from.Commit.Author.Date, + Login: from.Author.Login, + Avatar: from.Author.AvatarURL, + }, + Committer: scm.Signature{ + Name: from.Commit.Committer.Name, + Email: from.Commit.Committer.Email, + Date: from.Commit.Committer.Date, + Login: from.Committer.Login, + Avatar: from.Committer.AvatarURL, + }, + } +} diff --git a/scm/driver/gitee/pr_test.go b/scm/driver/gitee/pr_test.go new file mode 100644 index 000000000..bc20d30b5 --- /dev/null +++ b/scm/driver/gitee/pr_test.go @@ -0,0 +1,320 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "context" + "encoding/json" + "io/ioutil" + "testing" + + "github.com/drone/go-scm/scm" + + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" +) + +func TestPullFind(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test/pulls/6"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/pr.json") + + client := NewDefault() + got, res, err := client.PullRequests.Find(context.Background(), "kit101/drone-yml-test", 6) + if err != nil { + t.Error(err) + return + } + + want := new(scm.PullRequest) + raw, _ := ioutil.ReadFile("testdata/pr.json.golden") + json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestPullFindComment(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test/pulls/comments/6922557"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/pr_comment.json") + + client := NewDefault() + got, res, err := client.PullRequests.FindComment(context.Background(), "kit101/drone-yml-test", 7, 6922557) + if err != nil { + t.Error(err) + return + } + want := new(scm.Comment) + raw, _ := ioutil.ReadFile("testdata/pr_comment.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestPullList(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test/pulls"). + MatchParam("page", "1"). + MatchParam("per_page", "3"). + MatchParam("state", "all"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + SetHeaders(mockPageHeaders). + File("testdata/pulls.json") + + client := NewDefault() + got, res, err := client.PullRequests.List(context.Background(), "kit101/drone-yml-test", scm.PullRequestListOptions{Page: 1, Size: 3, Open: true, Closed: true}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.PullRequest{} + raw, _ := ioutil.ReadFile("testdata/pulls.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Page", testPage(res)) +} + +func TestPullListChanges(t *testing.T) { + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test/pulls/6/files"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + SetHeaders(mockPageHeaders). + File("testdata/pr_files.json") + + client := NewDefault() + got, res, err := client.PullRequests.ListChanges(context.Background(), "kit101/drone-yml-test", 6, scm.ListOptions{}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Change{} + raw, _ := ioutil.ReadFile("testdata/pr_files.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestPullListComments(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test/pulls/7/comments"). + MatchParam("page", "1"). + MatchParam("per_page", "3"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + SetHeaders(mockPageHeaders). + File("testdata/pr_comments.json") + + client := NewDefault() + got, res, err := client.PullRequests.ListComments(context.Background(), "kit101/drone-yml-test", 7, scm.ListOptions{Page: 1, Size: 3}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Comment{} + raw, _ := ioutil.ReadFile("testdata/pr_comments.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Page", testPage(res)) +} + +func TestPullListCommits(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test/pulls/7/commits"). + Reply(200). + Type("application/json"). + File("testdata/pr_commits.json") + + client := NewDefault() + got, _, err := client.PullRequests.ListCommits(context.Background(), "kit101/drone-yml-test", 7, scm.ListOptions{}) + if err != nil { + t.Error(err) + } + + want := []*scm.Commit{} + raw, _ := ioutil.ReadFile("testdata/pr_commits.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + +func TestPullMerge(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Put("/repos/kit101/drone-yml-test/pulls/6/merge"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders) + + client := NewDefault() + res, err := client.PullRequests.Merge(context.Background(), "kit101/drone-yml-test", 6) + if err != nil { + t.Error(err) + return + } + + t.Run("Request", testRequest(res)) +} + +func TestPullClose(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Patch("/repos/kit101/drone-yml-test/pulls/6"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders) + + client := NewDefault() + res, err := client.PullRequests.Close(context.Background(), "kit101/drone-yml-test", 6) + if err != nil { + t.Error(err) + return + } + + t.Run("Request", testRequest(res)) +} + +func TestPullCreate(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Post("/repos/kit101/drone-yml-test/pulls"). + Reply(201). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/pr.json") + + input := scm.PullRequestInput{ + Title: "new-feature", + Body: "Please pull these awesome changes", + Source: "crud", + Target: "master", + } + + client := NewDefault() + got, res, err := client.PullRequests.Create(context.Background(), "kit101/drone-yml-test", &input) + if err != nil { + t.Error(err) + return + } + + want := new(scm.PullRequest) + raw, _ := ioutil.ReadFile("testdata/pr.json.golden") + json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestPullCommentCreate(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Post("/repos/kit101/drone-yml-test/pulls/7/comments"). + Reply(201). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/pr_comment.json") + + client := NewDefault() + input := scm.CommentInput{ + Body: "test comment 1", + } + got, res, err := client.PullRequests.CreateComment(context.Background(), "kit101/drone-yml-test", 7, &input) + if err != nil { + t.Error(err) + return + } + want := new(scm.Comment) + raw, _ := ioutil.ReadFile("testdata/pr_comment.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestPullCommentDelete(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Delete("/repos/kit101/drone-yml-test/pulls/comments/6990588"). + Reply(204). + SetHeaders(mockHeaders) + + client := NewDefault() + res, err := client.PullRequests.DeleteComment(context.Background(), "kit101/drone-yml-test", 7, 6990588) + if err != nil { + t.Error(err) + return + } + + if got, want := res.Status, 204; got != want { + t.Errorf("Want response status %d, got %d", want, got) + } + t.Run("Request", testRequest(res)) +} diff --git a/scm/driver/gitee/repo.go b/scm/driver/gitee/repo.go new file mode 100644 index 000000000..2628c5df7 --- /dev/null +++ b/scm/driver/gitee/repo.go @@ -0,0 +1,233 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "context" + "fmt" + "strconv" + "time" + + "github.com/drone/go-scm/scm" +) + +type RepositoryService struct { + client *wrapper +} + +func (s *RepositoryService) Find(ctx context.Context, repo string) (*scm.Repository, *scm.Response, error) { + path := fmt.Sprintf("repos/%s", repo) + out := new(repository) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertRepository(out), res, err +} + +func (s *RepositoryService) FindHook(ctx context.Context, repo string, id string) (*scm.Hook, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/hooks/%s", repo, id) + out := new(hook) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertHook(out), res, err +} + +func (s *RepositoryService) FindPerms(ctx context.Context, repo string) (*scm.Perm, *scm.Response, error) { + repos, res, err := s.Find(ctx, repo) + if err == nil { + return repos.Perm, res, err + } + return nil, res, err +} + +func (s *RepositoryService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { + path := fmt.Sprintf("user/repos?%s", encodeListOptions(opts)) + out := []*repository{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertRepositoryList(out), res, err +} + +func (s *RepositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/hooks?%s", repo, encodeListOptions(opts)) + out := []*hook{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertHookList(out), res, err +} + +func (s *RepositoryService) ListStatus(context.Context, string, string, scm.ListOptions) ([]*scm.Status, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *RepositoryService) CreateHook(ctx context.Context, repo string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/hooks", repo) + in := new(hook) + // 1: signature + in.EncryptionType = 1 + in.Password = input.Secret + in.URL = input.Target + convertFromHookEvents(input.Events, in) + + out := new(hook) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertHook(out), res, err +} + +func (s *RepositoryService) CreateStatus(context.Context, string, string, *scm.StatusInput) (*scm.Status, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *RepositoryService) UpdateHook(ctx context.Context, repo, id string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) { + path := fmt.Sprintf("repos/%s/hooks/%s", repo, id) + in := new(hook) + // 1: signature + in.EncryptionType = 1 + in.Password = input.Secret + in.URL = input.Target + convertFromHookEvents(input.Events, in) + + out := new(hook) + res, err := s.client.do(ctx, "PATCH", path, in, out) + return convertHook(out), res, err +} + +func (s *RepositoryService) DeleteHook(ctx context.Context, repo, id string) (*scm.Response, error) { + path := fmt.Sprintf("repos/%s/hooks/%s", repo, id) + return s.client.do(ctx, "DELETE", path, nil, nil) +} + +type repository struct { + ID int `json:"id"` + Owner struct { + ID int `json:"id"` + Login string `json:"login"` + Name string `json:"name"` + AvatarURL string `json:"avatar_url"` + } `json:"owner"` + Namespace namespace `json:"namespace"` + Name string `json:"name"` + FullName string `json:"full_name"` + HumanName string `json:"human_name"` + Path string `json:"path"` + Public bool `json:"public"` + Private bool `json:"private"` + Internal bool `json:"internal"` + Fork bool `json:"fork"` + URL string `json:"url"` + HtmlURL string `json:"html_url"` + SshURL string `json:"ssh_url"` + DefaultBranch string `json:"default_branch"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + Permission struct { + Admin bool `json:"admin"` + Push bool `json:"push"` + Pull bool `json:"pull"` + } `json:"permission"` +} + +type hook struct { + ID int `json:"id"` + URL string `json:"url"` + CreatedAt time.Time `json:"created_at"` + // password encryption type, 0: password, 1: signature + EncryptionType int `json:"encryption_type"` + Password string `json:"password"` + ProjectID int `json:"project_id"` + Result string `json:"result"` + ResultCode int `json:"result_code"` + PushEvents bool `json:"push_events"` + TagPushEvents bool `json:"tag_push_events"` + IssuesEvents bool `json:"issues_events"` + NoteEvents bool `json:"note_events"` + MergeRequestsEvents bool `json:"merge_requests_events"` +} + +type namespace struct { + ID int `json:"id"` + Type string `json:"type"` + Name string `json:"name"` + Path string `json:"path"` + HtmlURL string `json:"html_url"` +} + +func convertRepositoryList(from []*repository) []*scm.Repository { + to := []*scm.Repository{} + for _, v := range from { + to = append(to, convertRepository(v)) + } + return to +} +func convertRepository(from *repository) *scm.Repository { + return &scm.Repository{ + ID: strconv.Itoa(from.ID), + Name: from.Name, + Namespace: from.Namespace.Path, + Perm: &scm.Perm{ + Push: from.Permission.Push, + Pull: from.Permission.Pull, + Admin: from.Permission.Admin, + }, + Link: from.HtmlURL, + Branch: from.DefaultBranch, + Private: from.Private, + Clone: from.HtmlURL, + CloneSSH: from.SshURL, + Created: from.CreatedAt, + Updated: from.UpdatedAt, + } +} + +func convertHookList(from []*hook) []*scm.Hook { + to := []*scm.Hook{} + for _, v := range from { + to = append(to, convertHook(v)) + } + return to +} +func convertHook(from *hook) *scm.Hook { + return &scm.Hook{ + ID: strconv.Itoa(from.ID), + Active: true, + Target: from.URL, + Events: convertHookEvent(from), + SkipVerify: true, + } +} + +func convertHookEvent(from *hook) []string { + var events []string + if from.PushEvents { + events = append(events, "push") + } + if from.TagPushEvents { + events = append(events, "tag_push") + } + if from.IssuesEvents { + events = append(events, "issues") + } + if from.NoteEvents { + events = append(events, "note") + } + if from.MergeRequestsEvents { + events = append(events, "merge_requests") + } + return events +} + +// convertFromHookEvents not support: Branch, Deployment +func convertFromHookEvents(from scm.HookEvents, to *hook) { + if from.Push { + to.PushEvents = true + } + if from.PullRequest { + to.MergeRequestsEvents = true + } + if from.Issue { + to.IssuesEvents = true + } + if from.IssueComment || from.PullRequestComment || from.ReviewComment { + to.NoteEvents = true + } + if from.Tag { + to.TagPushEvents = true + } +} diff --git a/scm/driver/gitee/repo_test.go b/scm/driver/gitee/repo_test.go new file mode 100644 index 000000000..1e3459ad9 --- /dev/null +++ b/scm/driver/gitee/repo_test.go @@ -0,0 +1,359 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "context" + "encoding/json" + "fmt" + "io/ioutil" + "testing" + + "github.com/drone/go-scm/scm" + + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" +) + +func TestRepositoryFind(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/repo.json") + + client := NewDefault() + got, res, err := client.Repositories.Find(context.Background(), "kit101/drone-yml-test") + if err != nil { + t.Error(err) + return + } + + want := new(scm.Repository) + raw, _ := ioutil.ReadFile("testdata/repo.json.golden") + json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestRepositoryHookFind(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test/hooks/787341"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/hook.json") + + client := NewDefault() + got, res, err := client.Repositories.FindHook(context.Background(), "kit101/drone-yml-test", "787341") + if err != nil { + t.Error(err) + return + } + + want := new(scm.Hook) + raw, _ := ioutil.ReadFile("testdata/hook.json.golden") + json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestRepositoryPerms(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/repo.json") + + client := NewDefault() + got, res, err := client.Repositories.FindPerms(context.Background(), "kit101/drone-yml-test") + if err != nil { + t.Error(err) + return + } + + want := new(scm.Repository) + raw, _ := ioutil.ReadFile("testdata/repo.json.golden") + json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want.Perm); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestRepositoryList(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/user/repos"). + MatchParam("page", "1"). + MatchParam("per_page", "3"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + SetHeaders(mockPageHeaders). + File("testdata/repos.json") + + client := NewDefault() + got, res, err := client.Repositories.List(context.Background(), scm.ListOptions{Page: 1, Size: 3}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Repository{} + raw, _ := ioutil.ReadFile("testdata/repos.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Page", testPage(res)) +} + +func TestRepositoryListHook(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/kit101/drone-yml-test/hooks"). + MatchParam("page", "1"). + MatchParam("per_page", "3"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + SetHeaders(mockPageHeaders). + File("testdata/hooks.json") + + client := NewDefault() + got, res, err := client.Repositories.ListHooks(context.Background(), "kit101/drone-yml-test", scm.ListOptions{Page: 1, Size: 3}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Hook{} + raw, _ := ioutil.ReadFile("testdata/hooks.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Page", testPage(res)) +} + +func TestRepositoryListStatus(t *testing.T) { + _, _, err := NewDefault().Repositories.ListStatus(context.Background(), "", "", scm.ListOptions{}) + if err != scm.ErrNotSupported { + t.Errorf("Expect Not Supported error") + } +} + +func TestRepositoryCreateHook(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Post("/repos/kit101/drone-yml-test/hooks"). + Reply(201). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/hook.json") + + in := &scm.HookInput{ + Target: "http://test.kit101.com/webhook", + Secret: "123asdas123", + } + + client := NewDefault() + got, res, err := client.Repositories.CreateHook(context.Background(), "kit101/drone-yml-test", in) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Hook) + raw, _ := ioutil.ReadFile("testdata/hook.json.golden") + json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestRepositoryCreateStatus(t *testing.T) { + _, _, err := NewDefault().Repositories.CreateStatus(context.Background(), "", "", &scm.StatusInput{}) + if err != scm.ErrNotSupported { + t.Errorf("Expect Not Supported error") + } +} + +func TestRepositoryUpdateHook(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Patch("/repos/kit101/drone-yml-test/hooks/787341"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/hook.json") + + in := &scm.HookInput{ + Target: "http://test.kit101.com/webhook", + Secret: "123asdas123", + } + + client := NewDefault() + got, res, err := client.Repositories.UpdateHook(context.Background(), "kit101/drone-yml-test", "787341", in) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Hook) + raw, _ := ioutil.ReadFile("testdata/hook.json.golden") + json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) +} + +func TestRepositoryDeleteHook(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Delete("/repos/kit101/drone-yml-test/hooks/787341"). + Reply(204). + Type("application/json"). + SetHeaders(mockHeaders) + + client := NewDefault() + res, err := client.Repositories.DeleteHook(context.Background(), "kit101/drone-yml-test", "787341") + if err != nil { + t.Error(err) + return + } + + if got, want := res.Status, 204; got != want { + t.Errorf("Want response status %d, got %d", want, got) + } + t.Run("Request", testRequest(res)) +} + +func TestRepositoryNotFound(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/repos/dev/null"). + Reply(404). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/error.json") + + client := NewDefault() + _, _, err := client.Repositories.Find(context.Background(), "dev/null") + if err == nil { + t.Errorf("Expect Not Found error") + return + } + if got, want := err.Error(), "404 Project Not Found"; got != want { + t.Errorf("Want error %q, got %q", want, got) + } +} + +func TestHookEvents(t *testing.T) { + tests := []struct { + in scm.HookEvents + out *hook + }{ + { + in: scm.HookEvents{Push: true}, + out: &hook{PushEvents: true}, + }, + { + in: scm.HookEvents{Branch: true}, + out: &hook{}, + }, + { + in: scm.HookEvents{IssueComment: true}, + out: &hook{NoteEvents: true}, + }, + { + in: scm.HookEvents{PullRequestComment: true}, + out: &hook{NoteEvents: true}, + }, + { + in: scm.HookEvents{Issue: true}, + out: &hook{IssuesEvents: true}, + }, + { + in: scm.HookEvents{PullRequest: true}, + out: &hook{MergeRequestsEvents: true}, + }, + { + in: scm.HookEvents{ + Branch: true, + Deployment: true, + Issue: true, + IssueComment: true, + PullRequest: true, + PullRequestComment: true, + Push: true, + ReviewComment: true, + Tag: true, + }, + out: &hook{ + IssuesEvents: true, + MergeRequestsEvents: true, + NoteEvents: true, + PushEvents: true, + TagPushEvents: true, + }, + }, + } + + for i, test := range tests { + fmt.Println(test, i) + got := new(hook) + convertFromHookEvents(test.in, got) + want := test.out + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results at index %d", i) + t.Log(diff) + } + } +} diff --git a/scm/driver/gitee/review.go b/scm/driver/gitee/review.go new file mode 100644 index 000000000..95749db1a --- /dev/null +++ b/scm/driver/gitee/review.go @@ -0,0 +1,31 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type reviewService struct { + client *wrapper +} + +func (s *reviewService) Find(context.Context, string, int, int) (*scm.Review, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *reviewService) List(context.Context, string, int, scm.ListOptions) ([]*scm.Review, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *reviewService) Create(context.Context, string, int, *scm.ReviewInput) (*scm.Review, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *reviewService) Delete(context.Context, string, int, int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} diff --git a/scm/driver/gitee/review_test.go b/scm/driver/gitee/review_test.go new file mode 100644 index 000000000..28b2fd775 --- /dev/null +++ b/scm/driver/gitee/review_test.go @@ -0,0 +1,44 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "context" + "testing" + + "github.com/drone/go-scm/scm" +) + +func TestReviewFind(t *testing.T) { + service := new(reviewService) + _, _, err := service.Find(context.Background(), "kit101/drone-yml-test", 1, 1) + if err != scm.ErrNotSupported { + t.Errorf("Expect Not Supported error") + } +} + +func TestReviewList(t *testing.T) { + service := new(reviewService) + _, _, err := service.List(context.Background(), "kit101/drone-yml-test", 1, scm.ListOptions{}) + if err != scm.ErrNotSupported { + t.Errorf("Expect Not Supported error") + } +} + +func TestReviewCreate(t *testing.T) { + service := new(reviewService) + _, _, err := service.Create(context.Background(), "kit101/drone-yml-test", 1, nil) + if err != scm.ErrNotSupported { + t.Errorf("Expect Not Supported error") + } +} + +func TestReviewDelete(t *testing.T) { + service := new(reviewService) + _, err := service.Delete(context.Background(), "kit101/drone-yml-test", 1, 1) + if err != scm.ErrNotSupported { + t.Errorf("Expect Not Supported error") + } +} diff --git a/scm/driver/gitee/testdata/branch.json b/scm/driver/gitee/testdata/branch.json new file mode 100644 index 000000000..ae0ad3dd7 --- /dev/null +++ b/scm/driver/gitee/testdata/branch.json @@ -0,0 +1,49 @@ +{ + "name": "master", + "commit": { + "sha": "e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "commit": { + "author": { + "name": "kit101", + "date": "2021-08-23T23:45:53+08:00", + "email": "qkssk1711@163.com" + }, + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/git/commits/e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "message": "add/update/delete/rename\n", + "tree": { + "sha": "55d4c682f3e2b276cc40c70e59cebb17dcb1273a", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/git/trees/55d4c682f3e2b276cc40c70e59cebb17dcb1273a" + }, + "committer": { + "name": "kit101", + "date": "2021-08-23T23:45:53+08:00", + "email": "qkssk1711@163.com" + } + }, + "author": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "id": 1535738, + "login": "kit101" + }, + "parents": [ + { + "sha": "537575f44a09c57dfc472e26fe067754fd2f9374", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/537575f44a09c57dfc472e26fe067754fd2f9374" + } + ], + "committer": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "id": 1535738, + "login": "kit101" + } + }, + "_links": { + "html": "https://gitee.com/kit101/drone-yml-test/tree/master", + "self": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/branches/master" + }, + "protected": false, + "protection_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/branches/master/protection" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/branch.json.golden b/scm/driver/gitee/testdata/branch.json.golden new file mode 100644 index 000000000..ec8a3ea78 --- /dev/null +++ b/scm/driver/gitee/testdata/branch.json.golden @@ -0,0 +1,5 @@ +{ + "Name": "master", + "Path": "refs/heads/master", + "Sha": "e3c0ff4d5cef439ea11b30866fb1ed79b420801d" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/branches.json b/scm/driver/gitee/testdata/branches.json new file mode 100644 index 000000000..7f49be0af --- /dev/null +++ b/scm/driver/gitee/testdata/branches.json @@ -0,0 +1,11 @@ +[ + { + "name": "master", + "commit": { + "sha": "e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/e3c0ff4d5cef439ea11b30866fb1ed79b420801d" + }, + "protected": false, + "protection_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/branches/master/protection" + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/branches.json.golden b/scm/driver/gitee/testdata/branches.json.golden new file mode 100644 index 000000000..161b33c27 --- /dev/null +++ b/scm/driver/gitee/testdata/branches.json.golden @@ -0,0 +1,7 @@ +[ + { + "Name": "master", + "Path": "refs/heads/master", + "Sha": "e3c0ff4d5cef439ea11b30866fb1ed79b420801d" + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/changes.json b/scm/driver/gitee/testdata/changes.json new file mode 100644 index 000000000..73aa16994 --- /dev/null +++ b/scm/driver/gitee/testdata/changes.json @@ -0,0 +1,87 @@ +{ + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/7e84b6f94b8d4bfaa051910cc4ce16b73bcffd51", + "sha": "7e84b6f94b8d4bfaa051910cc4ce16b73bcffd51", + "html_url": "https://gitee.com/kit101/drone-yml-test/commit/7e84b6f94b8d4bfaa051910cc4ce16b73bcffd51", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/7e84b6f94b8d4bfaa051910cc4ce16b73bcffd51/comments", + "commit": { + "author": { + "name": "kit101", + "date": "2021-08-23T23:41:22+08:00", + "email": "qkssk1711@163.com" + }, + "committer": { + "name": "kit101", + "date": "2021-08-23T23:41:22+08:00", + "email": "qkssk1711@163.com" + }, + "message": "rename\n", + "tree": { + "sha": "3dd0fe5f5bcde3966871c8eb2c91d55554dab80f", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/git/trees/3dd0fe5f5bcde3966871c8eb2c91d55554dab80f" + } + }, + "author": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "committer": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "parents": [ + { + "sha": "f87d3cca9d85a7e52bb9dadac176817812b76fbd", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/f87d3cca9d85a7e52bb9dadac176817812b76fbd" + } + ], + "stats": { + "id": "7e84b6f94b8d4bfaa051910cc4ce16b73bcffd51", + "additions": 3, + "deletions": 3, + "total": 6 + }, + "files": [ + { + "sha": "b748919728ba7080c9e41e2b888872b09d246d90", + "filename": "rename.4.txt", + "status": "modified", + "additions": 0, + "deletions": 0, + "changes": 0, + "blob_url": "https://gitee.com/kit101/drone-yml-test/blob/7e84b6f94b8d4bfaa051910cc4ce16b73bcffd51/rename.4.txt", + "raw_url": "https://gitee.com/kit101/drone-yml-test/raw/7e84b6f94b8d4bfaa051910cc4ce16b73bcffd51/rename.4.txt", + "content_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contents/rename.4.txt?ref=7e84b6f94b8d4bfaa051910cc4ce16b73bcffd51", + "patch": "" + } + ] +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/changes.json.golden b/scm/driver/gitee/testdata/changes.json.golden new file mode 100644 index 000000000..859972e23 --- /dev/null +++ b/scm/driver/gitee/testdata/changes.json.golden @@ -0,0 +1,9 @@ +[ + { + "Path": "rename.4.txt", + "Added": false, + "Renamed": true, + "Deleted": false, + "BlobID": "b748919728ba7080c9e41e2b888872b09d246d90" + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/commit.json b/scm/driver/gitee/testdata/commit.json new file mode 100644 index 000000000..c40d2ee30 --- /dev/null +++ b/scm/driver/gitee/testdata/commit.json @@ -0,0 +1,123 @@ +{ + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "sha": "e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "html_url": "https://gitee.com/kit101/drone-yml-test/commit/e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/e3c0ff4d5cef439ea11b30866fb1ed79b420801d/comments", + "commit": { + "author": { + "name": "kit101", + "date": "2021-08-23T23:45:53+08:00", + "email": "qkssk1711@163.com" + }, + "committer": { + "name": "kit101", + "date": "2021-08-23T23:45:53+08:00", + "email": "qkssk1711@163.com" + }, + "message": "add/update/delete/rename\n", + "tree": { + "sha": "55d4c682f3e2b276cc40c70e59cebb17dcb1273a", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/git/trees/55d4c682f3e2b276cc40c70e59cebb17dcb1273a" + } + }, + "author": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "committer": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "parents": [ + { + "sha": "537575f44a09c57dfc472e26fe067754fd2f9374", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/537575f44a09c57dfc472e26fe067754fd2f9374" + } + ], + "stats": { + "id": "e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "additions": 4, + "deletions": 3, + "total": 7 + }, + "files": [ + { + "sha": "d28d40b18823a27071d0e9ce89c149adb3f9c4ee", + "filename": "change/add.txt", + "status": "added", + "additions": 1, + "deletions": 0, + "changes": 1, + "blob_url": "https://gitee.com/kit101/drone-yml-test/blob/e3c0ff4d5cef439ea11b30866fb1ed79b420801d/change/add.txt", + "raw_url": "https://gitee.com/kit101/drone-yml-test/raw/e3c0ff4d5cef439ea11b30866fb1ed79b420801d/change/add.txt", + "content_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contents/change/add.txt?ref=e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "patch": "@@ -0,0 +1 @@\n+add\n\\ No newline at end of file\n" + }, + { + "sha": "41f6d1ab2598013cc08173771d81f67106bd15fc", + "filename": "change/modified.txt", + "status": "modified", + "additions": 2, + "deletions": 1, + "changes": 3, + "blob_url": "https://gitee.com/kit101/drone-yml-test/blob/e3c0ff4d5cef439ea11b30866fb1ed79b420801d/change/modified.txt", + "raw_url": "https://gitee.com/kit101/drone-yml-test/raw/e3c0ff4d5cef439ea11b30866fb1ed79b420801d/change/modified.txt", + "content_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contents/change/modified.txt?ref=e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "patch": "@@ -1 +1,2 @@\n-will be modified\n\\ No newline at end of file\n+will be modified\n+modified\n\\ No newline at end of file\n" + }, + { + "sha": "026c61940bebac2bd51a709af499db11a62b9beb", + "filename": "change/remove.txt", + "status": "removed", + "additions": 0, + "deletions": 1, + "changes": 1, + "blob_url": "https://gitee.com/kit101/drone-yml-test/blob/537575f44a09c57dfc472e26fe067754fd2f9374/change/remove.txt", + "raw_url": "https://gitee.com/kit101/drone-yml-test/raw/537575f44a09c57dfc472e26fe067754fd2f9374/change/remove.txt", + "content_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contents/change/remove.txt?ref=537575f44a09c57dfc472e26fe067754fd2f9374", + "patch": "@@ -1 +0,0 @@\n-will be removed\n\\ No newline at end of file\n" + }, + { + "sha": "b5442782c85d797e70d7bcd14abab49fd8c40b5b", + "filename": "change/rename.1.txt", + "status": "modified", + "additions": 0, + "deletions": 0, + "changes": 0, + "blob_url": "https://gitee.com/kit101/drone-yml-test/blob/e3c0ff4d5cef439ea11b30866fb1ed79b420801d/change/rename.1.txt", + "raw_url": "https://gitee.com/kit101/drone-yml-test/raw/e3c0ff4d5cef439ea11b30866fb1ed79b420801d/change/rename.1.txt", + "content_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contents/change/rename.1.txt?ref=e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "patch": "" + } + ] +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/commit.json.golden b/scm/driver/gitee/testdata/commit.json.golden new file mode 100644 index 000000000..4ee12ddcb --- /dev/null +++ b/scm/driver/gitee/testdata/commit.json.golden @@ -0,0 +1,19 @@ +{ + "Sha": "e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "Message": "add/update/delete/rename\n", + "Author": { + "Name": "kit101", + "Date": "2021-08-23T23:45:53+08:00", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Committer": { + "Name": "kit101", + "Date": "2021-08-23T23:45:53+08:00", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Link": "https://gitee.com/kit101/drone-yml-test/commit/e3c0ff4d5cef439ea11b30866fb1ed79b420801d" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/commits.json b/scm/driver/gitee/testdata/commits.json new file mode 100644 index 000000000..a4cb29163 --- /dev/null +++ b/scm/driver/gitee/testdata/commits.json @@ -0,0 +1,203 @@ +[ + { + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "sha": "e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "html_url": "https://gitee.com/kit101/drone-yml-test/commit/e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/e3c0ff4d5cef439ea11b30866fb1ed79b420801d/comments", + "commit": { + "author": { + "name": "kit101", + "date": "2021-08-23T23:45:53+08:00", + "email": "qkssk1711@163.com" + }, + "committer": { + "name": "kit101", + "date": "2021-08-23T23:45:53+08:00", + "email": "qkssk1711@163.com" + }, + "message": "add/update/delete/rename\n", + "tree": { + "sha": "55d4c682f3e2b276cc40c70e59cebb17dcb1273a", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/git/trees/55d4c682f3e2b276cc40c70e59cebb17dcb1273a" + } + }, + "author": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "committer": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "parents": [ + { + "sha": "537575f44a09c57dfc472e26fe067754fd2f9374", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/537575f44a09c57dfc472e26fe067754fd2f9374" + } + ] + }, + { + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/537575f44a09c57dfc472e26fe067754fd2f9374", + "sha": "537575f44a09c57dfc472e26fe067754fd2f9374", + "html_url": "https://gitee.com/kit101/drone-yml-test/commit/537575f44a09c57dfc472e26fe067754fd2f9374", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/537575f44a09c57dfc472e26fe067754fd2f9374/comments", + "commit": { + "author": { + "name": "kit101", + "date": "2021-08-23T23:45:04+08:00", + "email": "qkssk1711@163.com" + }, + "committer": { + "name": "kit101", + "date": "2021-08-23T23:45:04+08:00", + "email": "qkssk1711@163.com" + }, + "message": "change ready\n", + "tree": { + "sha": "c5851e358f5c1950ce15772b0cf05941470793bc", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/git/trees/c5851e358f5c1950ce15772b0cf05941470793bc" + } + }, + "author": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "committer": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "parents": [ + { + "sha": "7e84b6f94b8d4bfaa051910cc4ce16b73bcffd51", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/7e84b6f94b8d4bfaa051910cc4ce16b73bcffd51" + } + ] + }, + { + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/7e84b6f94b8d4bfaa051910cc4ce16b73bcffd51", + "sha": "7e84b6f94b8d4bfaa051910cc4ce16b73bcffd51", + "html_url": "https://gitee.com/kit101/drone-yml-test/commit/7e84b6f94b8d4bfaa051910cc4ce16b73bcffd51", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/7e84b6f94b8d4bfaa051910cc4ce16b73bcffd51/comments", + "commit": { + "author": { + "name": "kit101", + "date": "2021-08-23T23:41:22+08:00", + "email": "qkssk1711@163.com" + }, + "committer": { + "name": "kit101", + "date": "2021-08-23T23:41:22+08:00", + "email": "qkssk1711@163.com" + }, + "message": "rename\n", + "tree": { + "sha": "3dd0fe5f5bcde3966871c8eb2c91d55554dab80f", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/git/trees/3dd0fe5f5bcde3966871c8eb2c91d55554dab80f" + } + }, + "author": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "committer": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "parents": [ + { + "sha": "f87d3cca9d85a7e52bb9dadac176817812b76fbd", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/f87d3cca9d85a7e52bb9dadac176817812b76fbd" + } + ] + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/commits.json.golden b/scm/driver/gitee/testdata/commits.json.golden new file mode 100644 index 000000000..91c30b1f4 --- /dev/null +++ b/scm/driver/gitee/testdata/commits.json.golden @@ -0,0 +1,59 @@ +[ + { + "Sha": "e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "Message": "add/update/delete/rename\n", + "Author": { + "Name": "kit101", + "Email": "qkssk1711@163.com", + "Date": "2021-08-23T23:45:53+08:00", + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Committer": { + "Name": "kit101", + "Email": "qkssk1711@163.com", + "Date": "2021-08-23T23:45:53+08:00", + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Link": "https://gitee.com/kit101/drone-yml-test/commit/e3c0ff4d5cef439ea11b30866fb1ed79b420801d" + }, + { + "Sha": "537575f44a09c57dfc472e26fe067754fd2f9374", + "Message": "change ready\n", + "Author": { + "Name": "kit101", + "Email": "qkssk1711@163.com", + "Date": "2021-08-23T23:45:04+08:00", + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Committer": { + "Name": "kit101", + "Email": "qkssk1711@163.com", + "Date": "2021-08-23T23:45:04+08:00", + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Link": "https://gitee.com/kit101/drone-yml-test/commit/537575f44a09c57dfc472e26fe067754fd2f9374" + }, + { + "Sha": "7e84b6f94b8d4bfaa051910cc4ce16b73bcffd51", + "Message": "rename\n", + "Author": { + "Name": "kit101", + "Email": "qkssk1711@163.com", + "Date": "2021-08-23T23:41:22+08:00", + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Committer": { + "Name": "kit101", + "Email": "qkssk1711@163.com", + "Date": "2021-08-23T23:41:22+08:00", + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Link": "https://gitee.com/kit101/drone-yml-test/commit/7e84b6f94b8d4bfaa051910cc4ce16b73bcffd51" + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/compare.json b/scm/driver/gitee/testdata/compare.json new file mode 100644 index 000000000..24451e9c3 --- /dev/null +++ b/scm/driver/gitee/testdata/compare.json @@ -0,0 +1,201 @@ +{ + "base_commit": { + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "sha": "e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "html_url": "https://gitee.com/kit101/drone-yml-test/commit/e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/e3c0ff4d5cef439ea11b30866fb1ed79b420801d/comments", + "commit": { + "author": { + "name": "kit101", + "date": "2021-08-23T23:45:53+08:00", + "email": "qkssk1711@163.com" + }, + "committer": { + "name": "kit101", + "date": "2021-08-23T23:45:53+08:00", + "email": "qkssk1711@163.com" + }, + "message": "add/update/delete/rename\n", + "tree": { + "sha": "55d4c682f3e2b276cc40c70e59cebb17dcb1273a", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/git/trees/55d4c682f3e2b276cc40c70e59cebb17dcb1273a" + } + }, + "author": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "committer": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "parents": [ + { + "sha": "537575f44a09c57dfc472e26fe067754fd2f9374", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/537575f44a09c57dfc472e26fe067754fd2f9374" + } + ] + }, + "merge_base_commit": { + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "sha": "e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "html_url": "https://gitee.com/kit101/drone-yml-test/commit/e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/e3c0ff4d5cef439ea11b30866fb1ed79b420801d/comments", + "commit": { + "author": { + "name": "kit101", + "date": "2021-08-23T23:45:53+08:00", + "email": "qkssk1711@163.com" + }, + "committer": { + "name": "kit101", + "date": "2021-08-23T23:45:53+08:00", + "email": "qkssk1711@163.com" + }, + "message": "add/update/delete/rename\n", + "tree": { + "sha": "55d4c682f3e2b276cc40c70e59cebb17dcb1273a", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/git/trees/55d4c682f3e2b276cc40c70e59cebb17dcb1273a" + } + }, + "author": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "committer": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "parents": [ + { + "sha": "537575f44a09c57dfc472e26fe067754fd2f9374", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/537575f44a09c57dfc472e26fe067754fd2f9374" + } + ] + }, + "commits": [ + { + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/2700445cd84c08546f4d003f8aa54d2099a006b7", + "sha": "2700445cd84c08546f4d003f8aa54d2099a006b7", + "html_url": "https://gitee.com/kit101/drone-yml-test/commit/2700445cd84c08546f4d003f8aa54d2099a006b7", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/2700445cd84c08546f4d003f8aa54d2099a006b7/comments", + "commit": { + "author": { + "name": "kit101", + "date": "2021-09-28T16:45:33+00:00", + "email": "qkssk1711@163.com" + }, + "committer": { + "name": "Gitee", + "date": "2021-09-28T16:45:33+00:00", + "email": "noreply@gitee.com" + }, + "message": "add feat-compare.txt.\n", + "tree": { + "sha": "3743833f1906b6343c0e373e9d5c5c02bb793f4d", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/git/trees/3743833f1906b6343c0e373e9d5c5c02bb793f4d" + } + }, + "author": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "committer": null, + "parents": [ + { + "sha": "e3c0ff4d5cef439ea11b30866fb1ed79b420801d", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/e3c0ff4d5cef439ea11b30866fb1ed79b420801d" + } + ] + } + ], + "files": [ + { + "sha": "b3a3b1dc93cb4323ef918aa742227356e91ddf1e", + "filename": "feat-compare.txt", + "status": "added", + "additions": 1, + "deletions": 0, + "changes": 1, + "blob_url": "https://gitee.com/kit101/drone-yml-test/blob/2700445cd84c08546f4d003f8aa54d2099a006b7/feat-compare.txt", + "raw_url": "https://gitee.com/kit101/drone-yml-test/raw/2700445cd84c08546f4d003f8aa54d2099a006b7/feat-compare.txt", + "content_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contents/feat-compare.txt?ref=2700445cd84c08546f4d003f8aa54d2099a006b7", + "patch": "@@ -0,0 +1 @@\n+feat-compare\n\\ No newline at end of file\n" + } + ] +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/compare.json.golden b/scm/driver/gitee/testdata/compare.json.golden new file mode 100644 index 000000000..06be5bbcd --- /dev/null +++ b/scm/driver/gitee/testdata/compare.json.golden @@ -0,0 +1,9 @@ +[ + { + "Path": "feat-compare.txt", + "Added": true, + "Renamed": false, + "Deleted": false, + "BlobID": "b3a3b1dc93cb4323ef918aa742227356e91ddf1e" + } +] diff --git a/scm/driver/gitee/testdata/content.json b/scm/driver/gitee/testdata/content.json new file mode 100644 index 000000000..1f9136c8a --- /dev/null +++ b/scm/driver/gitee/testdata/content.json @@ -0,0 +1,16 @@ +{ + "type": "file", + "encoding": "base64", + "size": 22, + "name": "README.md", + "path": "README.md", + "content": "IyBkcm9uZS15bWwtdGVzdAoKdGVzdA==", + "sha": "1563ebda9da15e6a7753431774920c62b168e5bb", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contents/README.md", + "html_url": "https://gitee.com/kit101/drone-yml-test/blob/d295a4c616d46fbcdfa3dfd1473c1337a1ec6f83/README.md", + "download_url": "https://gitee.com/kit101/drone-yml-test/raw/d295a4c616d46fbcdfa3dfd1473c1337a1ec6f83/README.md", + "_links": { + "self": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contents/README.md", + "html": "https://gitee.com/kit101/drone-yml-test/blob/d295a4c616d46fbcdfa3dfd1473c1337a1ec6f83/README.md" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/content.json.golden b/scm/driver/gitee/testdata/content.json.golden new file mode 100644 index 000000000..8f970cd12 --- /dev/null +++ b/scm/driver/gitee/testdata/content.json.golden @@ -0,0 +1,5 @@ +{ + "Path": "README.md", + "Data": "IyBkcm9uZS15bWwtdGVzdAoKdGVzdA==", + "Sha": "1563ebda9da15e6a7753431774920c62b168e5bb" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/content_create.json b/scm/driver/gitee/testdata/content_create.json new file mode 100644 index 000000000..fe60e5d3b --- /dev/null +++ b/scm/driver/gitee/testdata/content_create.json @@ -0,0 +1,40 @@ +{ + "content": { + "name": "CreateByDroneGiteeProvider.md", + "path": "apitest/CreateByDroneGiteeProvider.md", + "size": 56, + "sha": "9de0cf94e1e3c1cbe0a25c3865de4cc9ede7ad3e", + "type": "file", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contents/apitest/CreateByDroneGiteeProvider.md", + "html_url": "https://gitee.com/kit101/drone-yml-test/blob/master/apitest/CreateByDroneGiteeProvider.md", + "download_url": "https://gitee.com/kit101/drone-yml-test/raw/master/apitest/CreateByDroneGiteeProvider.md", + "_links": { + "self": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contents/apitest/CreateByDroneGiteeProvider.md", + "html": "https://gitee.com/kit101/drone-yml-test/blob/master/apitest/CreateByDroneGiteeProvider.md" + } + }, + "commit": { + "sha": "261b772064f5aed55d626799417ec31b1c48080b", + "author": { + "name": "kit101", + "date": "2021-08-17T15:16:26+00:00", + "email": "kit101@gitee.com" + }, + "committer": { + "name": "Gitee", + "date": "2021-08-17T15:16:26+00:00", + "email": "noreply@gitee.com" + }, + "message": "my commit message", + "tree": { + "sha": "3830427494001c27ed6a9711a823a4fc6af836af", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/git/trees/3830427494001c27ed6a9711a823a4fc6af836af" + }, + "parents": [ + { + "sha": "d295a4c616d46fbcdfa3dfd1473c1337a1ec6f83", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/d295a4c616d46fbcdfa3dfd1473c1337a1ec6f83" + } + ] + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/content_delete.json b/scm/driver/gitee/testdata/content_delete.json new file mode 100644 index 000000000..3cfd6c802 --- /dev/null +++ b/scm/driver/gitee/testdata/content_delete.json @@ -0,0 +1,27 @@ +{ + "content": null, + "commit": { + "sha": "bdce92fc3e96f54d7e918c7f2b6e61053366da5e", + "author": { + "name": "kit101", + "date": "2021-08-17T15:49:36+00:00", + "email": "kit101@gitee.com" + }, + "committer": { + "name": "Gitee", + "date": "2021-08-17T15:49:36+00:00", + "email": "noreply@gitee.com" + }, + "message": "delete commit message", + "tree": { + "sha": "4de6efba7063724cb20ab9135be309db0477c186", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/git/trees/4de6efba7063724cb20ab9135be309db0477c186" + }, + "parents": [ + { + "sha": "56b7c68eea99df8469f819fca08ca71c2d942d8d", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/56b7c68eea99df8469f819fca08ca71c2d942d8d" + } + ] + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/content_list.json b/scm/driver/gitee/testdata/content_list.json new file mode 100644 index 000000000..64274caaf --- /dev/null +++ b/scm/driver/gitee/testdata/content_list.json @@ -0,0 +1,44 @@ +[ + { + "type": "file", + "size": null, + "name": "CreateByDroneGiteeProvider.md", + "path": "apitest/CreateByDroneGiteeProvider.md", + "sha": "9de0cf94e1e3c1cbe0a25c3865de4cc9ede7ad3e", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contents/apitest/CreateByDroneGiteeProvider.md", + "html_url": "https://gitee.com/kit101/drone-yml-test/blob/master/apitest/CreateByDroneGiteeProvider.md", + "download_url": "https://gitee.com/kit101/drone-yml-test/raw/master/apitest/CreateByDroneGiteeProvider.md", + "_links": { + "self": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contents/apitest/CreateByDroneGiteeProvider.md", + "html": "https://gitee.com/kit101/drone-yml-test/blob/master/apitest/CreateByDroneGiteeProvider.md" + } + }, + { + "type": "file", + "size": null, + "name": "UpdateByDroneGiteeProvider.md", + "path": "apitest/UpdateByDroneGiteeProvider.md", + "sha": "480a4b3865989bfa78d8f249b124716dda1581d7", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contents/apitest/UpdateByDroneGiteeProvider.md", + "html_url": "https://gitee.com/kit101/drone-yml-test/blob/master/apitest/UpdateByDroneGiteeProvider.md", + "download_url": "https://gitee.com/kit101/drone-yml-test/raw/master/apitest/UpdateByDroneGiteeProvider.md", + "_links": { + "self": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contents/apitest/UpdateByDroneGiteeProvider.md", + "html": "https://gitee.com/kit101/drone-yml-test/blob/master/apitest/UpdateByDroneGiteeProvider.md" + } + }, + { + "type": "dir", + "size": null, + "name": "newdir", + "path": "apitest/newdir", + "sha": "2f5fb87ae0d8b8a5f78b4dbfefc1fd70b356bdc4", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contents/apitest/newdir", + "html_url": "https://gitee.com/kit101/drone-yml-test/blob/master/apitest/newdir", + "download_url": "https://gitee.com/kit101/drone-yml-test/raw/master/apitest/newdir", + "_links": { + "self": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contents/apitest/newdir", + "html": "https://gitee.com/kit101/drone-yml-test/blob/master/apitest/newdir" + } + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/content_list.json.golden b/scm/driver/gitee/testdata/content_list.json.golden new file mode 100644 index 000000000..7fcd66370 --- /dev/null +++ b/scm/driver/gitee/testdata/content_list.json.golden @@ -0,0 +1,14 @@ +[ + { + "kind": "file", + "path": "apitest/CreateByDroneGiteeProvider.md" + }, + { + "kind": "file", + "path": "apitest/UpdateByDroneGiteeProvider.md" + }, + { + "kind": "directory", + "path": "apitest/newdir" + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/content_update.json b/scm/driver/gitee/testdata/content_update.json new file mode 100644 index 000000000..9ddbbd6ed --- /dev/null +++ b/scm/driver/gitee/testdata/content_update.json @@ -0,0 +1,40 @@ +{ + "content": { + "name": "UpdateByDroneGiteeProvider.md", + "path": "apitest/UpdateByDroneGiteeProvider.md", + "size": 56, + "sha": "480a4b3865989bfa78d8f249b124716dda1581d7", + "type": "file", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contents/apitest/UpdateByDroneGiteeProvider.md", + "html_url": "https://gitee.com/kit101/drone-yml-test/blob/master/apitest/UpdateByDroneGiteeProvider.md", + "download_url": "https://gitee.com/kit101/drone-yml-test/raw/master/apitest/UpdateByDroneGiteeProvider.md", + "_links": { + "self": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contents/apitest/UpdateByDroneGiteeProvider.md", + "html": "https://gitee.com/kit101/drone-yml-test/blob/master/apitest/UpdateByDroneGiteeProvider.md" + } + }, + "commit": { + "sha": "b280133ab20a219027584bd69671230503c916de", + "author": { + "name": "kit101", + "date": "2021-08-17T15:33:48+00:00", + "email": "kit101@gitee.com" + }, + "committer": { + "name": "Gitee", + "date": "2021-08-17T15:33:48+00:00", + "email": "noreply@gitee.com" + }, + "message": "my commit message by update", + "tree": { + "sha": "4de6efba7063724cb20ab9135be309db0477c186", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/git/trees/4de6efba7063724cb20ab9135be309db0477c186" + }, + "parents": [ + { + "sha": "f24c34e8d884b294c9f197460fc0840d9582220b", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/f24c34e8d884b294c9f197460fc0840d9582220b" + } + ] + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/error.json b/scm/driver/gitee/testdata/error.json new file mode 100644 index 000000000..74392666a --- /dev/null +++ b/scm/driver/gitee/testdata/error.json @@ -0,0 +1,3 @@ +{ + "message": "404 Project Not Found" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/hook.json b/scm/driver/gitee/testdata/hook.json new file mode 100644 index 000000000..b5c6184ac --- /dev/null +++ b/scm/driver/gitee/testdata/hook.json @@ -0,0 +1,14 @@ +{ + "id": 787341, + "url": "http://test.kit101.com/webhook", + "created_at": "2021-10-07T10:27:26+08:00", + "password": "123asdas123", + "project_id": 14836026, + "result": "\u003Chtml\u003E \u003Chead\u003E\u003Ctitle\u003E403 Forbidden\u003C/title\u003E\u003C/head\u003E \u003Cbody\u003E \u003Ccenter\u003E\u003Ch1\u003E403 Forbidden\u003C/h1\u003E\u003C/center\u003E \u003C/body\u003E \u003C/html\u003E", + "result_code": 403, + "push_events": true, + "tag_push_events": true, + "issues_events": true, + "note_events": true, + "merge_requests_events": true +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/hook.json.golden b/scm/driver/gitee/testdata/hook.json.golden new file mode 100644 index 000000000..0deb616ec --- /dev/null +++ b/scm/driver/gitee/testdata/hook.json.golden @@ -0,0 +1,14 @@ +{ + "ID": "787341", + "Name": "", + "Target": "http://test.kit101.com/webhook", + "Events": [ + "push", + "tag_push", + "issues", + "note", + "merge_requests" + ], + "Active": true, + "SkipVerify": true +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/hooks.json b/scm/driver/gitee/testdata/hooks.json new file mode 100644 index 000000000..cd8fa4164 --- /dev/null +++ b/scm/driver/gitee/testdata/hooks.json @@ -0,0 +1,16 @@ +[ + { + "id": 787341, + "url": "http://test.kit101.com/webhook", + "created_at": "2021-10-07T10:27:26+08:00", + "password": "123asdas123", + "project_id": 14836026, + "result": "\u003Chtml\u003E \u003Chead\u003E\u003Ctitle\u003E403 Forbidden\u003C/title\u003E\u003C/head\u003E \u003Cbody\u003E \u003Ccenter\u003E\u003Ch1\u003E403 Forbidden\u003C/h1\u003E\u003C/center\u003E \u003C/body\u003E \u003C/html\u003E", + "result_code": 403, + "push_events": true, + "tag_push_events": true, + "issues_events": true, + "note_events": true, + "merge_requests_events": true + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/hooks.json.golden b/scm/driver/gitee/testdata/hooks.json.golden new file mode 100644 index 000000000..ce6a0d17c --- /dev/null +++ b/scm/driver/gitee/testdata/hooks.json.golden @@ -0,0 +1,16 @@ +[ + { + "ID": "787341", + "Name": "", + "Target": "http://test.kit101.com/webhook", + "Events": [ + "push", + "tag_push", + "issues", + "note", + "merge_requests" + ], + "Active": true, + "SkipVerify": true + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/issue.json b/scm/driver/gitee/testdata/issue.json new file mode 100644 index 000000000..a93370864 --- /dev/null +++ b/scm/driver/gitee/testdata/issue.json @@ -0,0 +1,235 @@ +{ + "id": 7295389, + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/issues/I4CD5P", + "repository_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test", + "labels_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/issues/I4CD5P/labels", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/issues/I4CD5P/comments", + "html_url": "https://gitee.com/kit101/drone-yml-test/issues/I4CD5P", + "parent_url": null, + "number": "I4CD5P", + "parent_id": 0, + "depth": 0, + "state": "open", + "title": "test issue 1", + "body": "test issue 1", + "user": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "labels": [ + { + "id": 102145592, + "name": "feature", + "color": "B5CC18", + "repository_id": 14836026, + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/labels/feature", + "created_at": "2021-03-24T11:24:34+08:00", + "updated_at": "2021-09-29T09:55:42+08:00" + } + ], + "assignee": null, + "collaborators": [ + ], + "repository": { + "id": 14836026, + "full_name": "kit101/drone-yml-test", + "human_name": "kit101/drone-yml-test", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test", + "namespace": { + "id": 1576684, + "type": "personal", + "name": "kit101", + "path": "kit101", + "html_url": "https://gitee.com/kit101" + }, + "path": "drone-yml-test", + "name": "drone-yml-test", + "owner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "assigner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "description": "", + "private": false, + "public": true, + "internal": false, + "fork": false, + "html_url": "https://gitee.com/kit101/drone-yml-test.git", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "forks_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/forks", + "keys_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/keys{/key_id}", + "collaborators_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/collaborators{/collaborator}", + "hooks_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/hooks", + "branches_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/branches{/branch}", + "tags_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/tags", + "blobs_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/blobs{/sha}", + "stargazers_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/stargazers", + "contributors_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contributors", + "commits_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits{/sha}", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/comments{/number}", + "issue_comment_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/issues/comments{/number}", + "issues_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/issues{/number}", + "pulls_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls{/number}", + "milestones_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/milestones{/number}", + "notifications_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/notifications{?since,all,participating}", + "labels_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/labels{/name}", + "releases_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/releases{/id}", + "recommend": false, + "gvp": false, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "language": null, + "forks_count": 0, + "stargazers_count": 0, + "watchers_count": 1, + "default_branch": "master", + "open_issues_count": 1, + "has_issues": true, + "has_wiki": true, + "issue_comment": false, + "can_comment": true, + "pull_requests_enabled": true, + "has_page": false, + "license": null, + "outsourced": false, + "project_creator": "kit101", + "members": [ + "kit101" + ], + "pushed_at": "2021-09-29T00:46:59+08:00", + "created_at": "2021-03-24T11:24:34+08:00", + "updated_at": "2021-09-29T09:21:28+08:00", + "parent": null, + "paas": null, + "assignees_number": 1, + "testers_number": 1, + "assignee": [ + { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + } + ], + "testers": [ + { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + } + ], + "status": "开始", + "empty_repo": false, + "programs": [ + ], + "enterprise": null + }, + "milestone": null, + "created_at": "2021-09-29T09:21:28+08:00", + "updated_at": "2021-09-29T09:55:42+08:00", + "plan_started_at": null, + "deadline": null, + "finished_at": null, + "scheduled_time": 0.0, + "comments": 0, + "priority": 0, + "issue_type": "任务", + "program": null, + "security_hole": false, + "issue_state": "待办的", + "branch": null, + "issue_type_detail": { + "id": 1, + "title": "任务", + "template": null, + "ident": "task", + "color": "#0086D6", + "is_system": true, + "created_at": "2017-09-01T03:09:12+08:00", + "updated_at": "2017-09-01T03:09:12+08:00" + }, + "issue_state_detail": { + "id": 1, + "title": "待办的", + "color": "#8c92a4", + "icon": "icon-task-state-21", + "command": null, + "serial": 1, + "created_at": "2017-09-01T03:09:13+08:00", + "updated_at": "2017-09-01T03:09:13+08:00" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/issue.json.golden b/scm/driver/gitee/testdata/issue.json.golden new file mode 100644 index 000000000..6075529d9 --- /dev/null +++ b/scm/driver/gitee/testdata/issue.json.golden @@ -0,0 +1,16 @@ +{ + "Number": 735267685380, + "Title": "test issue 1", + "Body": "test issue 1", + "Link": "https://gitee.com/kit101/drone-yml-test/issues/I4CD5P", + "Labels": [ + "feature" + ], + "Closed": false, + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Created": "2021-09-29T09:21:28+08:00", + "Updated": "2021-09-29T09:55:42+08:00" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/issue_comment.json b/scm/driver/gitee/testdata/issue_comment.json new file mode 100644 index 000000000..09e3a289a --- /dev/null +++ b/scm/driver/gitee/testdata/issue_comment.json @@ -0,0 +1,34 @@ +{ + "id": 6877445, + "body": "it's ok.", + "user": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "source": null, + "target": { + "issue": { + "id": 7295389, + "title": "test issue 1", + "number": "I4CD5P" + }, + "pull_request": null + }, + "created_at": "2021-09-29T11:00:50+08:00", + "updated_at": "2021-09-29T11:00:50+08:00" +} diff --git a/scm/driver/gitee/testdata/issue_comment.json.golden b/scm/driver/gitee/testdata/issue_comment.json.golden new file mode 100644 index 000000000..283c558a7 --- /dev/null +++ b/scm/driver/gitee/testdata/issue_comment.json.golden @@ -0,0 +1,10 @@ +{ + "ID": 6877445, + "Body": "it's ok.", + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Created": "2021-09-29T11:00:50+08:00", + "Updated": "2021-09-29T11:00:50+08:00" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/issue_comments.json b/scm/driver/gitee/testdata/issue_comments.json new file mode 100644 index 000000000..c310a4348 --- /dev/null +++ b/scm/driver/gitee/testdata/issue_comments.json @@ -0,0 +1,36 @@ +[ + { + "id": 6877445, + "body": "it's ok.", + "user": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "source": null, + "target": { + "issue": { + "id": 7295389, + "title": "test issue 1", + "number": "I4CD5P" + }, + "pull_request": null + }, + "created_at": "2021-09-29T11:00:50+08:00", + "updated_at": "2021-09-29T11:00:50+08:00" + } +] diff --git a/scm/driver/gitee/testdata/issue_comments.json.golden b/scm/driver/gitee/testdata/issue_comments.json.golden new file mode 100644 index 000000000..ea7200e52 --- /dev/null +++ b/scm/driver/gitee/testdata/issue_comments.json.golden @@ -0,0 +1,12 @@ +[ + { + "ID": 6877445, + "Body": "it's ok.", + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Created": "2021-09-29T11:00:50+08:00", + "Updated": "2021-09-29T11:00:50+08:00" + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/issues.json b/scm/driver/gitee/testdata/issues.json new file mode 100644 index 000000000..ca238cbb4 --- /dev/null +++ b/scm/driver/gitee/testdata/issues.json @@ -0,0 +1,468 @@ +[ + { + "id": 7296764, + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/issues/I4CE7W", + "repository_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test", + "labels_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/issues/I4CE7W/labels", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/issues/I4CE7W/comments", + "html_url": "https://gitee.com/kit101/drone-yml-test/issues/I4CE7W", + "parent_url": null, + "number": "I4CE7W", + "parent_id": 0, + "depth": 0, + "state": "closed", + "title": "close issue test", + "body": "close issue test", + "user": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "labels": [ + { + "id": 102145594, + "name": "invalid", + "color": "1B1C1D", + "repository_id": 14836026, + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/labels/invalid", + "created_at": "2021-03-24T11:24:34+08:00", + "updated_at": "2021-09-29T11:05:30+08:00" + } + ], + "assignee": null, + "collaborators": [], + "repository": { + "id": 14836026, + "full_name": "kit101/drone-yml-test", + "human_name": "kit101/drone-yml-test", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test", + "namespace": { + "id": 1576684, + "type": "personal", + "name": "kit101", + "path": "kit101", + "html_url": "https://gitee.com/kit101" + }, + "path": "drone-yml-test", + "name": "drone-yml-test", + "owner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "assigner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "description": "", + "private": false, + "public": true, + "internal": false, + "fork": false, + "html_url": "https://gitee.com/kit101/drone-yml-test.git", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "forks_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/forks", + "keys_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/keys{/key_id}", + "collaborators_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/collaborators{/collaborator}", + "hooks_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/hooks", + "branches_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/branches{/branch}", + "tags_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/tags", + "blobs_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/blobs{/sha}", + "stargazers_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/stargazers", + "contributors_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contributors", + "commits_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits{/sha}", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/comments{/number}", + "issue_comment_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/issues/comments{/number}", + "issues_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/issues{/number}", + "pulls_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls{/number}", + "milestones_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/milestones{/number}", + "notifications_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/notifications{?since,all,participating}", + "labels_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/labels{/name}", + "releases_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/releases{/id}", + "recommend": false, + "gvp": false, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "language": null, + "forks_count": 0, + "stargazers_count": 0, + "watchers_count": 1, + "default_branch": "master", + "open_issues_count": 1, + "has_issues": true, + "has_wiki": true, + "issue_comment": false, + "can_comment": true, + "pull_requests_enabled": true, + "has_page": false, + "license": null, + "outsourced": false, + "project_creator": "kit101", + "members": [ + "kit101" + ], + "pushed_at": "2021-09-29T00:46:59+08:00", + "created_at": "2021-03-24T11:24:34+08:00", + "updated_at": "2021-09-29T11:05:49+08:00", + "parent": null, + "paas": null, + "assignees_number": 1, + "testers_number": 1, + "assignee": [ + { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + } + ], + "testers": [ + { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + } + ], + "status": "开始", + "empty_repo": false, + "programs": [], + "enterprise": null + }, + "milestone": null, + "created_at": "2021-09-29T11:05:30+08:00", + "updated_at": "2021-09-29T11:05:49+08:00", + "plan_started_at": null, + "deadline": null, + "finished_at": "2021-09-29T11:05:49+08:00", + "scheduled_time": 0.0, + "comments": 0, + "priority": 0, + "issue_type": "任务", + "program": null, + "security_hole": false, + "issue_state": "已完成", + "branch": null, + "issue_type_detail": { + "id": 1, + "title": "任务", + "template": null, + "ident": "task", + "color": "#0086D6", + "is_system": true, + "created_at": "2017-09-01T03:09:12+08:00", + "updated_at": "2017-09-01T03:09:12+08:00" + }, + "issue_state_detail": { + "id": 3, + "title": "已完成", + "color": "#4baf50", + "icon": "icon-task-state-24", + "command": null, + "serial": 3, + "created_at": "2017-09-01T03:09:13+08:00", + "updated_at": "2017-09-01T03:09:13+08:00" + } + }, + { + "id": 7295389, + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/issues/I4CD5P", + "repository_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test", + "labels_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/issues/I4CD5P/labels", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/issues/I4CD5P/comments", + "html_url": "https://gitee.com/kit101/drone-yml-test/issues/I4CD5P", + "parent_url": null, + "number": "I4CD5P", + "parent_id": 0, + "depth": 0, + "state": "open", + "title": "test issue 1", + "body": "test issue 1", + "user": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "labels": [ + { + "id": 102145592, + "name": "feature", + "color": "B5CC18", + "repository_id": 14836026, + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/labels/feature", + "created_at": "2021-03-24T11:24:34+08:00", + "updated_at": "2021-09-29T09:55:42+08:00" + } + ], + "assignee": null, + "collaborators": [], + "repository": { + "id": 14836026, + "full_name": "kit101/drone-yml-test", + "human_name": "kit101/drone-yml-test", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test", + "namespace": { + "id": 1576684, + "type": "personal", + "name": "kit101", + "path": "kit101", + "html_url": "https://gitee.com/kit101" + }, + "path": "drone-yml-test", + "name": "drone-yml-test", + "owner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "assigner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "description": "", + "private": false, + "public": true, + "internal": false, + "fork": false, + "html_url": "https://gitee.com/kit101/drone-yml-test.git", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "forks_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/forks", + "keys_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/keys{/key_id}", + "collaborators_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/collaborators{/collaborator}", + "hooks_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/hooks", + "branches_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/branches{/branch}", + "tags_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/tags", + "blobs_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/blobs{/sha}", + "stargazers_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/stargazers", + "contributors_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contributors", + "commits_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits{/sha}", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/comments{/number}", + "issue_comment_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/issues/comments{/number}", + "issues_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/issues{/number}", + "pulls_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls{/number}", + "milestones_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/milestones{/number}", + "notifications_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/notifications{?since,all,participating}", + "labels_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/labels{/name}", + "releases_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/releases{/id}", + "recommend": false, + "gvp": false, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "language": null, + "forks_count": 0, + "stargazers_count": 0, + "watchers_count": 1, + "default_branch": "master", + "open_issues_count": 1, + "has_issues": true, + "has_wiki": true, + "issue_comment": false, + "can_comment": true, + "pull_requests_enabled": true, + "has_page": false, + "license": null, + "outsourced": false, + "project_creator": "kit101", + "members": [ + "kit101" + ], + "pushed_at": "2021-09-29T00:46:59+08:00", + "created_at": "2021-03-24T11:24:34+08:00", + "updated_at": "2021-09-29T11:05:49+08:00", + "parent": null, + "paas": null, + "assignees_number": 1, + "testers_number": 1, + "assignee": [ + { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + } + ], + "testers": [ + { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + } + ], + "status": "开始", + "empty_repo": false, + "programs": [], + "enterprise": null + }, + "milestone": null, + "created_at": "2021-09-29T09:21:28+08:00", + "updated_at": "2021-09-29T11:00:50+08:00", + "plan_started_at": null, + "deadline": null, + "finished_at": null, + "scheduled_time": 0.0, + "comments": 1, + "priority": 0, + "issue_type": "任务", + "program": null, + "security_hole": false, + "issue_state": "待办的", + "branch": null, + "issue_type_detail": { + "id": 1, + "title": "任务", + "template": null, + "ident": "task", + "color": "#0086D6", + "is_system": true, + "created_at": "2017-09-01T03:09:12+08:00", + "updated_at": "2017-09-01T03:09:12+08:00" + }, + "issue_state_detail": { + "id": 1, + "title": "待办的", + "color": "#8c92a4", + "icon": "icon-task-state-21", + "command": null, + "serial": 1, + "created_at": "2017-09-01T03:09:13+08:00", + "updated_at": "2017-09-01T03:09:13+08:00" + } + } +] diff --git a/scm/driver/gitee/testdata/issues.json.golden b/scm/driver/gitee/testdata/issues.json.golden new file mode 100644 index 000000000..b9daeccaf --- /dev/null +++ b/scm/driver/gitee/testdata/issues.json.golden @@ -0,0 +1,34 @@ +[ + { + "Number": 735267695587, + "Title": "close issue test", + "Body": "close issue test", + "Link": "https://gitee.com/kit101/drone-yml-test/issues/I4CE7W", + "Labels": [ + "invalid" + ], + "Closed": true, + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Created": "2021-09-29T11:05:30+08:00", + "Updated": "2021-09-29T11:05:49+08:00" + }, + { + "Number": 735267685380, + "Title": "test issue 1", + "Body": "test issue 1", + "Link": "https://gitee.com/kit101/drone-yml-test/issues/I4CD5P", + "Labels": [ + "feature" + ], + "Closed": false, + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Created": "2021-09-29T09:21:28+08:00", + "Updated": "2021-09-29T11:00:50+08:00" + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/membership.json b/scm/driver/gitee/testdata/membership.json new file mode 100644 index 000000000..e6edce7dd --- /dev/null +++ b/scm/driver/gitee/testdata/membership.json @@ -0,0 +1,28 @@ +{ + "url": "https://gitee.com/api/v5/orgs/kit101-personal/memberships/kit101", + "active": true, + "remark": null, + "role": "admin", + "organization_url": "https://gitee.com/api/v5/orgs/kit101-personal", + "organization": { + "id": 8538153, + "login": "kit101-personal", + "name": "kit101-personal", + "url": "https://gitee.com/api/v5/orgs/kit101-personal", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/namespace/2846/8538153_kit101-personal_1632964073.png?is_link=true", + "repos_url": "https://gitee.com/api/v5/orgs/kit101-personal/repos", + "events_url": "https://gitee.com/api/v5/orgs/kit101-personal/events", + "members_url": "https://gitee.com/api/v5/orgs/kit101-personal/members{/member}", + "description": "", + "follow_count": 1 + }, + "user": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/membership.json.golden b/scm/driver/gitee/testdata/membership.json.golden new file mode 100644 index 000000000..96ec5685e --- /dev/null +++ b/scm/driver/gitee/testdata/membership.json.golden @@ -0,0 +1,4 @@ +{ + "Active": true, + "Role": 2 +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/org.json b/scm/driver/gitee/testdata/org.json new file mode 100644 index 000000000..30389776c --- /dev/null +++ b/scm/driver/gitee/testdata/org.json @@ -0,0 +1,12 @@ +{ + "id": 8538153, + "login": "kit101-personal", + "name": "kit101-personal", + "url": "https://gitee.com/api/v5/orgs/kit101-personal", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/namespace/2846/8538153_kit101-personal_1632964073.png?is_link=true", + "repos_url": "https://gitee.com/api/v5/orgs/kit101-personal/repos", + "events_url": "https://gitee.com/api/v5/orgs/kit101-personal/events", + "members_url": "https://gitee.com/api/v5/orgs/kit101-personal/members{/member}", + "description": "", + "follow_count": 1 +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/org.json.golden b/scm/driver/gitee/testdata/org.json.golden new file mode 100644 index 000000000..0259356f0 --- /dev/null +++ b/scm/driver/gitee/testdata/org.json.golden @@ -0,0 +1,4 @@ +{ + "Name": "kit101-personal", + "Avatar": "https://portrait.gitee.com/uploads/avatars/namespace/2846/8538153_kit101-personal_1632964073.png?is_link=true" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/orgs.json b/scm/driver/gitee/testdata/orgs.json new file mode 100644 index 000000000..bd511847a --- /dev/null +++ b/scm/driver/gitee/testdata/orgs.json @@ -0,0 +1,15 @@ +[ + { + "id": 8538153, + "login": "kit101-personal", + "name": "kit101-personal", + "url": "https://gitee.com/api/v5/orgs/kit101-personal", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/namespace/2846/8538153_kit101-personal_1632964073.png?is_link=true", + "repos_url": "https://gitee.com/api/v5/orgs/kit101-personal/repos", + "events_url": "https://gitee.com/api/v5/orgs/kit101-personal/events", + "members_url": "https://gitee.com/api/v5/orgs/kit101-personal/members{/member}", + "description": "", + "follow_count": 1 + } +] + \ No newline at end of file diff --git a/scm/driver/gitee/testdata/orgs.json.golden b/scm/driver/gitee/testdata/orgs.json.golden new file mode 100644 index 000000000..c0816e83d --- /dev/null +++ b/scm/driver/gitee/testdata/orgs.json.golden @@ -0,0 +1,6 @@ +[ + { + "Name": "kit101-personal", + "Avatar": "https://portrait.gitee.com/uploads/avatars/namespace/2846/8538153_kit101-personal_1632964073.png?is_link=true" + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/pr.json b/scm/driver/gitee/testdata/pr.json new file mode 100644 index 000000000..1cadc54a3 --- /dev/null +++ b/scm/driver/gitee/testdata/pr.json @@ -0,0 +1,239 @@ +{ + "id": 4730187, + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/6", + "html_url": "https://gitee.com/kit101/drone-yml-test/pulls/6", + "diff_url": "https://gitee.com/kit101/drone-yml-test/pulls/6.diff", + "patch_url": "https://gitee.com/kit101/drone-yml-test/pulls/6.patch", + "issue_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/6/issues", + "commits_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/6/commits", + "review_comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/comments/{/number}", + "review_comment_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/comments", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/6/comments", + "number": 6, + "state": "open", + "title": "new-feature", + "body": "Please pull these awesome changes", + "assignees_number": 1, + "testers_number": 1, + "assignees": [], + "testers": [], + "milestone": null, + "labels": [], + "locked": false, + "created_at": "2021-09-30T16:38:19+08:00", + "updated_at": "2021-09-30T16:38:19+08:00", + "closed_at": null, + "merged_at": null, + "mergeable": true, + "can_merge_check": false, + "head": { + "label": "crud", + "ref": "crud", + "sha": "411db0d9e9072851383751c260dc1601840906e4", + "user": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "repo": { + "id": 14836026, + "full_name": "kit101/drone-yml-test", + "human_name": "kit101/drone-yml-test", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test", + "namespace": { + "id": 1576684, + "type": "personal", + "name": "kit101", + "path": "kit101", + "html_url": "https://gitee.com/kit101" + }, + "path": "drone-yml-test", + "name": "drone-yml-test", + "owner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "assigner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "description": "", + "private": false, + "public": true, + "internal": false, + "fork": false, + "html_url": "https://gitee.com/kit101/drone-yml-test.git", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git" + } + }, + "base": { + "label": "master", + "ref": "master", + "sha": "2eac1cac02c325058cf959725c45b0612d3e8177", + "user": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "repo": { + "id": 14836026, + "full_name": "kit101/drone-yml-test", + "human_name": "kit101/drone-yml-test", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test", + "namespace": { + "id": 1576684, + "type": "personal", + "name": "kit101", + "path": "kit101", + "html_url": "https://gitee.com/kit101" + }, + "path": "drone-yml-test", + "name": "drone-yml-test", + "owner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "assigner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "description": "", + "private": false, + "public": true, + "internal": false, + "fork": false, + "html_url": "https://gitee.com/kit101/drone-yml-test.git", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git" + } + }, + "_links": { + "self": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/6" + }, + "html": { + "href": "https://gitee.com/kit101/drone-yml-test/pulls/6" + }, + "issue": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/6/issues" + }, + "comments": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/6/comments" + }, + "review_comments": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/6/comments" + }, + "review_comment": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/comments/6" + }, + "commits": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/6/commits" + } + }, + "user": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/pr.json.golden b/scm/driver/gitee/testdata/pr.json.golden new file mode 100644 index 000000000..f5fc30fe1 --- /dev/null +++ b/scm/driver/gitee/testdata/pr.json.golden @@ -0,0 +1,30 @@ +{ + "Number": 6, + "Title": "new-feature", + "Body": "Please pull these awesome changes", + "Sha": "411db0d9e9072851383751c260dc1601840906e4", + "Ref": "refs/pull/6/head", + "Source": "crud", + "Target": "master", + "Fork": "kit101/drone-yml-test", + "Link": "https://gitee.com/kit101/drone-yml-test/pulls/6", + "Diff": "https://gitee.com/kit101/drone-yml-test/pulls/6.diff", + "Closed": false, + "Merged": false, + "Base": { + "Sha": "2eac1cac02c325058cf959725c45b0612d3e8177", + "Path": "refs/heads/master", + "Name": "master" + }, + "Head": { + "Sha": "411db0d9e9072851383751c260dc1601840906e4", + "Path": "refs/heads/crud", + "Name": "crud" + }, + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Created": "2021-09-30T16:38:19+08:00", + "Updated": "2021-09-30T16:38:19+08:00" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/pr_comment.json b/scm/driver/gitee/testdata/pr_comment.json new file mode 100644 index 000000000..ff5892789 --- /dev/null +++ b/scm/driver/gitee/testdata/pr_comment.json @@ -0,0 +1,44 @@ +{ + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/comments/6922557", + "id": 6922557, + "path": null, + "position": null, + "original_position": null, + "commit_id": null, + "original_commit_id": null, + "user": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "created_at": "2021-10-07T09:26:45+08:00", + "updated_at": "2021-10-07T09:26:45+08:00", + "body": "test comment 1", + "html_url": "https://gitee.com/kit101/drone-yml-test/pulls/7#note_6922557", + "pull_request_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/7", + "_links": { + "self": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/comments/6922557" + }, + "html": { + "href": "https://gitee.com/kit101/drone-yml-test/pulls/7#note_6922557" + }, + "pull_request": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/7" + } + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/pr_comment.json.golden b/scm/driver/gitee/testdata/pr_comment.json.golden new file mode 100644 index 000000000..636bc0e05 --- /dev/null +++ b/scm/driver/gitee/testdata/pr_comment.json.golden @@ -0,0 +1,11 @@ +{ + "ID": 6922557, + "Body": "test comment 1", + "Author": { + "Login": "kit101", + "Name": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Created": "2021-10-07T09:26:45+08:00", + "Updated": "2021-10-07T09:26:45+08:00" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/pr_comments.json b/scm/driver/gitee/testdata/pr_comments.json new file mode 100644 index 000000000..02652c4f7 --- /dev/null +++ b/scm/driver/gitee/testdata/pr_comments.json @@ -0,0 +1,46 @@ +[ + { + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/comments/6922557", + "id": 6922557, + "path": null, + "position": null, + "original_position": null, + "commit_id": null, + "original_commit_id": null, + "user": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "created_at": "2021-10-07T09:26:45+08:00", + "updated_at": "2021-10-07T09:26:45+08:00", + "body": "test comment 1", + "html_url": "https://gitee.com/kit101/drone-yml-test/pulls/7#note_6922557", + "pull_request_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/7", + "_links": { + "self": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/comments/6922557" + }, + "html": { + "href": "https://gitee.com/kit101/drone-yml-test/pulls/7#note_6922557" + }, + "pull_request": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/7" + } + } + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/pr_comments.json.golden b/scm/driver/gitee/testdata/pr_comments.json.golden new file mode 100644 index 000000000..93743f276 --- /dev/null +++ b/scm/driver/gitee/testdata/pr_comments.json.golden @@ -0,0 +1,13 @@ +[ + { + "ID": 6922557, + "Body": "test comment 1", + "Author": { + "Login": "kit101", + "Name": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Created": "2021-10-07T09:26:45+08:00", + "Updated": "2021-10-07T09:26:45+08:00" + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/pr_commits.json b/scm/driver/gitee/testdata/pr_commits.json new file mode 100644 index 000000000..9c82717fe --- /dev/null +++ b/scm/driver/gitee/testdata/pr_commits.json @@ -0,0 +1,65 @@ +[ + { + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/00b76e8abd51ae6a96318b3450944b32995f9158", + "sha": "00b76e8abd51ae6a96318b3450944b32995f9158", + "html_url": "https://gitee.com/kit101/drone-yml-test/commits/00b76e8abd51ae6a96318b3450944b32995f9158", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/00b76e8abd51ae6a96318b3450944b32995f9158/comments", + "commit": { + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/00b76e8abd51ae6a96318b3450944b32995f9158", + "author": { + "name": "kit101", + "email": "qkssk1711@163.com", + "date": "2021-09-30T18:09:57+08:00" + }, + "committer": { + "name": "kit101", + "email": "qkssk1711@163.com", + "date": "2021-09-30T18:09:57+08:00" + }, + "message": "add3\n", + "comment_count": 7 + }, + "author": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "committer": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "parents": { + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits/00b76e8abd51ae6a96318b3450944b32995f9158", + "sha": "2eac1cac02c325058cf959725c45b0612d3e8177" + } + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/pr_commits.json.golden b/scm/driver/gitee/testdata/pr_commits.json.golden new file mode 100644 index 000000000..b28ce6888 --- /dev/null +++ b/scm/driver/gitee/testdata/pr_commits.json.golden @@ -0,0 +1,21 @@ +[ + { + "Message": "add3\n", + "Sha": "00b76e8abd51ae6a96318b3450944b32995f9158", + "Link": "https://gitee.com/kit101/drone-yml-test/commits/00b76e8abd51ae6a96318b3450944b32995f9158", + "Author": { + "Name": "kit101", + "Email": "qkssk1711@163.com", + "Date": "2021-09-30T18:09:57+08:00", + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Committer": { + "Name": "kit101", + "Email": "qkssk1711@163.com", + "Date": "2021-09-30T18:09:57+08:00", + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + } + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/pr_files.json b/scm/driver/gitee/testdata/pr_files.json new file mode 100644 index 000000000..975b27f21 --- /dev/null +++ b/scm/driver/gitee/testdata/pr_files.json @@ -0,0 +1,82 @@ +[ + { + "sha": "2eac1cac02c325058cf959725c45b0612d3e8177", + "filename": "change/add.txt", + "status": "deleted", + "additions": "0", + "deletions": "1", + "blob_url": "https://gitee.com/kit101/drone-yml-test/blob/2eac1cac02c325058cf959725c45b0612d3e8177/change/add.txt", + "raw_url": "https://gitee.com/kit101/drone-yml-test/raw/2eac1cac02c325058cf959725c45b0612d3e8177/change/add.txt", + "patch": { + "diff": "@@ -1 +0,0 @@\n-add\n\\ No newline at end of file\n", + "new_path": "change/add.txt", + "old_path": "change/add.txt", + "a_mode": "100644", + "b_mode": "0", + "new_file": false, + "renamed_file": false, + "deleted_file": true, + "too_large": false + } + }, + { + "sha": "411db0d9e9072851383751c260dc1601840906e4", + "filename": "change/add2.txt", + "status": "added", + "additions": "4", + "deletions": "0", + "blob_url": "https://gitee.com/kit101/drone-yml-test/blob/411db0d9e9072851383751c260dc1601840906e4/change/add2.txt", + "raw_url": "https://gitee.com/kit101/drone-yml-test/raw/411db0d9e9072851383751c260dc1601840906e4/change/add2.txt", + "patch": { + "diff": "@@ -0,0 +1,4 @@\n+add 2\n+add 2\n+add 2\n+add 2\n\\ No newline at end of file\n", + "new_path": "change/add2.txt", + "old_path": "change/add2.txt", + "a_mode": "0", + "b_mode": "100644", + "new_file": true, + "renamed_file": false, + "deleted_file": false, + "too_large": false + } + }, + { + "sha": "411db0d9e9072851383751c260dc1601840906e4", + "filename": "change/modified.txt", + "status": null, + "additions": "6", + "deletions": "1", + "blob_url": "https://gitee.com/kit101/drone-yml-test/blob/411db0d9e9072851383751c260dc1601840906e4/change/modified.txt", + "raw_url": "https://gitee.com/kit101/drone-yml-test/raw/411db0d9e9072851383751c260dc1601840906e4/change/modified.txt", + "patch": { + "diff": "@@ -1,2 +1,7 @@\n will be modified\n-modified\n\\ No newline at end of file\n+modified\n+modified 2\n+modified 2\n+modified 2\n+modified 2\n+modified 2\n\\ No newline at end of file\n", + "new_path": "change/modified.txt", + "old_path": "change/modified.txt", + "a_mode": "100644", + "b_mode": "100644", + "new_file": false, + "renamed_file": false, + "deleted_file": false, + "too_large": false + } + }, + { + "sha": "411db0d9e9072851383751c260dc1601840906e4", + "filename": "change/rename.2.txt", + "status": "renamed", + "additions": "0", + "deletions": "0", + "blob_url": "https://gitee.com/kit101/drone-yml-test/blob/411db0d9e9072851383751c260dc1601840906e4/change/rename.2.txt", + "raw_url": "https://gitee.com/kit101/drone-yml-test/raw/411db0d9e9072851383751c260dc1601840906e4/change/rename.2.txt", + "patch": { + "diff": "", + "new_path": "change/rename.2.txt", + "old_path": "change/rename.1.txt", + "a_mode": "100644", + "b_mode": "100644", + "new_file": false, + "renamed_file": true, + "deleted_file": false, + "too_large": false + } + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/pr_files.json.golden b/scm/driver/gitee/testdata/pr_files.json.golden new file mode 100644 index 000000000..be4c1d330 --- /dev/null +++ b/scm/driver/gitee/testdata/pr_files.json.golden @@ -0,0 +1,30 @@ +[ + { + "BlobID": "2eac1cac02c325058cf959725c45b0612d3e8177", + "Path": "change/add.txt", + "Added": false, + "Renamed": false, + "Deleted": true + }, + { + "BlobID": "411db0d9e9072851383751c260dc1601840906e4", + "Path": "change/add2.txt", + "Added": true, + "Renamed": false, + "Deleted": false + }, + { + "BlobID": "411db0d9e9072851383751c260dc1601840906e4", + "Path": "change/modified.txt", + "Added": false, + "Renamed": false, + "Deleted": false + }, + { + "BlobID": "411db0d9e9072851383751c260dc1601840906e4", + "Path": "change/rename.2.txt", + "Added": false, + "Renamed": true, + "Deleted": false + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/pulls.json b/scm/driver/gitee/testdata/pulls.json new file mode 100644 index 000000000..8f5b93450 --- /dev/null +++ b/scm/driver/gitee/testdata/pulls.json @@ -0,0 +1,839 @@ +[ + { + "id": 4730187, + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/6", + "html_url": "https://gitee.com/kit101/drone-yml-test/pulls/6", + "diff_url": "https://gitee.com/kit101/drone-yml-test/pulls/6.diff", + "patch_url": "https://gitee.com/kit101/drone-yml-test/pulls/6.patch", + "issue_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/6/issues", + "commits_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/6/commits", + "review_comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/comments/{/number}", + "review_comment_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/comments", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/6/comments", + "number": 6, + "state": "open", + "title": "new-feature", + "body": "Please pull these awesome changes", + "assignees_number": 1, + "testers_number": 1, + "assignees": [ + { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + } + ], + "testers": [ + { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + } + ], + "milestone": null, + "labels": [], + "locked": false, + "created_at": "2021-09-30T16:38:19+08:00", + "updated_at": "2021-09-30T16:38:19+08:00", + "closed_at": null, + "merged_at": null, + "mergeable": true, + "can_merge_check": false, + "head": { + "label": "crud", + "ref": "crud", + "sha": "411db0d9e9072851383751c260dc1601840906e4", + "user": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "repo": { + "id": 14836026, + "full_name": "kit101/drone-yml-test", + "human_name": "kit101/drone-yml-test", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test", + "namespace": { + "id": 1576684, + "type": "personal", + "name": "kit101", + "path": "kit101", + "html_url": "https://gitee.com/kit101" + }, + "path": "drone-yml-test", + "name": "drone-yml-test", + "owner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "assigner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "description": "", + "private": false, + "public": true, + "internal": false, + "fork": false, + "html_url": "https://gitee.com/kit101/drone-yml-test.git", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git" + } + }, + "base": { + "label": "master", + "ref": "master", + "sha": "2eac1cac02c325058cf959725c45b0612d3e8177", + "user": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "repo": { + "id": 14836026, + "full_name": "kit101/drone-yml-test", + "human_name": "kit101/drone-yml-test", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test", + "namespace": { + "id": 1576684, + "type": "personal", + "name": "kit101", + "path": "kit101", + "html_url": "https://gitee.com/kit101" + }, + "path": "drone-yml-test", + "name": "drone-yml-test", + "owner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "assigner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "description": "", + "private": false, + "public": true, + "internal": false, + "fork": false, + "html_url": "https://gitee.com/kit101/drone-yml-test.git", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git" + } + }, + "_links": { + "self": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/6" + }, + "html": { + "href": "https://gitee.com/kit101/drone-yml-test/pulls/6" + }, + "issue": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/6/issues" + }, + "comments": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/6/comments" + }, + "review_comments": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/6/comments" + }, + "review_comment": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/comments/6" + }, + "commits": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/6/commits" + } + }, + "user": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + } + }, + { + "id": 4730175, + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/5", + "html_url": "https://gitee.com/kit101/drone-yml-test/pulls/5", + "diff_url": "https://gitee.com/kit101/drone-yml-test/pulls/5.diff", + "patch_url": "https://gitee.com/kit101/drone-yml-test/pulls/5.patch", + "issue_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/5/issues", + "commits_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/5/commits", + "review_comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/comments/{/number}", + "review_comment_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/comments", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/5/comments", + "number": 5, + "state": "closed", + "title": "new-feature", + "body": "Please pull these awesome changes", + "assignees_number": 1, + "testers_number": 1, + "assignees": [ + { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + } + ], + "testers": [ + { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + } + ], + "milestone": null, + "labels": [], + "locked": false, + "created_at": "2021-09-30T16:37:34+08:00", + "updated_at": "2021-09-30T16:38:14+08:00", + "closed_at": "2021-09-30T16:38:14+08:00", + "merged_at": null, + "mergeable": true, + "can_merge_check": false, + "head": { + "label": "crud", + "ref": "crud", + "sha": "411db0d9e9072851383751c260dc1601840906e4", + "user": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "repo": { + "id": 14836026, + "full_name": "kit101/drone-yml-test", + "human_name": "kit101/drone-yml-test", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test", + "namespace": { + "id": 1576684, + "type": "personal", + "name": "kit101", + "path": "kit101", + "html_url": "https://gitee.com/kit101" + }, + "path": "drone-yml-test", + "name": "drone-yml-test", + "owner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "assigner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "description": "", + "private": false, + "public": true, + "internal": false, + "fork": false, + "html_url": "https://gitee.com/kit101/drone-yml-test.git", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git" + } + }, + "base": { + "label": "master", + "ref": "master", + "sha": "2eac1cac02c325058cf959725c45b0612d3e8177", + "user": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "repo": { + "id": 14836026, + "full_name": "kit101/drone-yml-test", + "human_name": "kit101/drone-yml-test", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test", + "namespace": { + "id": 1576684, + "type": "personal", + "name": "kit101", + "path": "kit101", + "html_url": "https://gitee.com/kit101" + }, + "path": "drone-yml-test", + "name": "drone-yml-test", + "owner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "assigner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "description": "", + "private": false, + "public": true, + "internal": false, + "fork": false, + "html_url": "https://gitee.com/kit101/drone-yml-test.git", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git" + } + }, + "_links": { + "self": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/5" + }, + "html": { + "href": "https://gitee.com/kit101/drone-yml-test/pulls/5" + }, + "issue": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/5/issues" + }, + "comments": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/5/comments" + }, + "review_comments": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/5/comments" + }, + "review_comment": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/comments/5" + }, + "commits": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/5/commits" + } + }, + "user": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + } + }, + { + "id": 4730041, + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/4", + "html_url": "https://gitee.com/kit101/drone-yml-test/pulls/4", + "diff_url": "https://gitee.com/kit101/drone-yml-test/pulls/4.diff", + "patch_url": "https://gitee.com/kit101/drone-yml-test/pulls/4.patch", + "issue_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/4/issues", + "commits_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/4/commits", + "review_comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/comments/{/number}", + "review_comment_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/comments", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/4/comments", + "number": 4, + "state": "open", + "title": "create crud pr by api", + "body": "create crud pr by api", + "assignees_number": 1, + "testers_number": 1, + "assignees": [ + { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + } + ], + "testers": [ + { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + } + ], + "milestone": null, + "labels": [], + "locked": false, + "created_at": "2021-09-30T16:28:09+08:00", + "updated_at": "2021-09-30T16:28:10+08:00", + "closed_at": null, + "merged_at": null, + "mergeable": true, + "can_merge_check": false, + "head": { + "label": "feat-1", + "ref": "feat-1", + "sha": "2700445cd84c08546f4d003f8aa54d2099a006b7", + "user": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "repo": { + "id": 14836026, + "full_name": "kit101/drone-yml-test", + "human_name": "kit101/drone-yml-test", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test", + "namespace": { + "id": 1576684, + "type": "personal", + "name": "kit101", + "path": "kit101", + "html_url": "https://gitee.com/kit101" + }, + "path": "drone-yml-test", + "name": "drone-yml-test", + "owner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "assigner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "description": "", + "private": false, + "public": true, + "internal": false, + "fork": false, + "html_url": "https://gitee.com/kit101/drone-yml-test.git", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git" + } + }, + "base": { + "label": "master", + "ref": "master", + "sha": "2eac1cac02c325058cf959725c45b0612d3e8177", + "user": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "repo": { + "id": 14836026, + "full_name": "kit101/drone-yml-test", + "human_name": "kit101/drone-yml-test", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test", + "namespace": { + "id": 1576684, + "type": "personal", + "name": "kit101", + "path": "kit101", + "html_url": "https://gitee.com/kit101" + }, + "path": "drone-yml-test", + "name": "drone-yml-test", + "owner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "assigner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "description": "", + "private": false, + "public": true, + "internal": false, + "fork": false, + "html_url": "https://gitee.com/kit101/drone-yml-test.git", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git" + } + }, + "_links": { + "self": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/4" + }, + "html": { + "href": "https://gitee.com/kit101/drone-yml-test/pulls/4" + }, + "issue": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/4/issues" + }, + "comments": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/4/comments" + }, + "review_comments": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/4/comments" + }, + "review_comment": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/comments/4" + }, + "commits": { + "href": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls/4/commits" + } + }, + "user": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + } + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/pulls.json.golden b/scm/driver/gitee/testdata/pulls.json.golden new file mode 100644 index 000000000..e0d127ef0 --- /dev/null +++ b/scm/driver/gitee/testdata/pulls.json.golden @@ -0,0 +1,92 @@ +[ + { + "Number": 6, + "Title": "new-feature", + "Body": "Please pull these awesome changes", + "Sha": "411db0d9e9072851383751c260dc1601840906e4", + "Ref": "refs/pull/6/head", + "Source": "crud", + "Target": "master", + "Fork": "kit101/drone-yml-test", + "Link": "https://gitee.com/kit101/drone-yml-test/pulls/6", + "Diff": "https://gitee.com/kit101/drone-yml-test/pulls/6.diff", + "Closed": false, + "Merged": false, + "Created": "2021-09-30T16:38:19+08:00", + "Updated": "2021-09-30T16:38:19+08:00", + "Head": { + "Sha": "411db0d9e9072851383751c260dc1601840906e4", + "Path": "refs/heads/crud", + "Name": "crud" + }, + "Base": { + "Sha": "2eac1cac02c325058cf959725c45b0612d3e8177", + "Path": "refs/heads/master", + "Name": "master" + }, + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + } + }, + { + "Number": 5, + "Title": "new-feature", + "Body": "Please pull these awesome changes", + "Sha": "411db0d9e9072851383751c260dc1601840906e4", + "Ref": "refs/pull/5/head", + "Source": "crud", + "Target": "master", + "Fork": "kit101/drone-yml-test", + "Link": "https://gitee.com/kit101/drone-yml-test/pulls/5", + "Diff": "https://gitee.com/kit101/drone-yml-test/pulls/5.diff", + "Closed": true, + "Merged": false, + "Created": "2021-09-30T16:37:34+08:00", + "Updated": "2021-09-30T16:38:14+08:00", + "Head": { + "Sha": "411db0d9e9072851383751c260dc1601840906e4", + "Path": "refs/heads/crud", + "Name": "crud" + }, + "Base": { + "Sha": "2eac1cac02c325058cf959725c45b0612d3e8177", + "Path": "refs/heads/master", + "Name": "master" + }, + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + } + }, + { + "Number": 4, + "Title": "create crud pr by api", + "Body": "create crud pr by api", + "Sha": "2700445cd84c08546f4d003f8aa54d2099a006b7", + "Ref": "refs/pull/4/head", + "Source": "feat-1", + "Target": "master", + "Fork": "kit101/drone-yml-test", + "Link": "https://gitee.com/kit101/drone-yml-test/pulls/4", + "Diff": "https://gitee.com/kit101/drone-yml-test/pulls/4.diff", + "Closed": false, + "Merged": false, + "Created": "2021-09-30T16:28:09+08:00", + "Updated": "2021-09-30T16:28:10+08:00", + "Head": { + "Sha": "2700445cd84c08546f4d003f8aa54d2099a006b7", + "Path": "refs/heads/feat-1", + "Name": "feat-1" + }, + "Base": { + "Sha": "2eac1cac02c325058cf959725c45b0612d3e8177", + "Path": "refs/heads/master", + "Name": "master" + }, + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + } + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/repo.json b/scm/driver/gitee/testdata/repo.json new file mode 100644 index 000000000..b567618b5 --- /dev/null +++ b/scm/driver/gitee/testdata/repo.json @@ -0,0 +1,160 @@ +{ + "id": 14836026, + "full_name": "kit101/drone-yml-test", + "human_name": "kit101/drone-yml-test", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test", + "namespace": { + "id": 1576684, + "type": "personal", + "name": "kit101", + "path": "kit101", + "html_url": "https://gitee.com/kit101" + }, + "path": "drone-yml-test", + "name": "drone-yml-test", + "owner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "assigner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "description": "", + "private": false, + "public": true, + "internal": false, + "fork": false, + "html_url": "https://gitee.com/kit101/drone-yml-test.git", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "forks_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/forks", + "keys_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/keys{/key_id}", + "collaborators_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/collaborators{/collaborator}", + "hooks_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/hooks", + "branches_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/branches{/branch}", + "tags_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/tags", + "blobs_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/blobs{/sha}", + "stargazers_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/stargazers", + "contributors_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contributors", + "commits_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits{/sha}", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/comments{/number}", + "issue_comment_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/issues/comments{/number}", + "issues_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/issues{/number}", + "pulls_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls{/number}", + "milestones_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/milestones{/number}", + "notifications_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/notifications{?since,all,participating}", + "labels_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/labels{/name}", + "releases_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/releases{/id}", + "recommend": false, + "gvp": false, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "language": null, + "forks_count": 0, + "stargazers_count": 0, + "watchers_count": 1, + "default_branch": "master", + "open_issues_count": 2, + "has_issues": true, + "has_wiki": true, + "issue_comment": false, + "can_comment": true, + "pull_requests_enabled": true, + "has_page": false, + "license": null, + "outsourced": false, + "project_creator": "kit101", + "members": [ + "kit101" + ], + "pushed_at": "2021-09-30T18:10:23+08:00", + "created_at": "2021-03-24T11:24:34+08:00", + "updated_at": "2021-09-30T18:10:27+08:00", + "parent": null, + "paas": null, + "stared": false, + "watched": true, + "permission": { + "pull": true, + "push": true, + "admin": true + }, + "relation": "master", + "assignees_number": 1, + "testers_number": 1, + "assignee": [ + { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + } + ], + "testers": [ + { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + } + ], + "status": "开始", + "empty_repo": false, + "programs": [], + "enterprise": null +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/repo.json.golden b/scm/driver/gitee/testdata/repo.json.golden new file mode 100644 index 000000000..fd7593d97 --- /dev/null +++ b/scm/driver/gitee/testdata/repo.json.golden @@ -0,0 +1,17 @@ +{ + "ID": "14836026", + "Namespace": "kit101", + "Name": "drone-yml-test", + "Perm": { + "Pull": true, + "Push": true, + "Admin": true + }, + "Branch": "master", + "Private": false, + "Clone": "https://gitee.com/kit101/drone-yml-test.git", + "CloneSSH": "git@gitee.com:kit101/drone-yml-test.git", + "Link": "https://gitee.com/kit101/drone-yml-test.git", + "Created": "2021-03-24T11:24:34+08:00", + "Updated": "2021-09-30T18:10:27+08:00" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/repos.json b/scm/driver/gitee/testdata/repos.json new file mode 100644 index 000000000..57b247b62 --- /dev/null +++ b/scm/driver/gitee/testdata/repos.json @@ -0,0 +1,162 @@ +[ + { + "id": 14836026, + "full_name": "kit101/drone-yml-test", + "human_name": "kit101/drone-yml-test", + "url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test", + "namespace": { + "id": 1576684, + "type": "personal", + "name": "kit101", + "path": "kit101", + "html_url": "https://gitee.com/kit101" + }, + "path": "drone-yml-test", + "name": "drone-yml-test", + "owner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "assigner": { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + }, + "description": "", + "private": false, + "public": true, + "internal": false, + "fork": false, + "html_url": "https://gitee.com/kit101/drone-yml-test.git", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "forks_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/forks", + "keys_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/keys{/key_id}", + "collaborators_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/collaborators{/collaborator}", + "hooks_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/hooks", + "branches_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/branches{/branch}", + "tags_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/tags", + "blobs_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/blobs{/sha}", + "stargazers_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/stargazers", + "contributors_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/contributors", + "commits_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/commits{/sha}", + "comments_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/comments{/number}", + "issue_comment_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/issues/comments{/number}", + "issues_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/issues{/number}", + "pulls_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/pulls{/number}", + "milestones_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/milestones{/number}", + "notifications_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/notifications{?since,all,participating}", + "labels_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/labels{/name}", + "releases_url": "https://gitee.com/api/v5/repos/kit101/drone-yml-test/releases{/id}", + "recommend": false, + "gvp": false, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "language": null, + "forks_count": 0, + "stargazers_count": 0, + "watchers_count": 1, + "default_branch": "master", + "open_issues_count": 2, + "has_issues": true, + "has_wiki": true, + "issue_comment": false, + "can_comment": true, + "pull_requests_enabled": true, + "has_page": false, + "license": null, + "outsourced": false, + "project_creator": "kit101", + "members": [ + "kit101" + ], + "pushed_at": "2021-09-30T18:10:23+08:00", + "created_at": "2021-03-24T11:24:34+08:00", + "updated_at": "2021-09-30T18:10:27+08:00", + "parent": null, + "paas": null, + "stared": false, + "watched": true, + "permission": { + "pull": true, + "push": true, + "admin": true + }, + "relation": "master", + "assignees_number": 1, + "testers_number": 1, + "assignee": [ + { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + } + ], + "testers": [ + { + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "remark": "", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User" + } + ], + "status": "开始", + "empty_repo": false, + "programs": [], + "enterprise": null + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/repos.json.golden b/scm/driver/gitee/testdata/repos.json.golden new file mode 100644 index 000000000..3437a1eb1 --- /dev/null +++ b/scm/driver/gitee/testdata/repos.json.golden @@ -0,0 +1,19 @@ +[ + { + "ID": "14836026", + "Namespace": "kit101", + "Name": "drone-yml-test", + "Perm": { + "Pull": true, + "Push": true, + "Admin": true + }, + "Branch": "master", + "Private": false, + "Clone": "https://gitee.com/kit101/drone-yml-test.git", + "CloneSSH": "git@gitee.com:kit101/drone-yml-test.git", + "Link": "https://gitee.com/kit101/drone-yml-test.git", + "Created": "2021-03-24T11:24:34+08:00", + "Updated": "2021-09-30T18:10:27+08:00" + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/tag.json b/scm/driver/gitee/testdata/tag.json new file mode 100644 index 000000000..34d894a5b --- /dev/null +++ b/scm/driver/gitee/testdata/tag.json @@ -0,0 +1,8 @@ +{ + "name": "1.0", + "message": "1.0", + "commit": { + "sha": "5e7876efb3468ff679410b82a72f7c002382d41e", + "date": "2021-03-24T11:29:35+08:00" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/tag.json.golden b/scm/driver/gitee/testdata/tag.json.golden new file mode 100644 index 000000000..1e286b6e4 --- /dev/null +++ b/scm/driver/gitee/testdata/tag.json.golden @@ -0,0 +1,5 @@ +{ + "name": "1.0", + "Path": "refs/tags/1.0", + "Sha": "5e7876efb3468ff679410b82a72f7c002382d41e" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/tags.json b/scm/driver/gitee/testdata/tags.json new file mode 100644 index 000000000..dd2ef627c --- /dev/null +++ b/scm/driver/gitee/testdata/tags.json @@ -0,0 +1,34 @@ +[ + { + "name": "release-test", + "message": "", + "commit": { + "sha": "25b13a79d771314d0075302178eb18aef79e80db", + "date": "2021-08-17T16:01:03+00:00" + } + }, + { + "name": "1.1", + "message": "1.1", + "commit": { + "sha": "5e7876efb3468ff679410b82a72f7c002382d41e", + "date": "2021-03-24T11:29:35+08:00" + } + }, + { + "name": "1.0", + "message": "1.0", + "commit": { + "sha": "5e7876efb3468ff679410b82a72f7c002382d41e", + "date": "2021-03-24T11:29:35+08:00" + } + }, + { + "name": "1.2", + "message": "", + "commit": { + "sha": "5e7876efb3468ff679410b82a72f7c002382d41e", + "date": "2021-03-24T11:29:35+08:00" + } + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/tags.json.golden b/scm/driver/gitee/testdata/tags.json.golden new file mode 100644 index 000000000..1bcaa50c6 --- /dev/null +++ b/scm/driver/gitee/testdata/tags.json.golden @@ -0,0 +1,22 @@ +[ + { + "Name": "release-test", + "Path": "refs/tags/release-test", + "Sha": "25b13a79d771314d0075302178eb18aef79e80db" + }, + { + "name": "1.1", + "Path": "refs/tags/1.1", + "Sha": "5e7876efb3468ff679410b82a72f7c002382d41e" + }, + { + "name": "1.0", + "Path": "refs/tags/1.0", + "Sha": "5e7876efb3468ff679410b82a72f7c002382d41e" + }, + { + "name": "1.2", + "Path": "refs/tags/1.2", + "Sha": "5e7876efb3468ff679410b82a72f7c002382d41e" + } +] \ No newline at end of file diff --git a/scm/driver/gitee/testdata/user.json b/scm/driver/gitee/testdata/user.json new file mode 100644 index 000000000..b46072350 --- /dev/null +++ b/scm/driver/gitee/testdata/user.json @@ -0,0 +1,30 @@ +{ + "id": 1535738, + "login": "kit101", + "name": "kit101", + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "url": "https://gitee.com/api/v5/users/kit101", + "html_url": "https://gitee.com/kit101", + "followers_url": "https://gitee.com/api/v5/users/kit101/followers", + "following_url": "https://gitee.com/api/v5/users/kit101/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/kit101/gists{/gist_id}", + "starred_url": "https://gitee.com/api/v5/users/kit101/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/kit101/subscriptions", + "organizations_url": "https://gitee.com/api/v5/users/kit101/orgs", + "repos_url": "https://gitee.com/api/v5/users/kit101/repos", + "events_url": "https://gitee.com/api/v5/users/kit101/events{/privacy}", + "received_events_url": "https://gitee.com/api/v5/users/kit101/received_events", + "type": "User", + "blog": null, + "weibo": null, + "bio": "", + "public_repos": 6, + "public_gists": 0, + "followers": 2, + "following": 3, + "stared": 12, + "watched": 17, + "created_at": "2017-09-15T11:34:30+08:00", + "updated_at": "2021-08-06T16:34:48+08:00", + "email": "qkssk1711@163.com" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/user.json.golden b/scm/driver/gitee/testdata/user.json.golden new file mode 100644 index 000000000..d0ddb0d43 --- /dev/null +++ b/scm/driver/gitee/testdata/user.json.golden @@ -0,0 +1,8 @@ +{ + "Login": "kit101", + "Name": "kit101", + "Email": "qkssk1711@163.com", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "Created": "2017-09-15T11:34:30+08:00", + "Updated": "2021-08-06T16:34:48+08:00" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/issue_hook_assign.json b/scm/driver/gitee/testdata/webhooks/issue_hook_assign.json new file mode 100644 index 000000000..913920c2d --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/issue_hook_assign.json @@ -0,0 +1,223 @@ +{ + "action": "assign", + "assignee": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "description": "test issue hook\nupdate 1", + "enterprise": null, + "hook_id": 788005, + "hook_name": "issue_hooks", + "hook_url": "https://gitee.com/kit101/drone-yml-test/hooks/788005/edit", + "iid": "I4CYEO", + "issue": { + "assignee": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "body": "test issue hook\nupdate 1", + "collaborators": [ + ], + "comments": 0, + "created_at": "2021-10-08T16:08:32+08:00", + "html_url": "https://gitee.com/kit101/drone-yml-test/issues/I4CYEO", + "id": 7322928, + "labels": [ + { + "color": "767676", + "id": 102145593, + "name": "duplicate" + } + ], + "milestone": null, + "number": "I4CYEO", + "state": "progressing", + "state_name": "进行中", + "title": "test issue hook", + "type_name": "任务", + "updated_at": "2021-10-08T16:12:33+08:00", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "milestone": null, + "password": "", + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T16:01:12+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T16:12:29+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "push_data": null, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T16:01:12+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T16:12:29+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sender": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "sign": "kBmUwLrajnSpjC4uH+Qkb7LpuEulsXRYt8Rf2H4eXg4=", + "state": "progressing", + "target_user": null, + "timestamp": "1633680755274", + "title": "test issue hook", + "updated_by": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "url": "https://gitee.com/kit101/drone-yml-test/issues/I4CYEO", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/issue_hook_assign.json.golden b/scm/driver/gitee/testdata/webhooks/issue_hook_assign.json.golden new file mode 100644 index 000000000..a16772286 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/issue_hook_assign.json.golden @@ -0,0 +1,37 @@ +{ + "Action": "updated", + "Repo": { + "ID": "14836026", + "Namespace": "kit101", + "Name": "drone-yml-test", + "Branch": "master", + "Private": false, + "Clone": "https://gitee.com/kit101/drone-yml-test.git", + "CloneSSH": "git@gitee.com:kit101/drone-yml-test.git", + "Link": "https://gitee.com/kit101/drone-yml-test", + "Created": "2021-03-24T11:24:34+08:00", + "Updated": "2021-10-08T16:12:29+08:00" + }, + "Issue": { + "Number": 735267896979, + "Title": "test issue hook", + "Body": "test issue hook\nupdate 1", + "Link": "https://gitee.com/kit101/drone-yml-test/issues/I4CYEO", + "Labels": [ + "duplicate" + ], + "Closed": false, + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Created": "2021-10-08T16:08:32+08:00", + "Updated": "2021-10-08T16:12:33+08:00" + }, + "Sender": { + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Name": "kit101" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/issue_hook_delete.json b/scm/driver/gitee/testdata/webhooks/issue_hook_delete.json new file mode 100644 index 000000000..3b09b5aeb --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/issue_hook_delete.json @@ -0,0 +1,235 @@ +{ + "action": "delete", + "assignee": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "description": "test issue hook\nupdate 1", + "enterprise": null, + "hook_id": 788005, + "hook_name": "issue_hooks", + "hook_url": "https://gitee.com/kit101/drone-yml-test/hooks/788005/edit", + "iid": "I4CYEO", + "issue": { + "assignee": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "body": "test issue hook\nupdate 1", + "collaborators": [ + ], + "comments": 0, + "created_at": "2021-10-08T16:08:32+08:00", + "html_url": "https://gitee.com/kit101/drone-yml-test/issues/I4CYEO", + "id": 7322928, + "labels": [ + { + "color": "767676", + "id": 102145593, + "name": "duplicate" + } + ], + "milestone": { + "closed_issues": 0, + "created_at": "2021-09-30T11:23:19+08:00", + "description": "测试里程碑", + "due_on": "2021-10-29", + "html_url": "https://gitee.com/kit101/drone-yml-test/milestones/147062", + "id": 147062, + "number": 147062, + "open_issues": 0, + "state": "open", + "title": "beta1.0", + "updated_at": "2021-09-30T11:23:19+08:00" + }, + "number": "I4CYEO", + "state": "progressing", + "state_name": "进行中", + "title": "test issue hook", + "type_name": "任务", + "updated_at": "2021-10-08T16:27:14+08:00", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "milestone": "beta1.0", + "password": "", + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T16:16:28+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T16:27:14+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "push_data": null, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T16:16:28+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T16:27:14+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sender": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "sign": "9J18Ih1nI+TKqddSYd1ORCjVjBUQhVGqIZdX3Jqk32Q=", + "state": "progressing", + "target_user": null, + "timestamp": "1633681683513", + "title": "test issue hook", + "updated_by": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "url": "https://gitee.com/kit101/drone-yml-test/issues/I4CYEO", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/issue_hook_delete.json.golden b/scm/driver/gitee/testdata/webhooks/issue_hook_delete.json.golden new file mode 100644 index 000000000..211795e90 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/issue_hook_delete.json.golden @@ -0,0 +1,37 @@ +{ + "Action": "closed", + "Repo": { + "ID": "14836026", + "Namespace": "kit101", + "Name": "drone-yml-test", + "Branch": "master", + "Private": false, + "Clone": "https://gitee.com/kit101/drone-yml-test.git", + "CloneSSH": "git@gitee.com:kit101/drone-yml-test.git", + "Link": "https://gitee.com/kit101/drone-yml-test", + "Created": "2021-03-24T11:24:34+08:00", + "Updated": "2021-10-08T16:27:14+08:00" + }, + "Issue": { + "Number": 735267896979, + "Title": "test issue hook", + "Body": "test issue hook\nupdate 1", + "Link": "https://gitee.com/kit101/drone-yml-test/issues/I4CYEO", + "Labels": [ + "duplicate" + ], + "Closed": false, + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Created": "2021-10-08T16:08:32+08:00", + "Updated": "2021-10-08T16:27:14+08:00" + }, + "Sender": { + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Name": "kit101" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/issue_hook_open.json b/scm/driver/gitee/testdata/webhooks/issue_hook_open.json new file mode 100644 index 000000000..f436f4738 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/issue_hook_open.json @@ -0,0 +1,192 @@ +{ + "action": "open", + "assignee": null, + "description": "test issue hook", + "enterprise": null, + "hook_id": 788005, + "hook_name": "issue_hooks", + "hook_url": "https://gitee.com/kit101/drone-yml-test/hooks/788005/edit", + "iid": "I4CYEO", + "issue": { + "assignee": null, + "body": "test issue hook", + "collaborators": [ + ], + "comments": 0, + "created_at": "2021-10-08T16:08:32+08:00", + "html_url": "https://gitee.com/kit101/drone-yml-test/issues/I4CYEO", + "id": 7322928, + "labels": [ + ], + "milestone": null, + "number": "I4CYEO", + "state": "open", + "state_name": "待办的", + "title": "test issue hook", + "type_name": "任务", + "updated_at": "2021-10-08T16:08:32+08:00", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "milestone": null, + "password": "", + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 3, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T16:01:12+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T16:08:32+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "push_data": null, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 3, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T16:01:12+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T16:08:32+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sender": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "sign": "8v2uENuUH9QeZVl3olFEA3aPE/5fECC6RkmmsJV62DQ=", + "state": "open", + "target_user": null, + "timestamp": "1633680515785", + "title": "test issue hook", + "updated_by": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "url": "https://gitee.com/kit101/drone-yml-test/issues/I4CYEO", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/issue_hook_open.json.golden b/scm/driver/gitee/testdata/webhooks/issue_hook_open.json.golden new file mode 100644 index 000000000..a87054c90 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/issue_hook_open.json.golden @@ -0,0 +1,34 @@ +{ + "Action": "opened", + "Repo": { + "ID": "14836026", + "Namespace": "kit101", + "Name": "drone-yml-test", + "Branch": "master", + "Private": false, + "Clone": "https://gitee.com/kit101/drone-yml-test.git", + "CloneSSH": "git@gitee.com:kit101/drone-yml-test.git", + "Link": "https://gitee.com/kit101/drone-yml-test", + "Created": "2021-03-24T11:24:34+08:00", + "Updated": "2021-10-08T16:08:32+08:00" + }, + "Issue": { + "Number": 735267896979, + "Title": "test issue hook", + "Body": "test issue hook", + "Link": "https://gitee.com/kit101/drone-yml-test/issues/I4CYEO", + "Closed": false, + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Created": "2021-10-08T16:08:32+08:00", + "Updated": "2021-10-08T16:08:32+08:00" + }, + "Sender": { + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Name": "kit101" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/issue_hook_state_change.json b/scm/driver/gitee/testdata/webhooks/issue_hook_state_change.json new file mode 100644 index 000000000..0b6c9c8a4 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/issue_hook_state_change.json @@ -0,0 +1,235 @@ +{ + "action": "state_change", + "assignee": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "description": "test issue hook\nupdate 1", + "enterprise": null, + "hook_id": 788005, + "hook_name": "issue_hooks", + "hook_url": "https://gitee.com/kit101/drone-yml-test/hooks/788005/edit", + "iid": "I4CYEO", + "issue": { + "assignee": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "body": "test issue hook\nupdate 1", + "collaborators": [ + ], + "comments": 0, + "created_at": "2021-10-08T16:08:32+08:00", + "html_url": "https://gitee.com/kit101/drone-yml-test/issues/I4CYEO", + "id": 7322928, + "labels": [ + { + "color": "767676", + "id": 102145593, + "name": "duplicate" + } + ], + "milestone": { + "closed_issues": 0, + "created_at": "2021-09-30T11:23:19+08:00", + "description": "测试里程碑", + "due_on": "2021-10-29", + "html_url": "https://gitee.com/kit101/drone-yml-test/milestones/147062", + "id": 147062, + "number": 147062, + "open_issues": 0, + "state": "open", + "title": "beta1.0", + "updated_at": "2021-09-30T11:23:19+08:00" + }, + "number": "I4CYEO", + "state": "progressing", + "state_name": "进行中", + "title": "test issue hook", + "type_name": "任务", + "updated_at": "2021-10-08T16:27:14+08:00", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "milestone": "beta1.0", + "password": "", + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T16:16:28+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T16:27:14+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "push_data": null, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T16:16:28+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T16:27:14+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sender": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "sign": "HdIghS5Ua3zzLgqI4LxxQz313V08QxrR3+0YITiGf1s=", + "state": "progressing", + "target_user": null, + "timestamp": "1633681635600", + "title": "test issue hook", + "updated_by": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "url": "https://gitee.com/kit101/drone-yml-test/issues/I4CYEO", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/issue_hook_state_change.json.golden b/scm/driver/gitee/testdata/webhooks/issue_hook_state_change.json.golden new file mode 100644 index 000000000..211c790b4 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/issue_hook_state_change.json.golden @@ -0,0 +1,37 @@ +{ + "Action": "opened", + "Repo": { + "ID": "14836026", + "Namespace": "kit101", + "Name": "drone-yml-test", + "Branch": "master", + "Private": false, + "Clone": "https://gitee.com/kit101/drone-yml-test.git", + "CloneSSH": "git@gitee.com:kit101/drone-yml-test.git", + "Link": "https://gitee.com/kit101/drone-yml-test", + "Created": "2021-03-24T11:24:34+08:00", + "Updated": "2021-10-08T16:27:14+08:00" + }, + "Issue": { + "Number": 735267896979, + "Title": "test issue hook", + "Body": "test issue hook\nupdate 1", + "Link": "https://gitee.com/kit101/drone-yml-test/issues/I4CYEO", + "Labels": [ + "duplicate" + ], + "Closed": false, + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Created": "2021-10-08T16:08:32+08:00", + "Updated": "2021-10-08T16:27:14+08:00" + }, + "Sender": { + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Name": "kit101" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/note_hook_issue_comment.json b/scm/driver/gitee/testdata/webhooks/note_hook_issue_comment.json new file mode 100644 index 000000000..3b0f78cea --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/note_hook_issue_comment.json @@ -0,0 +1,217 @@ +{ + "action": "comment", + "author": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "comment": { + "body": "test issue comment hook\r\n\r\n", + "created_at": "2021-10-08T15:45:08+08:00", + "html_url": "https://gitee.com/kit101/drone-yml-test/issues/I4CF12#note_6933558", + "id": 6933558, + "updated_at": "2021-10-08T15:45:08+08:00", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "enterprise": null, + "hook_id": 788005, + "hook_name": "note_hooks", + "hook_url": "https://gitee.com/kit101/drone-yml-test/hooks/788005/edit", + "issue": { + "assignee": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "body": "create by api body", + "collaborators": [ + ], + "comments": 2, + "created_at": "2021-09-29T13:33:00+08:00", + "html_url": "https://gitee.com/kit101/drone-yml-test/issues/I4CF12", + "id": 7297814, + "labels": [ + { + "color": "DB2828", + "id": 102145590, + "name": "bug" + } + ], + "milestone": null, + "number": "I4CF12", + "state": "open", + "state_name": "待办的", + "title": "create by api", + "type_name": "任务", + "updated_at": "2021-10-08T15:45:08+08:00", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "note": "test issue comment hook\r\n\r\n", + "noteable_id": 7297814, + "noteable_type": "Issue", + "password": "", + "per_iid": "#I4CF12", + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T13:26:59+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T13:26:59+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "pull_request": null, + "push_data": null, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T13:26:59+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T13:26:59+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sender": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "short_commit_id": null, + "sign": "Zzv7VMOnJ5SKrQhcEsL4XaC1zR1Kl1qMuxS0HbHwpBI=", + "timestamp": "1633679110217", + "title": "create by api", + "url": "https://gitee.com/kit101/drone-yml-test/issues/I4CF12#note_6933558" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/note_hook_issue_comment.json.golden b/scm/driver/gitee/testdata/webhooks/note_hook_issue_comment.json.golden new file mode 100644 index 000000000..53845e677 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/note_hook_issue_comment.json.golden @@ -0,0 +1,49 @@ +{ + "Action": "created", + "Repo": { + "ID": "14836026", + "Namespace": "kit101", + "Name": "drone-yml-test", + "Branch": "master", + "Private": false, + "Clone": "https://gitee.com/kit101/drone-yml-test.git", + "CloneSSH": "git@gitee.com:kit101/drone-yml-test.git", + "Link": "https://gitee.com/kit101/drone-yml-test", + "Created": "2021-03-24T11:24:34+08:00", + "Updated": "2021-10-08T13:26:59+08:00" + }, + "Issue": { + "Number": 735267704950, + "Title": "create by api", + "Body": "create by api body", + "Link": "https://gitee.com/kit101/drone-yml-test/issues/I4CF12", + "Labels": [ + "bug" + ], + "Closed": false, + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Created": "2021-09-29T13:33:00+08:00", + "Updated": "2021-10-08T15:45:08+08:00" + }, + "Comment": { + "ID": 6933558, + "Body": "test issue comment hook\r\n\r\n", + "Author": { + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Name": "kit101" + }, + "Created": "2021-10-08T15:45:08+08:00", + "Updated": "2021-10-08T15:45:08+08:00" + }, + "Sender": { + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Name": "kit101" + } +} diff --git a/scm/driver/gitee/testdata/webhooks/note_hook_pr_comment.json b/scm/driver/gitee/testdata/webhooks/note_hook_pr_comment.json new file mode 100644 index 000000000..7d871105b --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/note_hook_pr_comment.json @@ -0,0 +1,394 @@ +{ + "action": "comment", + "author": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "comment": { + "body": "comment", + "created_at": "2021-10-08T19:13:20+08:00", + "html_url": "https://gitee.com/kit101/drone-yml-test/pulls/7#note_6937563", + "id": 6937563, + "updated_at": "2021-10-08T19:13:20+08:00", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "enterprise": null, + "hook_id": 788005, + "hook_name": "note_hooks", + "hook_url": "https://gitee.com/kit101/drone-yml-test/hooks/788005/edit", + "issue": null, + "note": "comment", + "noteable_id": 4731382, + "noteable_type": "PullRequest", + "password": "", + "per_iid": "!7", + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:54:02+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:54:02+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "pull_request": { + "additions": 11, + "assignee": null, + "assignees": [ + { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + ], + "base": { + "label": "kit101:master", + "ref": "master", + "repo": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:54:02+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:54:02+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sha": "2eac1cac02c325058cf959725c45b0612d3e8177", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "body": "", + "changed_files": 2, + "closed_at": null, + "comments": 11, + "commits": 2, + "created_at": "2021-09-30T18:10:27+08:00", + "deletions": 0, + "diff_url": "https://gitee.com/kit101/drone-yml-test/pulls/7.diff", + "head": { + "label": "kit101:feat-2", + "ref": "feat-2", + "repo": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:54:02+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:54:02+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sha": "6168d9dae737b47f00c59fafca10c913a6850c3a", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "html_url": "https://gitee.com/kit101/drone-yml-test/pulls/7", + "id": 4731382, + "languages": [ + "Python" + ], + "merge_commit_sha": "d10df103c351de96ceb9e62e6e4097f0e3420b72", + "merge_reference_name": "refs/pull/7/MERGE", + "merge_status": "can_be_resolve", + "mergeable": false, + "merged": false, + "merged_at": null, + "milestone": null, + "need_review": true, + "need_test": true, + "number": 7, + "patch_url": "https://gitee.com/kit101/drone-yml-test/pulls/7.patch", + "state": "open", + "tester": null, + "testers": [ + { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + ], + "title": "feat add 3", + "updated_at": "2021-10-08T19:13:20+08:00", + "updated_by": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "push_data": null, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:54:02+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:54:02+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sender": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "short_commit_id": null, + "sign": "wi4uRDdmlbPvs3DMQsm88rV0rzx11rLvuo0AOJOH28s=", + "timestamp": "1633691608022", + "title": "feat add 3", + "url": "https://gitee.com/kit101/drone-yml-test/pulls/7#note_6937563" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/note_hook_pr_comment.json.golden b/scm/driver/gitee/testdata/webhooks/note_hook_pr_comment.json.golden new file mode 100644 index 000000000..c91349ba4 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/note_hook_pr_comment.json.golden @@ -0,0 +1,63 @@ +{ + "Action": "created", + "Repo": { + "ID": "14836026", + "Namespace": "kit101", + "Name": "drone-yml-test", + "Branch": "master", + "Private": false, + "Clone": "https://gitee.com/kit101/drone-yml-test.git", + "CloneSSH": "git@gitee.com:kit101/drone-yml-test.git", + "Link": "https://gitee.com/kit101/drone-yml-test", + "Created": "2021-03-24T11:24:34+08:00", + "Updated": "2021-10-08T17:54:02+08:00" + }, + "PullRequest": { + "Number": 7, + "Title": "feat add 3", + "Body": "", + "Sha": "6168d9dae737b47f00c59fafca10c913a6850c3a", + "Ref": "refs/pull/7/head", + "Source": "feat-2", + "Target": "master", + "Fork": "kit101/drone-yml-test", + "Link": "https://gitee.com/kit101/drone-yml-test/pulls/7", + "Diff": "https://gitee.com/kit101/drone-yml-test/pulls/7.diff", + "Closed": false, + "Merged": false, + "Head": { + "Name": "feat-2", + "Path": "refs/heads/feat-2", + "Sha": "6168d9dae737b47f00c59fafca10c913a6850c3a" + }, + "Base": { + "Name": "master", + "Path": "refs/heads/master", + "Sha": "2eac1cac02c325058cf959725c45b0612d3e8177" + }, + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Created": "2021-09-30T18:10:27+08:00", + "Updated": "2021-10-08T19:13:20+08:00" + }, + "Comment": { + "ID": 6937563, + "Body": "comment", + "Author": { + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Name": "kit101" + }, + "Created": "2021-10-08T19:13:20+08:00", + "Updated": "2021-10-08T19:13:20+08:00" + }, + "Sender": { + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Name": "kit101" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/pr_close.json b/scm/driver/gitee/testdata/webhooks/pr_close.json new file mode 100644 index 000000000..d5ad5c9a0 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/pr_close.json @@ -0,0 +1,601 @@ +{ + "action": "close", + "action_desc": "open", + "author": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "body": "feat-3 1", + "enterprise": null, + "hook_id": 788005, + "hook_name": "merge_request_hooks", + "hook_url": "https://gitee.com/kit101/drone-yml-test/hooks/788005/edit", + "iid": 8, + "languages": [ + "Python" + ], + "merge_commit_sha": "cd09abc1995aede07da6524a0ace587698d74bbc", + "merge_status": "can_be_merged", + "number": 8, + "password": "", + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:28:43+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "pull_request": { + "additions": 1, + "assignee": null, + "assignees": [ + { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + ], + "base": { + "label": "kit101:master", + "ref": "master", + "repo": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:28:43+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sha": "2eac1cac02c325058cf959725c45b0612d3e8177", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "body": "feat-3 1", + "changed_files": 1, + "closed_at": "2021-10-08T17:28:43+08:00", + "comments": 0, + "commits": 1, + "created_at": "2021-10-08T17:16:06+08:00", + "deletions": 0, + "diff_url": "https://gitee.com/kit101/drone-yml-test/pulls/8.diff", + "head": { + "label": "kit101:feat-3", + "ref": "feat-3", + "repo": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:28:43+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sha": "dc8fa2ebe050d63f639c5b834311e96bc2303523", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "html_url": "https://gitee.com/kit101/drone-yml-test/pulls/8", + "id": 4744094, + "labels": [ + { + "color": "D7C38B", + "id": 127956024, + "name": "test" + } + ], + "languages": [ + "Python" + ], + "merge_commit_sha": "cd09abc1995aede07da6524a0ace587698d74bbc", + "merge_reference_name": "refs/pull/8/MERGE", + "merge_status": "can_be_merged", + "mergeable": true, + "merged": false, + "merged_at": null, + "milestone": null, + "need_review": false, + "need_test": false, + "number": 8, + "patch_url": "https://gitee.com/kit101/drone-yml-test/pulls/8.patch", + "state": "closed", + "tester": null, + "testers": [ + { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + ], + "title": "feat-3 1", + "updated_at": "2021-10-08T17:28:43+08:00", + "updated_by": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "push_data": null, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:28:43+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sender": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "sign": "yuLVNqOZKWnXuYcQ8KbOm1UYgvd9KeiCHX5QsEyrrz8=", + "source_branch": "feat-3", + "source_repo": { + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:28:43+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:28:43+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + } + }, + "state": "closed", + "target_branch": "master", + "target_repo": { + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:28:43+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:28:43+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + } + }, + "target_user": null, + "timestamp": "1633685324936", + "title": "feat-3 1", + "updated_by": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "url": "https://gitee.com/kit101/drone-yml-test/pulls/8" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/pr_close.json.golden b/scm/driver/gitee/testdata/webhooks/pr_close.json.golden new file mode 100644 index 000000000..2c71509f2 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/pr_close.json.golden @@ -0,0 +1,57 @@ +{ + "Action": "closed", + "Repo": { + "ID": "14836026", + "Namespace": "kit101", + "Name": "drone-yml-test", + "Branch": "master", + "Private": false, + "Clone": "https://gitee.com/kit101/drone-yml-test.git", + "CloneSSH": "git@gitee.com:kit101/drone-yml-test.git", + "Link": "https://gitee.com/kit101/drone-yml-test", + "Created": "2021-03-24T11:24:34+08:00", + "Updated": "2021-10-08T17:28:43+08:00" + }, + "PullRequest": { + "Number": 8, + "Title": "feat-3 1", + "Body": "feat-3 1", + "Sha": "dc8fa2ebe050d63f639c5b834311e96bc2303523", + "Ref": "refs/pull/8/head", + "Source": "feat-3", + "Target": "master", + "Fork": "kit101/drone-yml-test", + "Link": "https://gitee.com/kit101/drone-yml-test/pulls/8", + "Diff": "https://gitee.com/kit101/drone-yml-test/pulls/8.diff", + "Closed": true, + "Merged": false, + "Head": { + "Name": "feat-3", + "Path": "refs/heads/feat-3", + "Sha": "dc8fa2ebe050d63f639c5b834311e96bc2303523" + }, + "Base": { + "Name": "master", + "Path": "refs/heads/master", + "Sha": "2eac1cac02c325058cf959725c45b0612d3e8177" + }, + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Created": "2021-10-08T17:16:06+08:00", + "Updated": "2021-10-08T17:28:43+08:00", + "Labels": [ + { + "Name": "test", + "Color": "D7C38B" + } + ] + }, + "Sender": { + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Name": "kit101" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/pr_labeled.json b/scm/driver/gitee/testdata/webhooks/pr_labeled.json new file mode 100644 index 000000000..bc682cc3f --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/pr_labeled.json @@ -0,0 +1,601 @@ +{ + "action": "update", + "action_desc": "update_label", + "author": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "body": "feat-3 1", + "enterprise": null, + "hook_id": 788005, + "hook_name": "merge_request_hooks", + "hook_url": "https://gitee.com/kit101/drone-yml-test/hooks/788005/edit", + "iid": 8, + "languages": [ + "Python" + ], + "merge_commit_sha": "cd09abc1995aede07da6524a0ace587698d74bbc", + "merge_status": "can_be_merged", + "number": 8, + "password": "", + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:16:06+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "pull_request": { + "additions": 1, + "assignee": null, + "assignees": [ + { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + ], + "base": { + "label": "kit101:master", + "ref": "master", + "repo": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:16:06+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sha": "2eac1cac02c325058cf959725c45b0612d3e8177", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "body": "feat-3 1", + "changed_files": 1, + "closed_at": null, + "comments": 0, + "commits": 1, + "created_at": "2021-10-08T17:16:06+08:00", + "deletions": 0, + "diff_url": "https://gitee.com/kit101/drone-yml-test/pulls/8.diff", + "head": { + "label": "kit101:feat-3", + "ref": "feat-3", + "repo": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:16:06+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sha": "dc8fa2ebe050d63f639c5b834311e96bc2303523", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "html_url": "https://gitee.com/kit101/drone-yml-test/pulls/8", + "id": 4744094, + "labels": [ + { + "color": "00B5AD", + "id": 102145595, + "name": "question" + } + ], + "languages": [ + "Python" + ], + "merge_commit_sha": "cd09abc1995aede07da6524a0ace587698d74bbc", + "merge_reference_name": "refs/pull/8/MERGE", + "merge_status": "can_be_merged", + "mergeable": true, + "merged": false, + "merged_at": null, + "milestone": null, + "need_review": true, + "need_test": true, + "number": 8, + "patch_url": "https://gitee.com/kit101/drone-yml-test/pulls/8.patch", + "state": "open", + "tester": null, + "testers": [ + { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + ], + "title": "feat-3 1", + "updated_at": "2021-10-08T17:19:39+08:00", + "updated_by": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "push_data": null, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:16:06+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sender": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "sign": "Fid06lsV72m4QMmmwMAPqTwYLLwFYNgjz32pUeAIaTE=", + "source_branch": "feat-3", + "source_repo": { + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:16:06+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:16:06+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + } + }, + "state": "open", + "target_branch": "master", + "target_repo": { + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:16:06+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:16:06+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + } + }, + "target_user": null, + "timestamp": "1633684782533", + "title": "feat-3 1", + "updated_by": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "url": "https://gitee.com/kit101/drone-yml-test/pulls/8" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/pr_labeled.json.golden b/scm/driver/gitee/testdata/webhooks/pr_labeled.json.golden new file mode 100644 index 000000000..1aaa28281 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/pr_labeled.json.golden @@ -0,0 +1,57 @@ +{ + "Action": "labeled", + "Repo": { + "ID": "14836026", + "Namespace": "kit101", + "Name": "drone-yml-test", + "Branch": "master", + "Private": false, + "Clone": "https://gitee.com/kit101/drone-yml-test.git", + "CloneSSH": "git@gitee.com:kit101/drone-yml-test.git", + "Link": "https://gitee.com/kit101/drone-yml-test", + "Created": "2021-03-24T11:24:34+08:00", + "Updated": "2021-10-08T17:16:06+08:00" + }, + "PullRequest": { + "Number": 8, + "Title": "feat-3 1", + "Body": "feat-3 1", + "Sha": "dc8fa2ebe050d63f639c5b834311e96bc2303523", + "Ref": "refs/pull/8/head", + "Source": "feat-3", + "Target": "master", + "Fork": "kit101/drone-yml-test", + "Link": "https://gitee.com/kit101/drone-yml-test/pulls/8", + "Diff": "https://gitee.com/kit101/drone-yml-test/pulls/8.diff", + "Closed": false, + "Merged": false, + "Head": { + "Name": "feat-3", + "Path": "refs/heads/feat-3", + "Sha": "dc8fa2ebe050d63f639c5b834311e96bc2303523" + }, + "Base": { + "Name": "master", + "Path": "refs/heads/master", + "Sha": "2eac1cac02c325058cf959725c45b0612d3e8177" + }, + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Created": "2021-10-08T17:16:06+08:00", + "Updated": "2021-10-08T17:19:39+08:00", + "Labels": [ + { + "Name": "question", + "Color": "00B5AD" + } + ] + }, + "Sender": { + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Name": "kit101" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/pr_merge.json b/scm/driver/gitee/testdata/webhooks/pr_merge.json new file mode 100644 index 000000000..9b94fc405 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/pr_merge.json @@ -0,0 +1,596 @@ +{ + "action": "merge", + "action_desc": "open", + "author": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "body": "feat-3", + "enterprise": null, + "hook_id": 788005, + "hook_name": "merge_request_hooks", + "hook_url": "https://gitee.com/kit101/drone-yml-test/hooks/788005/edit", + "iid": 9, + "languages": [ + "Python" + ], + "merge_commit_sha": "6c363013dfccedad4c68c88e8649f4ffacc644ea", + "merge_status": "can_be_merged", + "number": 9, + "password": "", + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:32:30+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:32:30+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "pull_request": { + "additions": 1, + "assignee": null, + "assignees": [ + { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + ], + "base": { + "label": "kit101:master", + "ref": "master", + "repo": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:32:30+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:32:30+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sha": "2eac1cac02c325058cf959725c45b0612d3e8177", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "body": "feat-3", + "changed_files": 1, + "closed_at": "2021-10-08T17:32:30+08:00", + "comments": 0, + "commits": 1, + "created_at": "2021-10-08T17:29:49+08:00", + "deletions": 0, + "diff_url": "https://gitee.com/kit101/drone-yml-test/pulls/9.diff", + "head": { + "label": "kit101:feat-3", + "ref": "feat-3", + "repo": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:32:30+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:32:30+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sha": "dc8fa2ebe050d63f639c5b834311e96bc2303523", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "html_url": "https://gitee.com/kit101/drone-yml-test/pulls/9", + "id": 4744278, + "labels": [ + ], + "languages": [ + "Python" + ], + "merge_commit_sha": "6c363013dfccedad4c68c88e8649f4ffacc644ea", + "merge_reference_name": "refs/pull/9/MERGE", + "merge_status": "can_be_merged", + "mergeable": true, + "merged": true, + "merged_at": "2021-10-08T17:32:30+08:00", + "milestone": null, + "need_review": false, + "need_test": false, + "number": 9, + "patch_url": "https://gitee.com/kit101/drone-yml-test/pulls/9.patch", + "state": "merged", + "tester": null, + "testers": [ + { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + ], + "title": "feat-3", + "updated_at": "2021-10-08T17:32:29+08:00", + "updated_by": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "push_data": null, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:32:30+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:32:30+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sender": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "sign": "SPeRZ3+TLzetOj+eEdAuMt8zVVbs6o+k5xrCPf5WGDI=", + "source_branch": "feat-3", + "source_repo": { + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:32:30+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:32:30+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:32:30+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:32:30+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + } + }, + "state": "merged", + "target_branch": "master", + "target_repo": { + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:32:30+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:32:30+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:32:30+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:32:30+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + } + }, + "target_user": null, + "timestamp": "1633685551222", + "title": "feat-3", + "updated_by": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "url": "https://gitee.com/kit101/drone-yml-test/pulls/9" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/pr_merge.json.golden b/scm/driver/gitee/testdata/webhooks/pr_merge.json.golden new file mode 100644 index 000000000..54e89f254 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/pr_merge.json.golden @@ -0,0 +1,51 @@ +{ + "Action": "merged", + "Repo": { + "ID": "14836026", + "Namespace": "kit101", + "Name": "drone-yml-test", + "Branch": "master", + "Private": false, + "Clone": "https://gitee.com/kit101/drone-yml-test.git", + "CloneSSH": "git@gitee.com:kit101/drone-yml-test.git", + "Link": "https://gitee.com/kit101/drone-yml-test", + "Created": "2021-03-24T11:24:34+08:00", + "Updated": "2021-10-08T17:32:30+08:00" + }, + "PullRequest": { + "Number": 9, + "Title": "feat-3", + "Body": "feat-3", + "Sha": "dc8fa2ebe050d63f639c5b834311e96bc2303523", + "Ref": "refs/pull/9/head", + "Source": "feat-3", + "Target": "master", + "Fork": "kit101/drone-yml-test", + "Link": "https://gitee.com/kit101/drone-yml-test/pulls/9", + "Diff": "https://gitee.com/kit101/drone-yml-test/pulls/9.diff", + "Closed": true, + "Merged": true, + "Head": { + "Name": "feat-3", + "Path": "refs/heads/feat-3", + "Sha": "dc8fa2ebe050d63f639c5b834311e96bc2303523" + }, + "Base": { + "Name": "master", + "Path": "refs/heads/master", + "Sha": "2eac1cac02c325058cf959725c45b0612d3e8177" + }, + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Created": "2021-10-08T17:29:49+08:00", + "Updated": "2021-10-08T17:32:29+08:00" + }, + "Sender": { + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Name": "kit101" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/pr_open.json b/scm/driver/gitee/testdata/webhooks/pr_open.json new file mode 100644 index 000000000..62b9bd0cb --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/pr_open.json @@ -0,0 +1,596 @@ +{ + "action": "open", + "action_desc": "open", + "author": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "body": "feat-3", + "enterprise": null, + "hook_id": 788005, + "hook_name": "merge_request_hooks", + "hook_url": "https://gitee.com/kit101/drone-yml-test/hooks/788005/edit", + "iid": 9, + "languages": [ + "Python" + ], + "merge_commit_sha": "3fbdff5796f6d57ed9f5a5dd48e5d0cad7f9c0a1", + "merge_status": "can_be_merged", + "number": 9, + "password": "", + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:29:49+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "pull_request": { + "additions": 1, + "assignee": null, + "assignees": [ + { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + ], + "base": { + "label": "kit101:master", + "ref": "master", + "repo": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:29:49+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sha": "2eac1cac02c325058cf959725c45b0612d3e8177", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "body": "feat-3", + "changed_files": 1, + "closed_at": null, + "comments": 0, + "commits": 1, + "created_at": "2021-10-08T17:29:49+08:00", + "deletions": 0, + "diff_url": "https://gitee.com/kit101/drone-yml-test/pulls/9.diff", + "head": { + "label": "kit101:feat-3", + "ref": "feat-3", + "repo": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:29:49+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sha": "dc8fa2ebe050d63f639c5b834311e96bc2303523", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "html_url": "https://gitee.com/kit101/drone-yml-test/pulls/9", + "id": 4744278, + "labels": [ + ], + "languages": [ + "Python" + ], + "merge_commit_sha": "3fbdff5796f6d57ed9f5a5dd48e5d0cad7f9c0a1", + "merge_reference_name": "refs/pull/9/MERGE", + "merge_status": "can_be_merged", + "mergeable": true, + "merged": false, + "merged_at": null, + "milestone": null, + "need_review": true, + "need_test": true, + "number": 9, + "patch_url": "https://gitee.com/kit101/drone-yml-test/pulls/9.patch", + "state": "open", + "tester": null, + "testers": [ + { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + ], + "title": "feat-3", + "updated_at": "2021-10-08T17:29:50+08:00", + "updated_by": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "push_data": null, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:29:49+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sender": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "sign": "o5L+cMcrXR+F8rVIRW+v2J/jTd9N8ZmyM3cXBte12Nc=", + "source_branch": "feat-3", + "source_repo": { + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:29:49+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:29:49+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + } + }, + "state": "open", + "target_branch": "master", + "target_repo": { + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:29:49+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:29:49+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + } + }, + "target_user": null, + "timestamp": "1633685391315", + "title": "feat-3", + "updated_by": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "url": "https://gitee.com/kit101/drone-yml-test/pulls/9" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/pr_open.json.golden b/scm/driver/gitee/testdata/webhooks/pr_open.json.golden new file mode 100644 index 000000000..6372fcc91 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/pr_open.json.golden @@ -0,0 +1,51 @@ +{ + "Action": "opened", + "Repo": { + "ID": "14836026", + "Namespace": "kit101", + "Name": "drone-yml-test", + "Branch": "master", + "Private": false, + "Clone": "https://gitee.com/kit101/drone-yml-test.git", + "CloneSSH": "git@gitee.com:kit101/drone-yml-test.git", + "Link": "https://gitee.com/kit101/drone-yml-test", + "Created": "2021-03-24T11:24:34+08:00", + "Updated": "2021-10-08T17:29:49+08:00" + }, + "PullRequest": { + "Number": 9, + "Title": "feat-3", + "Body": "feat-3", + "Sha": "dc8fa2ebe050d63f639c5b834311e96bc2303523", + "Ref": "refs/pull/9/head", + "Source": "feat-3", + "Target": "master", + "Fork": "kit101/drone-yml-test", + "Link": "https://gitee.com/kit101/drone-yml-test/pulls/9", + "Diff": "https://gitee.com/kit101/drone-yml-test/pulls/9.diff", + "Closed": false, + "Merged": false, + "Head": { + "Name": "feat-3", + "Path": "refs/heads/feat-3", + "Sha": "dc8fa2ebe050d63f639c5b834311e96bc2303523" + }, + "Base": { + "Name": "master", + "Path": "refs/heads/master", + "Sha": "2eac1cac02c325058cf959725c45b0612d3e8177" + }, + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Created": "2021-10-08T17:29:49+08:00", + "Updated": "2021-10-08T17:29:50+08:00" + }, + "Sender": { + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Name": "kit101" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/pr_unlabeled.json b/scm/driver/gitee/testdata/webhooks/pr_unlabeled.json new file mode 100644 index 000000000..2e317e8bb --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/pr_unlabeled.json @@ -0,0 +1,596 @@ +{ + "action": "update", + "action_desc": "update_label", + "author": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "body": "feat-3 1", + "enterprise": null, + "hook_id": 788005, + "hook_name": "merge_request_hooks", + "hook_url": "https://gitee.com/kit101/drone-yml-test/hooks/788005/edit", + "iid": 8, + "languages": [ + "Python" + ], + "merge_commit_sha": "cd09abc1995aede07da6524a0ace587698d74bbc", + "merge_status": "can_be_merged", + "number": 8, + "password": "", + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:16:06+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "pull_request": { + "additions": 1, + "assignee": null, + "assignees": [ + { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + ], + "base": { + "label": "kit101:master", + "ref": "master", + "repo": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:16:06+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sha": "2eac1cac02c325058cf959725c45b0612d3e8177", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "body": "feat-3 1", + "changed_files": 1, + "closed_at": null, + "comments": 0, + "commits": 1, + "created_at": "2021-10-08T17:16:06+08:00", + "deletions": 0, + "diff_url": "https://gitee.com/kit101/drone-yml-test/pulls/8.diff", + "head": { + "label": "kit101:feat-3", + "ref": "feat-3", + "repo": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:16:06+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sha": "dc8fa2ebe050d63f639c5b834311e96bc2303523", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "html_url": "https://gitee.com/kit101/drone-yml-test/pulls/8", + "id": 4744094, + "labels": [ + ], + "languages": [ + "Python" + ], + "merge_commit_sha": "cd09abc1995aede07da6524a0ace587698d74bbc", + "merge_reference_name": "refs/pull/8/MERGE", + "merge_status": "can_be_merged", + "mergeable": true, + "merged": false, + "merged_at": null, + "milestone": null, + "need_review": true, + "need_test": true, + "number": 8, + "patch_url": "https://gitee.com/kit101/drone-yml-test/pulls/8.patch", + "state": "open", + "tester": null, + "testers": [ + { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + ], + "title": "feat-3 1", + "updated_at": "2021-10-08T17:23:09+08:00", + "updated_by": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "push_data": null, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:16:06+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sender": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "sign": "X52dWAExMGFaN1+5a/RAuVtPmP5R0GL3AE4Br/MngRg=", + "source_branch": "feat-3", + "source_repo": { + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:16:06+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:16:06+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + } + }, + "state": "open", + "target_branch": "master", + "target_repo": { + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:16:06+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:15:39+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:16:06+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + } + }, + "target_user": null, + "timestamp": "1633684991291", + "title": "feat-3 1", + "updated_by": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "url": "https://gitee.com/kit101/drone-yml-test/pulls/8" +} diff --git a/scm/driver/gitee/testdata/webhooks/pr_unlabeled.json.golden b/scm/driver/gitee/testdata/webhooks/pr_unlabeled.json.golden new file mode 100644 index 000000000..4b66f143c --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/pr_unlabeled.json.golden @@ -0,0 +1,51 @@ +{ + "Action": "unlabeled", + "Repo": { + "ID": "14836026", + "Namespace": "kit101", + "Name": "drone-yml-test", + "Branch": "master", + "Private": false, + "Clone": "https://gitee.com/kit101/drone-yml-test.git", + "CloneSSH": "git@gitee.com:kit101/drone-yml-test.git", + "Link": "https://gitee.com/kit101/drone-yml-test", + "Created": "2021-03-24T11:24:34+08:00", + "Updated": "2021-10-08T17:16:06+08:00" + }, + "PullRequest": { + "Number": 8, + "Title": "feat-3 1", + "Body": "feat-3 1", + "Sha": "dc8fa2ebe050d63f639c5b834311e96bc2303523", + "Ref": "refs/pull/8/head", + "Source": "feat-3", + "Target": "master", + "Fork": "kit101/drone-yml-test", + "Link": "https://gitee.com/kit101/drone-yml-test/pulls/8", + "Diff": "https://gitee.com/kit101/drone-yml-test/pulls/8.diff", + "Closed": false, + "Merged": false, + "Head": { + "Name": "feat-3", + "Path": "refs/heads/feat-3", + "Sha": "dc8fa2ebe050d63f639c5b834311e96bc2303523" + }, + "Base": { + "Name": "master", + "Path": "refs/heads/master", + "Sha": "2eac1cac02c325058cf959725c45b0612d3e8177" + }, + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Created": "2021-10-08T17:16:06+08:00", + "Updated": "2021-10-08T17:23:09+08:00" + }, + "Sender": { + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Name": "kit101" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/pr_update.json b/scm/driver/gitee/testdata/webhooks/pr_update.json new file mode 100644 index 000000000..8ca8146eb --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/pr_update.json @@ -0,0 +1,596 @@ +{ + "action": "update", + "action_desc": "source_branch_changed", + "author": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "body": "", + "enterprise": null, + "hook_id": 788005, + "hook_name": "merge_request_hooks", + "hook_url": "https://gitee.com/kit101/drone-yml-test/hooks/788005/edit", + "iid": 7, + "languages": [ + "Python" + ], + "merge_commit_sha": "d10df103c351de96ceb9e62e6e4097f0e3420b72", + "merge_status": "can_be_resolve", + "number": 7, + "password": "", + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:38:53+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:38:53+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "pull_request": { + "additions": 11, + "assignee": null, + "assignees": [ + { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + ], + "base": { + "label": "kit101:master", + "ref": "master", + "repo": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:38:53+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:38:53+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sha": "2eac1cac02c325058cf959725c45b0612d3e8177", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "body": "", + "changed_files": 2, + "closed_at": null, + "comments": 8, + "commits": 2, + "created_at": "2021-09-30T18:10:27+08:00", + "deletions": 0, + "diff_url": "https://gitee.com/kit101/drone-yml-test/pulls/7.diff", + "head": { + "label": "kit101:feat-2", + "ref": "feat-2", + "repo": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:38:53+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:38:53+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sha": "6168d9dae737b47f00c59fafca10c913a6850c3a", + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "html_url": "https://gitee.com/kit101/drone-yml-test/pulls/7", + "id": 4731382, + "labels": [ + ], + "languages": [ + "Python" + ], + "merge_commit_sha": "d10df103c351de96ceb9e62e6e4097f0e3420b72", + "merge_reference_name": "refs/pull/7/MERGE", + "merge_status": "can_be_resolve", + "mergeable": false, + "merged": false, + "merged_at": null, + "milestone": null, + "need_review": true, + "need_test": true, + "number": 7, + "patch_url": "https://gitee.com/kit101/drone-yml-test/pulls/7.patch", + "state": "open", + "tester": null, + "testers": [ + { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + ], + "title": "feat add 3", + "updated_at": "2021-10-08T17:36:07+08:00", + "updated_by": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "user": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + } + }, + "push_data": null, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:38:53+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:38:53+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sender": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "sign": "/gLVmA+/dd5q+siOduWu3z6UGhBJ8I5Fe/Gl8zxLU7A=", + "source_branch": "feat-2", + "source_repo": { + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:38:53+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:38:53+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:38:53+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:38:53+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + } + }, + "state": "open", + "target_branch": "master", + "target_repo": { + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:38:53+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:38:53+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:38:53+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:38:53+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + } + }, + "target_user": null, + "timestamp": "1633685873030", + "title": "feat add 3", + "updated_by": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "url": "https://gitee.com/kit101/drone-yml-test/pulls/7" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/pr_update.json.golden b/scm/driver/gitee/testdata/webhooks/pr_update.json.golden new file mode 100644 index 000000000..2aaeffcd9 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/pr_update.json.golden @@ -0,0 +1,51 @@ +{ + "Action": "updated", + "Repo": { + "ID": "14836026", + "Namespace": "kit101", + "Name": "drone-yml-test", + "Branch": "master", + "Private": false, + "Clone": "https://gitee.com/kit101/drone-yml-test.git", + "CloneSSH": "git@gitee.com:kit101/drone-yml-test.git", + "Link": "https://gitee.com/kit101/drone-yml-test", + "Created": "2021-03-24T11:24:34+08:00", + "Updated": "2021-10-08T17:38:53+08:00" + }, + "PullRequest": { + "Number": 7, + "Title": "feat add 3", + "Body": "", + "Sha": "6168d9dae737b47f00c59fafca10c913a6850c3a", + "Ref": "refs/pull/7/head", + "Source": "feat-2", + "Target": "master", + "Fork": "kit101/drone-yml-test", + "Link": "https://gitee.com/kit101/drone-yml-test/pulls/7", + "Diff": "https://gitee.com/kit101/drone-yml-test/pulls/7.diff", + "Closed": false, + "Merged": false, + "Head": { + "Name": "feat-2", + "Path": "refs/heads/feat-2", + "Sha": "6168d9dae737b47f00c59fafca10c913a6850c3a" + }, + "Base": { + "Name": "master", + "Path": "refs/heads/master", + "Sha": "2eac1cac02c325058cf959725c45b0612d3e8177" + }, + "Author": { + "Login": "kit101", + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png" + }, + "Created": "2021-09-30T18:10:27+08:00", + "Updated": "2021-10-08T17:36:07+08:00" + }, + "Sender": { + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Name": "kit101" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/push.json b/scm/driver/gitee/testdata/webhooks/push.json new file mode 100644 index 000000000..24cde84b3 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/push.json @@ -0,0 +1,230 @@ +{ + "after": "9921e45e570db8e57e544650baf837932fb2100f", + "before": "6168d9dae737b47f00c59fafca10c913a6850c3a", + "commits": [ + { + "added": [ + ], + "author": { + "email": "qkssk1711@163.com", + "id": 1535738, + "name": "kit101", + "remark": null, + "time": "2021-10-08T17:53:12+08:00", + "url": "https://gitee.com/kit101", + "user": null, + "user_name": "kit101", + "username": "kit101" + }, + "committer": { + "email": "qkssk1711@163.com", + "id": 1535738, + "name": "kit101", + "remark": null, + "time": null, + "url": "https://gitee.com/kit101", + "user": null, + "user_name": "kit101", + "username": "kit101" + }, + "distinct": true, + "id": "9921e45e570db8e57e544650baf837932fb2100f", + "message": "feat-2-1\n", + "modified": [ + "modify.txt" + ], + "parent_ids": [ + "6168d9dae737b47f00c59fafca10c913a6850c3a" + ], + "removed": [ + ], + "timestamp": "2021-10-08T17:53:12+08:00", + "tree_id": "fdbf4a1239cdef7f81b6a0e76451735a8a27d2c8", + "url": "https://gitee.com/kit101/drone-yml-test/commit/9921e45e570db8e57e544650baf837932fb2100f" + } + ], + "commits_more_than_ten": false, + "compare": "https://gitee.com/kit101/drone-yml-test/compare/6168d9dae737b47f00c59fafca10c913a6850c3a...9921e45e570db8e57e544650baf837932fb2100f", + "created": false, + "deleted": false, + "enterprise": null, + "head_commit": { + "added": [ + ], + "author": { + "email": "qkssk1711@163.com", + "id": 1535738, + "name": "kit101", + "remark": null, + "time": "2021-10-08T17:53:12+08:00", + "url": "https://gitee.com/kit101", + "user": null, + "user_name": "kit101", + "username": "kit101" + }, + "committer": { + "email": "qkssk1711@163.com", + "id": 1535738, + "name": "kit101", + "remark": null, + "time": null, + "url": "https://gitee.com/kit101", + "user": null, + "user_name": "kit101", + "username": "kit101" + }, + "distinct": true, + "id": "9921e45e570db8e57e544650baf837932fb2100f", + "message": "feat-2-1\n", + "modified": [ + "modify.txt" + ], + "parent_ids": [ + "6168d9dae737b47f00c59fafca10c913a6850c3a" + ], + "removed": [ + ], + "timestamp": "2021-10-08T17:53:12+08:00", + "tree_id": "fdbf4a1239cdef7f81b6a0e76451735a8a27d2c8", + "url": "https://gitee.com/kit101/drone-yml-test/commit/9921e45e570db8e57e544650baf837932fb2100f" + }, + "hook_id": 788005, + "hook_name": "push_hooks", + "hook_url": "https://gitee.com/kit101/drone-yml-test/hooks/788005/edit", + "password": "", + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:53:18+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:53:18+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "push_data": null, + "pusher": { + "email": "qkssk1711@163.com", + "id": 1535738, + "name": "kit101", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "ref": "refs/heads/feat-2-1", + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:53:18+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:53:18+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sender": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "sign": "OyjGt7PDU9xXl5khawx5APOUmODD+SaulKYnS/Nifew=", + "timestamp": "1633686799688", + "total_commits_count": 1, + "user": { + "email": "qkssk1711@163.com", + "id": 1535738, + "name": "kit101", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "user_id": 1535738, + "user_name": "kit101" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/push.json.golden b/scm/driver/gitee/testdata/webhooks/push.json.golden new file mode 100644 index 000000000..ce613f8d6 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/push.json.golden @@ -0,0 +1,60 @@ +{ + "Ref": "refs/heads/feat-2-1", + "Before": "6168d9dae737b47f00c59fafca10c913a6850c3a", + "After": "9921e45e570db8e57e544650baf837932fb2100f", + "Repo": { + "ID": "14836026", + "Namespace": "kit101", + "Name": "drone-yml-test", + "Perm": null, + "Branch": "master", + "Private": false, + "Clone": "https://gitee.com/kit101/drone-yml-test.git", + "CloneSSH": "git@gitee.com:kit101/drone-yml-test.git", + "Link": "https://gitee.com/kit101/drone-yml-test", + "Created": "2021-03-24T11:24:34+08:00", + "Updated": "2021-10-08T17:53:18+08:00" + }, + "Commit": { + "Sha": "9921e45e570db8e57e544650baf837932fb2100f", + "Message": "feat-2-1\n", + "Author": { + "Login": "kit101", + "Name": "kit101", + "Email": "qkssk1711@163.com", + "Date": "2021-10-08T17:53:12+08:00" + }, + "Committer": { + "Login": "kit101", + "Name": "kit101", + "Email": "qkssk1711@163.com", + "Date": "2021-10-08T17:53:12+08:00" + }, + "Link": "https://gitee.com/kit101/drone-yml-test/compare/6168d9dae737b47f00c59fafca10c913a6850c3a...9921e45e570db8e57e544650baf837932fb2100f" + }, + "Commits": [ + { + "Sha": "9921e45e570db8e57e544650baf837932fb2100f", + "Message": "feat-2-1\n", + "Link": "https://gitee.com/kit101/drone-yml-test/commit/9921e45e570db8e57e544650baf837932fb2100f", + "Author": { + "Login": "kit101", + "Email": "qkssk1711@163.com", + "Name": "kit101", + "Date": "2021-10-08T17:53:12+08:00" + }, + "Committer": { + "Login": "kit101", + "Email": "qkssk1711@163.com", + "Name": "kit101", + "Date": "2021-10-08T17:53:12+08:00" + } + } + ], + "Sender": { + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Name": "kit101" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/push_branch_create.json b/scm/driver/gitee/testdata/webhooks/push_branch_create.json new file mode 100644 index 000000000..f6d56f311 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/push_branch_create.json @@ -0,0 +1,189 @@ +{ + "after": "6168d9dae737b47f00c59fafca10c913a6850c3a", + "before": "0000000000000000000000000000000000000000", + "commits": null, + "commits_more_than_ten": true, + "compare": "https://gitee.com/kit101/drone-yml-test/compare/0000000000000000000000000000000000000000...6168d9dae737b47f00c59fafca10c913a6850c3a", + "created": true, + "deleted": false, + "enterprise": null, + "head_commit": { + "added": [ + ], + "author": { + "email": "qkssk1711@163.com", + "id": 1535738, + "name": "kit101", + "remark": null, + "time": "2021-10-08T17:37:47+08:00", + "url": "https://gitee.com/kit101", + "user": null, + "user_name": "kit101", + "username": "kit101" + }, + "committer": { + "email": "qkssk1711@163.com", + "id": 1535738, + "name": "kit101", + "remark": null, + "time": null, + "url": "https://gitee.com/kit101", + "user": null, + "user_name": "kit101", + "username": "kit101" + }, + "distinct": true, + "id": "6168d9dae737b47f00c59fafca10c913a6850c3a", + "message": "feat-2\n", + "modified": [ + "modify.txt" + ], + "parent_ids": [ + "00b76e8abd51ae6a96318b3450944b32995f9158" + ], + "removed": [ + ], + "timestamp": "2021-10-08T17:37:47+08:00", + "tree_id": "59792feaa92f1bc2460eb1fbc0122dd5029ac583", + "url": "https://gitee.com/kit101/drone-yml-test/commit/6168d9dae737b47f00c59fafca10c913a6850c3a" + }, + "hook_id": 788005, + "hook_name": "push_hooks", + "hook_url": "https://gitee.com/kit101/drone-yml-test/hooks/788005/edit", + "password": "", + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:39:43+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:39:44+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "push_data": null, + "pusher": { + "email": "qkssk1711@163.com", + "id": 1535738, + "name": "kit101", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "ref": "refs/heads/feat-2-1", + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:39:43+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:39:44+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sender": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "sign": "5QkJzTgTd5PJ555MAindBUxryzHWESPOMeOz+dIzTFc=", + "timestamp": "1633686089510", + "total_commits_count": 13, + "user": { + "email": "qkssk1711@163.com", + "id": 1535738, + "name": "kit101", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "user_id": 1535738, + "user_name": "kit101" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/push_branch_create.json.golden b/scm/driver/gitee/testdata/webhooks/push_branch_create.json.golden new file mode 100644 index 000000000..3a185c633 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/push_branch_create.json.golden @@ -0,0 +1,41 @@ +{ + "Ref": "refs/heads/feat-2-1", + "Before": "0000000000000000000000000000000000000000", + "After": "6168d9dae737b47f00c59fafca10c913a6850c3a", + "Repo": { + "ID": "14836026", + "Namespace": "kit101", + "Name": "drone-yml-test", + "Perm": null, + "Branch": "master", + "Private": false, + "Clone": "https://gitee.com/kit101/drone-yml-test.git", + "CloneSSH": "git@gitee.com:kit101/drone-yml-test.git", + "Link": "https://gitee.com/kit101/drone-yml-test", + "Created": "2021-03-24T11:24:34+08:00", + "Updated": "2021-10-08T17:39:44+08:00" + }, + "Commit": { + "Sha": "6168d9dae737b47f00c59fafca10c913a6850c3a", + "Message": "feat-2\n", + "Author": { + "Login": "kit101", + "Name": "kit101", + "Email": "qkssk1711@163.com", + "Date": "2021-10-08T17:37:47+08:00" + }, + "Committer": { + "Login": "kit101", + "Name": "kit101", + "Email": "qkssk1711@163.com", + "Date": "2021-10-08T17:37:47+08:00" + }, + "Link": "https://gitee.com/kit101/drone-yml-test/compare/0000000000000000000000000000000000000000...6168d9dae737b47f00c59fafca10c913a6850c3a" + }, + "Sender": { + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Name": "kit101" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/push_branch_delete.json b/scm/driver/gitee/testdata/webhooks/push_branch_delete.json new file mode 100644 index 000000000..ed3d5c1f9 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/push_branch_delete.json @@ -0,0 +1,151 @@ +{ + "after": "0000000000000000000000000000000000000000", + "before": "dc8fa2ebe050d63f639c5b834311e96bc2303523", + "commits": [ + ], + "commits_more_than_ten": null, + "compare": "https://gitee.com/kit101/drone-yml-test/compare/dc8fa2ebe050d63f639c5b834311e96bc2303523...0000000000000000000000000000000000000000", + "created": false, + "deleted": true, + "enterprise": null, + "head_commit": null, + "hook_id": 788005, + "hook_name": "push_hooks", + "hook_url": "https://gitee.com/kit101/drone-yml-test/hooks/788005/edit", + "password": "", + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:32:30+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:32:30+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "push_data": null, + "pusher": { + "email": "qkssk1711@163.com", + "id": 1535738, + "name": "kit101", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "ref": "refs/heads/feat-3", + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T17:32:30+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T17:32:30+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sender": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "sign": "l9f7bD44j3IX+WILn5LlyNy8E37v4xP1xB6eaiMGa5A=", + "timestamp": "1633685551787", + "total_commits_count": null, + "user": { + "email": "qkssk1711@163.com", + "id": 1535738, + "name": "kit101", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "user_id": 1535738, + "user_name": "kit101" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/push_branch_delete.json.golden b/scm/driver/gitee/testdata/webhooks/push_branch_delete.json.golden new file mode 100644 index 000000000..1ddc616d3 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/push_branch_delete.json.golden @@ -0,0 +1,28 @@ +{ + "Ref": "refs/heads/feat-3", + "Before": "dc8fa2ebe050d63f639c5b834311e96bc2303523", + "After": "0000000000000000000000000000000000000000", + "Repo": { + "ID": "14836026", + "Namespace": "kit101", + "Name": "drone-yml-test", + "Perm": null, + "Branch": "master", + "Private": false, + "Clone": "https://gitee.com/kit101/drone-yml-test.git", + "CloneSSH": "git@gitee.com:kit101/drone-yml-test.git", + "Link": "https://gitee.com/kit101/drone-yml-test", + "Created": "2021-03-24T11:24:34+08:00", + "Updated": "2021-10-08T17:32:30+08:00" + }, + "Commit": { + "Sha": "0000000000000000000000000000000000000000", + "Link": "https://gitee.com/kit101/drone-yml-test/compare/dc8fa2ebe050d63f639c5b834311e96bc2303523...0000000000000000000000000000000000000000" + }, + "Sender": { + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Name": "kit101" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/tag_create.json b/scm/driver/gitee/testdata/webhooks/tag_create.json new file mode 100644 index 000000000..6a3e31511 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/tag_create.json @@ -0,0 +1,189 @@ +{ + "after": "aa9d11518a64dcd0d591a2a4eb35dfb4d91d49d5", + "before": "0000000000000000000000000000000000000000", + "commits": null, + "commits_more_than_ten": null, + "compare": "https://gitee.com/kit101/drone-yml-test/compare/0000000000000000000000000000000000000000...aa9d11518a64dcd0d591a2a4eb35dfb4d91d49d5", + "created": true, + "deleted": false, + "enterprise": null, + "head_commit": { + "added": [ + ], + "author": { + "email": "qkssk1711@163.com", + "id": 1535738, + "name": "kit101", + "remark": null, + "time": "2021-10-08T05:26:59+00:00", + "url": "https://gitee.com/kit101", + "user": null, + "user_name": "kit101", + "username": "kit101" + }, + "committer": { + "email": "noreply@gitee.com", + "id": null, + "name": "Gitee", + "remark": null, + "time": null, + "url": null, + "user": null, + "user_name": null, + "username": null + }, + "distinct": true, + "id": "aa9d11518a64dcd0d591a2a4eb35dfb4d91d49d5", + "message": "update .drone.yml.\n", + "modified": [ + ".drone.yml" + ], + "parent_ids": [ + "c2b3132aaed2dac67923a0bf7c30d8391f99d4a9" + ], + "removed": [ + ], + "timestamp": "2021-10-08T05:26:59+00:00", + "tree_id": "ce6ea40403ba16fa848a190acc5356bdb4ef2025", + "url": "https://gitee.com/kit101/drone-yml-test/commit/aa9d11518a64dcd0d591a2a4eb35dfb4d91d49d5" + }, + "hook_id": 788005, + "hook_name": "tag_push_hooks", + "hook_url": "https://gitee.com/kit101/drone-yml-test/hooks/788005/edit", + "password": "", + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T16:01:12+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T16:01:12+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "push_data": null, + "pusher": { + "email": "qkssk1711@163.com", + "id": 1535738, + "name": "kit101", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "ref": "refs/tags/1.3", + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T16:01:12+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T16:01:12+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sender": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "sign": "EDYOaI5dlyJgaiRE3jAe/fwaqZPNt1kLsRW1HY0p4tA=", + "timestamp": "1633680073933", + "total_commits_count": null, + "user": { + "email": "qkssk1711@163.com", + "id": 1535738, + "name": "kit101", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "user_id": 1535738, + "user_name": "kit101" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/tag_create.json.golden b/scm/driver/gitee/testdata/webhooks/tag_create.json.golden new file mode 100644 index 000000000..acb55e6b8 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/tag_create.json.golden @@ -0,0 +1,25 @@ +{ + "Action": "created", + "Ref": { + "Name": "1.3", + "Sha": "aa9d11518a64dcd0d591a2a4eb35dfb4d91d49d5" + }, + "Repo": { + "ID": "14836026", + "Namespace": "kit101", + "Name": "drone-yml-test", + "Branch": "master", + "Private": false, + "Clone": "https://gitee.com/kit101/drone-yml-test.git", + "CloneSSH": "git@gitee.com:kit101/drone-yml-test.git", + "Link": "https://gitee.com/kit101/drone-yml-test", + "Created": "2021-03-24T11:24:34+08:00", + "Updated": "2021-10-08T16:01:12+08:00" + }, + "Sender": { + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Name": "kit101" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/tag_delete.json b/scm/driver/gitee/testdata/webhooks/tag_delete.json new file mode 100644 index 000000000..d3eb43ca8 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/tag_delete.json @@ -0,0 +1,151 @@ +{ + "after": "0000000000000000000000000000000000000000", + "before": "aa9d11518a64dcd0d591a2a4eb35dfb4d91d49d5", + "commits": [ + ], + "commits_more_than_ten": null, + "compare": "https://gitee.com/kit101/drone-yml-test/compare/aa9d11518a64dcd0d591a2a4eb35dfb4d91d49d5...0000000000000000000000000000000000000000", + "created": false, + "deleted": true, + "enterprise": null, + "head_commit": null, + "hook_id": 788005, + "hook_name": "tag_push_hooks", + "hook_url": "https://gitee.com/kit101/drone-yml-test/hooks/788005/edit", + "password": "", + "project": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T16:16:28+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T16:16:28+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "push_data": null, + "pusher": { + "email": "qkssk1711@163.com", + "id": 1535738, + "name": "kit101", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "ref": "refs/tags/1.3", + "repository": { + "clone_url": "https://gitee.com/kit101/drone-yml-test.git", + "created_at": "2021-03-24T11:24:34+08:00", + "default_branch": "master", + "description": "", + "fork": false, + "forks_count": 0, + "full_name": "kit101/drone-yml-test", + "git_http_url": "https://gitee.com/kit101/drone-yml-test.git", + "git_ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "git_svn_url": "svn://gitee.com/kit101/drone-yml-test", + "git_url": "git://gitee.com/kit101/drone-yml-test.git", + "has_issues": true, + "has_pages": false, + "has_wiki": true, + "homepage": "https://gitee.com/kit101/drone-yml-test", + "html_url": "https://gitee.com/kit101/drone-yml-test", + "id": 14836026, + "language": null, + "license": null, + "name": "drone-yml-test", + "name_with_namespace": "kit101/drone-yml-test", + "namespace": "kit101", + "open_issues_count": 2, + "owner": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "path": "drone-yml-test", + "path_with_namespace": "kit101/drone-yml-test", + "private": false, + "pushed_at": "2021-10-08T16:16:28+08:00", + "ssh_url": "git@gitee.com:kit101/drone-yml-test.git", + "stargazers_count": 0, + "svn_url": "svn://gitee.com/kit101/drone-yml-test", + "updated_at": "2021-10-08T16:16:28+08:00", + "url": "https://gitee.com/kit101/drone-yml-test", + "watchers_count": 1 + }, + "sender": { + "avatar_url": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "email": "qkssk1711@163.com", + "html_url": "https://gitee.com/kit101", + "id": 1535738, + "login": "kit101", + "name": "kit101", + "remark": null, + "site_admin": false, + "type": "User", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "sign": "p2XLcddyIKP/Yf7VatUqTj+N1tuHchQ1c7//Lk4KSE8=", + "timestamp": "1633680992245", + "total_commits_count": null, + "user": { + "email": "qkssk1711@163.com", + "id": 1535738, + "name": "kit101", + "url": "https://gitee.com/kit101", + "user_name": "kit101", + "username": "kit101" + }, + "user_id": 1535738, + "user_name": "kit101" +} \ No newline at end of file diff --git a/scm/driver/gitee/testdata/webhooks/tag_delete.json.golden b/scm/driver/gitee/testdata/webhooks/tag_delete.json.golden new file mode 100644 index 000000000..7152c2287 --- /dev/null +++ b/scm/driver/gitee/testdata/webhooks/tag_delete.json.golden @@ -0,0 +1,25 @@ +{ + "Action": "deleted", + "Ref": { + "Name": "1.3", + "Sha": "" + }, + "Repo": { + "ID": "14836026", + "Namespace": "kit101", + "Name": "drone-yml-test", + "Branch": "master", + "Private": false, + "Clone": "https://gitee.com/kit101/drone-yml-test.git", + "CloneSSH": "git@gitee.com:kit101/drone-yml-test.git", + "Link": "https://gitee.com/kit101/drone-yml-test", + "Created": "2021-03-24T11:24:34+08:00", + "Updated": "2021-10-08T16:16:28+08:00" + }, + "Sender": { + "Avatar": "https://portrait.gitee.com/uploads/avatars/user/511/1535738_qkssk1711_1578953939.png", + "Email": "qkssk1711@163.com", + "Login": "kit101", + "Name": "kit101" + } +} \ No newline at end of file diff --git a/scm/driver/gitee/user.go b/scm/driver/gitee/user.go new file mode 100644 index 000000000..d893908de --- /dev/null +++ b/scm/driver/gitee/user.go @@ -0,0 +1,81 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "context" + "fmt" + "time" + + "github.com/drone/go-scm/scm" +) + +type userService struct { + client *wrapper +} + +func (s *userService) Find(ctx context.Context) (*scm.User, *scm.Response, error) { + out := new(user) + res, err := s.client.do(ctx, "GET", "user", nil, out) + return convertUser(out), res, err +} + +func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, error) { + user, res, err := s.Find(ctx) + if err != nil { + return "", nil, err + } + return user.Email, res, err +} + +func (s *userService) FindLogin(ctx context.Context, login string) (*scm.User, *scm.Response, error) { + path := fmt.Sprintf("users/%s", login) + out := new(user) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertUser(out), res, err +} + +type user struct { + ID int `json:"id"` + Login string `json:"login"` + Name string `json:"name"` + AvatarURL string `json:"avatar_url"` + URL string `json:"url"` + HtmlURL string `json:"html_url"` + FollowersURL string `json:"followers_url"` + FollowingURL string `json:"following_url"` + GistsURL string `json:"gists_url"` + StarredURL string `json:"starred_url"` + SubscriptionsURL string `json:"subscriptions_url"` + OrganizationsURL string `json:"organizations_url"` + ReposURL string `json:"repos_url"` + EventsURL string `json:"events_url"` + ReceivedEventsURL string `json:"received_events_url"` + Type string `json:"type"` + Blog string `json:"blog"` + Weibo string `json:"weibo"` + Bio string `json:"bio"` + PublicRepos int `json:"public_repos"` + PublicGists int `json:"public_gists"` + Followers int `json:"followers"` + Following int `json:"following"` + Stared int `json:"stared"` + Watched int `json:"watched"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + Email string `json:"email"` + Remark string `json:"remark"` +} + +func convertUser(from *user) *scm.User { + return &scm.User{ + Avatar: from.AvatarURL, + Email: from.Email, + Login: from.Login, + Name: from.Name, + Created: from.CreatedAt, + Updated: from.UpdatedAt, + } +} diff --git a/scm/driver/gitee/user_test.go b/scm/driver/gitee/user_test.go new file mode 100644 index 000000000..dc299ddb3 --- /dev/null +++ b/scm/driver/gitee/user_test.go @@ -0,0 +1,106 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "context" + "encoding/json" + "io/ioutil" + "os" + "testing" + + "github.com/drone/go-scm/scm" + + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" +) + +func TestUserFind(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/user"). + Reply(200). + Type("application/json"). + SetHeader("X-Request-Id", "7cb049dbf1fafae67b4f0aa81ca7e870"). + SetHeader("X-Runtime", "0.040217"). + SetHeader("ETag", "W/\"c50ecf93b72a24474a76423d6d5c338c\""). + File("testdata/user.json") + + client := NewDefault() + got, res, err := client.Users.Find(context.Background()) + if err != nil { + t.Error(err) + return + } + + want := new(scm.User) + raw, _ := ioutil.ReadFile("testdata/user.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + // t.Run("Rate", testRate(res)) +} + +func TestUserFindEmail(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/user"). + Reply(200). + Type("application/json"). + SetHeader("X-Request-Id", "7cb049dbf1fafae67b4f0aa81ca7e870"). + SetHeader("X-Runtime", "0.040217"). + SetHeader("ETag", "W/\"c50ecf93b72a24474a76423d6d5c338c\""). + File("testdata/user.json") + + client := NewDefault() + result, res, err := client.Users.FindEmail(context.Background()) + if err != nil { + t.Error(err) + return + } + if got, want := result, "qkssk1711@163.com"; got != want { + t.Errorf("Want user Email %q, got %q", want, got) + } + t.Run("Request", testRequest(res)) + // t.Run("Rate", testRate(res)) +} + +func TestUserFindLogin(t *testing.T) { + defer gock.Off() + + gock.New("https://gitee.com/api/v5"). + Get("/users/kit101"). + Reply(200). + Type("application/json"). + SetHeader("X-Request-Id", "7cb049dbf1fafae67b4f0aa81ca7e870"). + SetHeader("X-Runtime", "0.040217"). + File("testdata/user.json") + + client := NewDefault() + got, res, err := client.Users.FindLogin(context.Background(), "kit101") + if err != nil { + t.Error(err) + } + + want := new(scm.User) + raw, _ := ioutil.ReadFile("testdata/user.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + json.NewEncoder(os.Stdout).Encode(got) + } + + t.Run("Request", testRequest(res)) + // t.Run("Rate", testRate(res)) +} diff --git a/scm/driver/gitee/util.go b/scm/driver/gitee/util.go new file mode 100644 index 000000000..a5e1f973e --- /dev/null +++ b/scm/driver/gitee/util.go @@ -0,0 +1,75 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "net/url" + "strconv" + + "github.com/drone/go-scm/scm" +) + +func encodeListOptions(opts scm.ListOptions) string { + params := url.Values{} + if opts.Page != 0 { + params.Set("page", strconv.Itoa(opts.Page)) + } + if opts.Size != 0 { + params.Set("per_page", strconv.Itoa(opts.Size)) + } + return params.Encode() +} + +func encodeCommitListOptions(opts scm.CommitListOptions) string { + params := url.Values{} + if opts.Page != 0 { + params.Set("page", strconv.Itoa(opts.Page)) + } + if opts.Size != 0 { + params.Set("per_page", strconv.Itoa(opts.Size)) + } + if opts.Ref != "" { + params.Set("sha", opts.Ref) + } + return params.Encode() +} + +func encodeIssueListOptions(opts scm.IssueListOptions) string { + params := url.Values{} + if opts.Page != 0 { + params.Set("page", strconv.Itoa(opts.Page)) + } + if opts.Size != 0 { + params.Set("per_page", strconv.Itoa(opts.Size)) + } + // state: open, progressing, closed, rejected, all; default: open + if opts.Open && opts.Closed { + params.Set("state", "all") + } else if opts.Closed { + params.Set("state", "closed") + } else if opts.Open { + params.Set("state", "open") + } + return params.Encode() +} + +func encodePullRequestListOptions(opts scm.PullRequestListOptions) string { + params := url.Values{} + if opts.Page != 0 { + params.Set("page", strconv.Itoa(opts.Page)) + } + if opts.Size != 0 { + params.Set("per_page", strconv.Itoa(opts.Size)) + } + // state: open, closed, merged, all; default: open + if opts.Open && opts.Closed { + params.Set("state", "all") + } else if opts.Closed { + params.Set("state", "closed") + } else if opts.Open { + params.Set("state", "open") + } + return params.Encode() +} diff --git a/scm/driver/gitee/util_test.go b/scm/driver/gitee/util_test.go new file mode 100644 index 000000000..2846a9bf2 --- /dev/null +++ b/scm/driver/gitee/util_test.go @@ -0,0 +1,94 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "testing" + + "github.com/drone/go-scm/scm" +) + +func Test_encodeListOptions(t *testing.T) { + opts := scm.ListOptions{ + Page: 10, + Size: 30, + } + want := "page=10&per_page=30" + got := encodeListOptions(opts) + if got != want { + t.Errorf("Want encoded list options %q, got %q", want, got) + } +} + +func Test_encodeCommitListOptions(t *testing.T) { + opts := scm.CommitListOptions{ + Page: 10, + Size: 30, + Ref: "master", + } + want := "page=10&per_page=30&sha=master" + got := encodeCommitListOptions(opts) + if got != want { + t.Errorf("Want encoded commit list options %q, got %q", want, got) + } +} + +func Test_encodeIssueListOptions(t *testing.T) { + opts := scm.IssueListOptions{ + Page: 10, + Size: 30, + Open: true, + Closed: true, + } + want := "page=10&per_page=30&state=all" + got := encodeIssueListOptions(opts) + if got != want { + t.Errorf("Want encoded issue list options %q, got %q", want, got) + } +} + +func Test_encodeIssueListOptions_Closed(t *testing.T) { + opts := scm.IssueListOptions{ + Page: 10, + Size: 30, + Open: false, + Closed: true, + } + want := "page=10&per_page=30&state=closed" + got := encodeIssueListOptions(opts) + if got != want { + t.Errorf("Want encoded issue list options %q, got %q", want, got) + } +} + +func Test_encodePullRequestListOptions(t *testing.T) { + t.Parallel() + opts := scm.PullRequestListOptions{ + Page: 10, + Size: 30, + Open: true, + Closed: true, + } + want := "page=10&per_page=30&state=all" + got := encodePullRequestListOptions(opts) + if got != want { + t.Errorf("Want encoded pr list options %q, got %q", want, got) + } +} + +func Test_encodePullRequestListOptions_Closed(t *testing.T) { + t.Parallel() + opts := scm.PullRequestListOptions{ + Page: 10, + Size: 30, + Open: false, + Closed: true, + } + want := "page=10&per_page=30&state=closed" + got := encodePullRequestListOptions(opts) + if got != want { + t.Errorf("Want encoded pr list options %q, got %q", want, got) + } +} diff --git a/scm/driver/gitee/webhook.go b/scm/driver/gitee/webhook.go new file mode 100644 index 000000000..ec86d4d57 --- /dev/null +++ b/scm/driver/gitee/webhook.go @@ -0,0 +1,463 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "crypto/hmac" + "crypto/sha256" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net/http" + "time" + + "github.com/drone/go-scm/scm" +) + +type webhookService struct { + client *wrapper +} + +func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhook, error) { + data, err := ioutil.ReadAll( + io.LimitReader(req.Body, 10000000), + ) + if err != nil { + return nil, err + } + + var hook scm.Webhook + switch req.Header.Get("X-Gitee-Event") { + case "Push Hook": + hook, err = s.parsePushHook(data) + case "Merge Request Hook": + hook, err = s.parseMergeRequestHook(data) + case "Issue Hook": + hook, err = s.parseIssueHook(data) + case "Note Hook": + hook, err = s.parseNoteHook(data) + case "Tag Push Hook": + hook, err = s.parseTagPushHook(data) + default: + return nil, scm.ErrUnknownEvent + } + if err != nil { + return nil, err + } + + key, err := fn(hook) + if err != nil { + return hook, err + } else if key == "" { + return hook, nil + } + + agent := req.Header.Get("User-Agent") + if agent != "git-oschina-hook" { + return hook, &Error{ + Message: "hook's user-agent is not git-oschina-hook", + } + } + timestamp := req.Header.Get("X-Gitee-Timestamp") + signature := req.Header.Get("X-Gitee-Token") + + if !validateSignature(signature, key, timestamp) { + return hook, scm.ErrSignatureInvalid + } + return hook, nil +} + +func (s *webhookService) parsePushHook(data []byte) (scm.Webhook, error) { + dst := new(pushOrTagPushHook) + err := json.Unmarshal(data, dst) + return convertPushHook(dst), err +} + +func (s *webhookService) parseMergeRequestHook(data []byte) (scm.Webhook, error) { + dst := new(mergeRequestHook) + err := json.Unmarshal(data, dst) + return convertPullRequestHook(dst), err +} + +func (s *webhookService) parseIssueHook(data []byte) (scm.Webhook, error) { + dst := new(issueHook) + err := json.Unmarshal(data, dst) + return convertIssueHook(dst), err +} + +func (s *webhookService) parseTagPushHook(data []byte) (scm.Webhook, error) { + dst := new(pushOrTagPushHook) + err := json.Unmarshal(data, dst) + return convertTagPushHook(dst), err +} + +func (s *webhookService) parseNoteHook(data []byte) (scm.Webhook, error) { + dst := new(noteHook) + err := json.Unmarshal(data, dst) + return convertNoteHook(dst), err +} + +// validateSignature +// see https://gitee.com/help/articles/4290#article-header3 +func validateSignature(signature, key, timestamp string) bool { + stringToSign := timestamp + "\n" + key + h := hmac.New(sha256.New, []byte(key)) + h.Write([]byte(stringToSign)) + computedSignature := base64.StdEncoding.EncodeToString(h.Sum(nil)) + return computedSignature == signature +} + +type ( + pushOrTagPushHook struct { + Action string `json:"action"` + HookName string `json:"hook_name"` + Password string `json:"password"` + HookID int `json:"hook_id"` + HookURL string `json:"hook_url"` + Timestamp string `json:"timestamp"` + Sign string `json:"sign"` + Ref string `json:"ref"` + Before string `json:"before"` + After string `json:"after"` + Created bool `json:"created"` + Deleted bool `json:"deleted"` + Compare string `json:"compare"` + Commits []hookCommit `json:"commits"` + HeadCommit hookCommit `json:"head_commit"` + TotalCommitsCount int `json:"total_commits_count"` + CommitsMoreThanTen bool `json:"commits_more_than_ten"` + Repository hookRepository `json:"repository"` + Sender user `json:"sender"` + Enterprise enterprise `json:"enterprise"` + } + mergeRequestHook struct { + Action string `json:"action"` + + Number int `json:"number"` + Title string `json:"title"` + Project hookRepository `json:"project"` + PullRequest pr `json:"pull_request"` + + Iid int `json:"iid"` + ActionDesc string `json:"action_desc"` + Author user `json:"author"` + Body string `json:"body"` + Enterprise enterprise `json:"enterprise"` + Languages []string `json:"languages"` + MergeCommitSha string `json:"merge_commit_sha"` + MergeStatus string `json:"merge_status"` + Password string `json:"password"` + Repository hookRepository `json:"repository"` + Sender user `json:"sender"` + SourceBranch string `json:"source_branch"` + + SourceRepo struct { + Project hookRepository `json:"project"` + Repository hookRepository `json:"repository"` + } `json:"source_repo"` + TargetRepo struct { + Project hookRepository `json:"project"` + Repository hookRepository `json:"repository"` + } `json:"target_repo"` + State string `json:"state"` + TargetBranch string `json:"target_branch"` + TargetUser user `json:"target_user"` + Timestamp string `json:"timestamp"` + UpdatedBy user `json:"updated_by"` + URL string `json:"url"` + } + noteHook struct { + Action string `json:"action"` + HookName string `json:"hook_name"` + Password string `json:"password"` + HookID int `json:"hook_id"` + HookURL string `json:"hook_url"` + Timestamp string `json:"timestamp"` + Sign string `json:"sign"` + Comment hookComment `json:"comment"` + NoteableType string `json:"noteable_type"` + Issue issue `json:"issue"` + PullRequest pr `json:"pull_request"` + Repository hookRepository `json:"repository"` + Sender user `json:"sender"` + Enterprise enterprise `json:"enterprise"` + } + issueHook struct { + Action string `json:"action"` + HookName string `json:"hook_name"` + Password string `json:"password"` + HookID int `json:"hook_id"` + HookURL string `json:"hook_url"` + Timestamp string `json:"timestamp"` + Sign string `json:"sign"` + Issue issue `json:"issue"` + Repository hookRepository `json:"repository"` + Sender user `json:"sender"` + Enterprise enterprise `json:"enterprise"` + } + + hookAuthorOrCommitter struct { + Time time.Time `json:"time"` + Name string `json:"name"` + Email string `json:"email"` + Username string `json:"username"` + UserName string `json:"user_name"` + URL string `json:"url"` + } + hookCommit struct { + ID string `json:"id"` + TreeID string `json:"tree_id"` + Distinct bool `json:"distinct"` + Message string `json:"message"` + Timestamp time.Time `json:"timestamp"` + URL string `json:"url"` + Author hookAuthorOrCommitter `json:"author"` + Committer hookAuthorOrCommitter `json:"committer"` + Added interface{} `json:"added"` + Removed interface{} `json:"removed"` + Modified []string `json:"modified"` + } + hookComment struct { + HtmlURL string `json:"html_url"` + ID int `json:"id"` + Body string `json:"body"` + User user `json:"user"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + } + hookRepository struct { + CloneURL string `json:"clone_url"` + CreatedAt time.Time `json:"created_at"` + DefaultBranch string `json:"default_branch"` + Description string `json:"description"` + Fork bool `json:"fork"` + ForksCount int `json:"forks_count"` + FullName string `json:"full_name"` + GitHttpURL string `json:"git_http_url"` + GitSshURL string `json:"git_ssh_url"` + GitSvnURL string `json:"git_svn_url"` + GitURL string `json:"git_url"` + HasIssues bool `json:"has_issues"` + HasPages bool `json:"has_pages"` + HasWiki bool `json:"has_wiki"` + Homepage string `json:"homepage"` + HtmlURL string `json:"html_url"` + ID int `json:"id"` + Language interface{} `json:"language"` + License interface{} `json:"license"` + Name string `json:"name"` + NameWithNamespace string `json:"name_with_namespace"` + Namespace string `json:"namespace"` + OpenIssuesCount int `json:"open_issues_count"` + Owner user `json:"owner"` + Path string `json:"path"` + PathWithNamespace string `json:"path_with_namespace"` + Private bool `json:"private"` + PushedAt time.Time `json:"pushed_at"` + SSHURL string `json:"ssh_url"` + StargazersCount int `json:"stargazers_count"` + SvnURL string `json:"svn_url"` + UpdatedAt time.Time `json:"updated_at"` + URL string `json:"url"` + WatchersCount int `json:"watchers_count"` + } + enterprise struct { + Name string `json:"name"` + URL string `json:"url"` + } +) + +func convertPushHook(src *pushOrTagPushHook) *scm.PushHook { + var commits []scm.Commit + if &src.Commits != nil { + for _, c := range src.Commits { + commits = append(commits, + scm.Commit{ + Sha: c.ID, + Message: c.Message, + Link: c.URL, + Author: scm.Signature{ + Login: c.Author.Username, + Email: c.Author.Email, + Name: c.Author.Name, + Date: c.Timestamp, + }, + Committer: scm.Signature{ + Login: c.Committer.Username, + Email: c.Committer.Email, + Name: c.Committer.Name, + Date: c.Timestamp, + }, + }) + } + } + + dst := &scm.PushHook{ + Ref: src.Ref, + Repo: *convertHookRepository(&src.Repository), + Before: src.Before, + After: src.After, + Commit: scm.Commit{ + Sha: src.After, + Link: src.Compare, + }, + Sender: *convertUser(&src.Sender), + Commits: commits, + } + if &src.HeadCommit != nil { + dst.Commit.Message = src.HeadCommit.Message + dst.Commit.Author = scm.Signature{ + Login: src.HeadCommit.Author.Username, + Email: src.HeadCommit.Author.Email, + Name: src.HeadCommit.Author.Name, + Date: src.HeadCommit.Timestamp, + } + dst.Commit.Committer = scm.Signature{ + Login: src.HeadCommit.Committer.Username, + Email: src.HeadCommit.Committer.Email, + Name: src.HeadCommit.Committer.Name, + Date: src.HeadCommit.Timestamp, + } + } + return dst +} + +func convertPullRequestHook(src *mergeRequestHook) *scm.PullRequestHook { + dst := &scm.PullRequestHook{ + Repo: *convertHookRepository(&src.Repository), + PullRequest: *convertPullRequest(&src.PullRequest), + Sender: *convertUser(&src.Sender), + } + switch src.Action { + case "update": + if src.ActionDesc == "update_label" { + if len(src.PullRequest.Labels) == 0 { + dst.Action = scm.ActionUnlabel + } else { + dst.Action = scm.ActionLabel + } + } else { + if src.ActionDesc == "target_branch_changed" || src.ActionDesc == "source_branch_changed" { + dst.Action = scm.ActionUpdate + } + } + case "open": + dst.Action = scm.ActionOpen + case "close": + dst.Action = scm.ActionClose + case "merge": + dst.Action = scm.ActionMerge + case "test", "tested", "assign", "approved": + // do nothing + } + return dst +} + +func convertIssueHook(src *issueHook) *scm.IssueHook { + dst := &scm.IssueHook{ + Repo: *convertHookRepository(&src.Repository), + Issue: *convertIssue(&src.Issue), + Sender: *convertUser(&src.Sender), + } + switch src.Action { + case "open": + dst.Action = scm.ActionOpen + case "delete": + dst.Action = scm.ActionClose + case "state_change": + switch src.Issue.State { + case "open": + dst.Action = scm.ActionOpen + case "progressing": + dst.Action = scm.ActionOpen + case "close", "rejected": + dst.Action = scm.ActionClose + } + case "assign": + dst.Action = scm.ActionUpdate + } + return dst +} + +func convertTagPushHook(src *pushOrTagPushHook) scm.Webhook { + dst := &scm.TagHook{ + Ref: scm.Reference{ + Name: scm.TrimRef(src.Ref), + Sha: src.HeadCommit.ID, + }, + Repo: *convertHookRepository(&src.Repository), + Sender: *convertUser(&src.Sender), + } + if src.Created { + dst.Action = scm.ActionCreate + } else if src.Deleted { + dst.Action = scm.ActionDelete + dst.Ref.Sha = "" + } + return dst +} + +func convertNoteHook(src *noteHook) scm.Webhook { + convertHookComment := func(comment *hookComment) *scm.Comment { + return &scm.Comment{ + ID: comment.ID, + Body: comment.Body, + Author: *convertUser(&comment.User), + Created: comment.CreatedAt, + Updated: comment.UpdatedAt, + } + } + convertCommentAction := func(src string) (action scm.Action) { + switch src { + case "comment": + return scm.ActionCreate + case "edited": + return scm.ActionEdit + case "deleted": + return scm.ActionDelete + default: + return + } + } + + if src.NoteableType == "Issue" { + return &scm.IssueCommentHook{ + Action: convertCommentAction(src.Action), + Repo: *convertHookRepository(&src.Repository), + Issue: *convertIssue(&src.Issue), + Comment: *convertHookComment(&src.Comment), + Sender: *convertUser(&src.Sender), + } + } + + if src.NoteableType == "PullRequest" { + // not support review comment + return &scm.PullRequestCommentHook{ + Action: convertCommentAction(src.Action), + Repo: *convertHookRepository(&src.Repository), + PullRequest: *convertPullRequest(&src.PullRequest), + Comment: *convertHookComment(&src.Comment), + Sender: *convertUser(&src.Sender), + } + } + return nil +} + +func convertHookRepository(from *hookRepository) *scm.Repository { + return &scm.Repository{ + ID: fmt.Sprint(from.ID), + Namespace: from.Namespace, + Name: from.Name, + Branch: from.DefaultBranch, + Private: from.Private, + Clone: from.CloneURL, + CloneSSH: from.GitSshURL, + Link: from.HtmlURL, + Created: from.CreatedAt, + Updated: from.UpdatedAt, + } +} diff --git a/scm/driver/gitee/webhook_test.go b/scm/driver/gitee/webhook_test.go new file mode 100644 index 000000000..9cb013db3 --- /dev/null +++ b/scm/driver/gitee/webhook_test.go @@ -0,0 +1,265 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gitee + +import ( + "bytes" + "encoding/json" + "io/ioutil" + "net/http" + "strings" + "testing" + + "github.com/drone/go-scm/scm" + + "github.com/google/go-cmp/cmp" +) + +func TestWebhooks(t *testing.T) { + tests := []struct { + event string + before string + after string + obj interface{} + }{ + // + // Push Hook events + // + + // Push Hook + { + event: "Push Hook", + before: "testdata/webhooks/push.json", + after: "testdata/webhooks/push.json.golden", + obj: new(scm.PushHook), + }, + // Push Hook create + { + event: "Push Hook", + before: "testdata/webhooks/push_branch_create.json", + after: "testdata/webhooks/push_branch_create.json.golden", + obj: new(scm.PushHook), + }, + // Push Hook delete + { + event: "Push Hook", + before: "testdata/webhooks/push_branch_delete.json", + after: "testdata/webhooks/push_branch_delete.json.golden", + obj: new(scm.PushHook), + }, + + // + // Push Tag Hook events + // + + // Push Tag Hook create + { + event: "Tag Push Hook", + before: "testdata/webhooks/tag_create.json", + after: "testdata/webhooks/tag_create.json.golden", + obj: new(scm.TagHook), + }, + // Push Tag Hook delete + { + event: "Tag Push Hook", + before: "testdata/webhooks/tag_delete.json", + after: "testdata/webhooks/tag_delete.json.golden", + obj: new(scm.TagHook), + }, + + // + // Merge Request Hook events + // + + // Merge Request Hook merge + { + event: "Merge Request Hook", + before: "testdata/webhooks/pr_merge.json", + after: "testdata/webhooks/pr_merge.json.golden", + obj: new(scm.PullRequestHook), + }, + // Merge Request Hook open + { + event: "Merge Request Hook", + before: "testdata/webhooks/pr_open.json", + after: "testdata/webhooks/pr_open.json.golden", + obj: new(scm.PullRequestHook), + }, + // Merge Request Hook close + { + event: "Merge Request Hook", + before: "testdata/webhooks/pr_close.json", + after: "testdata/webhooks/pr_close.json.golden", + obj: new(scm.PullRequestHook), + }, + // pull request update + { + event: "Merge Request Hook", + before: "testdata/webhooks/pr_update.json", + after: "testdata/webhooks/pr_update.json.golden", + obj: new(scm.PullRequestHook), + }, + // Merge Request Hook labeled + { + event: "Merge Request Hook", + before: "testdata/webhooks/pr_labeled.json", + after: "testdata/webhooks/pr_labeled.json.golden", + obj: new(scm.PullRequestHook), + }, + // Merge Request Hook unlabeled + { + event: "Merge Request Hook", + before: "testdata/webhooks/pr_unlabeled.json", + after: "testdata/webhooks/pr_unlabeled.json.golden", + obj: new(scm.PullRequestHook), + }, + + // + // Issue Hook events + // + + // Issue Hook open + { + event: "Issue Hook", + before: "testdata/webhooks/issue_hook_open.json", + after: "testdata/webhooks/issue_hook_open.json.golden", + obj: new(scm.IssueHook), + }, + // Issue Hook delete + { + event: "Issue Hook", + before: "testdata/webhooks/issue_hook_delete.json", + after: "testdata/webhooks/issue_hook_delete.json.golden", + obj: new(scm.IssueHook), + }, + // Issue Hook state_change + { + event: "Issue Hook", + before: "testdata/webhooks/issue_hook_state_change.json", + after: "testdata/webhooks/issue_hook_state_change.json.golden", + obj: new(scm.IssueHook), + }, + // Issue Hook assign + { + event: "Issue Hook", + before: "testdata/webhooks/issue_hook_assign.json", + after: "testdata/webhooks/issue_hook_assign.json.golden", + obj: new(scm.IssueHook), + }, + + // + // Note Hook events + // + + // Note Hook issue comment + { + event: "Note Hook", + before: "testdata/webhooks/note_hook_issue_comment.json", + after: "testdata/webhooks/note_hook_issue_comment.json.golden", + obj: new(scm.IssueCommentHook), + }, + // Note Hook pull request comment + { + event: "Note Hook", + before: "testdata/webhooks/note_hook_pr_comment.json", + after: "testdata/webhooks/note_hook_pr_comment.json.golden", + obj: new(scm.PullRequestCommentHook), + }, + } + + for _, test := range tests { + before, err := ioutil.ReadFile(test.before) + if err != nil { + t.Error(err) + continue + } + after, err := ioutil.ReadFile(test.after) + if err != nil { + t.Error(err) + continue + } + + buf := bytes.NewBuffer(before) + r, _ := http.NewRequest("GET", "/", buf) + r.Header.Set("X-Gitee-Event", test.event) + r.Header.Set("X-Gitee-Token", "Xvh4YPVe6l31XpDRL9J2yeaEXabsckIoUUschpXiVck=") + r.Header.Set("X-Gitee-Timestamp", "1633679083918") + r.Header.Set("User-Agent", "git-oschina-hook") + + s := new(webhookService) + o, err := s.Parse(r, secretFunc) + if err != nil && err != scm.ErrSignatureInvalid { + t.Error(err) + continue + } + + err = json.Unmarshal(after, test.obj) + if err != nil { + t.Error(err) + continue + } + + if diff := cmp.Diff(test.obj, o); diff != "" { + t.Errorf("Error unmarshaling %s", test.before) + t.Log(diff) + } + + switch event := o.(type) { + case *scm.PushHook: + if !strings.HasPrefix(event.Ref, "refs/") { + t.Errorf("Push hook reference must start with refs/") + } + case *scm.TagHook: + if strings.HasPrefix(event.Ref.Name, "refs/") { + t.Errorf("Branch hook reference must not start with refs/") + } + } + } +} + +func TestWebhook_ErrUnknownEvent(t *testing.T) { + f, _ := ioutil.ReadFile("testdata/webhooks/push.json") + r, _ := http.NewRequest("GET", "/", bytes.NewBuffer(f)) + + s := new(webhookService) + _, err := s.Parse(r, secretFunc) + if err != scm.ErrUnknownEvent { + t.Errorf("Expect unknown event error, got %v", err) + } +} + +func TestWebhookInvalid(t *testing.T) { + f, _ := ioutil.ReadFile("testdata/webhooks/push.json") + r, _ := http.NewRequest("GET", "/", bytes.NewBuffer(f)) + r.Header.Set("X-Gitee-Event", "Push Hook") + r.Header.Set("X-Gitee-Token", "Xvh4YPVe6l31XpDRL9J2yeaEXabsckIoUUschpXiVck=") + r.Header.Set("X-Gitee-Timestamp", "1633679083917") + r.Header.Set("User-Agent", "git-oschina-hook") + + s := new(webhookService) + _, err := s.Parse(r, secretFunc) + if err != scm.ErrSignatureInvalid { + t.Errorf("Expect invalid signature error, got %v", err) + } +} + +func TestWebhookValid(t *testing.T) { + f, _ := ioutil.ReadFile("testdata/webhooks/push.json") + r, _ := http.NewRequest("GET", "/", bytes.NewBuffer(f)) + r.Header.Set("X-Gitee-Event", "Push Hook") + r.Header.Set("X-Gitee-Token", "Xvh4YPVe6l31XpDRL9J2yeaEXabsckIoUUschpXiVck=") + r.Header.Set("X-Gitee-Timestamp", "1633679083918") + r.Header.Set("User-Agent", "git-oschina-hook") + + s := new(webhookService) + _, err := s.Parse(r, secretFunc) + if err != nil { + t.Errorf("Expect valid signature, got %v", err) + } +} + +func secretFunc(scm.Webhook) (string, error) { + return "bBg5lrt03VixkX85CNqYIcecC0SIGASE", nil +} From 0f9d34907ff15943cd78382008eeffd3c0170fba Mon Sep 17 00:00:00 2001 From: Eoin McAfee Date: Fri, 19 Nov 2021 10:22:01 +0000 Subject: [PATCH 046/282] release prep for 1.16.0 --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9dd93640..0fe8af0d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [v1.16.0](https://github.com/drone/go-scm/tree/v1.16.0) (2021-11-19) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.15.2...v1.16.0) + +**Implemented enhancements:** + +- Feat: implemented gitee provider [\#124](https://github.com/drone/go-scm/pull/124) ([kit101](https://github.com/kit101)) +- add release & milestone functionality [\#121](https://github.com/drone/go-scm/pull/121) ([eoinmcafee00](https://github.com/eoinmcafee00)) + +**Fixed bugs:** + +- Fix Gitea example code on README.md [\#126](https://github.com/drone/go-scm/pull/126) ([lunny](https://github.com/lunny)) + ## [v1.15.2](https://github.com/drone/go-scm/tree/v1.15.2) (2021-07-20) [Full Changelog](https://github.com/drone/go-scm/compare/v1.15.1...v1.15.2) @@ -15,6 +28,7 @@ **Merged pull requests:** +- \(maint\) prep for v.1.15.2 release [\#118](https://github.com/drone/go-scm/pull/118) ([tphoney](https://github.com/tphoney)) - Add a vet step to drone config [\#83](https://github.com/drone/go-scm/pull/83) ([tboerger](https://github.com/tboerger)) All notable changes to this project will be documented in this file. From 477c7b0a665276e688851bc440f3c4ef68236c08 Mon Sep 17 00:00:00 2001 From: Jim Sheldon Date: Fri, 19 Nov 2021 09:57:42 -0500 Subject: [PATCH 047/282] swap repo and target in bitbucket CompareChanges (#127) bitbucket's API doc states the diffstat spec: "Note: This is the opposite of the order used in git diff." see https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories/%7Bworkspace%7D/%7Brepo_slug%7D/diffstat/%7Bspec%7D I was unable to use this function without this change --- scm/driver/bitbucket/git.go | 2 +- scm/driver/bitbucket/git_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scm/driver/bitbucket/git.go b/scm/driver/bitbucket/git.go index dcbc6c005..5048750fc 100644 --- a/scm/driver/bitbucket/git.go +++ b/scm/driver/bitbucket/git.go @@ -81,7 +81,7 @@ func (s *gitService) ListChanges(ctx context.Context, repo, ref string, opts scm } func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, opts scm.ListOptions) ([]*scm.Change, *scm.Response, error) { - path := fmt.Sprintf("2.0/repositories/%s/diffstat/%s..%s?%s", repo, source, target, encodeListOptions(opts)) + path := fmt.Sprintf("2.0/repositories/%s/diffstat/%s..%s?%s", repo, target, source, encodeListOptions(opts)) out := new(diffstats) res, err := s.client.do(ctx, "GET", path, nil, &out) copyPagination(out.pagination, res) diff --git a/scm/driver/bitbucket/git_test.go b/scm/driver/bitbucket/git_test.go index 8b305fa77..59e1ca4b6 100644 --- a/scm/driver/bitbucket/git_test.go +++ b/scm/driver/bitbucket/git_test.go @@ -233,7 +233,7 @@ func TestGitCompareChanges(t *testing.T) { defer gock.Off() gock.New("https://api.bitbucket.org"). - Get("/2.0/repositories/atlassian/atlaskit/diffstat/dec26e0fe887167743c2b7e36531dedfeb6cd478..425863f9dbe56d70c8dcdbf2e4e0805e85591fcc"). + Get("/2.0/repositories/atlassian/atlaskit/diffstat/425863f9dbe56d70c8dcdbf2e4e0805e85591fcc..dec26e0fe887167743c2b7e36531dedfeb6cd478"). MatchParam("page", "1"). MatchParam("pagelen", "30"). Reply(200). From 848abb9d674c1d75146ccf2e0572c4aef72b3648 Mon Sep 17 00:00:00 2001 From: Eoin McAfee Date: Fri, 19 Nov 2021 15:02:22 +0000 Subject: [PATCH 048/282] release prep --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fe8af0d8..0cbd91f07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,20 @@ # Changelog +## [v1.16.1](https://github.com/drone/go-scm/tree/v1.16.1) (2021-11-19) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.16.0...v1.16.1) + +**Fixed bugs:** + +- swap repo and target in bitbucket CompareChanges [\#127](https://github.com/drone/go-scm/pull/127) ([jimsheldon](https://github.com/jimsheldon)) + ## [v1.16.0](https://github.com/drone/go-scm/tree/v1.16.0) (2021-11-19) [Full Changelog](https://github.com/drone/go-scm/compare/v1.15.2...v1.16.0) **Implemented enhancements:** +- release prep for 1.16.0 [\#128](https://github.com/drone/go-scm/pull/128) ([eoinmcafee00](https://github.com/eoinmcafee00)) - Feat: implemented gitee provider [\#124](https://github.com/drone/go-scm/pull/124) ([kit101](https://github.com/kit101)) - add release & milestone functionality [\#121](https://github.com/drone/go-scm/pull/121) ([eoinmcafee00](https://github.com/eoinmcafee00)) From 0430535f62d654cc7eb003aaef1f225968c294b1 Mon Sep 17 00:00:00 2001 From: kit101 Date: Tue, 30 Nov 2021 18:14:14 +0800 Subject: [PATCH 049/282] fixbug: gitee webhook parse (#131) * fixbug: pull request hook action * unit test --- .../testdata/webhooks/pr_update.json.golden | 2 +- scm/driver/gitee/webhook.go | 23 +++++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/scm/driver/gitee/testdata/webhooks/pr_update.json.golden b/scm/driver/gitee/testdata/webhooks/pr_update.json.golden index 2aaeffcd9..5e11ac3d7 100644 --- a/scm/driver/gitee/testdata/webhooks/pr_update.json.golden +++ b/scm/driver/gitee/testdata/webhooks/pr_update.json.golden @@ -1,5 +1,5 @@ { - "Action": "updated", + "Action": "synchronized", "Repo": { "ID": "14836026", "Namespace": "kit101", diff --git a/scm/driver/gitee/webhook.go b/scm/driver/gitee/webhook.go index ec86d4d57..6866baa54 100644 --- a/scm/driver/gitee/webhook.go +++ b/scm/driver/gitee/webhook.go @@ -340,10 +340,11 @@ func convertPullRequestHook(src *mergeRequestHook) *scm.PullRequestHook { } else { dst.Action = scm.ActionLabel } - } else { - if src.ActionDesc == "target_branch_changed" || src.ActionDesc == "source_branch_changed" { - dst.Action = scm.ActionUpdate - } + } else if src.ActionDesc == "source_branch_changed" { + // Gitee does not provide a synchronize action. + // But when action_desc is 'source_branch_changed', + // what happens is the same as GitHub's synchronize + dst.Action = scm.ActionSync } case "open": dst.Action = scm.ActionOpen @@ -352,7 +353,9 @@ func convertPullRequestHook(src *mergeRequestHook) *scm.PullRequestHook { case "merge": dst.Action = scm.ActionMerge case "test", "tested", "assign", "approved": - // do nothing + dst.Action = scm.ActionUnknown + default: + dst.Action = scm.ActionUnknown } return dst } @@ -370,15 +373,15 @@ func convertIssueHook(src *issueHook) *scm.IssueHook { dst.Action = scm.ActionClose case "state_change": switch src.Issue.State { - case "open": - dst.Action = scm.ActionOpen - case "progressing": + case "open", "progressing": dst.Action = scm.ActionOpen case "close", "rejected": dst.Action = scm.ActionClose } case "assign": dst.Action = scm.ActionUpdate + default: + dst.Action = scm.ActionUnknown } return dst } @@ -397,6 +400,8 @@ func convertTagPushHook(src *pushOrTagPushHook) scm.Webhook { } else if src.Deleted { dst.Action = scm.ActionDelete dst.Ref.Sha = "" + } else { + dst.Action = scm.ActionUnknown } return dst } @@ -420,7 +425,7 @@ func convertNoteHook(src *noteHook) scm.Webhook { case "deleted": return scm.ActionDelete default: - return + return scm.ActionUnknown } } From 0d046871e2640119cc255cfc437be6439d95d576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Ga=C4=87e=C5=A1a?= Date: Tue, 30 Nov 2021 11:49:41 +0100 Subject: [PATCH 050/282] release prep v1.16.2 --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cbd91f07..c1c35fcd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [v1.16.2](https://github.com/drone/go-scm/tree/v1.16.2) (2021-11-30) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.16.1...v1.16.2) + +**Merged pull requests:** + +- fixbug: gitee webhook parse [\#131](https://github.com/drone/go-scm/pull/131) ([kit101](https://github.com/kit101)) + ## [v1.16.1](https://github.com/drone/go-scm/tree/v1.16.1) (2021-11-19) [Full Changelog](https://github.com/drone/go-scm/compare/v1.16.0...v1.16.1) @@ -8,6 +16,10 @@ - swap repo and target in bitbucket CompareChanges [\#127](https://github.com/drone/go-scm/pull/127) ([jimsheldon](https://github.com/jimsheldon)) +**Merged pull requests:** + +- release prep v1.16.1 [\#129](https://github.com/drone/go-scm/pull/129) ([eoinmcafee00](https://github.com/eoinmcafee00)) + ## [v1.16.0](https://github.com/drone/go-scm/tree/v1.16.0) (2021-11-19) [Full Changelog](https://github.com/drone/go-scm/compare/v1.15.2...v1.16.0) From 3dbe29d23a0514fd29c929d4cd2101a04b936474 Mon Sep 17 00:00:00 2001 From: Eoin McAfee <83226740+eoinmcafee00@users.noreply.github.com> Date: Thu, 30 Dec 2021 13:10:19 +0000 Subject: [PATCH 051/282] fixes issue due to change by atlassian https://developer.atlassian.com/cloud/bitbucket/bitbucket-api-teams-deprecation/ (#137) --- scm/driver/bitbucket/org.go | 6 ++--- scm/driver/bitbucket/org_test.go | 4 +-- scm/driver/bitbucket/testdata/team.json | 34 +++++++++++++++++++----- scm/driver/bitbucket/testdata/teams.json | 8 +++--- 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/scm/driver/bitbucket/org.go b/scm/driver/bitbucket/org.go index e14ba594c..7efd0e2a3 100644 --- a/scm/driver/bitbucket/org.go +++ b/scm/driver/bitbucket/org.go @@ -16,7 +16,7 @@ type organizationService struct { } func (s *organizationService) Find(ctx context.Context, name string) (*scm.Organization, *scm.Response, error) { - path := fmt.Sprintf("2.0/teams/%s", name) + path := fmt.Sprintf("2.0/workspaces/%s", name) out := new(organization) res, err := s.client.do(ctx, "GET", path, nil, out) return convertOrganization(out), res, err @@ -27,7 +27,7 @@ func (s *organizationService) FindMembership(ctx context.Context, name, username } func (s *organizationService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Organization, *scm.Response, error) { - path := fmt.Sprintf("2.0/teams?%s", encodeListRoleOptions(opts)) + path := fmt.Sprintf("2.0/workspaces?%s", encodeListRoleOptions(opts)) out := new(organizationList) res, err := s.client.do(ctx, "GET", path, nil, out) copyPagination(out.pagination, res) @@ -48,7 +48,7 @@ type organizationList struct { } type organization struct { - Login string `json:"username"` + Login string `json:"slug"` } func convertOrganization(from *organization) *scm.Organization { diff --git a/scm/driver/bitbucket/org_test.go b/scm/driver/bitbucket/org_test.go index 0868f7b34..62f19c7df 100644 --- a/scm/driver/bitbucket/org_test.go +++ b/scm/driver/bitbucket/org_test.go @@ -20,7 +20,7 @@ func TestOrganizationFind(t *testing.T) { defer gock.Off() gock.New("https://api.bitbucket.org"). - Get("/2.0/teams/atlassian"). + Get("/2.0/workspaces/atlassian"). Reply(200). Type("application/json"). File("testdata/team.json") @@ -45,7 +45,7 @@ func TestOrganizationList(t *testing.T) { defer gock.Off() gock.New("https://api.bitbucket.org"). - Get("/2.0/teams"). + Get("/2.0/workspaces"). MatchParam("pagelen", "30"). MatchParam("page", "1"). Reply(200). diff --git a/scm/driver/bitbucket/testdata/team.json b/scm/driver/bitbucket/testdata/team.json index 929b2595f..97a446fad 100644 --- a/scm/driver/bitbucket/testdata/team.json +++ b/scm/driver/bitbucket/testdata/team.json @@ -1,17 +1,37 @@ { - "username": "atlassian", - "type": "team", - "display_name": "Atlassian", "uuid": "{02b941e3-cfaa-40f9-9a58-cec53e20bdc3}", "links": { + "owners": { + "href": "https://api.bitbucket.org/2.0/workspaces/atlassian/members?q=permission%3D%22owner%22" + }, + "hooks": { + "href": "https://api.bitbucket.org/2.0/workspaces/atlassian/hooks" + }, "self": { - "href": "https:\/\/api.bitbucket.org\/2.0\/teams\/atlassian" + "href": "https://api.bitbucket.org/2.0/workspaces/atlassian" + }, + "repositories": { + "href": "https://api.bitbucket.org/2.0/repositories/atlassian" }, "html": { - "href": "https:\/\/bitbucket.org\/atlassian\/" + "href": "https://bitbucket.org/atlassian/" }, "avatar": { - "href": "https:\/\/bitbucket.org\/account\/atlassian\/avatar\/32\/" + "href": "https://bitbucket.org/workspaces/atlassian/avatar/?ts=1612327398" + }, + "members": { + "href": "https://api.bitbucket.org/2.0/workspaces/atlassian/members" + }, + "projects": { + "href": "https://api.bitbucket.org/2.0/workspaces/atlassian/projects" + }, + "snippets": { + "href": "https://api.bitbucket.org/2.0/snippets/atlassian" } - } + }, + "created_on": "2018-11-29T02:26:39.297476+00:00", + "type": "workspace", + "slug": "atlassian", + "is_private": true, + "name": "Atlassian" } \ No newline at end of file diff --git a/scm/driver/bitbucket/testdata/teams.json b/scm/driver/bitbucket/testdata/teams.json index b767565d1..3b47bbf52 100644 --- a/scm/driver/bitbucket/testdata/teams.json +++ b/scm/driver/bitbucket/testdata/teams.json @@ -2,9 +2,10 @@ "pagelen": 30, "values": [ { - "username": "atlassian", + "slug": "atlassian", "website": null, - "display_name": "Atlassian", + "is_private": false, + "name": "Atlassian", "uuid": "{d5bb8c49-f033-4498-910e-7e4b546b04ee}", "links": { "hooks": { @@ -39,8 +40,7 @@ } }, "created_on": "2012-11-08T19:05:39.080491+00:00", - "location": null, - "type": "team" + "type": "workspace" } ], "page": 1, From 6f375cd990b71b1d37109df3b060158952bc4fe5 Mon Sep 17 00:00:00 2001 From: Eoin McAfee <83226740+eoinmcafee00@users.noreply.github.com> Date: Thu, 30 Dec 2021 13:19:19 +0000 Subject: [PATCH 052/282] V1.16.3 (#138) * release prep v1.16.3 --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1c35fcd0..86b5a8169 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,24 @@ # Changelog +## [v1.16.3](https://github.com/drone/go-scm/tree/v1.16.3) (2021-12-30) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.16.2...v1.16.3) + +**Fixed bugs:** + +- fix the deprecation of Bitbucket API endpoint /2.0/teams breaks user registration \(136\) [\#137](https://github.com/drone/go-scm/pull/137) ([eoinmcafee00](https://github.com/eoinmcafee00)) + +**Closed issues:** + +- Any plans to support manage wehook [\#134](https://github.com/drone/go-scm/issues/134) + ## [v1.16.2](https://github.com/drone/go-scm/tree/v1.16.2) (2021-11-30) [Full Changelog](https://github.com/drone/go-scm/compare/v1.16.1...v1.16.2) **Merged pull requests:** +- release prep v1.16.2 [\#132](https://github.com/drone/go-scm/pull/132) ([marko-gacesa](https://github.com/marko-gacesa)) - fixbug: gitee webhook parse [\#131](https://github.com/drone/go-scm/pull/131) ([kit101](https://github.com/kit101)) ## [v1.16.1](https://github.com/drone/go-scm/tree/v1.16.1) (2021-11-19) From abe308c453f9a76896ea94e60818b6726c9435a7 Mon Sep 17 00:00:00 2001 From: Deepak Patankar Date: Tue, 4 Jan 2022 16:33:09 +0530 Subject: [PATCH 053/282] Add the support for delete of the bitbucket file (#139) * Add the support for delete of the bitbucket * Removed the print statements * Fix the delete file in bitbucket test --- scm/driver/bitbucket/bitbucket.go | 30 ++++++++++++++++++++++++ scm/driver/bitbucket/content.go | 20 +++++++++++++++- scm/driver/bitbucket/content_test.go | 34 ++++++++++++++++++++++++---- 3 files changed, 79 insertions(+), 5 deletions(-) diff --git a/scm/driver/bitbucket/bitbucket.go b/scm/driver/bitbucket/bitbucket.go index 1b8a1af77..d5afda370 100644 --- a/scm/driver/bitbucket/bitbucket.go +++ b/scm/driver/bitbucket/bitbucket.go @@ -98,6 +98,36 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface req.Header = map[string][]string{ "Content-Type": {w.FormDataContentType()}, } + case *contentDelete: + body := &bytes.Buffer{} + writer := multipart.NewWriter(body) + fw, err := writer.CreateFormField("files") + _, err = io.Copy(fw, strings.NewReader(content.File)) + if err != nil { + return nil, err + } + fw, err = writer.CreateFormField("message") + _, err = io.Copy(fw, strings.NewReader(content.Message)) + if err != nil { + return nil, err + } + fw, err = writer.CreateFormField("author") + _, err = io.Copy(fw, strings.NewReader(content.Author)) + if err != nil { + return nil, err + } + if content.Branch != "" { + fw, err = writer.CreateFormField("branch") + _, err = io.Copy(fw, strings.NewReader(content.Branch)) + if err != nil { + return nil, err + } + } + writer.Close() + req.Body = bytes.NewReader(body.Bytes()) + req.Header = map[string][]string{ + "Content-Type": {writer.FormDataContentType()}, + } default: buf := new(bytes.Buffer) json.NewEncoder(buf).Encode(in) diff --git a/scm/driver/bitbucket/content.go b/scm/driver/bitbucket/content.go index 73f91d79e..eda337ad7 100644 --- a/scm/driver/bitbucket/content.go +++ b/scm/driver/bitbucket/content.go @@ -68,7 +68,17 @@ func (s *contentService) Update(ctx context.Context, repo, path string, params * } func (s *contentService) Delete(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { - return nil, scm.ErrNotSupported + author := fmt.Sprintf("%s <%s>", params.Signature.Name, params.Signature.Email) + endpoint := fmt.Sprintf("/2.0/repositories/%s/src", repo) + in := &contentDelete{ + File: path, + Branch: params.Branch, + Message: params.Message, + Sha: params.Sha, + Author: author, + } + res, err := s.client.do(ctx, "POST", endpoint, in, nil) + return res, err } func (s *contentService) List(ctx context.Context, repo, path, ref string, opts scm.ListOptions) ([]*scm.ContentInfo, *scm.Response, error) { @@ -109,6 +119,14 @@ type contentCreateUpdate struct { Author string `json:"author"` } +type contentDelete struct { + File string `json:"file"` + Branch string `json:"branch"` + Message string `json:"message"` + Sha string `json:"sha"` + Author string `json:"author"` +} + func convertContentInfoList(from *contents) []*scm.ContentInfo { to := []*scm.ContentInfo{} for _, v := range from.Values { diff --git a/scm/driver/bitbucket/content_test.go b/scm/driver/bitbucket/content_test.go index 3336f8cd2..3ec8083cd 100644 --- a/scm/driver/bitbucket/content_test.go +++ b/scm/driver/bitbucket/content_test.go @@ -183,10 +183,36 @@ func TestContentUpdateBadCommitID(t *testing.T) { } func TestContentDelete(t *testing.T) { - content := new(contentService) - _, err := content.Delete(context.Background(), "atlassian/atlaskit", "README", &scm.ContentParams{}) - if err != scm.ErrNotSupported { - t.Errorf("Expect Not Supported error") + defer gock.Off() + + gock.New("https://api.bitbucket.org"). + Post("/2.0/repositories/atlassian/atlaskit/src"). + Reply(201). + Type("application/json") + + params := &scm.ContentParams{ + Message: "my commit message", + Signature: scm.Signature{ + Name: "Monalisa Octocat", + Email: "octocat@github.com", + }, + } + + client := NewDefault() + res, err := client.Contents.Update( + context.Background(), + "atlassian/atlaskit", + "test/hello", + params, + ) + + if err != nil { + t.Error(err) + return + } + + if res.Status != 201 { + t.Errorf("Unexpected Results") } } From 97f72c06217691b3ac195c10aaf00aa53b504b23 Mon Sep 17 00:00:00 2001 From: Rick <1450685+LinuxSuRen@users.noreply.github.com> Date: Tue, 4 Jan 2022 19:08:15 +0800 Subject: [PATCH 054/282] Fix the syntax error of the example code (#135) --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c149e22e3..8de18fd6b 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,7 @@ package main import ( "github.com/drone/go-scm/scm" "github.com/drone/go-scm/scm/driver/github" + "github.com/drone/go-scm/scm/transport" "github.com/drone/go-scm/scm/driver/transport/oauth2" ) @@ -104,9 +105,9 @@ func main() { // provide a custom http.Client with a transport // that injects the oauth2 token. - client.Client := &http.Client{ - Transport: &Transport{ - Source: StaticTokenSource( + client.Client = &http.Client{ + Transport: &oauth2.Transport{ + Source: oauth2.StaticTokenSource( &scm.Token{ Token: "ecf4c1f9869f59758e679ab54b4", }, @@ -117,8 +118,8 @@ func main() { // provide a custom http.Client with a transport // that injects the private GitLab token through // the PRIVATE_TOKEN header variable. - client.Client := &http.Client{ - Transport: &PrivateToken{ + client.Client = &http.Client{ + Transport: &transport.PrivateToken{ Token: "ecf4c1f9869f59758e679ab54b4", }, } From 6645267b11205239fc97c57a441a845a9fe03ee3 Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Tue, 4 Jan 2022 15:57:05 -0500 Subject: [PATCH 055/282] Update README.md --- README.md | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8de18fd6b..1d21878d8 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ func main() { ## Authentication -The scm client does not directly handle authentication. Instead, when creating a new client, provide a `http.Client` that can handle authentication for you. For convenience, this library includes oauth1 and oauth2 implementations that can be used to authenticate requests. +The scm client does not directly handle authentication. Instead, when creating a new client, provide an `http.Client` that can handle authentication for you. For convenience, this library includes oauth1 and oauth2 implementations that can be used to authenticate requests. ```Go package main @@ -97,7 +97,7 @@ import ( "github.com/drone/go-scm/scm" "github.com/drone/go-scm/scm/driver/github" "github.com/drone/go-scm/scm/transport" - "github.com/drone/go-scm/scm/driver/transport/oauth2" + "github.com/drone/go-scm/scm/transport/oauth2" ) func main() { @@ -126,6 +126,48 @@ func main() { } ``` +## Usage + +The scm client exposes dozens of endpoints for working with repositories, issues, comments, files and more. Please see the [godocs](https://pkg.go.dev/github.com/drone/go-scm/scm#pkg-examples) to learn more. + +Example code to get an issue: + +```Go +issue, _, err := client.Issues.Find(ctx, "octocat/Hello-World", 1) +if err != nil { + log.Fatal(err) +} +``` + +Example code to get a list of issues: + +```Go +opts := scm.IssueListOptions{ + Page: 1, + Size: 30, + Open: true, + Closed: false, +} + +issues, _, err := client.Issues.List(ctx, "octocat/Hello-World", opts) +if err != nil { + log.Fatal(err) +} +``` + +Example code to create a comment: + +```Go +in := &scm.CommentInput{ + Body: "Found a bug", +} + +comment, _, err := client.Issues.CreateComment(ctx, "octocat/Hello-World", 1, in) +if err != nil { + log.Fatal(err) +} +``` + ## Release procedure Run the changelog generator. From 5c272c281bce131ca498898e5633289491aff6f9 Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Tue, 4 Jan 2022 15:57:33 -0500 Subject: [PATCH 056/282] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1d21878d8..939f8ec87 100644 --- a/README.md +++ b/README.md @@ -155,7 +155,7 @@ if err != nil { } ``` -Example code to create a comment: +Example code to create an issue comment: ```Go in := &scm.CommentInput{ From 1d3b75a76707a5ca00d1e9e4e7704d1eee27fb6b Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Tue, 4 Jan 2022 15:58:25 -0500 Subject: [PATCH 057/282] Update README.md [CI SKIP] --- README.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/README.md b/README.md index 939f8ec87..9046a8518 100644 --- a/README.md +++ b/README.md @@ -134,9 +134,6 @@ Example code to get an issue: ```Go issue, _, err := client.Issues.Find(ctx, "octocat/Hello-World", 1) -if err != nil { - log.Fatal(err) -} ``` Example code to get a list of issues: @@ -150,9 +147,6 @@ opts := scm.IssueListOptions{ } issues, _, err := client.Issues.List(ctx, "octocat/Hello-World", opts) -if err != nil { - log.Fatal(err) -} ``` Example code to create an issue comment: @@ -163,9 +157,6 @@ in := &scm.CommentInput{ } comment, _, err := client.Issues.CreateComment(ctx, "octocat/Hello-World", 1, in) -if err != nil { - log.Fatal(err) -} ``` ## Release procedure From aa33b4279af2c13c8ba0a73dbf93f049c566f92e Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Thu, 6 Jan 2022 16:02:28 -0500 Subject: [PATCH 058/282] added Archived flag to Repository struct for GitHub and GitLab --- scm/driver/github/repo.go | 2 ++ scm/driver/github/testdata/repo.json | 2 +- scm/driver/github/testdata/repo.json.golden | 1 + scm/driver/gitlab/repo.go | 2 ++ scm/repo.go | 1 + 5 files changed, 7 insertions(+), 1 deletion(-) diff --git a/scm/driver/github/repo.go b/scm/driver/github/repo.go index 27cb11794..ce8049fde 100644 --- a/scm/driver/github/repo.go +++ b/scm/driver/github/repo.go @@ -24,6 +24,7 @@ type repository struct { FullName string `json:"full_name"` Private bool `json:"private"` Fork bool `json:"fork"` + Archived bool `json:"archived"` Visibility string `json:"visibility"` HTMLURL string `json:"html_url"` SSHURL string `json:"ssh_url"` @@ -205,6 +206,7 @@ func convertRepository(from *repository) *scm.Repository { }, Link: from.HTMLURL, Branch: from.DefaultBranch, + Archived: from.Archived, Private: from.Private, Visibility: convertVisibility(from.Visibility), Clone: from.CloneURL, diff --git a/scm/driver/github/testdata/repo.json b/scm/driver/github/testdata/repo.json index 7a759a19b..b30d1d653 100644 --- a/scm/driver/github/testdata/repo.json +++ b/scm/driver/github/testdata/repo.json @@ -86,7 +86,7 @@ "has_wiki": true, "has_pages": false, "has_downloads": true, - "archived": false, + "archived": true, "pushed_at": "2011-01-26T19:06:43Z", "created_at": "2011-01-26T19:01:12Z", "updated_at": "2011-01-26T19:14:43Z", diff --git a/scm/driver/github/testdata/repo.json.golden b/scm/driver/github/testdata/repo.json.golden index 5fa8c4db1..472a08636 100644 --- a/scm/driver/github/testdata/repo.json.golden +++ b/scm/driver/github/testdata/repo.json.golden @@ -9,6 +9,7 @@ }, "Branch": "master", "Private": true, + "Archived": true, "Visibility": 1, "Clone": "https://github.com/octocat/Hello-World.git", "CloneSSH": "git@github.com:octocat/Hello-World.git", diff --git a/scm/driver/gitlab/repo.go b/scm/driver/gitlab/repo.go index 4ed8b39e5..23a04ffc6 100644 --- a/scm/driver/gitlab/repo.go +++ b/scm/driver/gitlab/repo.go @@ -22,6 +22,7 @@ type repository struct { PathNamespace string `json:"path_with_namespace"` DefaultBranch string `json:"default_branch"` Visibility string `json:"visibility"` + Archived bool `json:"archived"` WebURL string `json:"web_url"` SSHURL string `json:"ssh_url_to_repo"` HTTPURL string `json:"http_url_to_repo"` @@ -180,6 +181,7 @@ func convertRepository(from *repository) *scm.Repository { Namespace: from.Namespace.Path, Name: from.Path, Branch: from.DefaultBranch, + Archived: from.Archived, Private: convertPrivate(from.Visibility), Visibility: convertVisibility(from.Visibility), Clone: from.HTTPURL, diff --git a/scm/repo.go b/scm/repo.go index 8bcfa7231..b62b53755 100644 --- a/scm/repo.go +++ b/scm/repo.go @@ -17,6 +17,7 @@ type ( Name string Perm *Perm Branch string + Archived bool Private bool Visibility Visibility Clone string From 2a7233f5f4d57a994af6c4b64c710a9f6e22e287 Mon Sep 17 00:00:00 2001 From: Eoin McAfee <83226740+eoinmcafee00@users.noreply.github.com> Date: Fri, 7 Jan 2022 14:21:20 +0000 Subject: [PATCH 059/282] map archive repo response (#141) --- scm/driver/gitea/repo.go | 2 ++ scm/driver/gitea/testdata/repo.json | 3 ++- scm/driver/gitea/testdata/repo.json.golden | 3 ++- scm/driver/gitea/testdata/repos.json | 3 ++- scm/driver/gitea/testdata/repos.json.golden | 3 ++- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/scm/driver/gitea/repo.go b/scm/driver/gitea/repo.go index 154c7f322..4a58ef2bc 100644 --- a/scm/driver/gitea/repo.go +++ b/scm/driver/gitea/repo.go @@ -148,6 +148,7 @@ type ( CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` Permissions perm `json:"permissions"` + Archived bool `json:"archived"` } // gitea permissions details. @@ -215,6 +216,7 @@ func convertRepository(src *repository) *scm.Repository { Clone: src.CloneURL, CloneSSH: src.SSHURL, Link: src.HTMLURL, + Archived: src.Archived, } } diff --git a/scm/driver/gitea/testdata/repo.json b/scm/driver/gitea/testdata/repo.json index 536d5f238..2f1756fb5 100644 --- a/scm/driver/gitea/testdata/repo.json +++ b/scm/driver/gitea/testdata/repo.json @@ -32,5 +32,6 @@ "admin": true, "push": true, "pull": true - } + }, + "archived": false } \ No newline at end of file diff --git a/scm/driver/gitea/testdata/repo.json.golden b/scm/driver/gitea/testdata/repo.json.golden index 15fc567c1..62aee5e3c 100644 --- a/scm/driver/gitea/testdata/repo.json.golden +++ b/scm/driver/gitea/testdata/repo.json.golden @@ -13,5 +13,6 @@ "CloneSSH": "git@try.gitea.io:go-gitea/gitea.git", "Link": "https://try.gitea.io/go-gitea/gitea", "Created": "0001-01-01T00:00:00Z", - "Updated": "0001-01-01T00:00:00Z" + "Updated": "0001-01-01T00:00:00Z", + "Archived": false } \ No newline at end of file diff --git a/scm/driver/gitea/testdata/repos.json b/scm/driver/gitea/testdata/repos.json index 89e446201..8576aaeab 100644 --- a/scm/driver/gitea/testdata/repos.json +++ b/scm/driver/gitea/testdata/repos.json @@ -33,6 +33,7 @@ "admin": true, "push": true, "pull": true - } + }, + "archived": false } ] diff --git a/scm/driver/gitea/testdata/repos.json.golden b/scm/driver/gitea/testdata/repos.json.golden index 620565c96..35314d2ac 100644 --- a/scm/driver/gitea/testdata/repos.json.golden +++ b/scm/driver/gitea/testdata/repos.json.golden @@ -14,6 +14,7 @@ "CloneSSH": "git@try.gitea.io:go-gitea/gitea.git", "Link": "https://try.gitea.io/go-gitea/gitea", "Created": "0001-01-01T00:00:00Z", - "Updated": "0001-01-01T00:00:00Z" + "Updated": "0001-01-01T00:00:00Z", + "Archived": false } ] \ No newline at end of file From c1649f4aa1dd6719a6e8510780e7c72dcfcaab09 Mon Sep 17 00:00:00 2001 From: Eoin McAfee <83226740+eoinmcafee00@users.noreply.github.com> Date: Fri, 7 Jan 2022 14:42:11 +0000 Subject: [PATCH 060/282] release prep for v1.17.0 (#142) * release prep for v1.17.0 --- CHANGELOG.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86b5a8169..f455f84e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [v1.17.0](https://github.com/drone/go-scm/tree/v1.17.0) (2022-01-07) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.16.3...v1.17.0) + +**Implemented enhancements:** + +- \(feat\) map archive flag to repo response [\#141](https://github.com/drone/go-scm/pull/141) ([eoinmcafee00](https://github.com/eoinmcafee00)) +- Add the support for delete of the bitbucket file [\#139](https://github.com/drone/go-scm/pull/139) ([DeepakPatankar](https://github.com/DeepakPatankar)) + +**Fixed bugs:** + +- Fix the syntax error of the example code [\#135](https://github.com/drone/go-scm/pull/135) ([LinuxSuRen](https://github.com/LinuxSuRen)) + +**Closed issues:** + +- The deprecation of Bitbucket API endpoint /2.0/teams breaks user registration [\#136](https://github.com/drone/go-scm/issues/136) + ## [v1.16.3](https://github.com/drone/go-scm/tree/v1.16.3) (2021-12-30) [Full Changelog](https://github.com/drone/go-scm/compare/v1.16.2...v1.16.3) @@ -12,6 +29,10 @@ - Any plans to support manage wehook [\#134](https://github.com/drone/go-scm/issues/134) +**Merged pull requests:** + +- V1.16.3 [\#138](https://github.com/drone/go-scm/pull/138) ([eoinmcafee00](https://github.com/eoinmcafee00)) + ## [v1.16.2](https://github.com/drone/go-scm/tree/v1.16.2) (2021-11-30) [Full Changelog](https://github.com/drone/go-scm/compare/v1.16.1...v1.16.2) From e4fe5885683e6d69323c731842a80282549e14ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaakko=20Kantoj=C3=A4rvi?= Date: Tue, 23 Nov 2021 15:44:42 +0200 Subject: [PATCH 061/282] Implement pull-request related events in Stash driver * handle rebases to a pull request * handle target branch changes of a pull request * handle deletion of a pull request --- scm/driver/stash/pr.go | 10 + scm/driver/stash/testdata/pr.json.golden | 10 + scm/driver/stash/testdata/prs.json.golden | 10 + .../testdata/webhooks/pr_declined.json.golden | 10 + .../testdata/webhooks/pr_deleted.json.golden | 54 ++++- .../webhooks/pr_from_ref_updated.json | 159 +++++++++++++ .../webhooks/pr_from_ref_updated.json.golden | 53 +++++ .../testdata/webhooks/pr_merged.json.golden | 10 + .../testdata/webhooks/pr_modified_meta.json | 224 ++++++++++++++++++ .../webhooks/pr_modified_meta.json.golden | 53 +++++ .../testdata/webhooks/pr_modified_toref.json | 167 +++++++++++++ .../webhooks/pr_modified_toref.json.golden | 53 +++++ .../testdata/webhooks/pr_open.json.golden | 10 + scm/driver/stash/webhook.go | 30 ++- scm/driver/stash/webhook_test.go | 32 +++ 15 files changed, 882 insertions(+), 3 deletions(-) create mode 100644 scm/driver/stash/testdata/webhooks/pr_from_ref_updated.json create mode 100644 scm/driver/stash/testdata/webhooks/pr_from_ref_updated.json.golden create mode 100644 scm/driver/stash/testdata/webhooks/pr_modified_meta.json create mode 100644 scm/driver/stash/testdata/webhooks/pr_modified_meta.json.golden create mode 100644 scm/driver/stash/testdata/webhooks/pr_modified_toref.json create mode 100644 scm/driver/stash/testdata/webhooks/pr_modified_toref.json.golden diff --git a/scm/driver/stash/pr.go b/scm/driver/stash/pr.go index 061b27b3a..836c5392b 100644 --- a/scm/driver/stash/pr.go +++ b/scm/driver/stash/pr.go @@ -230,6 +230,16 @@ func convertPullRequest(from *pr) *scm.PullRequest { Merged: from.State == "MERGED", Created: time.Unix(from.CreatedDate/1000, 0), Updated: time.Unix(from.UpdatedDate/1000, 0), + Head: scm.Reference{ + Name: from.FromRef.DisplayID, + Path: from.FromRef.ID, + Sha: from.FromRef.LatestCommit, + }, + Base: scm.Reference{ + Name: from.ToRef.DisplayID, + Path: from.ToRef.ID, + Sha: from.ToRef.LatestCommit, + }, Author: scm.User{ Login: from.Author.User.Slug, Name: from.Author.User.DisplayName, diff --git a/scm/driver/stash/testdata/pr.json.golden b/scm/driver/stash/testdata/pr.json.golden index 8ec0d5d2f..72e48a411 100644 --- a/scm/driver/stash/testdata/pr.json.golden +++ b/scm/driver/stash/testdata/pr.json.golden @@ -10,6 +10,16 @@ "Link": "http://example.com:7990/projects/PRJ/repos/my-repo/pull-requests/1", "Closed": false, "Merged": false, + "Base": { + "Name": "master", + "Path": "refs/heads/master", + "Sha": "5c64a07cd6c0f21b753bf261ef059c7e7633c50a" + }, + "Head": { + "Name": "feature/x", + "Path": "refs/heads/feature/x", + "Sha": "131cb13f4aed12e725177bc4b7c28db67839bf9f" + }, "Author": { "Login": "jcitizen", "Name": "Jane Citizen", diff --git a/scm/driver/stash/testdata/prs.json.golden b/scm/driver/stash/testdata/prs.json.golden index c9ede89d8..085a38788 100644 --- a/scm/driver/stash/testdata/prs.json.golden +++ b/scm/driver/stash/testdata/prs.json.golden @@ -11,6 +11,16 @@ "Link": "http://example.com:7990/projects/PRJ/repos/my-repo/pull-requests/1", "Closed": false, "Merged": false, + "Base": { + "Name": "master", + "Path": "refs/heads/master", + "Sha": "5c64a07cd6c0f21b753bf261ef059c7e7633c50a" + }, + "Head": { + "Name": "feature/x", + "Path": "refs/heads/feature/x", + "Sha": "131cb13f4aed12e725177bc4b7c28db67839bf9f" + }, "Author": { "Login": "jcitizen", "Name": "Jane Citizen", diff --git a/scm/driver/stash/testdata/webhooks/pr_declined.json.golden b/scm/driver/stash/testdata/webhooks/pr_declined.json.golden index 828961b05..936b70c82 100644 --- a/scm/driver/stash/testdata/webhooks/pr_declined.json.golden +++ b/scm/driver/stash/testdata/webhooks/pr_declined.json.golden @@ -25,6 +25,16 @@ "Link": "", "Closed": true, "Merged": false, + "Base": { + "Name": "master", + "Path": "refs/heads/master", + "Sha": "823b2230a56056231c9425d63758fa87078a66b4" + }, + "Head": { + "Name": "develop", + "Path": "refs/heads/develop", + "Sha": "b9eaed50a03c073b20dfa82e5e753d295e7f0e56" + }, "Author": { "Login": "jcitizen", "Name": "Jane Citizen", diff --git a/scm/driver/stash/testdata/webhooks/pr_deleted.json.golden b/scm/driver/stash/testdata/webhooks/pr_deleted.json.golden index 9e26dfeeb..7852bd44a 100644 --- a/scm/driver/stash/testdata/webhooks/pr_deleted.json.golden +++ b/scm/driver/stash/testdata/webhooks/pr_deleted.json.golden @@ -1 +1,53 @@ -{} \ No newline at end of file +{ + "Action": "closed", + "Repo": { + "ID": "1", + "Namespace": "PRJ", + "Name": "my-repo", + "Perm": null, + "Branch": "master", + "Private": true, + "Clone": "", + "CloneSSH": "", + "Link": "", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 2, + "Title": "added LICENSE", + "Body": "added BSD license text", + "Sha": "b9eaed50a03c073b20dfa82e5e753d295e7f0e56", + "Ref": "refs/pull-requests/2/from", + "Source": "develop", + "Target": "master", + "Fork": "PRJ/my-repo", + "Link": "", + "Closed": true, + "Merged": false, + "Base": { + "Name": "master", + "Path": "refs/heads/master", + "Sha": "823b2230a56056231c9425d63758fa87078a66b4" + }, + "Head": { + "Name": "develop", + "Path": "refs/heads/develop", + "Sha": "b9eaed50a03c073b20dfa82e5e753d295e7f0e56" + }, + "Author": { + "Login": "jcitizen", + "Name": "Jane Citizen", + "Email": "jane@example.com", + "Avatar": "https://www.gravatar.com/avatar/9e26471d35a78862c17e467d87cddedf.jpg" + }, + "Created": "2018-07-05T12:21:30-07:00", + "Updated": "2018-07-05T12:30:48-07:00" + }, + "Sender": { + "Login": "jcitizen", + "Name": "Jane Citizen", + "Email": "jane@example.com", + "Avatar": "https://www.gravatar.com/avatar/9e26471d35a78862c17e467d87cddedf.jpg" + } +} diff --git a/scm/driver/stash/testdata/webhooks/pr_from_ref_updated.json b/scm/driver/stash/testdata/webhooks/pr_from_ref_updated.json new file mode 100644 index 000000000..aaf938392 --- /dev/null +++ b/scm/driver/stash/testdata/webhooks/pr_from_ref_updated.json @@ -0,0 +1,159 @@ +{ + "eventKey": "pr:from_ref_updated", + "date": "2021-11-23T10:02:52+0000", + "actor": { + "name": "jcitizen", + "emailAddress": "jane@example.com", + "id": 1, + "displayName": "Jane Citizen", + "active": true, + "slug": "jcitizen", + "type": "NORMAL", + "links": { + "self": [ + { + "href": "http://example.com:7990/users/jcitizen" + } + ] + } + }, + "pullRequest": { + "id": 2, + "version": 0, + "title": "added LICENSE", + "description": "added BSD license text", + "state": "OPEN", + "open": true, + "closed": false, + "createdDate": 1637591800463, + "updatedDate": 1637661772258, + "fromRef": { + "id": "refs/heads/feature-2", + "displayId": "feature-2", + "latestCommit": "c00d0f269a9844dd168f72f6a9d78a9cff49a318", + "type": "BRANCH", + "repository": { + "slug": "my-repo", + "id": 1, + "name": "my-repo", + "hierarchyId": "5aa23c1a1280b0c0acce", + "scmId": "git", + "state": "AVAILABLE", + "statusMessage": "Available", + "forkable": true, + "project": { + "key": "PRJ", + "id": 2, + "name": "PRJ", + "public": false, + "type": "NORMAL", + "links": { + "self": [ + { + "href": "http://example.com:7990/projects/PRJ" + } + ] + } + }, + "public": false, + "links": { + "clone": [ + { + "href": "http://example.com:7990/scm/prj/my-repo.git", + "name": "http" + }, + { + "href": "ssh://git@example.com:7999/prj/my-repo.git", + "name": "ssh" + } + ], + "self": [ + { + "href": "http://example.com:7990/projects/PRJ/repos/my-repo/browse" + } + ] + } + } + }, + "toRef": { + "id": "refs/heads/master", + "displayId": "master", + "type": "BRANCH", + "latestCommit": "823b2230a56056231c9425d63758fa87078a66b4", + "repository": { + "slug": "my-repo", + "id": 1, + "name": "my-repo", + "hierarchyId": "5aa23c1a1280b0c0acce", + "scmId": "git", + "state": "AVAILABLE", + "statusMessage": "Available", + "forkable": true, + "project": { + "key": "PRJ", + "id": 2, + "name": "PRJ", + "public": false, + "type": "NORMAL", + "links": { + "self": [ + { + "href": "http://example.com:7990/projects/PRJ" + } + ] + } + }, + "public": false, + "links": { + "clone": [ + { + "href": "http://example.com:7990/scm/prj/my-repo.git", + "name": "http" + }, + { + "href": "ssh://git@example.com:7999/prj/my-repo.git", + "name": "ssh" + } + ], + "self": [ + { + "href": "http://example.com:7990/projects/PRJ/repos/my-repo/browse" + } + ] + } + } + }, + "locked": false, + "author": { + "user": { + "name": "jcitizen", + "emailAddress": "jane@example.com", + "id": 1, + "displayName": "Jane Citizen", + "active": true, + "slug": "jcitizen", + "type": "NORMAL", + "links": { + "self": [ + { + "href": "http://example.com:7990/users/jcitizen" + } + ] + } + }, + "role": "AUTHOR", + "approved": false, + "status": "UNAPPROVED" + }, + "reviewers": [], + "participants": [], + "links": { + "self": [ + { + "href": "http://example.com:7990/projects/PRJ/repos/my-repo/pull-requests/2" + } + ] + } + }, + "previousFromHash": "caf52ccb18c039cd9b930ed1f7b3edfb34cb92dd" +} diff --git a/scm/driver/stash/testdata/webhooks/pr_from_ref_updated.json.golden b/scm/driver/stash/testdata/webhooks/pr_from_ref_updated.json.golden new file mode 100644 index 000000000..ce48bb948 --- /dev/null +++ b/scm/driver/stash/testdata/webhooks/pr_from_ref_updated.json.golden @@ -0,0 +1,53 @@ +{ + "Action": "synchronized", + "Repo": { + "ID": "1", + "Namespace": "PRJ", + "Name": "my-repo", + "Perm": null, + "Branch": "master", + "Private": true, + "Clone": "http://example.com:7990/scm/prj/my-repo.git", + "CloneSSH": "ssh://git@example.com:7999/prj/my-repo.git", + "Link": "http://example.com:7990/projects/PRJ/repos/my-repo/browse", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 2, + "Title": "added LICENSE", + "Body": "added BSD license text", + "Sha": "c00d0f269a9844dd168f72f6a9d78a9cff49a318", + "Ref": "refs/pull-requests/2/from", + "Source": "feature-2", + "Target": "master", + "Fork": "PRJ/my-repo", + "Link": "http://example.com:7990/projects/PRJ/repos/my-repo/pull-requests/2", + "Closed": false, + "Merged": false, + "Base": { + "Name": "master", + "Path": "refs/heads/master", + "Sha": "823b2230a56056231c9425d63758fa87078a66b4" + }, + "Head": { + "Name": "feature-2", + "Path": "refs/heads/feature-2", + "Sha": "c00d0f269a9844dd168f72f6a9d78a9cff49a318" + }, + "Author": { + "Login": "jcitizen", + "Name": "Jane Citizen", + "Email": "jane@example.com", + "Avatar": "https://www.gravatar.com/avatar/9e26471d35a78862c17e467d87cddedf.jpg" + }, + "Created": "2021-11-22T14:36:40Z", + "Updated": "2021-11-23T10:02:52Z" + }, + "Sender": { + "Login": "jcitizen", + "Name": "Jane Citizen", + "Email": "jane@example.com", + "Avatar": "https://www.gravatar.com/avatar/9e26471d35a78862c17e467d87cddedf.jpg" + } +} diff --git a/scm/driver/stash/testdata/webhooks/pr_merged.json.golden b/scm/driver/stash/testdata/webhooks/pr_merged.json.golden index 7f15cd419..344032d2c 100644 --- a/scm/driver/stash/testdata/webhooks/pr_merged.json.golden +++ b/scm/driver/stash/testdata/webhooks/pr_merged.json.golden @@ -25,6 +25,16 @@ "Link": "", "Closed": true, "Merged": true, + "Base": { + "Name": "master", + "Path": "refs/heads/master", + "Sha": "823b2230a56056231c9425d63758fa87078a66b4" + }, + "Head": { + "Name": "develop", + "Path": "refs/heads/develop", + "Sha": "b9eaed50a03c073b20dfa82e5e753d295e7f0e56" + }, "Author": { "Login": "jcitizen", "Name": "Jane Citizen", diff --git a/scm/driver/stash/testdata/webhooks/pr_modified_meta.json b/scm/driver/stash/testdata/webhooks/pr_modified_meta.json new file mode 100644 index 000000000..a44e432b7 --- /dev/null +++ b/scm/driver/stash/testdata/webhooks/pr_modified_meta.json @@ -0,0 +1,224 @@ +{ + "eventKey": "pr:modified", + "date": "2021-11-24T14:43:48+0000", + "actor": { + "name": "jcitizen", + "emailAddress": "jane@example.com", + "id": 1, + "displayName": "Jane Citizen", + "active": true, + "slug": "jcitizen", + "type": "NORMAL", + "links": { + "self": [ + { + "href": "http://example.com:7990/users/jcitizen" + } + ] + } + }, + "pullRequest": { + "id": 6, + "version": 1, + "title": "Clean README.md", + "description": "Removed old information out of `REAME.nd`.", + "state": "OPEN", + "open": true, + "closed": false, + "createdDate": 1637764009216, + "updatedDate": 1637765028112, + "fromRef": { + "id": "refs/heads/cleanup", + "displayId": "cleanup", + "latestCommit": "a268fca7b65055e13f60ac1a2c9a527615f113ca", + "type": "BRANCH", + "repository": { + "slug": "my-repo", + "id": 12, + "name": "My Repo", + "hierarchyId": "5aa23c1a1280b0c0acce", + "scmId": "git", + "state": "AVAILABLE", + "statusMessage": "Available", + "forkable": true, + "origin": { + "slug": "my-repo", + "id": 1, + "name": "My Repo", + "hierarchyId": "5aa23c1a1280b0c0acce", + "scmId": "git", + "state": "AVAILABLE", + "statusMessage": "Available", + "forkable": true, + "project": { + "key": "PRJ", + "id": 2, + "name": "Project", + "public": false, + "type": "NORMAL", + "links": { + "self": [ + { + "href": "http://example.com:7990/projects/PRJ" + } + ] + } + }, + "public": false, + "links": { + "clone": [ + { + "href": "ssh://git@example.com:7999/prj/my-repo.git", + "name": "ssh" + }, + { + "href": "http://example.com:7990/scm/prj/my-repo.git", + "name": "http" + } + ], + "self": [ + { + "href": "http://example.com:7990/projects/PRJ/repos/my-repo/browse" + } + ] + } + }, + "project": { + "key": "~jcitizen", + "id": 1, + "name": "Jane Citizen", + "type": "PERSONAL", + "owner": { + "name": "jcitizen", + "emailAddress": "jane@example.com", + "id": 2, + "displayName": "Jane Citizen", + "active": true, + "slug": "jcitizen", + "type": "NORMAL", + "links": { + "self": [ + { + "href": "http://example.com:7990/users/jcitizen" + } + ] + } + }, + "links": { + "self": [ + { + "href": "http://example.com:7990/users/jcitizen" + } + ] + } + }, + "public": false, + "links": { + "clone": [ + { + "href": "http://example.com:7990/scm/~jcitizen/my-repo.git", + "name": "http" + }, + { + "href": "ssh://git@example.com:7999/~jcitizen/my-repo.git", + "name": "ssh" + } + ], + "self": [ + { + "href": "http://example.com:7990/users/jcitizen/repos/my-repo/browse" + } + ] + } + } + }, + "toRef": { + "id": "refs/heads/master", + "displayId": "master", + "latestCommit": "a4dae7792cf772d72149730091141ef48bba8697", + "type": "BRANCH", + "repository": { + "slug": "my-repo", + "id": 1, + "name": "My Repo", + "hierarchyId": "5aa23c1a1280b0c0acce", + "scmId": "git", + "state": "AVAILABLE", + "statusMessage": "Available", + "forkable": true, + "project": { + "key": "PRJ", + "id": 2, + "name": "Project", + "public": false, + "type": "NORMAL", + "links": { + "self": [ + { + "href": "http://example.com:7990/projects/PRJ" + } + ] + } + }, + "public": false, + "links": { + "clone": [ + { + "href": "ssh://git@example.com:7999/prj/my-repo.git", + "name": "ssh" + }, + { + "href": "http://example.com:7990/scm/prj/my-repo.git", + "name": "http" + } + ], + "self": [ + { + "href": "http://example.com:7990/projects/PRJ/repos/my-repo/browse" + } + ] + } + } + }, + "locked": false, + "author": { + "user": { + "name": "jcitizen", + "emailAddress": "jane@example.com", + "id": 1, + "displayName": "Jane Citizen", + "active": true, + "slug": "jcitizen", + "type": "NORMAL", + "links": { + "self": [ + { + "href": "http://example.com:7990/users/jcitizen" + } + ] + } + }, + "role": "AUTHOR", + "approved": false, + "status": "UNAPPROVED" + }, + "reviewers": [], + "participants": [], + "links": { + "self": [ + { + "href": "http://example.com:7990/projects/PRJ/repos/my-repo/pull-requests/6" + } + ] + } + }, + "previousTitle": "Clean README.md", + "previousDescription": "Cleaned old info out of REAME.", + "previousTarget": { + "id": "refs/heads/master", + "displayId": "master", + "type": "BRANCH", + "latestCommit": "a4dae7792cf772d72149730091141ef48bba8697", + "latestChangeset": "a4dae7792cf772d72149730091141ef48bba8697" + } +} diff --git a/scm/driver/stash/testdata/webhooks/pr_modified_meta.json.golden b/scm/driver/stash/testdata/webhooks/pr_modified_meta.json.golden new file mode 100644 index 000000000..d901de8cc --- /dev/null +++ b/scm/driver/stash/testdata/webhooks/pr_modified_meta.json.golden @@ -0,0 +1,53 @@ +{ + "Action": "updated", + "Repo": { + "ID": "1", + "Namespace": "PRJ", + "Name": "my-repo", + "Perm": null, + "Branch": "master", + "Private": true, + "Clone": "http://example.com:7990/scm/prj/my-repo.git", + "CloneSSH": "ssh://git@example.com:7999/prj/my-repo.git", + "Link": "http://example.com:7990/projects/PRJ/repos/my-repo/browse", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 6, + "Title": "Clean README.md", + "Body": "Removed old information out of `REAME.nd`.", + "Sha": "a268fca7b65055e13f60ac1a2c9a527615f113ca", + "Ref": "refs/pull-requests/6/from", + "Source": "cleanup", + "Target": "master", + "Fork": "~jcitizen/my-repo", + "Link": "http://example.com:7990/projects/PRJ/repos/my-repo/pull-requests/6", + "Closed": false, + "Merged": false, + "Base": { + "Name": "master", + "Path": "refs/heads/master", + "Sha": "a4dae7792cf772d72149730091141ef48bba8697" + }, + "Head": { + "Name": "cleanup", + "Path": "refs/heads/cleanup", + "Sha": "a268fca7b65055e13f60ac1a2c9a527615f113ca" + }, + "Author": { + "Login": "jcitizen", + "Name": "Jane Citizen", + "Email": "jane@example.com", + "Avatar": "https://www.gravatar.com/avatar/9e26471d35a78862c17e467d87cddedf.jpg" + }, + "Created": "2021-11-24T14:26:49Z", + "Updated": "2021-11-24T14:43:48Z" + }, + "Sender": { + "Login": "jcitizen", + "Name": "Jane Citizen", + "Email": "jane@example.com", + "Avatar": "https://www.gravatar.com/avatar/9e26471d35a78862c17e467d87cddedf.jpg" + } +} diff --git a/scm/driver/stash/testdata/webhooks/pr_modified_toref.json b/scm/driver/stash/testdata/webhooks/pr_modified_toref.json new file mode 100644 index 000000000..ff33036c6 --- /dev/null +++ b/scm/driver/stash/testdata/webhooks/pr_modified_toref.json @@ -0,0 +1,167 @@ +{ + "eventKey": "pr:modified", + "date": "2021-11-23T13:16:20+0000", + "actor": { + "name": "jcitizen", + "emailAddress": "jane@example.com", + "id": 1, + "displayName": "Jane Citizen", + "active": true, + "slug": "jcitizen", + "type": "NORMAL", + "links": { + "self": [ + { + "href": "http://example.com:7990/users/jcitizen" + } + ] + } + }, + "pullRequest": { + "id": 2, + "version": 0, + "title": "added LICENSE", + "description": "added BSD license text", + "state": "OPEN", + "open": true, + "closed": false, + "createdDate": 1637591800463, + "updatedDate": 1637673380977, + "fromRef": { + "id": "refs/heads/feature-2", + "displayId": "feature-2", + "latestCommit": "c00d0f269a9844dd168f72f6a9d78a9cff49a318", + "type": "BRANCH", + "repository": { + "slug": "my-repo", + "id": 1, + "name": "my-repo", + "hierarchyId": "5aa23c1a1280b0c0acce", + "scmId": "git", + "state": "AVAILABLE", + "statusMessage": "Available", + "forkable": true, + "project": { + "key": "PRJ", + "id": 2, + "name": "PRJ", + "public": false, + "type": "NORMAL", + "links": { + "self": [ + { + "href": "http://example.com:7990/projects/PRJ" + } + ] + } + }, + "public": false, + "links": { + "clone": [ + { + "href": "http://example.com:7990/scm/prj/my-repo.git", + "name": "http" + }, + { + "href": "ssh://git@example.com:7999/prj/my-repo.git", + "name": "ssh" + } + ], + "self": [ + { + "href": "http://example.com:7990/projects/PRJ/repos/my-repo/browse" + } + ] + } + } + }, + "toRef": { + "id": "refs/heads/master", + "displayId": "master", + "latestCommit": "0667def9e377a8fa76ce67b6d4e53e21b246f030", + "type": "BRANCH", + "repository": { + "slug": "my-repo", + "id": 1, + "name": "my-repo", + "hierarchyId": "5aa23c1a1280b0c0acce", + "scmId": "git", + "state": "AVAILABLE", + "statusMessage": "Available", + "forkable": true, + "project": { + "key": "PRJ", + "id": 2, + "name": "PRJ", + "public": false, + "type": "NORMAL", + "links": { + "self": [ + { + "href": "http://example.com:7990/projects/PRJ" + } + ] + } + }, + "public": false, + "links": { + "clone": [ + { + "href": "http://example.com:7990/scm/prj/my-repo.git", + "name": "http" + }, + { + "href": "ssh://git@example.com:7999/prj/my-repo.git", + "name": "ssh" + } + ], + "self": [ + { + "href": "http://example.com:7990/projects/PRJ/repos/my-repo/browse" + } + ] + } + } + }, + "locked": false, + "author": { + "user": { + "name": "jcitizen", + "emailAddress": "jane@example.com", + "id": 1, + "displayName": "Jane Citizen", + "active": true, + "slug": "jcitizen", + "type": "NORMAL", + "links": { + "self": [ + { + "href": "http://example.com:7990/users/jcitizen" + } + ] + } + }, + "role": "AUTHOR", + "approved": false, + "status": "UNAPPROVED" + }, + "reviewers": [], + "participants": [], + "links": { + "self": [ + { + "href": "http://example.com:7990/projects/PRJ/repos/my-repo/pull-requests/2" + } + ] + } + }, + "previousTitle": "old title", + "previousDescription": "old description", + "previousTarget": { + "id": "refs/heads/wrong", + "displayId": "wrong", + "type": "BRANCH", + "latestCommit": "2bbad782fd5453ded95fc5ce8b16839ff10615e0", + "latestChangeset": "2bbad782fd5453ded95fc5ce8b16839ff10615e0" + } +} diff --git a/scm/driver/stash/testdata/webhooks/pr_modified_toref.json.golden b/scm/driver/stash/testdata/webhooks/pr_modified_toref.json.golden new file mode 100644 index 000000000..c7d808d75 --- /dev/null +++ b/scm/driver/stash/testdata/webhooks/pr_modified_toref.json.golden @@ -0,0 +1,53 @@ +{ + "Action": "synchronized", + "Repo": { + "ID": "1", + "Namespace": "PRJ", + "Name": "my-repo", + "Perm": null, + "Branch": "master", + "Private": true, + "Clone": "http://example.com:7990/scm/prj/my-repo.git", + "CloneSSH": "ssh://git@example.com:7999/prj/my-repo.git", + "Link": "http://example.com:7990/projects/PRJ/repos/my-repo/browse", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 2, + "Title": "added LICENSE", + "Body": "added BSD license text", + "Sha": "c00d0f269a9844dd168f72f6a9d78a9cff49a318", + "Ref": "refs/pull-requests/2/from", + "Source": "feature-2", + "Target": "master", + "Fork": "PRJ/my-repo", + "Link": "http://example.com:7990/projects/PRJ/repos/my-repo/pull-requests/2", + "Closed": false, + "Merged": false, + "Base": { + "Name": "master", + "Path": "refs/heads/master", + "Sha": "0667def9e377a8fa76ce67b6d4e53e21b246f030" + }, + "Head": { + "Name": "feature-2", + "Path": "refs/heads/feature-2", + "Sha": "c00d0f269a9844dd168f72f6a9d78a9cff49a318" + }, + "Author": { + "Login": "jcitizen", + "Name": "Jane Citizen", + "Email": "jane@example.com", + "Avatar": "https://www.gravatar.com/avatar/9e26471d35a78862c17e467d87cddedf.jpg" + }, + "Created": "2021-11-22T14:36:40Z", + "Updated": "2021-11-23T13:16:20Z" + }, + "Sender": { + "Login": "jcitizen", + "Name": "Jane Citizen", + "Email": "jane@example.com", + "Avatar": "https://www.gravatar.com/avatar/9e26471d35a78862c17e467d87cddedf.jpg" + } +} diff --git a/scm/driver/stash/testdata/webhooks/pr_open.json.golden b/scm/driver/stash/testdata/webhooks/pr_open.json.golden index 5d29c8f49..cfed1a2ed 100644 --- a/scm/driver/stash/testdata/webhooks/pr_open.json.golden +++ b/scm/driver/stash/testdata/webhooks/pr_open.json.golden @@ -25,6 +25,16 @@ "Link": "", "Closed": false, "Merged": false, + "Base": { + "Name": "master", + "Path": "refs/heads/master", + "Sha": "823b2230a56056231c9425d63758fa87078a66b4" + }, + "Head": { + "Name": "develop", + "Path": "refs/heads/develop", + "Sha": "208b0a5c05eddadad01f2aed8802fe0c3b3eaf5e" + }, "Author": { "Login": "jcitizen", "Name": "Jane Citizen", diff --git a/scm/driver/stash/webhook.go b/scm/driver/stash/webhook.go index 84ef85cb1..31c130638 100644 --- a/scm/driver/stash/webhook.go +++ b/scm/driver/stash/webhook.go @@ -21,7 +21,6 @@ import ( // TODO(bradrydzewski) push hook does not include repository git+http link // TODO(bradrydzewski) push hook does not include repository git+ssh link // TODO(bradrydzewski) push hook does not include repository html link -// TODO(bradrydzewski) missing pull request synchrnoized webhook. See https://jira.atlassian.com/browse/BSERV-10279 // TODO(bradrydzewski) pr hook does not include repository git+http link // TODO(bradrydzewski) pr hook does not include repository git+ssh link // TODO(bradrydzewski) pr hook does not include repository html link @@ -42,7 +41,7 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo switch req.Header.Get("X-Event-Key") { case "repo:refs_changed": hook, err = s.parsePushHook(data) - case "pr:opened", "pr:declined", "pr:merged": + case "pr:opened", "pr:from_ref_updated", "pr:modified", "pr:declined", "pr:deleted", "pr:merged": hook, err = s.parsePullRequest(data) } if err != nil { @@ -100,8 +99,25 @@ func (s *webhookService) parsePullRequest(data []byte) (scm.Webhook, error) { switch src.EventKey { case "pr:opened": dst.Action = scm.ActionOpen + case "pr:from_ref_updated": + // The request includes field "previousFromHash", which could be compared + // to the FromRef.Latestcommit to ensure there is actually a change, + // but there is unlikely need for that. + dst.Action = scm.ActionSync + case "pr:modified": + // BitBucket Server (Stash) sends "pr:modified" for any edits to the PR, + // including edits to the title or description. Thus, return the hook + // action only when the target reference has changed (name or hash). + if src.PullRequest.ToRef.DisplayID == src.PreviousTarget.DisplayID && + src.PullRequest.ToRef.LatestCommit == src.PreviousTarget.LatestCommit { + dst.Action = scm.ActionUpdate + } else { + dst.Action = scm.ActionSync + } case "pr:declined": dst.Action = scm.ActionClose + case "pr:deleted": + dst.Action = scm.ActionClose case "pr:merged": dst.Action = scm.ActionMerge default: @@ -127,6 +143,16 @@ type pullRequestHook struct { Date string `json:"date"` Actor *user `json:"actor"` PullRequest *pr `json:"pullRequest"` + // only in pr:from_ref_updated + PreviousFromHash string `json:"previousFromHash"` + // only in pr:modified + PreviousTarget struct { + ID string `json:"id"` // "refs/heads/master" + DisplayID string `json:"displayId"` // "master" + Type string `json:"type"` // "BRANCH" + LatestCommit string `json:"latestCommit"` // "860c4eb4ed0f969b47144234ba13c31c498cca69" + LatestChangeset string `json:"latestChangeset"` // "860c4eb4ed0f969b47144234ba13c31c498cca69" + } `json:"previousTarget"` } type change struct { diff --git a/scm/driver/stash/webhook_test.go b/scm/driver/stash/webhook_test.go index eb0486ef1..711adc694 100644 --- a/scm/driver/stash/webhook_test.go +++ b/scm/driver/stash/webhook_test.go @@ -92,6 +92,30 @@ func TestWebhooks(t *testing.T) { after: "testdata/webhooks/pr_open.json.golden", obj: new(scm.PullRequestHook), }, + // pull request source branch updated + { + sig: "71295b197fa25f4356d2fb9965df3f2379d903d7", + event: "pr:from_ref_updated", + before: "testdata/webhooks/pr_from_ref_updated.json", + after: "testdata/webhooks/pr_from_ref_updated.json.golden", + obj: new(scm.PullRequestHook), + }, + // pull request modified, target branch updated + { + sig: "71295b197fa25f4356d2fb9965df3f2379d903d7", + event: "pr:modified", + before: "testdata/webhooks/pr_modified_toref.json", + after: "testdata/webhooks/pr_modified_toref.json.golden", + obj: new(scm.PullRequestHook), + }, + // pull request modified, no change to toref + { + sig: "71295b197fa25f4356d2fb9965df3f2379d903d7", + event: "pr:modified", + before: "testdata/webhooks/pr_modified_meta.json", + after: "testdata/webhooks/pr_modified_meta.json.golden", + obj: new(scm.PullRequestHook), + }, // pull request fulfilled (merged) { sig: "71295b197fa25f4356d2fb9965df3f2379d903d7", @@ -108,6 +132,14 @@ func TestWebhooks(t *testing.T) { after: "testdata/webhooks/pr_declined.json.golden", obj: new(scm.PullRequestHook), }, + // pull request deleted + { + sig: "71295b197fa25f4356d2fb9965df3f2379d903d7", + event: "pr:deleted", + before: "testdata/webhooks/pr_deleted.json", + after: "testdata/webhooks/pr_deleted.json.golden", + obj: new(scm.PullRequestHook), + }, } for _, test := range tests { From 98db106454870a2be4ba7fd953784f4ac32b842d Mon Sep 17 00:00:00 2001 From: Mohit Garg Date: Wed, 12 Jan 2022 20:14:24 +0530 Subject: [PATCH 062/282] Added support for parsing prevFilePath field from github compare commits API response --- scm/driver/github/pr.go | 24 +++++++++++++----------- scm/pr.go | 13 +++++++------ 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/scm/driver/github/pr.go b/scm/driver/github/pr.go index 39c5d20e2..2dc083b4c 100644 --- a/scm/driver/github/pr.go +++ b/scm/driver/github/pr.go @@ -118,12 +118,13 @@ type prInput struct { } type file struct { - BlobID string `json:"sha"` - Filename string `json:"filename"` - Status string `json:"status"` - Additions int `json:"additions"` - Deletions int `json:"deletions"` - Changes int `json:"changes"` + BlobID string `json:"sha"` + Filename string `json:"filename"` + Status string `json:"status"` + Additions int `json:"additions"` + Deletions int `json:"deletions"` + Changes int `json:"changes"` + PreviousFilename string `json:"previous_filename"` } func convertPullRequestList(from []*pr) []*scm.PullRequest { @@ -185,10 +186,11 @@ func convertChangeList(from []*file) []*scm.Change { func convertChange(from *file) *scm.Change { return &scm.Change{ - Path: from.Filename, - Added: from.Status == "added", - Deleted: from.Status == "removed", - Renamed: from.Status == "renamed", - BlobID: from.BlobID, + Path: from.Filename, + Added: from.Status == "added", + Deleted: from.Status == "removed", + Renamed: from.Status == "renamed", + BlobID: from.BlobID, + PrevFilePath: from.PreviousFilename, } } diff --git a/scm/pr.go b/scm/pr.go index f08147bae..b36254a34 100644 --- a/scm/pr.go +++ b/scm/pr.go @@ -51,12 +51,13 @@ type ( // Change represents a changed file. Change struct { - Path string - Added bool - Renamed bool - Deleted bool - Sha string - BlobID string + Path string + Added bool + Renamed bool + Deleted bool + Sha string + BlobID string + PrevFilePath string } Label struct { From b5086f6093993e8efa6cdc2dcc78994d3af1e752 Mon Sep 17 00:00:00 2001 From: Mohit Garg Date: Thu, 13 Jan 2022 00:18:38 +0530 Subject: [PATCH 063/282] fix tests --- scm/driver/github/testdata/pr_files.json.golden | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scm/driver/github/testdata/pr_files.json.golden b/scm/driver/github/testdata/pr_files.json.golden index 2add0e0b7..4be7ddc87 100644 --- a/scm/driver/github/testdata/pr_files.json.golden +++ b/scm/driver/github/testdata/pr_files.json.golden @@ -4,27 +4,31 @@ "Added": false, "Renamed": false, "Deleted": false, - "BlobID": "291b15982c4926705f5639abffe96b2b6c419ce7" + "BlobID": "291b15982c4926705f5639abffe96b2b6c419ce7", + "PrevFilePath": "" }, { "Path": "remove_me", "Added": true, "Renamed": false, "Deleted": false, - "BlobID": "ce013625030ba8dba906f756967f9e9ca394464a" + "BlobID": "ce013625030ba8dba906f756967f9e9ca394464a", + "PrevFilePath": "" }, { "Path": "tp", "Added": false, "Renamed": true, "Deleted": false, - "BlobID": "70c379b63ffa0795fdbfbc128e5a2818397b7ef8" + "BlobID": "70c379b63ffa0795fdbfbc128e5a2818397b7ef8", + "PrevFilePath": "abhinav" }, { "Path": "upsert", "Added": false, "Renamed": false, "Deleted": true, - "BlobID": "0f9282d7e71e0f8cb748bfe00e52d7ed13dad036" + "BlobID": "0f9282d7e71e0f8cb748bfe00e52d7ed13dad036", + "PrevFilePath": "" } ] \ No newline at end of file From d0bd0a1c56d6b44191fef755d96ede430d885abf Mon Sep 17 00:00:00 2001 From: Eoin McAfee Date: Tue, 18 Jan 2022 09:34:33 +0000 Subject: [PATCH 064/282] release prep v1.18.0 --- CHANGELOG.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f455f84e5..7cc215149 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## [v1.18.0](https://github.com/drone/go-scm/tree/v1.18.0) (2022-01-18) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.17.0...v1.18.0) + +**Implemented enhancements:** + +- Added support for parsing prevFilePath field from github compare commits API response [\#143](https://github.com/drone/go-scm/pull/143) ([mohitg0795](https://github.com/mohitg0795)) + +**Fixed bugs:** + +- Implement parsing/handling for missing pull request webhook events for BitBucket Server \(Stash\) driver [\#130](https://github.com/drone/go-scm/pull/130) ([raphendyr](https://github.com/raphendyr)) + +**Closed issues:** + +- Bitbucket Stash driver doesn't handle event `pr:from_ref_updated` \(new commits / force push\) [\#116](https://github.com/drone/go-scm/issues/116) + ## [v1.17.0](https://github.com/drone/go-scm/tree/v1.17.0) (2022-01-07) [Full Changelog](https://github.com/drone/go-scm/compare/v1.16.3...v1.17.0) @@ -17,6 +33,10 @@ - The deprecation of Bitbucket API endpoint /2.0/teams breaks user registration [\#136](https://github.com/drone/go-scm/issues/136) +**Merged pull requests:** + +- release prep for v1.17.0 [\#142](https://github.com/drone/go-scm/pull/142) ([eoinmcafee00](https://github.com/eoinmcafee00)) + ## [v1.16.3](https://github.com/drone/go-scm/tree/v1.16.3) (2021-12-30) [Full Changelog](https://github.com/drone/go-scm/compare/v1.16.2...v1.16.3) From 37ec420b65c2c4cd544ad49817986c3ccdb41644 Mon Sep 17 00:00:00 2001 From: Nicolas Lecoy Date: Tue, 25 Jan 2022 16:56:26 +0100 Subject: [PATCH 065/282] Update GitHub signature header to use sha256 (#123) * Update GitHub signature header to use sha256 * fix: Add fallback for GitHub webhook signature check --- scm/driver/github/webhook.go | 5 ++++- scm/driver/github/webhook_test.go | 21 +++++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/scm/driver/github/webhook.go b/scm/driver/github/webhook.go index 4aa87f5c4..e0f6ae77a 100644 --- a/scm/driver/github/webhook.go +++ b/scm/driver/github/webhook.go @@ -63,7 +63,10 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo return hook, nil } - sig := req.Header.Get("X-Hub-Signature") + sig := req.Header.Get("X-Hub-Signature-256") + if sig == "" { + sig = req.Header.Get("X-Hub-Signature") + } if !hmac.ValidatePrefix(data, []byte(key), sig) { return hook, scm.ErrSignatureInvalid } diff --git a/scm/driver/github/webhook_test.go b/scm/driver/github/webhook_test.go index 99ba0d327..e54970f0d 100644 --- a/scm/driver/github/webhook_test.go +++ b/scm/driver/github/webhook_test.go @@ -202,7 +202,7 @@ func TestWebhooks(t *testing.T) { buf := bytes.NewBuffer(before) r, _ := http.NewRequest("GET", "/", buf) r.Header.Set("X-GitHub-Event", test.event) - r.Header.Set("X-Hub-Signature", "sha1=380f462cd2e160b84765144beabdad2e930a7ec5") + r.Header.Set("X-Hub-Signature-256", "sha256=3bfbbc3bfc44498db2254f577b2e4bed201ece6163518ba91cb2c21f0f59d512") r.Header.Set("X-GitHub-Delivery", "f2467dea-70d6-11e8-8955-3c83993e0aef") s := new(webhookService) @@ -259,7 +259,7 @@ func TestWebhookInvalid(t *testing.T) { r, _ := http.NewRequest("GET", "/", bytes.NewBuffer(f)) r.Header.Set("X-GitHub-Event", "push") r.Header.Set("X-GitHub-Delivery", "ee8d97b4-1479-43f1-9cac-fbbd1b80da55") - r.Header.Set("X-Hub-Signature", "sha1=380f462cd2e160b84765144beabdad2e930a7ec5") + r.Header.Set("X-Hub-Signature-256", "sha256=3bfbbc3bfc44498db2254f577b2e4bed201ece6163518ba91cb2c21f0f59d512") s := new(webhookService) _, err := s.Parse(r, secretFunc) @@ -269,6 +269,23 @@ func TestWebhookInvalid(t *testing.T) { } func TestWebhookValid(t *testing.T) { + // the sha can be recalculated with the below command + // openssl dgst -sha256 -hmac + + f, _ := ioutil.ReadFile("testdata/webhooks/push.json") + r, _ := http.NewRequest("GET", "/", bytes.NewBuffer(f)) + r.Header.Set("X-GitHub-Event", "push") + r.Header.Set("X-GitHub-Delivery", "ee8d97b4-1479-43f1-9cac-fbbd1b80da55") + r.Header.Set("X-Hub-Signature-256", "sha256=e3bfe744d4e2e29ed990bde8acfb8255ca51ef65f99657767989fb6349f32957") + + s := new(webhookService) + _, err := s.Parse(r, secretFunc) + if err != nil { + t.Errorf("Expect valid signature, got %v", err) + } +} + +func TestWebhookSignatureFallback(t *testing.T) { // the sha can be recalculated with the below command // openssl dgst -sha1 -hmac From dafaf7e443a9af7910eec7c46a589f347bfec537 Mon Sep 17 00:00:00 2001 From: Mohit Garg Date: Wed, 9 Feb 2022 19:25:36 +0530 Subject: [PATCH 066/282] Extending bitbucket listCommits API to fetch commits for a given file (#148) * extending bitbucket listCommits API to fetch commits for a given path --- scm/driver/bitbucket/git_test.go | 3 ++- scm/driver/bitbucket/util.go | 3 +++ scm/git.go | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/scm/driver/bitbucket/git_test.go b/scm/driver/bitbucket/git_test.go index 59e1ca4b6..9cc19c2b6 100644 --- a/scm/driver/bitbucket/git_test.go +++ b/scm/driver/bitbucket/git_test.go @@ -123,12 +123,13 @@ func TestGitListCommits(t *testing.T) { Get("/2.0/repositories/atlassian/stash-example-plugin/commits/master"). MatchParam("page", "1"). MatchParam("pagelen", "30"). + MatchParam("path", "LICENSE"). Reply(200). Type("application/json"). File("testdata/commits.json") client, _ := New("https://api.bitbucket.org") - got, res, err := client.Git.ListCommits(context.Background(), "atlassian/stash-example-plugin", scm.CommitListOptions{Ref: "master", Page: 1, Size: 30}) + got, res, err := client.Git.ListCommits(context.Background(), "atlassian/stash-example-plugin", scm.CommitListOptions{Ref: "master", Page: 1, Size: 30, Path: "LICENSE"}) if err != nil { t.Error(err) } diff --git a/scm/driver/bitbucket/util.go b/scm/driver/bitbucket/util.go index 38314c051..03c5eaae4 100644 --- a/scm/driver/bitbucket/util.go +++ b/scm/driver/bitbucket/util.go @@ -55,6 +55,9 @@ func encodeCommitListOptions(opts scm.CommitListOptions) string { if opts.Size != 0 { params.Set("pagelen", strconv.Itoa(opts.Size)) } + if opts.Path != "" { + params.Set("path", opts.Path) + } return params.Encode() } diff --git a/scm/git.go b/scm/git.go index d775a4fe8..07811b1fc 100644 --- a/scm/git.go +++ b/scm/git.go @@ -41,6 +41,7 @@ type ( Ref string Page int Size int + Path string } // Signature identifies a git commit creator. From 62e8881d80146ad929e6ab099bacf193de8b112e Mon Sep 17 00:00:00 2001 From: TP Honey Date: Wed, 9 Feb 2022 14:31:06 +0000 Subject: [PATCH 067/282] (feat) add path support for list commits on github and gitlab --- README.md | 108 ++++++++++++++++++--------------- scm/driver/github/util.go | 5 +- scm/driver/github/util_test.go | 3 +- scm/driver/gitlab/util.go | 5 +- scm/driver/gitlab/util_test.go | 3 +- 5 files changed, 72 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 9046a8518..224ed457a 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Go Doc](https://img.shields.io/badge/godoc-reference-5272B4.svg?style=flat-square)](http://godoc.org/github.com/drone/go-scm/scm) -Package scm provides a unified interface to multiple source code management systems including GitHub, GitHub Enterprise, Bitbucket, Bitbucket Server, Gitea and Gogs. +Package scm provides a unified interface to multiple source code management systems including GitHub, GitHub Enterprise, Bitbucket, Bitbucket Server, Gitee, Gitea and Gogs. ## Getting Started @@ -12,12 +12,12 @@ Create a GitHub client: package main import ( - "github.com/drone/go-scm/scm" - "github.com/drone/go-scm/scm/driver/github" + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/github" ) func main() { - client := github.NewDefault() +client := github.NewDefault() } ``` @@ -25,8 +25,8 @@ Create a GitHub Enterprise client: ```Go import ( - "github.com/drone/go-scm/scm" - "github.com/drone/go-scm/scm/driver/github" + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/github" ) func main() { @@ -38,8 +38,8 @@ Create a Bitbucket client: ```Go import ( - "github.com/drone/go-scm/scm" - "github.com/drone/go-scm/scm/driver/bitbucket" + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/bitbucket" ) func main() { @@ -51,8 +51,8 @@ Create a Bitbucket Server (Stash) client: ```Go import ( - "github.com/drone/go-scm/scm" - "github.com/drone/go-scm/scm/driver/stash" + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/stash" ) func main() { @@ -64,12 +64,12 @@ Create a Gitea client: ```Go import ( - "github.com/drone/go-scm/scm" - "github.com/drone/go-scm/scm/driver/gitea" + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/gitea" ) func main() { - client, err := gitea.New("https://gitea.company.com") + client, err := gitea.New("https://gitea.company.com") } ``` @@ -77,12 +77,12 @@ Create a Gitee client: ```Go import ( - "github.com/drone/go-scm/scm" - "github.com/drone/go-scm/scm/driver/gitee" + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/gitee" ) func main() { - client, err := gitee.New("https://gitee.com/api/v5") + client, err := gitee.New("https://gitee.com/api/v5") } ``` @@ -94,35 +94,35 @@ The scm client does not directly handle authentication. Instead, when creating a package main import ( - "github.com/drone/go-scm/scm" - "github.com/drone/go-scm/scm/driver/github" - "github.com/drone/go-scm/scm/transport" - "github.com/drone/go-scm/scm/transport/oauth2" + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/github" + "github.com/drone/go-scm/scm/transport" + "github.com/drone/go-scm/scm/transport/oauth2" ) func main() { - client := github.NewDefault() - - // provide a custom http.Client with a transport - // that injects the oauth2 token. - client.Client = &http.Client{ - Transport: &oauth2.Transport{ - Source: oauth2.StaticTokenSource( - &scm.Token{ - Token: "ecf4c1f9869f59758e679ab54b4", - }, - ), - }, - } - - // provide a custom http.Client with a transport - // that injects the private GitLab token through - // the PRIVATE_TOKEN header variable. - client.Client = &http.Client{ - Transport: &transport.PrivateToken{ - Token: "ecf4c1f9869f59758e679ab54b4", - }, - } + client := github.NewDefault() + + // provide a custom http.Client with a transport + // that injects the oauth2 token. + client.Client = &http.Client{ + Transport: &oauth2.Transport{ + Source: oauth2.StaticTokenSource( + &scm.Token{ + Token: "ecf4c1f9869f59758e679ab54b4", + }, + ), + }, + } + + // provide a custom http.Client with a transport + // that injects the private GitLab token through + // the PRIVATE_TOKEN header variable. + client.Client = &http.Client{ + Transport: &transport.PrivateToken{ + Token: "ecf4c1f9869f59758e679ab54b4", + }, + } } ``` @@ -136,14 +136,14 @@ Example code to get an issue: issue, _, err := client.Issues.Find(ctx, "octocat/Hello-World", 1) ``` -Example code to get a list of issues: +Example code to get a list of issues: ```Go opts := scm.IssueListOptions{ - Page: 1, - Size: 30, - Open: true, - Closed: false, + Page: 1, + Size: 30, + Open: true, + Closed: false, } issues, _, err := client.Issues.List(ctx, "octocat/Hello-World", opts) @@ -153,12 +153,24 @@ Example code to create an issue comment: ```Go in := &scm.CommentInput{ - Body: "Found a bug", + Body: "Found a bug", } comment, _, err := client.Issues.CreateComment(ctx, "octocat/Hello-World", 1, in) ``` +## Useful links + +Here are some useful links to providers API documentation: + +Bitbucket cloud API: `https://developer.atlassian.com/cloud/bitbucket/rest/intro/` +Bitbucket server/Stash API: `https://docs.atlassian.com/bitbucket-server/rest/5.16.0/bitbucket-rest.html` +Gitea API: `https://gitea.com/api/swagger/#/` +Gitee API: `https://gitee.com/api/swagger/#/` +Github API: `https://docs.github.com/en/rest/reference` +Gitlab API: `https://docs.gitlab.com/ee/api/api_resources.html` +Gogs API: `https://github.com/gogs/docs-api` + ## Release procedure Run the changelog generator. diff --git a/scm/driver/github/util.go b/scm/driver/github/util.go index e92b63c88..7f441b751 100644 --- a/scm/driver/github/util.go +++ b/scm/driver/github/util.go @@ -33,6 +33,9 @@ func encodeCommitListOptions(opts scm.CommitListOptions) string { if opts.Ref != "" { params.Set("ref", opts.Ref) } + if opts.Path != "" { + params.Set("path", opts.Path) + } return params.Encode() } @@ -98,4 +101,4 @@ func encodeReleaseListOptions(opts scm.ReleaseListOptions) string { params.Set("state", "closed") } return params.Encode() -} \ No newline at end of file +} diff --git a/scm/driver/github/util_test.go b/scm/driver/github/util_test.go index c6a266433..3cc66bdc9 100644 --- a/scm/driver/github/util_test.go +++ b/scm/driver/github/util_test.go @@ -27,8 +27,9 @@ func Test_encodeCommitListOptions(t *testing.T) { Page: 10, Size: 30, Ref: "master", + Path: "readme.md", } - want := "page=10&per_page=30&ref=master" + want := "page=10&path=readme.md&per_page=30&ref=master" got := encodeCommitListOptions(opts) if got != want { t.Errorf("Want encoded commit list options %q, got %q", want, got) diff --git a/scm/driver/gitlab/util.go b/scm/driver/gitlab/util.go index 6228e4759..05670bcd2 100644 --- a/scm/driver/gitlab/util.go +++ b/scm/driver/gitlab/util.go @@ -58,6 +58,9 @@ func encodeCommitListOptions(opts scm.CommitListOptions) string { if opts.Ref != "" { params.Set("ref_name", opts.Ref) } + if opts.Path != "" { + params.Set("path", opts.Path) + } return params.Encode() } @@ -111,4 +114,4 @@ func encodeMilestoneListOptions(opts scm.MilestoneListOptions) string { params.Set("state", "closed") } return params.Encode() -} \ No newline at end of file +} diff --git a/scm/driver/gitlab/util_test.go b/scm/driver/gitlab/util_test.go index 6eedbac27..25fcbf933 100644 --- a/scm/driver/gitlab/util_test.go +++ b/scm/driver/gitlab/util_test.go @@ -39,8 +39,9 @@ func Test_encodeCommitListOptions(t *testing.T) { Page: 10, Size: 30, Ref: "master", + Path: "Readme.md", } - want := "page=10&per_page=30&ref_name=master" + want := "page=10&path=Readme.md&per_page=30&ref_name=master" got := encodeCommitListOptions(opts) if got != want { t.Errorf("Want encoded commit list options %q, got %q", want, got) From 294692cca69fc7ff4aed55428b3ca75a5b57b2ab Mon Sep 17 00:00:00 2001 From: TP Honey Date: Wed, 9 Feb 2022 14:42:35 +0000 Subject: [PATCH 068/282] v1.19.0 release prep --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cc215149..fd0287f4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [v1.19.0](https://github.com/drone/go-scm/tree/v1.19.0) (2022-02-09) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.18.0...v1.19.0) + +**Implemented enhancements:** + +- \(feat\) add path support for list commits on github and gitlab [\#149](https://github.com/drone/go-scm/pull/149) ([tphoney](https://github.com/tphoney)) +- Extending bitbucket listCommits API to fetch commits for a given file [\#148](https://github.com/drone/go-scm/pull/148) ([mohitg0795](https://github.com/mohitg0795)) +- Update GitHub signature header to use sha256 [\#123](https://github.com/drone/go-scm/pull/123) ([nlecoy](https://github.com/nlecoy)) + ## [v1.18.0](https://github.com/drone/go-scm/tree/v1.18.0) (2022-01-18) [Full Changelog](https://github.com/drone/go-scm/compare/v1.17.0...v1.18.0) @@ -16,6 +26,10 @@ - Bitbucket Stash driver doesn't handle event `pr:from_ref_updated` \(new commits / force push\) [\#116](https://github.com/drone/go-scm/issues/116) +**Merged pull requests:** + +- release prep v1.18.0 [\#147](https://github.com/drone/go-scm/pull/147) ([eoinmcafee00](https://github.com/eoinmcafee00)) + ## [v1.17.0](https://github.com/drone/go-scm/tree/v1.17.0) (2022-01-07) [Full Changelog](https://github.com/drone/go-scm/compare/v1.16.3...v1.17.0) From 3fe10285a3b4f4baf82a51110cc69627ef05135e Mon Sep 17 00:00:00 2001 From: TP Honey Date: Wed, 9 Feb 2022 15:49:14 +0000 Subject: [PATCH 069/282] (maint) Fix links to git providers --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 224ed457a..7cfaa5ef1 100644 --- a/README.md +++ b/README.md @@ -163,13 +163,13 @@ comment, _, err := client.Issues.CreateComment(ctx, "octocat/Hello-World", 1, in Here are some useful links to providers API documentation: -Bitbucket cloud API: `https://developer.atlassian.com/cloud/bitbucket/rest/intro/` -Bitbucket server/Stash API: `https://docs.atlassian.com/bitbucket-server/rest/5.16.0/bitbucket-rest.html` -Gitea API: `https://gitea.com/api/swagger/#/` -Gitee API: `https://gitee.com/api/swagger/#/` -Github API: `https://docs.github.com/en/rest/reference` -Gitlab API: `https://docs.gitlab.com/ee/api/api_resources.html` -Gogs API: `https://github.com/gogs/docs-api` +- [Bitbucket cloud API](https://developer.atlassian.com/cloud/bitbucket/rest/intro/) +- [Bitbucket server/Stash API](https://docs.atlassian.com/bitbucket-server/rest/5.16.0/bitbucket-rest.html) +- [Gitea API](https://gitea.com/api/swagger/#/) +- [Gitee API](https://gitee.com/api/swagger/#/) +- [Github API](https://docs.github.com/en/rest/reference) +- [Gitlab API](https://docs.gitlab.com/ee/api/api_resources.html) +- [Gogs API](https://github.com/gogs/docs-api) ## Release procedure From 8a8597dbdbe0e75837d4f0ab5816f13fd1a58561 Mon Sep 17 00:00:00 2001 From: Mohit Garg Date: Mon, 21 Feb 2022 15:14:55 +0530 Subject: [PATCH 070/282] GitHub list commits fix (#152) * fixing commit list options for github list commits API * added integration tests * fix UT --- scm/driver/github/git_test.go | 2 +- scm/driver/github/integration/git_test.go | 32 +++++++++++++++++++++-- scm/driver/github/util.go | 2 +- scm/driver/github/util_test.go | 2 +- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/scm/driver/github/git_test.go b/scm/driver/github/git_test.go index 9c0a6c530..65c2562c9 100644 --- a/scm/driver/github/git_test.go +++ b/scm/driver/github/git_test.go @@ -145,7 +145,7 @@ func TestGitListCommits(t *testing.T) { Get("/repos/octocat/hello-world/commits"). MatchParam("page", "1"). MatchParam("per_page", "30"). - MatchParam("ref", "master"). + MatchParam("sha", "master"). Reply(200). Type("application/json"). SetHeaders(mockHeaders). diff --git a/scm/driver/github/integration/git_test.go b/scm/driver/github/integration/git_test.go index c6192cc91..2915ad2f8 100644 --- a/scm/driver/github/integration/git_test.go +++ b/scm/driver/github/integration/git_test.go @@ -114,7 +114,8 @@ func testCommits(client *scm.Client) func(t *testing.T) { return func(t *testing.T) { t.Parallel() t.Run("Find", testCommitFind(client)) - t.Run("List", testCommitList(client)) + t.Run("List-Default-Branch", testCommitListDefaultBranch(client)) + t.Run("List-Non-Default-Branch", testCommitListNonDefaultBranch(client)) } } @@ -130,7 +131,7 @@ func testCommitFind(client *scm.Client) func(t *testing.T) { } } -func testCommitList(client *scm.Client) func(t *testing.T) { +func testCommitListDefaultBranch(client *scm.Client) func(t *testing.T) { return func(t *testing.T) { t.Parallel() opts := scm.CommitListOptions{ @@ -152,6 +153,33 @@ func testCommitList(client *scm.Client) func(t *testing.T) { } } +func testCommitListNonDefaultBranch(client *scm.Client) func(t *testing.T) { + return func(t *testing.T) { + t.Parallel() + opts := scm.CommitListOptions{ + Ref: "octocat-patch-1", + } + result, _, err := client.Git.ListCommits(context.Background(), "octocat/Hello-World", opts) + if err != nil { + t.Error(err) + return + } + if len(result) == 0 { + t.Errorf("Want a non-empty commit list") + } + + if got, want := result[0].Sha, "b1b3f9723831141a31a1a7252a213e216ea76e56"; got != want { + t.Errorf("Want commit Sha %q, got %q", want, got) + } + + for _, commit := range result { + if commit.Sha == "7fd1a60b01f91b314f59955a4e4d4e80d8edf11d" { + t.Run("Commit", testCommit(commit)) + } + } + } +} + // // struct sub-tests // diff --git a/scm/driver/github/util.go b/scm/driver/github/util.go index 7f441b751..5d5fb4741 100644 --- a/scm/driver/github/util.go +++ b/scm/driver/github/util.go @@ -31,7 +31,7 @@ func encodeCommitListOptions(opts scm.CommitListOptions) string { params.Set("per_page", strconv.Itoa(opts.Size)) } if opts.Ref != "" { - params.Set("ref", opts.Ref) + params.Set("sha", opts.Ref) } if opts.Path != "" { params.Set("path", opts.Path) diff --git a/scm/driver/github/util_test.go b/scm/driver/github/util_test.go index 3cc66bdc9..46a87888e 100644 --- a/scm/driver/github/util_test.go +++ b/scm/driver/github/util_test.go @@ -29,7 +29,7 @@ func Test_encodeCommitListOptions(t *testing.T) { Ref: "master", Path: "readme.md", } - want := "page=10&path=readme.md&per_page=30&ref=master" + want := "page=10&path=readme.md&per_page=30&sha=master" got := encodeCommitListOptions(opts) if got != want { t.Errorf("Want encoded commit list options %q, got %q", want, got) From 2f3e807200bed7f73f0585889d00b66b29b50ed7 Mon Sep 17 00:00:00 2001 From: Mohit Garg Date: Mon, 21 Feb 2022 15:15:17 +0530 Subject: [PATCH 071/282] Bitbucket compare changes fix for rename and removed file ops (#151) * fix bitbucket compare commits response in case of rename and delete ops --- scm/driver/bitbucket/git.go | 10 +++- scm/driver/bitbucket/testdata/diffstat.json | 48 +++++++++++++++++++ .../bitbucket/testdata/diffstat.json.golden | 13 +++++ 3 files changed, 70 insertions(+), 1 deletion(-) diff --git a/scm/driver/bitbucket/git.go b/scm/driver/bitbucket/git.go index 5048750fc..059cc89cf 100644 --- a/scm/driver/bitbucket/git.go +++ b/scm/driver/bitbucket/git.go @@ -210,12 +210,20 @@ func convertDiffstats(from *diffstats) []*scm.Change { } func convertDiffstat(from *diffstat) *scm.Change { - return &scm.Change{ + response := &scm.Change{ Path: from.New.Path, Added: from.Status == "added", Renamed: from.Status == "renamed", Deleted: from.Status == "removed", } + + if (response.Renamed) { + response.PrevFilePath = from.Old.Path + } else if (response.Deleted) { + response.Path = from.Old.Path + } + + return response } func convertCommitList(from *commits) []*scm.Commit { diff --git a/scm/driver/bitbucket/testdata/diffstat.json b/scm/driver/bitbucket/testdata/diffstat.json index 6d6030ad5..97a36f5bf 100644 --- a/scm/driver/bitbucket/testdata/diffstat.json +++ b/scm/driver/bitbucket/testdata/diffstat.json @@ -24,6 +24,54 @@ } }, "type": "diffstat" + }, + { + "status": "renamed", + "old": { + "path": "old-folder/CONTRIBUTING.md", + "type": "commit_file", + "links": { + "self": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/atlaskit\/src\/dec26e0fe887167743c2b7e36531dedfeb6cd478\/CONTRIBUTING.md" + } + } + }, + "lines_removed": 0, + "lines_added": 0, + "new": { + "path": "new-folder/CONTRIBUTING.md", + "type": "commit_file", + "links": { + "self": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/atlaskit\/src\/425863f9dbe56d70c8dcdbf2e4e0805e85591fcc\/CONTRIBUTING.md" + } + } + }, + "type": "diffstat" + }, + { + "status": "removed", + "old": { + "path": "CONTRIBUTING.md", + "type": "commit_file", + "links": { + "self": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/atlaskit\/src\/dec26e0fe887167743c2b7e36531dedfeb6cd478\/CONTRIBUTING.md" + } + } + }, + "lines_removed": 15, + "lines_added": 0, + "new": { + "path": "", + "type": "commit_file", + "links": { + "self": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/atlaskit\/src\/425863f9dbe56d70c8dcdbf2e4e0805e85591fcc\/CONTRIBUTING.md" + } + } + }, + "type": "diffstat" } ], "page": 1, diff --git a/scm/driver/bitbucket/testdata/diffstat.json.golden b/scm/driver/bitbucket/testdata/diffstat.json.golden index 168e87d94..03fecb3ff 100644 --- a/scm/driver/bitbucket/testdata/diffstat.json.golden +++ b/scm/driver/bitbucket/testdata/diffstat.json.golden @@ -4,5 +4,18 @@ "Added": false, "Renamed": false, "Deleted": false + }, + { + "Path": "new-folder/CONTRIBUTING.md", + "Added": false, + "Renamed": true, + "Deleted": false, + "PrevFilePath": "old-folder/CONTRIBUTING.md" + }, + { + "Path": "CONTRIBUTING.md", + "Added": false, + "Renamed": false, + "Deleted": true } ] \ No newline at end of file From d3dd72e400d170c6e498abe94c54f00ee940cdf7 Mon Sep 17 00:00:00 2001 From: Mohit Garg Date: Tue, 22 Feb 2022 22:11:29 +0530 Subject: [PATCH 072/282] Bitbucket list files fix (#154) * if input page args has url, then it should be used to fetch list of files --- scm/driver/bitbucket/content.go | 4 ++++ scm/driver/bitbucket/content_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/scm/driver/bitbucket/content.go b/scm/driver/bitbucket/content.go index eda337ad7..3501de53f 100644 --- a/scm/driver/bitbucket/content.go +++ b/scm/driver/bitbucket/content.go @@ -83,6 +83,10 @@ func (s *contentService) Delete(ctx context.Context, repo, path string, params * func (s *contentService) List(ctx context.Context, repo, path, ref string, opts scm.ListOptions) ([]*scm.ContentInfo, *scm.Response, error) { endpoint := fmt.Sprintf("/2.0/repositories/%s/src/%s/%s?%s", repo, ref, path, encodeListOptions(opts)) + if opts.URL != "" { + endpoint = opts.URL + } + out := new(contents) res, err := s.client.do(ctx, "GET", endpoint, nil, out) copyPagination(out.pagination, res) diff --git a/scm/driver/bitbucket/content_test.go b/scm/driver/bitbucket/content_test.go index 3ec8083cd..7c16f4e7e 100644 --- a/scm/driver/bitbucket/content_test.go +++ b/scm/driver/bitbucket/content_test.go @@ -240,3 +240,29 @@ func TestContentList(t *testing.T) { t.Log(diff) } } + +func TestContentListWithUrlInput(t *testing.T) { + defer gock.Off() + + mockNextPageUri := "https://api.bitbucket.org/2.0/repositories/atlassian/atlaskit/src/master/packages/activity?pageLen=3&page=RPfL" + + gock.New(mockNextPageUri). + Reply(200). + Type("application/json"). + File("testdata/content_list.json") + + client, _ := New("https://api.bitbucket.org") + got, _, err := client.Contents.List(context.Background(), "atlassian/atlaskit", "packages/activity", "master", scm.ListOptions{URL: mockNextPageUri}) + if err != nil { + t.Error(err) + } + + want := []*scm.ContentInfo{} + raw, _ := ioutil.ReadFile("testdata/content_list.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} From 6bcfae1f0005d384c21a85668b3cd2c8bc949f5c Mon Sep 17 00:00:00 2001 From: TP Honey Date: Wed, 23 Feb 2022 11:28:34 +0000 Subject: [PATCH 073/282] prep for v1.19.1 --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd0287f4e..ebdc0c0aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [v1.19.1](https://github.com/drone/go-scm/tree/v1.19.1) (2022-02-23) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.19.0...v1.19.1) + +**Fixed bugs:** + +- Bitbucket list files fix [\#154](https://github.com/drone/go-scm/pull/154) ([mohitg0795](https://github.com/mohitg0795)) +- GitHub list commits fix [\#152](https://github.com/drone/go-scm/pull/152) ([mohitg0795](https://github.com/mohitg0795)) +- Bitbucket compare changes fix for rename and removed file ops [\#151](https://github.com/drone/go-scm/pull/151) ([mohitg0795](https://github.com/mohitg0795)) + ## [v1.19.0](https://github.com/drone/go-scm/tree/v1.19.0) (2022-02-09) [Full Changelog](https://github.com/drone/go-scm/compare/v1.18.0...v1.19.0) @@ -10,6 +20,10 @@ - Extending bitbucket listCommits API to fetch commits for a given file [\#148](https://github.com/drone/go-scm/pull/148) ([mohitg0795](https://github.com/mohitg0795)) - Update GitHub signature header to use sha256 [\#123](https://github.com/drone/go-scm/pull/123) ([nlecoy](https://github.com/nlecoy)) +**Merged pull requests:** + +- v1.19.0 release prep [\#150](https://github.com/drone/go-scm/pull/150) ([tphoney](https://github.com/tphoney)) + ## [v1.18.0](https://github.com/drone/go-scm/tree/v1.18.0) (2022-01-18) [Full Changelog](https://github.com/drone/go-scm/compare/v1.17.0...v1.18.0) From 42c58b81dc989b55ffaab06e876af20532124793 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Fri, 25 Feb 2022 12:12:30 +0000 Subject: [PATCH 074/282] (DRON-242) initial implementation of azure devops support --- README.md | 1 + scm/const.go | 3 + scm/driver/azure/azure.go | 118 ++++++++++ scm/driver/azure/azure_test.go | 71 ++++++ scm/driver/azure/content.go | 198 +++++++++++++++++ scm/driver/azure/content_test.go | 202 ++++++++++++++++++ scm/driver/azure/git.go | 172 +++++++++++++++ scm/driver/azure/git_test.go | 96 +++++++++ scm/driver/azure/integration/content_test.go | 132 ++++++++++++ scm/driver/azure/integration/git_test.go | 96 +++++++++ scm/driver/azure/integration/pr_test.go | 42 ++++ scm/driver/azure/integration/testSettings.go | 25 +++ scm/driver/azure/issue.go | 55 +++++ scm/driver/azure/linker.go | 25 +++ scm/driver/azure/org.go | 27 +++ scm/driver/azure/pr.go | 172 +++++++++++++++ scm/driver/azure/pr_test.go | 50 +++++ scm/driver/azure/repo.go | 72 +++++++ scm/driver/azure/review.go | 31 +++ scm/driver/azure/testdata/branch_create.json | 14 ++ scm/driver/azure/testdata/branches.json | 77 +++++++ .../azure/testdata/branches.json.golden | 22 ++ scm/driver/azure/testdata/commits.json | 71 ++++++ scm/driver/azure/testdata/commits.json.golden | 59 +++++ scm/driver/azure/testdata/content.json | 19 ++ scm/driver/azure/testdata/content.json.golden | 6 + scm/driver/azure/testdata/content_create.json | 83 +++++++ scm/driver/azure/testdata/content_delete.json | 83 +++++++ scm/driver/azure/testdata/content_list.json | 20 ++ .../azure/testdata/content_list.json.golden | 14 ++ scm/driver/azure/testdata/content_update.json | 83 +++++++ scm/driver/azure/testdata/pr.json | 74 +++++++ scm/driver/azure/testdata/pr.json.golden | 35 +++ .../azure/testdata/webhooks/pr_created.json | 85 ++++++++ .../testdata/webhooks/pr_created.json.golden | 61 ++++++ scm/driver/azure/user.go | 27 +++ scm/driver/azure/util.go | 23 ++ scm/driver/azure/webhook.go | 175 +++++++++++++++ scm/driver/azure/webhook_test.go | 96 +++++++++ 39 files changed, 2715 insertions(+) create mode 100644 scm/driver/azure/azure.go create mode 100644 scm/driver/azure/azure_test.go create mode 100644 scm/driver/azure/content.go create mode 100644 scm/driver/azure/content_test.go create mode 100644 scm/driver/azure/git.go create mode 100644 scm/driver/azure/git_test.go create mode 100644 scm/driver/azure/integration/content_test.go create mode 100644 scm/driver/azure/integration/git_test.go create mode 100644 scm/driver/azure/integration/pr_test.go create mode 100644 scm/driver/azure/integration/testSettings.go create mode 100644 scm/driver/azure/issue.go create mode 100644 scm/driver/azure/linker.go create mode 100644 scm/driver/azure/org.go create mode 100644 scm/driver/azure/pr.go create mode 100644 scm/driver/azure/pr_test.go create mode 100644 scm/driver/azure/repo.go create mode 100644 scm/driver/azure/review.go create mode 100644 scm/driver/azure/testdata/branch_create.json create mode 100644 scm/driver/azure/testdata/branches.json create mode 100644 scm/driver/azure/testdata/branches.json.golden create mode 100644 scm/driver/azure/testdata/commits.json create mode 100644 scm/driver/azure/testdata/commits.json.golden create mode 100644 scm/driver/azure/testdata/content.json create mode 100644 scm/driver/azure/testdata/content.json.golden create mode 100644 scm/driver/azure/testdata/content_create.json create mode 100644 scm/driver/azure/testdata/content_delete.json create mode 100644 scm/driver/azure/testdata/content_list.json create mode 100644 scm/driver/azure/testdata/content_list.json.golden create mode 100644 scm/driver/azure/testdata/content_update.json create mode 100644 scm/driver/azure/testdata/pr.json create mode 100644 scm/driver/azure/testdata/pr.json.golden create mode 100644 scm/driver/azure/testdata/webhooks/pr_created.json create mode 100644 scm/driver/azure/testdata/webhooks/pr_created.json.golden create mode 100644 scm/driver/azure/user.go create mode 100644 scm/driver/azure/util.go create mode 100644 scm/driver/azure/webhook.go create mode 100644 scm/driver/azure/webhook_test.go diff --git a/README.md b/README.md index 7cfaa5ef1..7ada651d4 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,7 @@ comment, _, err := client.Issues.CreateComment(ctx, "octocat/Hello-World", 1, in Here are some useful links to providers API documentation: +- [Azure DevOps](https://docs.microsoft.com/en-us/rest/api/azure/devops/git/?view=azure-devops-rest-6.0)) - [Bitbucket cloud API](https://developer.atlassian.com/cloud/bitbucket/rest/intro/) - [Bitbucket server/Stash API](https://docs.atlassian.com/bitbucket-server/rest/5.16.0/bitbucket-rest.html) - [Gitea API](https://gitea.com/api/swagger/#/) diff --git a/scm/const.go b/scm/const.go index 66551e2ac..55bedf568 100644 --- a/scm/const.go +++ b/scm/const.go @@ -122,6 +122,7 @@ const ( DriverStash DriverCoding DriverGitee + DriverAzure ) // String returns the string representation of Driver. @@ -143,6 +144,8 @@ func (d Driver) String() (s string) { return "coding" case DriverGitee: return "gitee" + case DriverAzure: + return "azure" default: return "unknown" } diff --git a/scm/driver/azure/azure.go b/scm/driver/azure/azure.go new file mode 100644 index 000000000..aa0f69927 --- /dev/null +++ b/scm/driver/azure/azure.go @@ -0,0 +1,118 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package azure implements a azure client. +package azure + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net/url" + "strings" + + "github.com/drone/go-scm/scm" +) + +// New returns a new azure API client. +func New(uri, owner, project string) (*scm.Client, error) { + base, err := url.Parse(uri) + if err != nil { + return nil, err + } + if !strings.HasSuffix(base.Path, "/") { + base.Path = base.Path + "/" + } + if owner == "" || project == "" { + return nil, fmt.Errorf("azure owner and azure project are required") + } + client := &wrapper{ + new(scm.Client), + owner, + project, + } + client.BaseURL = base + // initialize services + client.Driver = scm.DriverAzure + client.Linker = &linker{base.String()} + client.Contents = &contentService{client} + client.Git = &gitService{client} + client.Issues = &issueService{client} + client.Organizations = &organizationService{client} + client.PullRequests = &pullService{&issueService{client}} + client.Repositories = &RepositoryService{client} + client.Reviews = &reviewService{client} + client.Users = &userService{client} + client.Webhooks = &webhookService{client} + return client.Client, nil +} + +// NewDefault returns a new azure API client. +func NewDefault(owner, project string) *scm.Client { + client, _ := New("https://dev.azure.com", owner, project) + return client +} + +// wrapper wraps the Client to provide high level helper functions for making http requests and unmarshaling the response. +type wrapper struct { + *scm.Client + owner string + project string +} + +// do wraps the Client.Do function by creating the Request and unmarshalling the response. +func (c *wrapper) do(ctx context.Context, method, path string, in, out interface{}) (*scm.Response, error) { + req := &scm.Request{ + Method: method, + Path: path, + } + // if we are posting or putting data, we need to write it to the body of the request. + if in != nil { + buf := new(bytes.Buffer) + _ = json.NewEncoder(buf).Encode(in) + req.Header = map[string][]string{ + "Content-Type": {"application/json"}, + } + req.Body = buf + } + // execute the http request + res, err := c.Client.Do(ctx, req) + if err != nil { + return nil, err + } + defer res.Body.Close() + + // error response. + if res.Status > 300 { + err := new(Error) + _ = json.NewDecoder(res.Body).Decode(err) + return res, err + } + + if out == nil { + return res, nil + } + // if a json response is expected, parse and return the json response. + decodeErr := json.NewDecoder(res.Body).Decode(out) + // following line is used for debugging purposes. + //_ = json.NewEncoder(os.Stdout).Encode(out) + return res, decodeErr +} + +// Error represents am Azure error. +type Error struct { + Message string `json:"message"` +} + +func (e *Error) Error() string { + return e.Message +} + +func SanitizeBranchName(name string) string { + if strings.Contains(name, "/") { + return name + } + return "refs/heads/" + name +} diff --git a/scm/driver/azure/azure_test.go b/scm/driver/azure/azure_test.go new file mode 100644 index 000000000..0347567a9 --- /dev/null +++ b/scm/driver/azure/azure_test.go @@ -0,0 +1,71 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package azure + +import ( + "testing" +) + +func TestClient_Base(t *testing.T) { + client, err := New("https://dev.azure.com", "org", "proj") + if err != nil { + t.Error(err) + } + got, want := client.BaseURL.String(), "https://dev.azure.com/" + if got != want { + t.Errorf("Want Client URL %q, got %q", want, got) + } +} + +func TestClient_Default(t *testing.T) { + client := NewDefault("org", "proj") + if got, want := client.BaseURL.String(), "https://dev.azure.com/"; got != want { + t.Errorf("Want Client URL %q, got %q", want, got) + } +} + +func TestClient_azure_special(t *testing.T) { + client, _ := New("https://dev.azure.com", "org", "") + if client != nil { + t.Errorf("Want nil client, got %v", client) + } + client2, _ := New("https://dev.azure.com", "", "proj") + if client2 != nil { + t.Errorf("Want nil client, got %v", client2) + } +} + +func TestSanitizeBranchName(t *testing.T) { + type args struct { + name string + } + tests := []struct { + name string + args args + want string + }{ + { + "master", + args{ + "master", + }, + "refs/heads/master", + }, + { + "refs/heads/master", + args{ + "refs/heads/master", + }, + "refs/heads/master", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := SanitizeBranchName(tt.args.name); got != tt.want { + t.Errorf("SanitizeBranchName() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/scm/driver/azure/content.go b/scm/driver/azure/content.go new file mode 100644 index 000000000..4acd84848 --- /dev/null +++ b/scm/driver/azure/content.go @@ -0,0 +1,198 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package azure + +import ( + "context" + "encoding/base64" + "fmt" + + "github.com/drone/go-scm/scm" +) + +type contentService struct { + client *wrapper +} + +func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm.Content, *scm.Response, error) { + // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/items/get?view=azure-devops-rest-6.0 + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/items?path=%s&includeContent=true&$format=json", s.client.owner, s.client.project, repo, path) + endpoint += generateURIFromRef(ref) + endpoint += "&api-version=6.0" + out := new(content) + res, err := s.client.do(ctx, "GET", endpoint, nil, out) + data := []byte(out.Content) + return &scm.Content{ + Path: out.Path, + Data: data, + Sha: out.CommitID, + BlobID: out.ObjectID, + }, res, err +} + +func (s *contentService) Create(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/pushes?api-version=6.0", s.client.owner, s.client.project, repo) + ref := refUpdate{ + Name: SanitizeBranchName(params.Branch), + OldObjectID: params.Ref, + } + cha := change{ + ChangeType: "add", + } + cha.Item.Path = path + cha.NewContent.Content = base64.StdEncoding.EncodeToString(params.Data) + cha.NewContent.ContentType = "base64encoded" + + com := commit{ + Comment: params.Message, + Changes: []change{cha}, + } + in := &contentCreateUpdate{ + RefUpdates: []refUpdate{ref}, + Commits: []commit{com}, + } + + res, err := s.client.do(ctx, "POST", endpoint, in, nil) + return res, err +} + +func (s *contentService) Update(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/pushes?api-version=6.0", s.client.owner, s.client.project, repo) + ref := refUpdate{ + Name: SanitizeBranchName(params.Branch), + OldObjectID: params.Sha, + } + cha := change{ + ChangeType: "edit", + } + cha.Item.Path = path + cha.NewContent.Content = base64.StdEncoding.EncodeToString(params.Data) + cha.NewContent.ContentType = "base64encoded" + + com := commit{ + Comment: params.Message, + Changes: []change{cha}, + } + in := &contentCreateUpdate{ + RefUpdates: []refUpdate{ref}, + Commits: []commit{com}, + } + + res, err := s.client.do(ctx, "POST", endpoint, in, nil) + return res, err +} + +func (s *contentService) Delete(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/pushes?api-version=6.0", s.client.owner, s.client.project, repo) + ref := refUpdate{ + Name: SanitizeBranchName(params.Branch), + OldObjectID: params.Sha, + } + change1 := change{ + ChangeType: "delete", + } + change1.Item.Path = path + com := commit{ + Comment: params.Message, + Changes: []change{change1}, + } + in := &contentCreateUpdate{ + RefUpdates: []refUpdate{ref}, + Commits: []commit{com}, + } + + res, err := s.client.do(ctx, "POST", endpoint, in, nil) + return res, err +} + +func (s *contentService) List(ctx context.Context, repo, path, ref string, _ scm.ListOptions) ([]*scm.ContentInfo, *scm.Response, error) { + // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/items/list?view=azure-devops-rest-6.0 + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/items?path=%s&recursionLevel=Full&$format=json", s.client.owner, s.client.project, repo, path) + endpoint += generateURIFromRef(ref) + out := new(contentList) + res, err := s.client.do(ctx, "GET", endpoint, nil, &out) + return convertContentInfoList(out.Value), res, err +} + +type content struct { + ObjectID string `json:"objectId"` + GitObjectType string `json:"gitObjectType"` + CommitID string `json:"commitId"` + Path string `json:"path"` + Content string `json:"content"` + URL string `json:"url"` + Links struct { + Self struct { + Href string `json:"href"` + } `json:"self"` + Repository struct { + Href string `json:"href"` + } `json:"repository"` + Blob struct { + Href string `json:"href"` + } `json:"blob"` + } `json:"_links"` +} + +type contentList struct { + Count int `json:"count"` + Value []*content `json:"value"` +} +type refUpdate struct { + Name string `json:"name"` + OldObjectID string `json:"oldObjectId,omitempty"` +} +type change struct { + ChangeType string `json:"changeType"` + Item struct { + Path string `json:"path"` + } `json:"item"` + NewContent struct { + Content string `json:"content,omitempty"` + ContentType string `json:"contentType,omitempty"` + } `json:"newContent,omitempty"` +} +type commit struct { + Comment string `json:"comment"` + Changes []change `json:"changes"` +} +type contentCreateUpdate struct { + RefUpdates []refUpdate `json:"refUpdates"` + Commits []commit `json:"commits"` +} + +func convertContentInfoList(from []*content) []*scm.ContentInfo { + to := []*scm.ContentInfo{} + for _, v := range from { + to = append(to, convertContentInfo(v)) + } + return to +} +func convertContentInfo(from *content) *scm.ContentInfo { + to := &scm.ContentInfo{Path: from.Path} + switch from.GitObjectType { + case "blob": + to.Kind = scm.ContentKindFile + case "tree": + to.Kind = scm.ContentKindDirectory + default: + to.Kind = scm.ContentKindUnsupported + } + to.Path = from.Path + to.BlobID = from.ObjectID + to.Sha = from.CommitID + return to +} + +func generateURIFromRef(ref string) (uri string) { + if ref != "" { + if len(ref) == 40 { + return fmt.Sprintf("&versionDescriptor.versionType=commit&versionDescriptor.version=%s", ref) + } else { + return fmt.Sprintf("&versionDescriptor.versionType=branch&versionDescriptor.version=%s", ref) + } + } + return "" +} diff --git a/scm/driver/azure/content_test.go b/scm/driver/azure/content_test.go new file mode 100644 index 000000000..e674ccdaf --- /dev/null +++ b/scm/driver/azure/content_test.go @@ -0,0 +1,202 @@ +package azure + +import ( + "context" + "encoding/json" + "io/ioutil" + "testing" + + "github.com/drone/go-scm/scm" + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" +) + +func TestContentFind(t *testing.T) { + defer gock.Off() + + gock.New("https:/dev.azure.com/"). + Get("/ORG/PROJ/_apis/git/repositories/REPOID/items"). + MatchParam("path", "README"). + Reply(200). + Type("application/json"). + File("testdata/content.json") + + client := NewDefault("ORG", "PROJ") + got, _, err := client.Contents.Find( + context.Background(), + "REPOID", + "README", + "", + ) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Content) + raw, _ := ioutil.ReadFile("testdata/content.json.golden") + _ = json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + +func TestContentCreate(t *testing.T) { + defer gock.Off() + + gock.New("https:/dev.azure.com/"). + Post("/ORG/PROJ/_apis/git/repositories/REPOID/"). + Reply(201). + Type("application/json"). + File("testdata/content_create.json") + + params := &scm.ContentParams{ + Message: "my commit message", + Data: []byte("bXkgbmV3IGZpbGUgY29udGVudHM="), + } + + client := NewDefault("ORG", "PROJ") + res, err := client.Contents.Create( + context.Background(), + "REPOID", + "README", + params, + ) + + if err != nil { + t.Error(err) + return + } + + if res.Status != 201 { + t.Errorf("Unexpected Results") + } +} + +func TestContentUpdate(t *testing.T) { + defer gock.Off() + + gock.New("https:/dev.azure.com/"). + Post("/ORG/PROJ/_apis/git/repositories/REPOID/"). + Reply(200). + Type("application/json"). + File("testdata/content_update.json") + + params := &scm.ContentParams{ + Message: "a new commit message", + Data: []byte("bXkgdXBkYXRlZCBmaWxlIGNvbnRlbnRz"), + Sha: "95b966ae1c166bd92f8ae7d1c313e738c731dfc3", + } + + client := NewDefault("ORG", "PROJ") + res, err := client.Contents.Update( + context.Background(), + "REPOID", + "README", + params, + ) + + if err != nil { + t.Error(err) + return + } + + if res.Status != 200 { + t.Errorf("Unexpected Results") + } +} + +func TestContentDelete(t *testing.T) { + defer gock.Off() + + gock.New("https:/dev.azure.com/"). + Post("/ORG/PROJ/_apis/git/repositories/REPOID/"). + Reply(200). + Type("application/json"). + File("testdata/content_delete.json") + + params := &scm.ContentParams{ + Message: "a new commit message", + BlobID: "95b966ae1c166bd92f8ae7d1c313e738c731dfc3", + } + + client := NewDefault("ORG", "PROJ") + res, err := client.Contents.Delete( + context.Background(), + "REPOID", + "README", + params, + ) + + if err != nil { + t.Error(err) + return + } + + if res.Status != 200 { + t.Errorf("Unexpected Results") + } +} + +func TestContentList(t *testing.T) { + defer gock.Off() + + gock.New("https:/dev.azure.com/"). + Get("/ORG/PROJ/_apis/git/repositories/REPOID/"). + Reply(200). + Type("application/json"). + File("testdata/content_list.json") + + client := NewDefault("ORG", "PROJ") + got, _, err := client.Contents.List( + context.Background(), + "REPOID", + "", + "", + scm.ListOptions{}, + ) + if err != nil { + t.Error(err) + return + } + + want := []*scm.ContentInfo{} + raw, _ := ioutil.ReadFile("testdata/content_list.json.golden") + _ = json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + +func Test_generateURIFromRef(t *testing.T) { + type args struct { + ref string + } + tests := []struct { + name string + args args + wantUri string + }{ + { + name: "branch", + args: args{ref: "branch"}, + wantUri: "&versionDescriptor.versionType=branch&versionDescriptor.version=branch", + }, + { + name: "commit", + args: args{ref: "6bbcbc818c804d35b88a12bbd2ed297e41c4d10d"}, + wantUri: "&versionDescriptor.versionType=commit&versionDescriptor.version=6bbcbc818c804d35b88a12bbd2ed297e41c4d10d", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if gotUri := generateURIFromRef(tt.args.ref); gotUri != tt.wantUri { + t.Errorf("generateURIFromRef() = %v, want %v", gotUri, tt.wantUri) + } + }) + } +} diff --git a/scm/driver/azure/git.go b/scm/driver/azure/git.go new file mode 100644 index 000000000..8ee1b7370 --- /dev/null +++ b/scm/driver/azure/git.go @@ -0,0 +1,172 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package azure + +import ( + "context" + "fmt" + "time" + + "github.com/drone/go-scm/scm" +) + +type gitService struct { + client *wrapper +} + +func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.CreateBranch) (*scm.Response, error) { + // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/refs/update-refs?view=azure-devops-rest-6.0 + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/refs?api-version=6.0", s.client.owner, s.client.project, repo) + + in := make(crudBranch, 1) + in[0].Name = scm.ExpandRef(params.Name, "refs/heads") + in[0].NewObjectID = params.Sha + in[0].OldObjectID = "0000000000000000000000000000000000000000" + return s.client.do(ctx, "POST", endpoint, in, nil) +} + +func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *gitService) FindCommit(ctx context.Context, repo, ref string) (*scm.Commit, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *gitService) FindTag(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *gitService) ListBranches(ctx context.Context, repo string, _ scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { + // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/refs/list?view=azure-devops-rest-6.0 + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/refs?api-version=6.0", s.client.owner, s.client.project, repo) + out := new(branchList) + res, err := s.client.do(ctx, "GET", endpoint, nil, &out) + return convertBranchList(out.Value), res, err +} + +func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { + // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/commits/get-commits?view=azure-devops-rest-6.0 + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/commits?", s.client.owner, s.client.project, repo) + if opts.Ref != "" { + endpoint += fmt.Sprintf("searchCriteria.itemVersion.version=%s&api-version=6.0", opts.Ref) + } else { + endpoint += "&api-version=6.0" + } + out := new(commitList) + res, err := s.client.do(ctx, "GET", endpoint, nil, &out) + return convertCommitList(out.Value), res, err +} + +func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *gitService) ListChanges(ctx context.Context, repo, ref string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +type crudBranch []struct { + Name string `json:"name"` + OldObjectID string `json:"oldObjectId"` + NewObjectID string `json:"newObjectId"` +} + +type branchList struct { + Value []*branch `json:"value"` + Count int `json:"count"` +} + +type branch struct { + Name string `json:"name"` + ObjectID string `json:"objectId"` + Creator struct { + DisplayName string `json:"displayName"` + URL string `json:"url"` + Links struct { + Avatar struct { + Href string `json:"href"` + } `json:"avatar"` + } `json:"_links"` + ID string `json:"id"` + UniqueName string `json:"uniqueName"` + ImageURL string `json:"imageUrl"` + Descriptor string `json:"descriptor"` + } `json:"creator"` + URL string `json:"url"` +} + +type commitList struct { + Value []*gitCommit `json:"value"` + Count int `json:"count"` +} +type gitCommit struct { + CommitID string `json:"commitId"` + Author struct { + Name string `json:"name"` + Email string `json:"email"` + Date time.Time `json:"date"` + } `json:"author"` + Committer struct { + Name string `json:"name"` + Email string `json:"email"` + Date time.Time `json:"date"` + } `json:"committer"` + Comment string `json:"comment"` + CommentTruncated bool `json:"commentTruncated"` + ChangeCounts struct { + Add int `json:"Add"` + Edit int `json:"Edit"` + Delete int `json:"Delete"` + } `json:"changeCounts"` + URL string `json:"url"` + RemoteURL string `json:"remoteUrl"` +} + +func convertBranchList(from []*branch) []*scm.Reference { + to := []*scm.Reference{} + for _, v := range from { + to = append(to, convertBranch(v)) + } + return to +} + +func convertBranch(from *branch) *scm.Reference { + return &scm.Reference{ + Name: scm.TrimRef(from.Name), + Path: from.Name, + Sha: from.ObjectID, + } +} + +func convertCommitList(from []*gitCommit) []*scm.Commit { + to := []*scm.Commit{} + for _, v := range from { + to = append(to, convertCommit(v)) + } + return to +} + +func convertCommit(from *gitCommit) *scm.Commit { + return &scm.Commit{ + Message: from.Comment, + Sha: from.CommitID, + Link: from.URL, + Author: scm.Signature{ + Name: from.Author.Name, + Email: from.Author.Email, + Date: from.Author.Date, + }, + Committer: scm.Signature{ + Name: from.Committer.Name, + Email: from.Committer.Email, + Date: from.Committer.Date, + }, + } +} diff --git a/scm/driver/azure/git_test.go b/scm/driver/azure/git_test.go new file mode 100644 index 000000000..9f2521518 --- /dev/null +++ b/scm/driver/azure/git_test.go @@ -0,0 +1,96 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package azure + +import ( + "context" + "encoding/json" + "io/ioutil" + "testing" + + "github.com/drone/go-scm/scm" + + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" +) + +func TestGitCreateBranch(t *testing.T) { + defer gock.Off() + + gock.New("https:/dev.azure.com/"). + Post("/ORG/PROJ/_apis/git/repositories/REPOID/"). + Reply(201). + Type("application/json"). + File("testdata/branch_create.json") + + params := &scm.CreateBranch{ + Name: "test_branch", + Sha: "312797ba52425353dec56871a255e2a36fc96344", + } + + client := NewDefault("ORG", "PROJ") + res, err := client.Git.CreateBranch(context.Background(), "REPOID", params) + + if err != nil { + t.Error(err) + return + } + + if res.Status != 201 { + t.Errorf("Unexpected Results") + } +} + +func TestGitListCommits(t *testing.T) { + defer gock.Off() + + gock.New("https:/dev.azure.com/"). + Get("/ORG/PROJ/_apis/git/repositories/REPOID/"). + Reply(200). + Type("application/json"). + File("testdata/commits.json") + + client := NewDefault("ORG", "PROJ") + got, _, err := client.Git.ListCommits(context.Background(), "REPOID", scm.CommitListOptions{}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Commit{} + raw, _ := ioutil.ReadFile("testdata/commits.json.golden") + _ = json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + +func TestGitListBranches(t *testing.T) { + defer gock.Off() + + gock.New("https:/dev.azure.com/"). + Get("/ORG/PROJ/_apis/git/repositories/REPOID/"). + Reply(200). + Type("application/json"). + File("testdata/branches.json") + + client := NewDefault("ORG", "PROJ") + got, _, err := client.Git.ListBranches(context.Background(), "REPOID", scm.ListOptions{}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Reference{} + raw, _ := ioutil.ReadFile("testdata/branches.json.golden") + _ = json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} diff --git a/scm/driver/azure/integration/content_test.go b/scm/driver/azure/integration/content_test.go new file mode 100644 index 000000000..c85ad2d4c --- /dev/null +++ b/scm/driver/azure/integration/content_test.go @@ -0,0 +1,132 @@ +package integration + +import ( + "context" + "fmt" + "net/http" + "testing" + + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/azure" + "github.com/drone/go-scm/scm/transport" +) + +func TestContentsFind(t *testing.T) { + if token == "" { + t.Skip("Skipping, Integration test") + } + client = azure.NewDefault(organization, project) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("Authorization", fmt.Sprintf("Basic %s", token)) + }, + }, + } + content, response, err := client.Contents.Find(context.Background(), repoID, "README.md", "") + if err != nil { + t.Errorf("We got an error %v", err) + } + if content.Sha == "" { + t.Errorf("we did not get a sha back %v", content.Sha) + } + if response.Status != http.StatusOK { + t.Errorf("we did not get a 200 back %v", response.Status) + } +} + +func TestCreateUpdateDeleteFileAzure(t *testing.T) { + if token == "" { + t.Skip("Skipping, Acceptance test") + } + client = azure.NewDefault(organization, project) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("Authorization", fmt.Sprintf("Basic %s", token)) + }, + }, + } + // get latest commit first + currentCommit, commitErr := GetCurrentCommitOfBranch(client, "main") + if commitErr != nil { + t.Errorf("we got an error %v", commitErr) + } + // create a new file + createParams := scm.ContentParams{ + Message: "go-scm create crud file", + Data: []byte("hello"), + Branch: "refs/heads/main", + Ref: currentCommit, + } + createResponse, createErr := client.Contents.Create(context.Background(), repoID, "CRUD", &createParams) + if createErr != nil { + t.Errorf("Contents.Create we got an error %v", createErr) + } + if createResponse.Status != http.StatusCreated { + t.Errorf("Contents.Create we did not get a 201 back %v", createResponse.Status) + } + // get latest commit first + currentCommit, commitErr = GetCurrentCommitOfBranch(client, "main") + if commitErr != nil { + t.Errorf("we got an error %v", commitErr) + } + // update the file + updateParams := scm.ContentParams{ + Message: "go-scm update crud file", + Data: []byte("updated test data"), + Branch: "refs/heads/main", + Sha: currentCommit, + } + updateResponse, updateErr := client.Contents.Update(context.Background(), repoID, "CRUD", &updateParams) + if updateErr != nil { + t.Errorf("Contents.Update we got an error %v", updateErr) + } + if updateResponse.Status != http.StatusCreated { + t.Errorf("Contents.Update we did not get a 201 back %v", updateResponse.Status) + } + // get latest commit first + currentCommit, commitErr = GetCurrentCommitOfBranch(client, "main") + if commitErr != nil { + t.Errorf("we got an error %v", commitErr) + } + // delete the file + deleteParams := scm.ContentParams{ + Message: "go-scm delete crud file", + Branch: "refs/heads/main", + Sha: currentCommit, + } + deleteResponse, deleteErr := client.Contents.Delete(context.Background(), repoID, "CRUD", &deleteParams) + if deleteErr != nil { + t.Errorf("Contents.Delete we got an error %v", deleteErr) + } + if deleteResponse.Status != http.StatusCreated { + t.Errorf("Contents.Delete we did not get a 201 back %v", deleteResponse.Status) + } +} + +func TestListFiles(t *testing.T) { + if token == "" { + t.Skip("Skipping, Acceptance test") + } + client = azure.NewDefault(organization, project) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("Authorization", fmt.Sprintf("Basic %s", token)) + }, + }, + } + contentInfo, listResponse, listerr := client.Contents.List(context.Background(), + repoID, "", "", scm.ListOptions{}) + if listerr != nil { + t.Errorf("Contents.List we got an error %v", listerr) + } + if listResponse.Status != http.StatusOK { + t.Errorf("Contents.Delete we did not get a 200 back %v", listResponse.Status) + } + if len(contentInfo) != 2 { + t.Errorf("Contents.List there should be at least 2 files %v", contentInfo) + } + +} diff --git a/scm/driver/azure/integration/git_test.go b/scm/driver/azure/integration/git_test.go new file mode 100644 index 000000000..57eaf3f21 --- /dev/null +++ b/scm/driver/azure/integration/git_test.go @@ -0,0 +1,96 @@ +package integration + +import ( + "context" + "fmt" + "net/http" + "testing" + + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/azure" + "github.com/drone/go-scm/scm/transport" +) + +func TestListBranches(t *testing.T) { + if token == "" { + t.Skip("Skipping, Acceptance test") + } + client = azure.NewDefault(organization, project) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("Authorization", fmt.Sprintf("Basic %s", token)) + }, + }, + } + references, response, listerr := client.Git.ListBranches(context.Background(), repoID, scm.ListOptions{}) + if listerr != nil { + t.Errorf("ListBranches got an error %v", listerr) + } + if response.Status != http.StatusOK { + t.Errorf("ListBranches did not get a 200 back %v", response.Status) + } + if len(references) < 1 { + t.Errorf("ListBranches should have at least 1 branch %d", len(references)) + } + if references[0].Sha == "" { + t.Errorf("ListBranches first entry did not get a sha back %v", references[0].Sha) + } +} + +func TestCreateBranch(t *testing.T) { + if token == "" { + t.Skip("Skipping, Acceptance test") + } + client = azure.NewDefault(organization, project) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("Authorization", fmt.Sprintf("Basic %s", token)) + }, + }, + } + currentCommit, commitErr := GetCurrentCommitOfBranch(client, "main") + if commitErr != nil { + t.Errorf("we got an error %v", commitErr) + } + input := &scm.CreateBranch{ + Name: "test_branch", + Sha: currentCommit, + } + response, listerr := client.Git.CreateBranch(context.Background(), repoID, input) + if listerr != nil { + t.Errorf("CreateBranch got an error %v", listerr) + } + if response.Status != http.StatusOK { + t.Errorf("CreateBranch did not get a 200 back %v", response.Status) + } + +} + +func TestListCommits(t *testing.T) { + if token == "" { + t.Skip("Skipping, Acceptance test") + } + client = azure.NewDefault(organization, project) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("Authorization", fmt.Sprintf("Basic %s", token)) + }, + }, + } + commits, response, listerr := client.Git.ListCommits(context.Background(), repoID, scm.CommitListOptions{}) + if listerr != nil { + t.Errorf("ListCommits got an error %v", listerr) + } + if response.Status != http.StatusOK { + t.Errorf("ListCommitsdid not get a 200 back %v", response.Status) + } + if len(commits) < 1 { + t.Errorf("Contents.List there should be at least 1 commit %d", len(commits)) + } + if commits[0].Sha == "" { + t.Errorf("Contents.List first entry did not get a sha back %v", commits[0].Sha) + } +} diff --git a/scm/driver/azure/integration/pr_test.go b/scm/driver/azure/integration/pr_test.go new file mode 100644 index 000000000..941b30526 --- /dev/null +++ b/scm/driver/azure/integration/pr_test.go @@ -0,0 +1,42 @@ +package integration + +import ( + "context" + "fmt" + "net/http" + "testing" + + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/azure" + "github.com/drone/go-scm/scm/transport" +) + +func TestCreatePR(t *testing.T) { + if token == "" { + t.Skip("Skipping, Acceptance test") + } + client = azure.NewDefault(organization, project) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("Authorization", fmt.Sprintf("Basic %s", token)) + }, + }, + } + input := &scm.PullRequestInput{ + Title: "test_pr", + Body: "test_pr_body", + Source: "pr_branch", + Target: "main", + } + outputPR, response, listerr := client.PullRequests.Create(context.Background(), repoID, input) + if listerr != nil { + t.Errorf("PullRequests.Create got an error %v", listerr) + } + if response.Status != http.StatusCreated { + t.Errorf("PullRequests.Create did not get a 201 back %v", response.Status) + } + if outputPR.Title != "test_pr" { + t.Errorf("PullRequests.Create does not have the correct title %v", outputPR.Title) + } +} diff --git a/scm/driver/azure/integration/testSettings.go b/scm/driver/azure/integration/testSettings.go new file mode 100644 index 000000000..682b35830 --- /dev/null +++ b/scm/driver/azure/integration/testSettings.go @@ -0,0 +1,25 @@ +package integration + +import ( + "context" + "os" + + "github.com/drone/go-scm/scm" +) + +var ( + client *scm.Client + token = os.Getenv("AZURE_TOKEN") + + organization = "tphoney" + project = "test_project" + repoID = "fde2d21f-13b9-4864-a995-83329045289a" +) + +func GetCurrentCommitOfBranch(client *scm.Client, branch string) (string, error) { + commit, _, err := client.Contents.List(context.Background(), repoID, "", "main", scm.ListOptions{}) + if err != nil { + return "", err + } + return commit[0].Sha, nil +} diff --git a/scm/driver/azure/issue.go b/scm/driver/azure/issue.go new file mode 100644 index 000000000..6179d8312 --- /dev/null +++ b/scm/driver/azure/issue.go @@ -0,0 +1,55 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package azure + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type issueService struct { + client *wrapper +} + +func (s *issueService) Find(ctx context.Context, repo string, number int) (*scm.Issue, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *issueService) FindComment(ctx context.Context, repo string, index, id int) (*scm.Comment, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *issueService) List(ctx context.Context, repo string, opts scm.IssueListOptions) ([]*scm.Issue, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *issueService) ListComments(ctx context.Context, repo string, index int, opts scm.ListOptions) ([]*scm.Comment, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *issueService) Create(ctx context.Context, repo string, input *scm.IssueInput) (*scm.Issue, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *issueService) CreateComment(ctx context.Context, repo string, number int, input *scm.CommentInput) (*scm.Comment, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *issueService) DeleteComment(ctx context.Context, repo string, number, id int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *issueService) Close(ctx context.Context, repo string, number int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *issueService) Lock(ctx context.Context, repo string, number int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *issueService) Unlock(ctx context.Context, repo string, number int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} diff --git a/scm/driver/azure/linker.go b/scm/driver/azure/linker.go new file mode 100644 index 000000000..fc08ef2cc --- /dev/null +++ b/scm/driver/azure/linker.go @@ -0,0 +1,25 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package azure + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type linker struct { + base string +} + +// Resource returns a link to the resource. +func (l *linker) Resource(ctx context.Context, repo string, ref scm.Reference) (string, error) { + return "", scm.ErrNotSupported +} + +// Diff returns a link to the diff. +func (l *linker) Diff(ctx context.Context, repo string, source, target scm.Reference) (string, error) { + return "", scm.ErrNotSupported +} diff --git a/scm/driver/azure/org.go b/scm/driver/azure/org.go new file mode 100644 index 000000000..9ad977b9b --- /dev/null +++ b/scm/driver/azure/org.go @@ -0,0 +1,27 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package azure + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type organizationService struct { + client *wrapper +} + +func (s *organizationService) Find(ctx context.Context, name string) (*scm.Organization, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *organizationService) FindMembership(ctx context.Context, name, username string) (*scm.Membership, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *organizationService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Organization, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} diff --git a/scm/driver/azure/pr.go b/scm/driver/azure/pr.go new file mode 100644 index 000000000..647332899 --- /dev/null +++ b/scm/driver/azure/pr.go @@ -0,0 +1,172 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package azure + +import ( + "context" + "fmt" + "time" + + "github.com/drone/go-scm/scm" +) + +type pullService struct { + *issueService +} + +func (s *pullService) Find(ctx context.Context, repo string, number int) (*scm.PullRequest, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *pullService) List(ctx context.Context, repo string, opts scm.PullRequestListOptions) ([]*scm.PullRequest, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *pullService) ListChanges(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *pullService) ListCommits(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Commit, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *pullService) Merge(ctx context.Context, repo string, number int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *pullService) Close(ctx context.Context, repo string, number int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *pullService) Create(ctx context.Context, repo string, input *scm.PullRequestInput) (*scm.PullRequest, *scm.Response, error) { + // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/pull-requests/create?view=azure-devops-rest-6.0 + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/pullrequests?api-version=6.0", s.client.owner, s.client.project, repo) + in := &prInput{ + Title: input.Title, + Description: input.Body, + SourceRefName: scm.ExpandRef(input.Source, "refs/heads"), + TargetRefName: scm.ExpandRef(input.Target, "refs/heads"), + } + out := new(pr) + res, err := s.client.do(ctx, "POST", endpoint, in, out) + return convertPullRequest(out), res, err +} + +type prInput struct { + SourceRefName string `json:"sourceRefName"` + TargetRefName string `json:"targetRefName"` + Title string `json:"title"` + Description string `json:"description"` + Reviewers []struct { + ID string `json:"id"` + } `json:"reviewers"` +} + +type pr struct { + Repository struct { + ID string `json:"id"` + Name string `json:"name"` + URL string `json:"url"` + Project struct { + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + URL string `json:"url"` + State string `json:"state"` + Revision int `json:"revision"` + } `json:"project"` + RemoteURL string `json:"remoteUrl"` + } `json:"repository"` + PullRequestID int `json:"pullRequestId"` + CodeReviewID int `json:"codeReviewId"` + Status string `json:"status"` + CreatedBy struct { + ID string `json:"id"` + DisplayName string `json:"displayName"` + UniqueName string `json:"uniqueName"` + URL string `json:"url"` + ImageURL string `json:"imageUrl"` + } `json:"createdBy"` + CreationDate time.Time `json:"creationDate"` + Title string `json:"title"` + Description string `json:"description"` + SourceRefName string `json:"sourceRefName"` + TargetRefName string `json:"targetRefName"` + MergeStatus string `json:"mergeStatus"` + MergeID string `json:"mergeId"` + LastMergeSourceCommit struct { + CommitID string `json:"commitId"` + URL string `json:"url"` + } `json:"lastMergeSourceCommit"` + LastMergeTargetCommit struct { + CommitID string `json:"commitId"` + URL string `json:"url"` + } `json:"lastMergeTargetCommit"` + Reviewers []struct { + ReviewerURL string `json:"reviewerUrl"` + Vote int `json:"vote"` + ID string `json:"id"` + DisplayName string `json:"displayName"` + UniqueName string `json:"uniqueName"` + URL string `json:"url"` + ImageURL string `json:"imageUrl"` + } `json:"reviewers"` + URL string `json:"url"` + Links struct { + Self struct { + Href string `json:"href"` + } `json:"self"` + Repository struct { + Href string `json:"href"` + } `json:"repository"` + WorkItems struct { + Href string `json:"href"` + } `json:"workItems"` + SourceBranch struct { + Href string `json:"href"` + } `json:"sourceBranch"` + TargetBranch struct { + Href string `json:"href"` + } `json:"targetBranch"` + SourceCommit struct { + Href string `json:"href"` + } `json:"sourceCommit"` + TargetCommit struct { + Href string `json:"href"` + } `json:"targetCommit"` + CreatedBy struct { + Href string `json:"href"` + } `json:"createdBy"` + Iterations struct { + Href string `json:"href"` + } `json:"iterations"` + } `json:"_links"` + SupportsIterations bool `json:"supportsIterations"` + ArtifactID string `json:"artifactId"` +} + +func convertPullRequest(from *pr) *scm.PullRequest { + return &scm.PullRequest{ + Number: from.PullRequestID, + Title: from.Title, + Body: from.Description, + Sha: from.LastMergeSourceCommit.CommitID, + Source: from.SourceRefName, + Target: from.TargetRefName, + Link: from.URL, + Head: scm.Reference{ + Sha: from.LastMergeSourceCommit.CommitID, + }, + Base: scm.Reference{ + + Sha: from.LastMergeSourceCommit.CommitID, + }, + Author: scm.User{ + Login: from.CreatedBy.UniqueName, + Avatar: from.CreatedBy.ImageURL, + }, + Created: from.CreationDate, + } +} diff --git a/scm/driver/azure/pr_test.go b/scm/driver/azure/pr_test.go new file mode 100644 index 000000000..afddc8da7 --- /dev/null +++ b/scm/driver/azure/pr_test.go @@ -0,0 +1,50 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package azure + +import ( + "context" + "encoding/json" + "io/ioutil" + "testing" + + "github.com/drone/go-scm/scm" + + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" +) + +func TestPullCreate(t *testing.T) { + defer gock.Off() + + gock.New("https:/dev.azure.com/"). + Post("/ORG/PROJ/_apis/git/repositories/REPOID/"). + Reply(201). + Type("application/json"). + File("testdata/pr.json") + + input := scm.PullRequestInput{ + Title: "test_pr", + Body: "test_pr_body", + Source: "pr_branch", + Target: "main", + } + + client := NewDefault("ORG", "PROJ") + got, _, err := client.PullRequests.Create(context.Background(), "REPOID", &input) + if err != nil { + t.Error(err) + return + } + + want := new(scm.PullRequest) + raw, _ := ioutil.ReadFile("testdata/pr.json.golden") + _ = json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} diff --git a/scm/driver/azure/repo.go b/scm/driver/azure/repo.go new file mode 100644 index 000000000..0f312143a --- /dev/null +++ b/scm/driver/azure/repo.go @@ -0,0 +1,72 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package azure + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +// RepositoryService implements the repository service for +// the GitHub driver. +type RepositoryService struct { + client *wrapper +} + +// Find returns the repository by name. +func (s *RepositoryService) Find(ctx context.Context, repo string) (*scm.Repository, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +// FindHook returns a repository hook. +func (s *RepositoryService) FindHook(ctx context.Context, repo string, id string) (*scm.Hook, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +// FindPerms returns the repository permissions. +func (s *RepositoryService) FindPerms(ctx context.Context, repo string) (*scm.Perm, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +// List returns the user repository list. +func (s *RepositoryService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +// ListHooks returns a list or repository hooks. +func (s *RepositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +// ListStatus returns a list of commit statuses. +func (s *RepositoryService) ListStatus(ctx context.Context, repo, ref string, opts scm.ListOptions) ([]*scm.Status, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +// CreateHook creates a new repository webhook. +func (s *RepositoryService) CreateHook(ctx context.Context, repo string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +// CreateStatus creates a new commit status. +func (s *RepositoryService) CreateStatus(ctx context.Context, repo, ref string, input *scm.StatusInput) (*scm.Status, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +// CreateDeployStatus creates a new deployment status. +func (s *RepositoryService) CreateDeployStatus(ctx context.Context, repo string, input *scm.DeployStatus) (*scm.DeployStatus, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +// UpdateHook updates a repository webhook. +func (s *RepositoryService) UpdateHook(ctx context.Context, repo, id string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +// DeleteHook deletes a repository webhook. +func (s *RepositoryService) DeleteHook(ctx context.Context, repo, id string) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} diff --git a/scm/driver/azure/review.go b/scm/driver/azure/review.go new file mode 100644 index 000000000..f93a1f2b8 --- /dev/null +++ b/scm/driver/azure/review.go @@ -0,0 +1,31 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package azure + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type reviewService struct { + client *wrapper +} + +func (s *reviewService) Find(ctx context.Context, repo string, number, id int) (*scm.Review, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *reviewService) List(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Review, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *reviewService) Create(ctx context.Context, repo string, number int, input *scm.ReviewInput) (*scm.Review, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *reviewService) Delete(ctx context.Context, repo string, number, id int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} diff --git a/scm/driver/azure/testdata/branch_create.json b/scm/driver/azure/testdata/branch_create.json new file mode 100644 index 000000000..6a6700ae4 --- /dev/null +++ b/scm/driver/azure/testdata/branch_create.json @@ -0,0 +1,14 @@ +{ + "value": [ + { + "repositoryId": "d3d1760b-311c-4175-a726-20dfc6a7f885", + "name": "refs/heads/vsts-api-sample/answer-woman-flame", + "oldObjectId": "0000000000000000000000000000000000000000", + "newObjectId": "ffe9cba521f00d7f60e322845072238635edb451", + "isLocked": false, + "updateStatus": "succeeded", + "success": true + } + ], + "count": 1 + } \ No newline at end of file diff --git a/scm/driver/azure/testdata/branches.json b/scm/driver/azure/testdata/branches.json new file mode 100644 index 000000000..8f804ee43 --- /dev/null +++ b/scm/driver/azure/testdata/branches.json @@ -0,0 +1,77 @@ +{ + "value": [ + { + "name": "refs/heads/main", + "objectId": "e0aee6aa543294d62520fb906689da6710af149c", + "creator": { + "displayName": "tp", + "url": "https://spsproduks1.vssps.visualstudio.com/A93f74f38-2b8d-42d4-a5cb-74646f46666e/_apis/Identities/3ff4a20f-306e-677e-8a01-57f35e71f109", + "_links": { + "avatar": { + "href": "https://dev.azure.com/tphoney/_apis/GraphProfile/MemberAvatars/msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + } + }, + "id": "3ff4a20f-306e-677e-8a01-57f35e71f109", + "uniqueName": "tp@harness.io", + "imageUrl": "https://dev.azure.com/tphoney/_api/_common/identityImage?id=3ff4a20f-306e-677e-8a01-57f35e71f109", + "descriptor": "msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + }, + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/refs?filter=heads%2Fmain" + }, + { + "name": "refs/heads/pr_branch", + "objectId": "01768d964c03e97260af0bd8cd9e5cd1f9ac6356", + "creator": { + "displayName": "tp", + "url": "https://spsproduks1.vssps.visualstudio.com/A93f74f38-2b8d-42d4-a5cb-74646f46666e/_apis/Identities/3ff4a20f-306e-677e-8a01-57f35e71f109", + "_links": { + "avatar": { + "href": "https://dev.azure.com/tphoney/_apis/GraphProfile/MemberAvatars/msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + } + }, + "id": "3ff4a20f-306e-677e-8a01-57f35e71f109", + "uniqueName": "tp@harness.io", + "imageUrl": "https://dev.azure.com/tphoney/_api/_common/identityImage?id=3ff4a20f-306e-677e-8a01-57f35e71f109", + "descriptor": "msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + }, + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/refs?filter=heads%2Fpr_branch" + }, + { + "name": "refs/heads/test_branch", + "objectId": "d2036abdecd80290e971e263fe668ca87608f8d1", + "creator": { + "displayName": "tp", + "url": "https://spsproduks1.vssps.visualstudio.com/A93f74f38-2b8d-42d4-a5cb-74646f46666e/_apis/Identities/3ff4a20f-306e-677e-8a01-57f35e71f109", + "_links": { + "avatar": { + "href": "https://dev.azure.com/tphoney/_apis/GraphProfile/MemberAvatars/msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + } + }, + "id": "3ff4a20f-306e-677e-8a01-57f35e71f109", + "uniqueName": "tp@harness.io", + "imageUrl": "https://dev.azure.com/tphoney/_api/_common/identityImage?id=3ff4a20f-306e-677e-8a01-57f35e71f109", + "descriptor": "msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + }, + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/refs?filter=heads%2Ftest_branch" + }, + { + "name": "refs/pull/1/merge", + "objectId": "e29c0a25614589e1310574b42f799101903b7e30", + "creator": { + "displayName": "Microsoft.VisualStudio.Services.TFS", + "url": "https://spsproduks1.vssps.visualstudio.com/A93f74f38-2b8d-42d4-a5cb-74646f46666e/_apis/Identities/00000002-0000-8888-8000-000000000000", + "_links": { + "avatar": { + "href": "https://dev.azure.com/tphoney/_apis/GraphProfile/MemberAvatars/s2s.MDAwMDAwMDItMDAwMC04ODg4LTgwMDAtMDAwMDAwMDAwMDAwQDJjODk1OTA4LTA0ZTAtNDk1Mi04OWZkLTU0YjAwNDZkNjI4OA" + } + }, + "id": "00000002-0000-8888-8000-000000000000", + "uniqueName": "00000002-0000-8888-8000-000000000000@2c895908-04e0-4952-89fd-54b0046d6288", + "imageUrl": "https://dev.azure.com/tphoney/_api/_common/identityImage?id=00000002-0000-8888-8000-000000000000", + "descriptor": "s2s.MDAwMDAwMDItMDAwMC04ODg4LTgwMDAtMDAwMDAwMDAwMDAwQDJjODk1OTA4LTA0ZTAtNDk1Mi04OWZkLTU0YjAwNDZkNjI4OA" + }, + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/refs?filter=pull%2F1%2Fmerge" + } + ], + "count": 4 +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/branches.json.golden b/scm/driver/azure/testdata/branches.json.golden new file mode 100644 index 000000000..6bfe635cb --- /dev/null +++ b/scm/driver/azure/testdata/branches.json.golden @@ -0,0 +1,22 @@ +[ + { + "Name": "main", + "Path": "refs/heads/main", + "Sha": "e0aee6aa543294d62520fb906689da6710af149c" + }, + { + "Name": "pr_branch", + "Path": "refs/heads/pr_branch", + "Sha": "01768d964c03e97260af0bd8cd9e5cd1f9ac6356" + }, + { + "Name": "test_branch", + "Path": "refs/heads/test_branch", + "Sha": "d2036abdecd80290e971e263fe668ca87608f8d1" + }, + { + "Name": "refs/pull/1/merge", + "Path": "refs/pull/1/merge", + "Sha": "e29c0a25614589e1310574b42f799101903b7e30" + } +] \ No newline at end of file diff --git a/scm/driver/azure/testdata/commits.json b/scm/driver/azure/testdata/commits.json new file mode 100644 index 000000000..4f4748d75 --- /dev/null +++ b/scm/driver/azure/testdata/commits.json @@ -0,0 +1,71 @@ +{ + "value": [ + { + "commitId": "e0aee6aa543294d62520fb906689da6710af149c", + "author": { + "name": "tp", + "email": "tp@harness.io", + "date": "2022-03-04T12:19:58Z" + }, + "committer": { + "name": "tp", + "email": "tp@harness.io", + "date": "2022-03-04T12:19:58Z" + }, + "comment": "go-scm delete crud file", + "commentTruncated": false, + "changeCounts": { + "Add": 0, + "Edit": 0, + "Delete": 1 + }, + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/e0aee6aa543294d62520fb906689da6710af149c", + "remoteUrl": "https://dev.azure.com/tphoney/test_project/_git/test_repo2/commit/e0aee6aa543294d62520fb906689da6710af149c" + }, + { + "commitId": "1fe456794debece7c4125b9e283b601c974977a9", + "author": { + "name": "tp", + "email": "tp@harness.io", + "date": "2022-03-04T12:19:57Z" + }, + "committer": { + "name": "tp", + "email": "tp@harness.io", + "date": "2022-03-04T12:19:57Z" + }, + "comment": "go-scm update crud file", + "commentTruncated": false, + "changeCounts": { + "Add": 0, + "Edit": 1, + "Delete": 0 + }, + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/1fe456794debece7c4125b9e283b601c974977a9", + "remoteUrl": "https://dev.azure.com/tphoney/test_project/_git/test_repo2/commit/1fe456794debece7c4125b9e283b601c974977a9" + }, + { + "commitId": "dc49e8e6e22bb3456366a09365ce9e72912f26b5", + "author": { + "name": "tp", + "email": "tp@harness.io", + "date": "2022-03-04T12:19:56Z" + }, + "committer": { + "name": "tp", + "email": "tp@harness.io", + "date": "2022-03-04T12:19:56Z" + }, + "comment": "go-scm create crud file", + "commentTruncated": false, + "changeCounts": { + "Add": 1, + "Edit": 0, + "Delete": 0 + }, + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/dc49e8e6e22bb3456366a09365ce9e72912f26b5", + "remoteUrl": "https://dev.azure.com/tphoney/test_project/_git/test_repo2/commit/dc49e8e6e22bb3456366a09365ce9e72912f26b5" + } + ], + "count": 3 +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/commits.json.golden b/scm/driver/azure/testdata/commits.json.golden new file mode 100644 index 000000000..7f2eb4a47 --- /dev/null +++ b/scm/driver/azure/testdata/commits.json.golden @@ -0,0 +1,59 @@ +[ + { + "Sha": "e0aee6aa543294d62520fb906689da6710af149c", + "Message": "go-scm delete crud file", + "Author": { + "Name": "tp", + "Email": "tp@harness.io", + "Date": "2022-03-04T12:19:58Z", + "Login": "", + "Avatar": "" + }, + "Committer": { + "Name": "tp", + "Email": "tp@harness.io", + "Date": "2022-03-04T12:19:58Z", + "Login": "", + "Avatar": "" + }, + "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/e0aee6aa543294d62520fb906689da6710af149c" + }, + { + "Sha": "1fe456794debece7c4125b9e283b601c974977a9", + "Message": "go-scm update crud file", + "Author": { + "Name": "tp", + "Email": "tp@harness.io", + "Date": "2022-03-04T12:19:57Z", + "Login": "", + "Avatar": "" + }, + "Committer": { + "Name": "tp", + "Email": "tp@harness.io", + "Date": "2022-03-04T12:19:57Z", + "Login": "", + "Avatar": "" + }, + "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/1fe456794debece7c4125b9e283b601c974977a9" + }, + { + "Sha": "dc49e8e6e22bb3456366a09365ce9e72912f26b5", + "Message": "go-scm create crud file", + "Author": { + "Name": "tp", + "Email": "tp@harness.io", + "Date": "2022-03-04T12:19:56Z", + "Login": "", + "Avatar": "" + }, + "Committer": { + "Name": "tp", + "Email": "tp@harness.io", + "Date": "2022-03-04T12:19:56Z", + "Login": "", + "Avatar": "" + }, + "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/dc49e8e6e22bb3456366a09365ce9e72912f26b5" + } +] \ No newline at end of file diff --git a/scm/driver/azure/testdata/content.json b/scm/driver/azure/testdata/content.json new file mode 100644 index 000000000..34dc1a328 --- /dev/null +++ b/scm/driver/azure/testdata/content.json @@ -0,0 +1,19 @@ +{ + "objectId": "0ca446aab9d09eac8625b53e3df8da661976c458", + "gitObjectType": "blob", + "commitId": "2c0c712b26c3328ed66d5771213360812be9d035", + "path": "/README.md", + "content": "Hello World!\n", + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/items?path=%2FREADME.md&versionType=Branch&versionOptions=None", + "_links": { + "self": { + "href": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/items?path=%2FREADME.md&versionType=Branch&versionOptions=None" + }, + "repository": { + "href": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a" + }, + "blob": { + "href": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/blobs/0ca446aab9d09eac8625b53e3df8da661976c458" + } + } +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/content.json.golden b/scm/driver/azure/testdata/content.json.golden new file mode 100644 index 000000000..d5e39f579 --- /dev/null +++ b/scm/driver/azure/testdata/content.json.golden @@ -0,0 +1,6 @@ +{ + "Path": "/README.md", + "Data": "SGVsbG8gV29ybGQhCg==", + "Sha": "2c0c712b26c3328ed66d5771213360812be9d035", + "BlobID": "0ca446aab9d09eac8625b53e3df8da661976c458" +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/content_create.json b/scm/driver/azure/testdata/content_create.json new file mode 100644 index 000000000..e1bf88fc5 --- /dev/null +++ b/scm/driver/azure/testdata/content_create.json @@ -0,0 +1,83 @@ +{ + "commits": [ + { + "treeId": "175455a66a5fee6f99aeed0c75b4716835d22c64", + "commitId": "aa97ef963bff4dd90dde7456d503dd6ba8a28703", + "author": { + "name": "tp", + "email": "tp@harness.io", + "date": "2022-03-01T14:40:55Z" + }, + "committer": { + "name": "tp", + "email": "tp@harness.io", + "date": "2022-03-01T14:40:55Z" + }, + "comment": "test message create tickles", + "parents": [ + "2c0c712b26c3328ed66d5771213360812be9d035" + ], + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/aa97ef963bff4dd90dde7456d503dd6ba8a28703" + } + ], + "refUpdates": [ + { + "repositoryId": "fde2d21f-13b9-4864-a995-83329045289a", + "name": "refs/heads/main", + "oldObjectId": "2c0c712b26c3328ed66d5771213360812be9d035", + "newObjectId": "aa97ef963bff4dd90dde7456d503dd6ba8a28703" + } + ], + "repository": { + "id": "fde2d21f-13b9-4864-a995-83329045289a", + "name": "test_repo2", + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a", + "project": { + "id": "d350c9c0-7749-4ff8-a78f-f9c1f0e56729", + "name": "test_project", + "url": "https://dev.azure.com/tphoney/_apis/projects/d350c9c0-7749-4ff8-a78f-f9c1f0e56729", + "state": "wellFormed", + "revision": 11, + "visibility": "private", + "lastUpdateTime": "2022-02-24T15:31:27.89Z" + }, + "size": 713, + "remoteUrl": "https://tphoney@dev.azure.com/tphoney/test_project/_git/test_repo2", + "sshUrl": "git@ssh.dev.azure.com:v3/tphoney/test_project/test_repo2", + "webUrl": "https://dev.azure.com/tphoney/test_project/_git/test_repo2", + "isDisabled": false + }, + "pushedBy": { + "displayName": "tp", + "url": "https://spsproduks1.vssps.visualstudio.com/A93f74f38-2b8d-42d4-a5cb-74646f46666e/_apis/Identities/3ff4a20f-306e-677e-8a01-57f35e71f109", + "_links": { + "avatar": { + "href": "https://dev.azure.com/tphoney/_apis/GraphProfile/MemberAvatars/msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + } + }, + "id": "3ff4a20f-306e-677e-8a01-57f35e71f109", + "uniqueName": "tp@harness.io", + "imageUrl": "https://dev.azure.com/tphoney/_api/_common/identityImage?id=3ff4a20f-306e-677e-8a01-57f35e71f109", + "descriptor": "msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + }, + "pushId": 11, + "date": "2022-03-01T14:40:55.3379799Z", + "url": "https://dev.azure.com/tphoney/test_project/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/pushes/11", + "_links": { + "self": { + "href": "https://dev.azure.com/tphoney/test_project/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/pushes/11" + }, + "repository": { + "href": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a" + }, + "commits": { + "href": "https://dev.azure.com/tphoney/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/pushes/11/commits" + }, + "pusher": { + "href": "https://spsproduks1.vssps.visualstudio.com/A93f74f38-2b8d-42d4-a5cb-74646f46666e/_apis/Identities/3ff4a20f-306e-677e-8a01-57f35e71f109" + }, + "refs": { + "href": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/refs/heads/main" + } + } +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/content_delete.json b/scm/driver/azure/testdata/content_delete.json new file mode 100644 index 000000000..68eff44ed --- /dev/null +++ b/scm/driver/azure/testdata/content_delete.json @@ -0,0 +1,83 @@ +{ + "commits": [ + { + "treeId": "9804b758e84cac41a6acc4d011f57310a1f63102", + "commitId": "e25d5d5f8dba6a25d5d66c020b101278d818a8b8", + "author": { + "name": "tp", + "email": "tp@harness.io", + "date": "2022-03-01T14:54:53Z" + }, + "committer": { + "name": "tp", + "email": "tp@harness.io", + "date": "2022-03-01T14:54:53Z" + }, + "comment": "test delete message", + "parents": [ + "86260582b1ace66941ea2d1230ac083b68eb95cc" + ], + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/e25d5d5f8dba6a25d5d66c020b101278d818a8b8" + } + ], + "refUpdates": [ + { + "repositoryId": "fde2d21f-13b9-4864-a995-83329045289a", + "name": "refs/heads/main", + "oldObjectId": "86260582b1ace66941ea2d1230ac083b68eb95cc", + "newObjectId": "e25d5d5f8dba6a25d5d66c020b101278d818a8b8" + } + ], + "repository": { + "id": "fde2d21f-13b9-4864-a995-83329045289a", + "name": "test_repo2", + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a", + "project": { + "id": "d350c9c0-7749-4ff8-a78f-f9c1f0e56729", + "name": "test_project", + "url": "https://dev.azure.com/tphoney/_apis/projects/d350c9c0-7749-4ff8-a78f-f9c1f0e56729", + "state": "wellFormed", + "revision": 11, + "visibility": "private", + "lastUpdateTime": "2022-02-24T15:31:27.89Z" + }, + "size": 713, + "remoteUrl": "https://tphoney@dev.azure.com/tphoney/test_project/_git/test_repo2", + "sshUrl": "git@ssh.dev.azure.com:v3/tphoney/test_project/test_repo2", + "webUrl": "https://dev.azure.com/tphoney/test_project/_git/test_repo2", + "isDisabled": false + }, + "pushedBy": { + "displayName": "tp", + "url": "https://spsproduks1.vssps.visualstudio.com/A93f74f38-2b8d-42d4-a5cb-74646f46666e/_apis/Identities/3ff4a20f-306e-677e-8a01-57f35e71f109", + "_links": { + "avatar": { + "href": "https://dev.azure.com/tphoney/_apis/GraphProfile/MemberAvatars/msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + } + }, + "id": "3ff4a20f-306e-677e-8a01-57f35e71f109", + "uniqueName": "tp@harness.io", + "imageUrl": "https://dev.azure.com/tphoney/_api/_common/identityImage?id=3ff4a20f-306e-677e-8a01-57f35e71f109", + "descriptor": "msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + }, + "pushId": 13, + "date": "2022-03-01T14:54:54.0241357Z", + "url": "https://dev.azure.com/tphoney/test_project/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/pushes/13", + "_links": { + "self": { + "href": "https://dev.azure.com/tphoney/test_project/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/pushes/13" + }, + "repository": { + "href": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a" + }, + "commits": { + "href": "https://dev.azure.com/tphoney/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/pushes/13/commits" + }, + "pusher": { + "href": "https://spsproduks1.vssps.visualstudio.com/A93f74f38-2b8d-42d4-a5cb-74646f46666e/_apis/Identities/3ff4a20f-306e-677e-8a01-57f35e71f109" + }, + "refs": { + "href": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/refs/heads/main" + } + } +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/content_list.json b/scm/driver/azure/testdata/content_list.json new file mode 100644 index 000000000..00e9899bf --- /dev/null +++ b/scm/driver/azure/testdata/content_list.json @@ -0,0 +1,20 @@ +{ + "count": 2, + "value": [ + { + "objectId": "9804b758e84cac41a6acc4d011f57310a1f63102", + "gitObjectType": "tree", + "commitId": "e25d5d5f8dba6a25d5d66c020b101278d818a8b8", + "path": "/", + "isFolder": true, + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/items?path=%2F&versionType=Branch&versionOptions=None" + }, + { + "objectId": "0ca446aab9d09eac8625b53e3df8da661976c458", + "gitObjectType": "blob", + "commitId": "e25d5d5f8dba6a25d5d66c020b101278d818a8b8", + "path": "/README.md", + "url": "https://dev.azure.com/tphoney/test_project/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/items//README.md?versionType=Branch&versionOptions=None" + } + ] +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/content_list.json.golden b/scm/driver/azure/testdata/content_list.json.golden new file mode 100644 index 000000000..b5644b732 --- /dev/null +++ b/scm/driver/azure/testdata/content_list.json.golden @@ -0,0 +1,14 @@ +[ + { + "path": "/", + "kind": "directory", + "Sha": "e25d5d5f8dba6a25d5d66c020b101278d818a8b8", + "BlobID": "9804b758e84cac41a6acc4d011f57310a1f63102" + }, + { + "path": "/README.md", + "kind": "file", + "Sha": "e25d5d5f8dba6a25d5d66c020b101278d818a8b8", + "BlobID": "0ca446aab9d09eac8625b53e3df8da661976c458" + } +] \ No newline at end of file diff --git a/scm/driver/azure/testdata/content_update.json b/scm/driver/azure/testdata/content_update.json new file mode 100644 index 000000000..c9ebc450e --- /dev/null +++ b/scm/driver/azure/testdata/content_update.json @@ -0,0 +1,83 @@ +{ + "commits": [ + { + "treeId": "8c48e1f820617b4d33efb453feef450f4252a8b0", + "commitId": "86260582b1ace66941ea2d1230ac083b68eb95cc", + "author": { + "name": "tp", + "email": "tp@harness.io", + "date": "2022-03-01T14:50:23Z" + }, + "committer": { + "name": "tp", + "email": "tp@harness.io", + "date": "2022-03-01T14:50:23Z" + }, + "comment": "test message update tickles", + "parents": [ + "aa97ef963bff4dd90dde7456d503dd6ba8a28703" + ], + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/86260582b1ace66941ea2d1230ac083b68eb95cc" + } + ], + "refUpdates": [ + { + "repositoryId": "fde2d21f-13b9-4864-a995-83329045289a", + "name": "refs/heads/main", + "oldObjectId": "aa97ef963bff4dd90dde7456d503dd6ba8a28703", + "newObjectId": "86260582b1ace66941ea2d1230ac083b68eb95cc" + } + ], + "repository": { + "id": "fde2d21f-13b9-4864-a995-83329045289a", + "name": "test_repo2", + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a", + "project": { + "id": "d350c9c0-7749-4ff8-a78f-f9c1f0e56729", + "name": "test_project", + "url": "https://dev.azure.com/tphoney/_apis/projects/d350c9c0-7749-4ff8-a78f-f9c1f0e56729", + "state": "wellFormed", + "revision": 11, + "visibility": "private", + "lastUpdateTime": "2022-02-24T15:31:27.89Z" + }, + "size": 713, + "remoteUrl": "https://tphoney@dev.azure.com/tphoney/test_project/_git/test_repo2", + "sshUrl": "git@ssh.dev.azure.com:v3/tphoney/test_project/test_repo2", + "webUrl": "https://dev.azure.com/tphoney/test_project/_git/test_repo2", + "isDisabled": false + }, + "pushedBy": { + "displayName": "tp", + "url": "https://spsproduks1.vssps.visualstudio.com/A93f74f38-2b8d-42d4-a5cb-74646f46666e/_apis/Identities/3ff4a20f-306e-677e-8a01-57f35e71f109", + "_links": { + "avatar": { + "href": "https://dev.azure.com/tphoney/_apis/GraphProfile/MemberAvatars/msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + } + }, + "id": "3ff4a20f-306e-677e-8a01-57f35e71f109", + "uniqueName": "tp@harness.io", + "imageUrl": "https://dev.azure.com/tphoney/_api/_common/identityImage?id=3ff4a20f-306e-677e-8a01-57f35e71f109", + "descriptor": "msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + }, + "pushId": 12, + "date": "2022-03-01T14:50:23.2995Z", + "url": "https://dev.azure.com/tphoney/test_project/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/pushes/12", + "_links": { + "self": { + "href": "https://dev.azure.com/tphoney/test_project/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/pushes/12" + }, + "repository": { + "href": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a" + }, + "commits": { + "href": "https://dev.azure.com/tphoney/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/pushes/12/commits" + }, + "pusher": { + "href": "https://spsproduks1.vssps.visualstudio.com/A93f74f38-2b8d-42d4-a5cb-74646f46666e/_apis/Identities/3ff4a20f-306e-677e-8a01-57f35e71f109" + }, + "refs": { + "href": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/refs/heads/main" + } + } +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/pr.json b/scm/driver/azure/testdata/pr.json new file mode 100644 index 000000000..b721e0dae --- /dev/null +++ b/scm/driver/azure/testdata/pr.json @@ -0,0 +1,74 @@ +{ + "repository": { + "id": "fde2d21f-13b9-4864-a995-83329045289a", + "name": "test_repo2", + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a", + "project": { + "id": "d350c9c0-7749-4ff8-a78f-f9c1f0e56729", + "name": "test_project", + "description": "", + "url": "https://dev.azure.com/tphoney/_apis/projects/d350c9c0-7749-4ff8-a78f-f9c1f0e56729", + "state": "wellFormed", + "revision": 11 + }, + "remoteUrl": "https://tphoney@dev.azure.com/tphoney/test_project/_git/test_repo2" + }, + "pullRequestId": 19, + "codeReviewId": 19, + "status": "active", + "createdBy": { + "id": "3ff4a20f-306e-677e-8a01-57f35e71f109", + "displayName": "tp", + "uniqueName": "tp@harness.io", + "url": "https://spsproduks1.vssps.visualstudio.com/A93f74f38-2b8d-42d4-a5cb-74646f46666e/_apis/Identities/3ff4a20f-306e-677e-8a01-57f35e71f109", + "imageUrl": "https://dev.azure.com/tphoney/_api/_common/identityImage?id=3ff4a20f-306e-677e-8a01-57f35e71f109" + }, + "creationDate": "2022-03-04T13:34:54.3177724Z", + "title": "test_pr", + "description": "test_pr_body", + "sourceRefName": "refs/heads/pr_branch", + "targetRefName": "refs/heads/main", + "mergeStatus": "queued", + "mergeId": "36c88bf7-3d14-437f-82aa-e38cce733261", + "lastMergeSourceCommit": { + "commitId": "01768d964c03e97260af0bd8cd9e5cd1f9ac6356", + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/01768d964c03e97260af0bd8cd9e5cd1f9ac6356" + }, + "lastMergeTargetCommit": { + "commitId": "b748ab7eb49b8627214f22f631f878c4af9893b5", + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/b748ab7eb49b8627214f22f631f878c4af9893b5" + }, + "reviewers": [], + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/pullRequests/19", + "_links": { + "self": { + "href": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/pullRequests/19" + }, + "repository": { + "href": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a" + }, + "workItems": { + "href": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/pullRequests/19/workitems" + }, + "sourceBranch": { + "href": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/refs/heads/pr_branch" + }, + "targetBranch": { + "href": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/refs/heads/main" + }, + "sourceCommit": { + "href": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/01768d964c03e97260af0bd8cd9e5cd1f9ac6356" + }, + "targetCommit": { + "href": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/b748ab7eb49b8627214f22f631f878c4af9893b5" + }, + "createdBy": { + "href": "https://spsproduks1.vssps.visualstudio.com/A93f74f38-2b8d-42d4-a5cb-74646f46666e/_apis/Identities/3ff4a20f-306e-677e-8a01-57f35e71f109" + }, + "iterations": { + "href": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/pullRequests/19/iterations" + } + }, + "supportsIterations": true, + "artifactId": "vstfs:///Git/PullRequestId/d350c9c0-7749-4ff8-a78f-f9c1f0e56729%2ffde2d21f-13b9-4864-a995-83329045289a%2f19" +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/pr.json.golden b/scm/driver/azure/testdata/pr.json.golden new file mode 100644 index 000000000..291b6f063 --- /dev/null +++ b/scm/driver/azure/testdata/pr.json.golden @@ -0,0 +1,35 @@ +{ + "Number": 19, + "Title": "test_pr", + "Body": "test_pr_body", + "Sha": "01768d964c03e97260af0bd8cd9e5cd1f9ac6356", + "Ref": "", + "Source": "refs/heads/pr_branch", + "Target": "refs/heads/main", + "Fork": "", + "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/pullRequests/19", + "Diff": "", + "Closed": false, + "Merged": false, + "Base": { + "Name": "", + "Path": "", + "Sha": "01768d964c03e97260af0bd8cd9e5cd1f9ac6356" + }, + "Head": { + "Name": "", + "Path": "", + "Sha": "01768d964c03e97260af0bd8cd9e5cd1f9ac6356" + }, + "Author": { + "Login": "tp@harness.io", + "Name": "", + "Email": "", + "Avatar": "https://dev.azure.com/tphoney/_api/_common/identityImage?id=3ff4a20f-306e-677e-8a01-57f35e71f109", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Created": "2022-03-04T13:34:54.3177724Z", + "Updated": "0001-01-01T00:00:00Z", + "Labels": null +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/webhooks/pr_created.json b/scm/driver/azure/testdata/webhooks/pr_created.json new file mode 100644 index 000000000..746cacec8 --- /dev/null +++ b/scm/driver/azure/testdata/webhooks/pr_created.json @@ -0,0 +1,85 @@ +{ + "id": "2ab4e3d3-b7a6-425e-92b1-5a9982c1269e", + "eventType": "git.pullrequest.created", + "publisherId": "tfs", + "scope": "all", + "message": { + "text": "Jamal Hartnett created a new pull request", + "html": "Jamal Hartnett created a new pull request", + "markdown": "Jamal Hartnett created a new pull request" + }, + "detailedMessage": { + "text": "Jamal Hartnett created a new pull request\r\n\r\n- Merge status: Succeeded\r\n- Merge commit: eef717(https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/eef717f69257a6333f221566c1c987dc94cc0d72)\r\n", + "html": "Jamal Hartnett created a new pull request\r\n
    \r\n
  • Merge status: Succeeded
  • \r\n
  • Merge commit: eef717
  • \r\n
", + "markdown": "Jamal Hartnett created a new pull request\r\n\r\n+ Merge status: Succeeded\r\n+ Merge commit: [eef717](https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/eef717f69257a6333f221566c1c987dc94cc0d72)\r\n" + }, + "resource": { + "repository": { + "id": "4bc14d40-c903-45e2-872e-0462c7748079", + "name": "Fabrikam", + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079", + "project": { + "id": "6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c", + "name": "Fabrikam", + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/projects/6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c", + "state": "wellFormed" + }, + "defaultBranch": "refs/heads/master", + "remoteUrl": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam" + }, + "pullRequestId": 1, + "status": "active", + "createdBy": { + "id": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "displayName": "Jamal Hartnett", + "uniqueName": "fabrikamfiber4@hotmail.com", + "url": "https://vssps.dev.azure.com/fabrikam/_apis/Identities/54d125f7-69f7-4191-904f-c5b96b6261c8", + "imageUrl": "https://dev.azure.com/fabrikam/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8" + }, + "creationDate": "2014-06-17T16:55:46.589889Z", + "title": "my first pull request", + "description": " - test2\r\n", + "sourceRefName": "refs/heads/mytopic", + "targetRefName": "refs/heads/master", + "mergeStatus": "succeeded", + "mergeId": "a10bb228-6ba6-4362-abd7-49ea21333dbd", + "lastMergeSourceCommit": { + "commitId": "53d54ac915144006c2c9e90d2c7d3880920db49c", + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/53d54ac915144006c2c9e90d2c7d3880920db49c" + }, + "lastMergeTargetCommit": { + "commitId": "a511f535b1ea495ee0c903badb68fbc83772c882", + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/a511f535b1ea495ee0c903badb68fbc83772c882" + }, + "lastMergeCommit": { + "commitId": "eef717f69257a6333f221566c1c987dc94cc0d72", + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/eef717f69257a6333f221566c1c987dc94cc0d72" + }, + "reviewers": [ + { + "reviewerUrl": null, + "vote": 0, + "id": "2ea2d095-48f9-4cd6-9966-62f6f574096c", + "displayName": "[Mobile]\\Mobile Team", + "uniqueName": "vstfs:///Classification/TeamProject/f0811a3b-8c8a-4e43-a3bf-9a049b4835bd\\Mobile Team", + "url": "https://vssps.dev.azure.com/fabrikam/_apis/Identities/2ea2d095-48f9-4cd6-9966-62f6f574096c", + "imageUrl": "https://dev.azure.com/fabrikam/DefaultCollection/_api/_common/identityImage?id=2ea2d095-48f9-4cd6-9966-62f6f574096c", + "isContainer": true + } + ], + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1" + }, + "resourceVersion": "1.0", + "resourceContainers": { + "collection": { + "id": "c12d0eb8-e382-443b-9f9c-c52cba5014c2" + }, + "account": { + "id": "f844ec47-a9db-4511-8281-8b63f4eaf94e" + }, + "project": { + "id": "be9b3917-87e6-42a4-a549-2bc06a7a878f" + } + }, + "createdDate": "2016-09-19T13:03:27.2879096Z" +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/webhooks/pr_created.json.golden b/scm/driver/azure/testdata/webhooks/pr_created.json.golden new file mode 100644 index 000000000..3ca595b6c --- /dev/null +++ b/scm/driver/azure/testdata/webhooks/pr_created.json.golden @@ -0,0 +1,61 @@ +{ + "Action": "opened", + "Repo": { + "ID": "4bc14d40-c903-45e2-872e-0462c7748079", + "Namespace": "Fabrikam", + "Name": "4bc14d40-c903-45e2-872e-0462c7748079", + "Perm": null, + "Branch": "", + "Archived": false, + "Private": false, + "Visibility": 0, + "Clone": "", + "CloneSSH": "", + "Link": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 1, + "Title": "my first pull request", + "Body": " - test2\r\n", + "Sha": "a10bb228-6ba6-4362-abd7-49ea21333dbd", + "Ref": "refs/heads/mytopic", + "Source": "refs/heads/mytopic", + "Target": "refs/heads/master", + "Fork": "", + "Link": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1", + "Diff": "", + "Closed": false, + "Merged": false, + "Base": { + "Name": "", + "Path": "", + "Sha": "" + }, + "Head": { + "Name": "", + "Path": "", + "Sha": "" + }, + "Author": { + "Login": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "Name": "Jamal Hartnett", + "Email": "fabrikamfiber4@hotmail.com", + "Avatar": "https://dev.azure.com/fabrikam/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Created": "2014-06-17T16:55:46.589889Z", + "Updated": "0001-01-01T00:00:00Z", + "Labels": null + }, + "Sender": { + "Login": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "Name": "Jamal Hartnett", + "Email": "fabrikamfiber4@hotmail.com", + "Avatar": "https://dev.azure.com/fabrikam/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + } +} \ No newline at end of file diff --git a/scm/driver/azure/user.go b/scm/driver/azure/user.go new file mode 100644 index 000000000..78bfbe2e1 --- /dev/null +++ b/scm/driver/azure/user.go @@ -0,0 +1,27 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package azure + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type userService struct { + client *wrapper +} + +func (s *userService) Find(ctx context.Context) (*scm.User, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *userService) FindLogin(ctx context.Context, login string) (*scm.User, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, error) { + return "", nil, scm.ErrNotSupported +} diff --git a/scm/driver/azure/util.go b/scm/driver/azure/util.go new file mode 100644 index 000000000..d9f74acdd --- /dev/null +++ b/scm/driver/azure/util.go @@ -0,0 +1,23 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package azure + +import ( + "net/url" + "strconv" + + "github.com/drone/go-scm/scm" +) + +func encodeListOptions(opts scm.ListOptions) string { + params := url.Values{} + if opts.Page != 0 { + params.Set("page", strconv.Itoa(opts.Page)) + } + if opts.Size != 0 { + params.Set("per_page", strconv.Itoa(opts.Size)) + } + return params.Encode() +} diff --git a/scm/driver/azure/webhook.go b/scm/driver/azure/webhook.go new file mode 100644 index 000000000..c2c1168c7 --- /dev/null +++ b/scm/driver/azure/webhook.go @@ -0,0 +1,175 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package azure + +import ( + "encoding/json" + "io" + "io/ioutil" + "net/http" + "time" + + "github.com/drone/go-scm/scm" +) + +type webhookService struct { + client *wrapper +} + +func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhook, error) { + data, err := ioutil.ReadAll( + io.LimitReader(req.Body, 10000000), + ) + if err != nil { + return nil, err + } + + var hook scm.Webhook + // switch req.Header.Get("SOMETHING") { + // case "pull_request": + hook, err = s.parsePullRequest(data) + // default: + // return nil, scm.ErrUnknownEvent + // } + return hook, err +} + +func (s *webhookService) parsePullRequest(data []byte) (scm.Webhook, error) { + src := new(pullRequestHook) + err := json.Unmarshal(data, src) + if err != nil { + return nil, err + } + dst := convertPullRequestHook(src) + switch src.EventType { + case "git.pullrequest.created": + dst.Action = scm.ActionOpen + case "git.pullrequest.updated": + dst.Action = scm.ActionUpdate + default: + dst.Action = scm.ActionUnknown + } + + return dst, nil +} + +func convertPullRequestHook(src *pullRequestHook) (returnVal *scm.PullRequestHook) { + returnVal = &scm.PullRequestHook{ + PullRequest: scm.PullRequest{ + Number: src.Resource.PullRequestID, + Title: src.Resource.Title, + Body: src.Resource.Description, + Sha: src.Resource.MergeID, + Ref: src.Resource.SourceRefName, + Source: src.Resource.SourceRefName, + Target: src.Resource.TargetRefName, + Link: src.Resource.URL, + Author: scm.User{ + Login: src.Resource.CreatedBy.ID, + Name: src.Resource.CreatedBy.DisplayName, + Email: src.Resource.CreatedBy.UniqueName, + Avatar: src.Resource.CreatedBy.ImageURL, + }, + Created: src.Resource.CreationDate, + }, + Repo: scm.Repository{ + ID: src.Resource.Repository.ID, + Name: src.Resource.Repository.ID, + Namespace: src.Resource.Repository.Name, + Link: src.Resource.Repository.URL, + }, + Sender: scm.User{ + Login: src.Resource.CreatedBy.ID, + Name: src.Resource.CreatedBy.DisplayName, + Email: src.Resource.CreatedBy.UniqueName, + Avatar: src.Resource.CreatedBy.ImageURL, + }, + } + return returnVal +} + +type pullRequestHook struct { + ID string `json:"id"` + EventType string `json:"eventType"` + PublisherID string `json:"publisherId"` + Scope string `json:"scope"` + Message struct { + Text string `json:"text"` + HTML string `json:"html"` + Markdown string `json:"markdown"` + } `json:"message"` + DetailedMessage struct { + Text string `json:"text"` + HTML string `json:"html"` + Markdown string `json:"markdown"` + } `json:"detailedMessage"` + Resource struct { + Repository struct { + ID string `json:"id"` + Name string `json:"name"` + URL string `json:"url"` + Project struct { + ID string `json:"id"` + Name string `json:"name"` + URL string `json:"url"` + State string `json:"state"` + } `json:"project"` + DefaultBranch string `json:"defaultBranch"` + RemoteURL string `json:"remoteUrl"` + } `json:"repository"` + PullRequestID int `json:"pullRequestId"` + Status string `json:"status"` + CreatedBy struct { + ID string `json:"id"` + DisplayName string `json:"displayName"` + UniqueName string `json:"uniqueName"` + URL string `json:"url"` + ImageURL string `json:"imageUrl"` + } `json:"createdBy"` + CreationDate time.Time `json:"creationDate"` + Title string `json:"title"` + Description string `json:"description"` + SourceRefName string `json:"sourceRefName"` + TargetRefName string `json:"targetRefName"` + MergeStatus string `json:"mergeStatus"` + MergeID string `json:"mergeId"` + LastMergeSourceCommit struct { + CommitID string `json:"commitId"` + URL string `json:"url"` + } `json:"lastMergeSourceCommit"` + LastMergeTargetCommit struct { + CommitID string `json:"commitId"` + URL string `json:"url"` + } `json:"lastMergeTargetCommit"` + LastMergeCommit struct { + CommitID string `json:"commitId"` + URL string `json:"url"` + } `json:"lastMergeCommit"` + Reviewers []struct { + ReviewerURL interface{} `json:"reviewerUrl"` + Vote int `json:"vote"` + ID string `json:"id"` + DisplayName string `json:"displayName"` + UniqueName string `json:"uniqueName"` + URL string `json:"url"` + ImageURL string `json:"imageUrl"` + IsContainer bool `json:"isContainer"` + } `json:"reviewers"` + URL string `json:"url"` + } `json:"resource"` + ResourceVersion string `json:"resourceVersion"` + ResourceContainers struct { + Collection struct { + ID string `json:"id"` + } `json:"collection"` + Account struct { + ID string `json:"id"` + } `json:"account"` + Project struct { + ID string `json:"id"` + } `json:"project"` + } `json:"resourceContainers"` + CreatedDate time.Time `json:"createdDate"` +} diff --git a/scm/driver/azure/webhook_test.go b/scm/driver/azure/webhook_test.go new file mode 100644 index 000000000..9ee1028ff --- /dev/null +++ b/scm/driver/azure/webhook_test.go @@ -0,0 +1,96 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package azure + +import ( + "bytes" + "encoding/json" + "io/ioutil" + "net/http" + "strings" + "testing" + + "github.com/drone/go-scm/scm" + "github.com/google/go-cmp/cmp" +) + +func TestWebhooks(t *testing.T) { + tests := []struct { + sig string + event string + before string + after string + obj interface{} + }{ + // + // pull request events + // + // pull request created + { + sig: "71295b197fa25f4356d2fb9965df3f2379d903d7", + event: "pullrequest:created", + before: "testdata/webhooks/pr_created.json", + after: "testdata/webhooks/pr_created.json.golden", + obj: new(scm.PullRequestHook), + }, + } + + for _, test := range tests { + before, err := ioutil.ReadFile(test.before) + if err != nil { + t.Error(err) + continue + } + after, err := ioutil.ReadFile(test.after) + if err != nil { + t.Error(err) + continue + } + + buf := bytes.NewBuffer(before) + r, _ := http.NewRequest("GET", "/?secret=71295b197fa25f4356d2fb9965df3f2379d903d7", buf) + r.Header.Set("x-event-key", test.event) + + s := new(webhookService) + o, err := s.Parse(r, secretFunc) + if err != nil { + t.Error(err) + continue + } + + err = json.Unmarshal(after, &test.obj) + if err != nil { + t.Error(err) + continue + } + + if diff := cmp.Diff(test.obj, o); diff != "" { + t.Errorf("Error unmarshaling %s", test.before) + t.Log(diff) + + // debug only. remove once implemented + // _ = json.NewEncoder(os.Stdout).Encode(o) + } + + switch event := o.(type) { + case *scm.PushHook: + if !strings.HasPrefix(event.Ref, "refs/") { + t.Errorf("Push hook reference must start with refs/") + } + case *scm.BranchHook: + if strings.HasPrefix(event.Ref.Name, "refs/") { + t.Errorf("Branch hook reference must not start with refs/") + } + case *scm.TagHook: + if strings.HasPrefix(event.Ref.Name, "refs/") { + t.Errorf("Branch hook reference must not start with refs/") + } + } + } +} + +func secretFunc(scm.Webhook) (string, error) { + return "71295b197fa25f4356d2fb9965df3f2379d903d7", nil +} From 20ea640a4c6b666a9e7215e0c7da8695c37fc695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Ga=C4=87e=C5=A1a?= Date: Tue, 8 Mar 2022 13:28:24 +0100 Subject: [PATCH 075/282] fixed raw response dumping in client --- scm/client.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scm/client.go b/scm/client.go index 20ece1f21..d3d8a7d21 100644 --- a/scm/client.go +++ b/scm/client.go @@ -10,6 +10,7 @@ import ( "io" "net/http" "net/url" + "os" "strconv" "strings" "sync" @@ -167,7 +168,9 @@ func (c *Client) Do(ctx context.Context, in *Request) (*Response, error) { // dumps the response for debugging purposes. if c.DumpResponse != nil { - c.DumpResponse(res, true) + if raw, errDump := c.DumpResponse(res, true); errDump == nil { + _, _ = os.Stdout.Write(raw) + } } return newResponse(res), nil } From fcc6e222742cf3ae798a9d5b87e5a8e087f17a4f Mon Sep 17 00:00:00 2001 From: Dan Wilson Date: Tue, 8 Mar 2022 16:17:49 +0000 Subject: [PATCH 076/282] (maint) release prep for 1.20.0 (#160) --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ebdc0c0aa..d3c835d85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [v1.20.0](https://github.com/drone/go-scm/tree/v1.20.0) (2022-03-08) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.19.1...v1.20.0) + +**Implemented enhancements:** + +- \(DRON-242\) initial implementation of azure devops support [\#158](https://github.com/drone/go-scm/pull/158) ([tphoney](https://github.com/tphoney)) + +**Fixed bugs:** + +- fixed raw response dumping in client [\#159](https://github.com/drone/go-scm/pull/159) ([marko-gacesa](https://github.com/marko-gacesa)) + ## [v1.19.1](https://github.com/drone/go-scm/tree/v1.19.1) (2022-02-23) [Full Changelog](https://github.com/drone/go-scm/compare/v1.19.0...v1.19.1) @@ -10,6 +22,10 @@ - GitHub list commits fix [\#152](https://github.com/drone/go-scm/pull/152) ([mohitg0795](https://github.com/mohitg0795)) - Bitbucket compare changes fix for rename and removed file ops [\#151](https://github.com/drone/go-scm/pull/151) ([mohitg0795](https://github.com/mohitg0795)) +**Merged pull requests:** + +- prep for v1.19.1 [\#155](https://github.com/drone/go-scm/pull/155) ([tphoney](https://github.com/tphoney)) + ## [v1.19.0](https://github.com/drone/go-scm/tree/v1.19.0) (2022-02-09) [Full Changelog](https://github.com/drone/go-scm/compare/v1.18.0...v1.19.0) From 7bd378dd06c8f91d02674280b9db4dfeb55a1883 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Fri, 25 Mar 2022 10:13:49 +0000 Subject: [PATCH 077/282] (DRON-242) azure add compare commits,get commit,list repos --- scm/driver/azure/azure.go | 6 ++ scm/driver/azure/git.go | 78 +++++++++++++++++-- scm/driver/azure/git_test.go | 55 +++++++++++++ scm/driver/azure/integration/content_test.go | 4 +- scm/driver/azure/integration/git_test.go | 58 ++++++++++++++ scm/driver/azure/integration/repo_test.go | 36 +++++++++ scm/driver/azure/repo.go | 48 +++++++++++- scm/driver/azure/repo_test.go | 46 +++++++++++ scm/driver/azure/testdata/commit.json | 53 +++++++++++++ scm/driver/azure/testdata/commit.json.golden | 19 +++++ scm/driver/azure/testdata/compare.json | 24 ++++++ scm/driver/azure/testdata/compare.json.golden | 9 +++ scm/driver/azure/testdata/repos.json | 45 +++++++++++ scm/driver/azure/testdata/repos.json.golden | 14 ++++ 14 files changed, 487 insertions(+), 8 deletions(-) create mode 100644 scm/driver/azure/integration/repo_test.go create mode 100644 scm/driver/azure/repo_test.go create mode 100644 scm/driver/azure/testdata/commit.json create mode 100644 scm/driver/azure/testdata/commit.json.golden create mode 100644 scm/driver/azure/testdata/compare.json create mode 100644 scm/driver/azure/testdata/compare.json.golden create mode 100644 scm/driver/azure/testdata/repos.json create mode 100644 scm/driver/azure/testdata/repos.json.golden diff --git a/scm/driver/azure/azure.go b/scm/driver/azure/azure.go index aa0f69927..ab61f1126 100644 --- a/scm/driver/azure/azure.go +++ b/scm/driver/azure/azure.go @@ -90,6 +90,12 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface _ = json.NewDecoder(res.Body).Decode(err) return res, err } + // the following is used for debugging purposes. + // bytes, err := io.ReadAll(res.Body) + // if err != nil { + // log.Fatal(err) + // } + // fmt.Println(string(bytes)) if out == nil { return res, nil diff --git a/scm/driver/azure/git.go b/scm/driver/azure/git.go index 8ee1b7370..0e28cb24d 100644 --- a/scm/driver/azure/git.go +++ b/scm/driver/azure/git.go @@ -32,7 +32,11 @@ func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Re } func (s *gitService) FindCommit(ctx context.Context, repo, ref string) (*scm.Commit, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/commits/get?view=azure-devops-rest-6.0#get-by-id + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/commits/%s?api-version=6.0", s.client.owner, s.client.project, repo, ref) + out := new(gitCommit) + res, err := s.client.do(ctx, "GET", endpoint, nil, out) + return convertCommit(out), res, err } func (s *gitService) FindTag(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { @@ -51,10 +55,13 @@ func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.Comm // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/commits/get-commits?view=azure-devops-rest-6.0 endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/commits?", s.client.owner, s.client.project, repo) if opts.Ref != "" { - endpoint += fmt.Sprintf("searchCriteria.itemVersion.version=%s&api-version=6.0", opts.Ref) - } else { - endpoint += "&api-version=6.0" + endpoint += fmt.Sprintf("searchCriteria.itemVersion.version=%s&", opts.Ref) + } + if opts.Path != "" { + endpoint += fmt.Sprintf("searchCriteria.itemPath=%s&", opts.Path) } + endpoint += "api-version=6.0" + out := new(commitList) res, err := s.client.do(ctx, "GET", endpoint, nil, &out) return convertCommitList(out.Value), res, err @@ -69,7 +76,17 @@ func (s *gitService) ListChanges(ctx context.Context, repo, ref string, _ scm.Li } func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/diffs/get?view=azure-devops-rest-6.0 + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/diffs/commits?", s.client.owner, s.client.project, repo) + // add base + endpoint += fmt.Sprintf("baseVersion=%s&baseVersionType=commit&", source) + // add target + endpoint += fmt.Sprintf("targetVersion=%s&targetVersionType=commit&api-version=6.0", target) + out := new(compare) + res, err := s.client.do(ctx, "GET", endpoint, nil, &out) + + changes := out.Changes + return convertChangeList(changes), res, err } type crudBranch []struct { @@ -129,6 +146,33 @@ type gitCommit struct { RemoteURL string `json:"remoteUrl"` } +type file struct { + ChangeType string `json:"changeType"` + Item struct { + CommitID string `json:"commitId"` + GitObjectType string `json:"gitObjectType"` + IsFolder bool `json:"isFolder"` + ObjectID string `json:"objectId"` + OriginalObjectID string `json:"originalObjectId"` + Path string `json:"path"` + URL string `json:"url"` + } `json:"item"` +} + +type compare struct { + AheadCount int64 `json:"aheadCount"` + AllChangesIncluded bool `json:"allChangesIncluded"` + BaseCommit string `json:"baseCommit"` + BehindCount int64 `json:"behindCount"` + ChangeCounts struct { + Add int64 `json:"Add"` + Edit int64 `json:"Edit"` + } `json:"changeCounts"` + Changes []*file `json:"changes"` + CommonCommit string `json:"commonCommit"` + TargetCommit string `json:"targetCommit"` +} + func convertBranchList(from []*branch) []*scm.Reference { to := []*scm.Reference{} for _, v := range from { @@ -170,3 +214,27 @@ func convertCommit(from *gitCommit) *scm.Commit { }, } } + +func convertChangeList(from []*file) []*scm.Change { + to := []*scm.Change{} + for _, v := range from { + to = append(to, convertChange(v)) + } + return to +} + +func convertChange(from *file) *scm.Change { + returnVal := &scm.Change{ + Path: from.Item.Path, + } + switch from.ChangeType { + case "add": + returnVal.Added = true + case "delete": + returnVal.Deleted = true + case "rename": + returnVal.Renamed = true + } + + return returnVal +} diff --git a/scm/driver/azure/git_test.go b/scm/driver/azure/git_test.go index 9f2521518..0e652eca2 100644 --- a/scm/driver/azure/git_test.go +++ b/scm/driver/azure/git_test.go @@ -16,6 +16,34 @@ import ( "github.com/h2non/gock" ) +func TestGitFindCommit(t *testing.T) { + defer gock.Off() + + gock.New("https:/dev.azure.com/"). + Get("/ORG/PROJ/_apis/git/repositories/REPOID/"). + Reply(200). + Type("application/json"). + File("testdata/commit.json") + + client := NewDefault("ORG", "PROJ") + + got, _, err := client.Git.FindCommit(context.Background(), "REPOID", "14897f4465d2d63508242b5cbf68aa2865f693e7") + if err != nil { + t.Error(err) + return + } + + want := new(scm.Commit) + raw, _ := ioutil.ReadFile("testdata/commit.json.golden") + + _ = json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + func TestGitCreateBranch(t *testing.T) { defer gock.Off() @@ -94,3 +122,30 @@ func TestGitListBranches(t *testing.T) { t.Log(diff) } } + +func TestGitCompareChanges(t *testing.T) { + defer gock.Off() + + gock.New("https:/dev.azure.com/"). + Get("/ORG/PROJ/_apis/git/repositories/REPOID/"). + Reply(200). + Type("application/json"). + File("testdata/compare.json") + + client := NewDefault("ORG", "PROJ") + got, _, err := client.Git.CompareChanges(context.Background(), "REPOID", "9788e5ddf8b387cb79228628f34d8dc18582d606", "66df312dad61e84dd896d1e8d14ee3dce53b62f0", scm.ListOptions{}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Change{} + raw, _ := ioutil.ReadFile("testdata/compare.json.golden") + _ = json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + +} diff --git a/scm/driver/azure/integration/content_test.go b/scm/driver/azure/integration/content_test.go index c85ad2d4c..b2b200052 100644 --- a/scm/driver/azure/integration/content_test.go +++ b/scm/driver/azure/integration/content_test.go @@ -125,8 +125,8 @@ func TestListFiles(t *testing.T) { if listResponse.Status != http.StatusOK { t.Errorf("Contents.Delete we did not get a 200 back %v", listResponse.Status) } - if len(contentInfo) != 2 { - t.Errorf("Contents.List there should be at least 2 files %v", contentInfo) + if 2 >= len(contentInfo) { + t.Errorf("Contents.List there should be at least 2 files %d", len(contentInfo)) } } diff --git a/scm/driver/azure/integration/git_test.go b/scm/driver/azure/integration/git_test.go index 57eaf3f21..ce9eefca6 100644 --- a/scm/driver/azure/integration/git_test.go +++ b/scm/driver/azure/integration/git_test.go @@ -68,6 +68,34 @@ func TestCreateBranch(t *testing.T) { } +func TestFindCommit(t *testing.T) { + if token == "" { + t.Skip("Skipping, Acceptance test") + } + client = azure.NewDefault(organization, project) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("Authorization", fmt.Sprintf("Basic %s", token)) + }, + }, + } + currentCommit, commitErr := GetCurrentCommitOfBranch(client, "main") + if commitErr != nil { + t.Errorf("we got an error %v", commitErr) + } + commit, response, listerr := client.Git.FindCommit(context.Background(), repoID, currentCommit) + if listerr != nil { + t.Errorf("FindCommit got an error %v", listerr) + } + if response.Status != http.StatusOK { + t.Errorf("FindCommit did not get a 200 back %v", response.Status) + } + if commit.Author.Name == "" { + t.Errorf("There is no author %v", commit.Author) + } +} + func TestListCommits(t *testing.T) { if token == "" { t.Skip("Skipping, Acceptance test") @@ -94,3 +122,33 @@ func TestListCommits(t *testing.T) { t.Errorf("Contents.List first entry did not get a sha back %v", commits[0].Sha) } } + +func TestCompareChanges(t *testing.T) { + if token == "" { + t.Skip("Skipping, Acceptance test") + } + client = azure.NewDefault(organization, project) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("Authorization", fmt.Sprintf("Basic %s", token)) + }, + }, + } + // get all the commits + commits, _, err := client.Git.ListCommits(context.Background(), repoID, scm.CommitListOptions{}) + if err != nil { + t.Errorf("we got an error %v", err) + } + // compare the last two commits + changes, response, listerr := client.Git.CompareChanges(context.Background(), repoID, commits[10].Sha, commits[0].Sha, scm.ListOptions{}) + if listerr != nil { + t.Errorf("CompareChanges got an error %v", listerr) + } + if response.Status != http.StatusOK { + t.Errorf("CompareChanges did not get a 200 back %v", response.Status) + } + if len(changes) == 0 { + t.Errorf("There is at least one change %d", len(changes)) + } +} diff --git a/scm/driver/azure/integration/repo_test.go b/scm/driver/azure/integration/repo_test.go new file mode 100644 index 000000000..a0cb5e816 --- /dev/null +++ b/scm/driver/azure/integration/repo_test.go @@ -0,0 +1,36 @@ +package integration + +import ( + "context" + "fmt" + "net/http" + "testing" + + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/azure" + "github.com/drone/go-scm/scm/transport" +) + +func TestListRepos(t *testing.T) { + if token == "" { + t.Skip("Skipping, Acceptance test") + } + client = azure.NewDefault(organization, project) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("Authorization", fmt.Sprintf("Basic %s", token)) + }, + }, + } + references, response, listerr := client.Repositories.List(context.Background(), scm.ListOptions{}) + if listerr != nil { + t.Errorf("List got an error %v", listerr) + } + if response.Status != http.StatusOK { + t.Errorf("List did not get a 200 back %v", response.Status) + } + if len(references) < 1 { + t.Errorf("List should have at least 1 repo %d", len(references)) + } +} diff --git a/scm/driver/azure/repo.go b/scm/driver/azure/repo.go index 0f312143a..ba38be25b 100644 --- a/scm/driver/azure/repo.go +++ b/scm/driver/azure/repo.go @@ -6,6 +6,7 @@ package azure import ( "context" + "fmt" "github.com/drone/go-scm/scm" ) @@ -33,7 +34,12 @@ func (s *RepositoryService) FindPerms(ctx context.Context, repo string) (*scm.Pe // List returns the user repository list. func (s *RepositoryService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/repositories/list?view=azure-devops-rest-6.0 + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories?api-version=6.0", s.client.owner, s.client.project) + + out := new(repositories) + res, err := s.client.do(ctx, "GET", endpoint, nil, &out) + return convertRepositoryList(out), res, err } // ListHooks returns a list or repository hooks. @@ -70,3 +76,43 @@ func (s *RepositoryService) UpdateHook(ctx context.Context, repo, id string, inp func (s *RepositoryService) DeleteHook(ctx context.Context, repo, id string) (*scm.Response, error) { return nil, scm.ErrNotSupported } + +type repositories struct { + Count int64 `json:"count"` + Value []*repository `json:"value"` +} + +type repository struct { + DefaultBranch string `json:"defaultBranch"` + ID string `json:"id"` + Name string `json:"name"` + Project struct { + ID string `json:"id"` + Name string `json:"name"` + State string `json:"state"` + URL string `json:"url"` + } `json:"project"` + RemoteURL string `json:"remoteUrl"` + URL string `json:"url"` +} + +// helper function to convert from the gogs repository list to +// the common repository structure. +func convertRepositoryList(from *repositories) []*scm.Repository { + to := []*scm.Repository{} + for _, v := range from.Value { + to = append(to, convertRepository(v)) + } + return to +} + +// helper function to convert from the gogs repository structure +// to the common repository structure. +func convertRepository(from *repository) *scm.Repository { + return &scm.Repository{ + ID: from.ID, + Name: from.Name, + Link: from.URL, + Branch: from.DefaultBranch, + } +} diff --git a/scm/driver/azure/repo_test.go b/scm/driver/azure/repo_test.go new file mode 100644 index 000000000..345f7cfb4 --- /dev/null +++ b/scm/driver/azure/repo_test.go @@ -0,0 +1,46 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package azure + +import ( + "context" + "encoding/json" + "io/ioutil" + "testing" + + "github.com/drone/go-scm/scm" + + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" +) + +func TestRepositoryList(t *testing.T) { + defer gock.Off() + + gock.New("https:/dev.azure.com/"). + Get("/ORG/PROJ/_apis/git/repositories"). + Reply(200). + Type("application/json"). + File("testdata/repos.json") + + client := NewDefault("ORG", "PROJ") + got, _, err := client.Repositories.List(context.Background(), scm.ListOptions{}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Repository{} + raw, _ := ioutil.ReadFile("testdata/repos.json.golden") + jsonErr := json.Unmarshal(raw, &want) + if jsonErr != nil { + t.Error(jsonErr) + } + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} diff --git a/scm/driver/azure/testdata/commit.json b/scm/driver/azure/testdata/commit.json new file mode 100644 index 000000000..ea37dc05b --- /dev/null +++ b/scm/driver/azure/testdata/commit.json @@ -0,0 +1,53 @@ +{ + "treeId": "efbaf98cd9984e7480f600f8c4b592432a428518", + "commitId": "14897f4465d2d63508242b5cbf68aa2865f693e7", + "author": { + "name": "tp", + "email": "tp@harness.io", + "date": "2022-03-15T17:08:22Z", + "imageUrl": "https://dev.azure.com/tphoney/_apis/GraphProfile/MemberAvatars/msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + }, + "committer": { + "name": "tp", + "email": "tp@harness.io", + "date": "2022-03-15T17:08:22Z", + "imageUrl": "https://dev.azure.com/tphoney/_apis/GraphProfile/MemberAvatars/msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + }, + "comment": "update CRUD", + "parents": [ + "0e969a16c531c2a6961e5dcf9f82f4456c7bbe68" + ], + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/14897f4465d2d63508242b5cbf68aa2865f693e7", + "remoteUrl": "https://dev.azure.com/tphoney/test_project/_git/test_repo2/commit/14897f4465d2d63508242b5cbf68aa2865f693e7", + "_links": { + "self": { + "href": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/14897f4465d2d63508242b5cbf68aa2865f693e7" + }, + "repository": { + "href": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a" + }, + "web": { + "href": "https://dev.azure.com/tphoney/test_project/_git/test_repo2/commit/14897f4465d2d63508242b5cbf68aa2865f693e7" + }, + "changes": { + "href": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/14897f4465d2d63508242b5cbf68aa2865f693e7/changes" + } + }, + "push": { + "pushedBy": { + "displayName": "tp", + "url": "https://spsproduks1.vssps.visualstudio.com/A93f74f38-2b8d-42d4-a5cb-74646f46666e/_apis/Identities/3ff4a20f-306e-677e-8a01-57f35e71f109", + "_links": { + "avatar": { + "href": "https://dev.azure.com/tphoney/_apis/GraphProfile/MemberAvatars/msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + } + }, + "id": "3ff4a20f-306e-677e-8a01-57f35e71f109", + "uniqueName": "tp@harness.io", + "imageUrl": "https://dev.azure.com/tphoney/_api/_common/identityImage?id=3ff4a20f-306e-677e-8a01-57f35e71f109", + "descriptor": "msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + }, + "pushId": 296, + "date": "2022-03-15T17:08:22.7905002Z" + } +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/commit.json.golden b/scm/driver/azure/testdata/commit.json.golden new file mode 100644 index 000000000..36b73b3cf --- /dev/null +++ b/scm/driver/azure/testdata/commit.json.golden @@ -0,0 +1,19 @@ +{ + "Sha": "14897f4465d2d63508242b5cbf68aa2865f693e7", + "Message": "update CRUD", + "Author": { + "Name": "tp", + "Email": "tp@harness.io", + "Date": "2022-03-15T17:08:22Z", + "Login": "", + "Avatar": "" + }, + "Committer": { + "Name": "tp", + "Email": "tp@harness.io", + "Date": "2022-03-15T17:08:22Z", + "Login": "", + "Avatar": "" + }, + "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/14897f4465d2d63508242b5cbf68aa2865f693e7" +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/compare.json b/scm/driver/azure/testdata/compare.json new file mode 100644 index 000000000..7e23610f0 --- /dev/null +++ b/scm/driver/azure/testdata/compare.json @@ -0,0 +1,24 @@ +{ + "allChangesIncluded": true, + "changeCounts": { + "Edit": 1 + }, + "changes": [ + { + "item": { + "objectId": "a493dad221fb22ff4c35ff89f112a61f8c39e924", + "originalObjectId": "c42585a91aea68fcdd2f06508f7073983689aa5f", + "gitObjectType": "blob", + "commitId": "66df312dad61e84dd896d1e8d14ee3dce53b62f0", + "path": "/testfile", + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/items/testfile?versionType=Commit&version=66df312dad61e84dd896d1e8d14ee3dce53b62f0" + }, + "changeType": "edit" + } + ], + "commonCommit": "9788e5ddf8b387cb79228628f34d8dc18582d606", + "baseCommit": "9788e5ddf8b387cb79228628f34d8dc18582d606", + "targetCommit": "66df312dad61e84dd896d1e8d14ee3dce53b62f0", + "aheadCount": 10, + "behindCount": 0 +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/compare.json.golden b/scm/driver/azure/testdata/compare.json.golden new file mode 100644 index 000000000..adbdcb42a --- /dev/null +++ b/scm/driver/azure/testdata/compare.json.golden @@ -0,0 +1,9 @@ +[ + { + "Path": "/testfile", + "Added": false, + "Renamed": false, + "Deleted": false, + "BlobID": "" + } +] diff --git a/scm/driver/azure/testdata/repos.json b/scm/driver/azure/testdata/repos.json new file mode 100644 index 000000000..a05b6ce13 --- /dev/null +++ b/scm/driver/azure/testdata/repos.json @@ -0,0 +1,45 @@ +{ + "value": [ + { + "id": "91f0d4cb-4c36-49a5-b28d-2d72da089c4d", + "name": "test_project", + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/91f0d4cb-4c36-49a5-b28d-2d72da089c4d", + "project": { + "id": "d350c9c0-7749-4ff8-a78f-f9c1f0e56729", + "name": "test_project", + "url": "https://dev.azure.com/tphoney/_apis/projects/d350c9c0-7749-4ff8-a78f-f9c1f0e56729", + "state": "wellFormed", + "revision": 11, + "visibility": "private", + "lastUpdateTime": "2022-02-24T15:31:27.89Z" + }, + "defaultBranch": "refs/heads/main", + "size": 1232, + "remoteUrl": "https://tphoney@dev.azure.com/tphoney/test_project/_git/test_project", + "sshUrl": "git@ssh.dev.azure.com:v3/tphoney/test_project/test_project", + "webUrl": "https://dev.azure.com/tphoney/test_project/_git/test_project", + "isDisabled": false + }, + { + "id": "fde2d21f-13b9-4864-a995-83329045289a", + "name": "test_repo2", + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a", + "project": { + "id": "d350c9c0-7749-4ff8-a78f-f9c1f0e56729", + "name": "test_project", + "url": "https://dev.azure.com/tphoney/_apis/projects/d350c9c0-7749-4ff8-a78f-f9c1f0e56729", + "state": "wellFormed", + "revision": 11, + "visibility": "private", + "lastUpdateTime": "2022-02-24T15:31:27.89Z" + }, + "defaultBranch": "refs/heads/main", + "size": 37687, + "remoteUrl": "https://tphoney@dev.azure.com/tphoney/test_project/_git/test_repo2", + "sshUrl": "git@ssh.dev.azure.com:v3/tphoney/test_project/test_repo2", + "webUrl": "https://dev.azure.com/tphoney/test_project/_git/test_repo2", + "isDisabled": false + } + ], + "count": 2 +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/repos.json.golden b/scm/driver/azure/testdata/repos.json.golden new file mode 100644 index 000000000..cf0a77b5d --- /dev/null +++ b/scm/driver/azure/testdata/repos.json.golden @@ -0,0 +1,14 @@ +[ + { + "ID": "91f0d4cb-4c36-49a5-b28d-2d72da089c4d", + "Name": "test_project", + "Branch": "refs/heads/main", + "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/91f0d4cb-4c36-49a5-b28d-2d72da089c4d" + }, + { + "ID": "fde2d21f-13b9-4864-a995-83329045289a", + "Name": "test_repo2", + "Branch": "refs/heads/main", + "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a" + } +] \ No newline at end of file From 7e9ed2b3a1ede9797d988325cb1dcf09a2b7440e Mon Sep 17 00:00:00 2001 From: TP Honey Date: Mon, 28 Mar 2022 16:53:16 +0100 Subject: [PATCH 078/282] (feat) add azure webhook parsing, creation deletion & list --- scm/driver/azure/integration/repo_test.go | 73 +++ scm/driver/azure/repo.go | 152 ++++++- scm/driver/azure/repo_test.go | 59 +++ scm/driver/azure/testdata/hook.json | 58 +++ scm/driver/azure/testdata/hook.json.golden | 10 + scm/driver/azure/testdata/projects.json | 14 + .../azure/testdata/webhooks/pr_merged.json | 86 ++++ .../testdata/webhooks/pr_merged.json.golden | 61 +++ .../azure/testdata/webhooks/pr_updated.json | 92 ++++ .../testdata/webhooks/pr_updated.json.golden | 61 +++ scm/driver/azure/testdata/webhooks/push.json | 76 ++++ .../azure/testdata/webhooks/push.json.golden | 45 ++ scm/driver/azure/webhook.go | 421 +++++++++++++++++- scm/driver/azure/webhook_test.go | 25 +- 14 files changed, 1201 insertions(+), 32 deletions(-) create mode 100644 scm/driver/azure/testdata/hook.json create mode 100644 scm/driver/azure/testdata/hook.json.golden create mode 100644 scm/driver/azure/testdata/projects.json create mode 100644 scm/driver/azure/testdata/webhooks/pr_merged.json create mode 100644 scm/driver/azure/testdata/webhooks/pr_merged.json.golden create mode 100644 scm/driver/azure/testdata/webhooks/pr_updated.json create mode 100644 scm/driver/azure/testdata/webhooks/pr_updated.json.golden create mode 100644 scm/driver/azure/testdata/webhooks/push.json create mode 100644 scm/driver/azure/testdata/webhooks/push.json.golden diff --git a/scm/driver/azure/integration/repo_test.go b/scm/driver/azure/integration/repo_test.go index a0cb5e816..27f0bf543 100644 --- a/scm/driver/azure/integration/repo_test.go +++ b/scm/driver/azure/integration/repo_test.go @@ -34,3 +34,76 @@ func TestListRepos(t *testing.T) { t.Errorf("List should have at least 1 repo %d", len(references)) } } + +func TestListHooks(t *testing.T) { + if token == "" { + t.Skip("Skipping, Acceptance test") + } + client = azure.NewDefault(organization, project) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("Authorization", fmt.Sprintf("Basic %s", token)) + }, + }, + } + hooks, response, listerr := client.Repositories.ListHooks(context.Background(), repoID, scm.ListOptions{}) + if listerr != nil { + t.Errorf("List got an error %v", listerr) + } + if response.Status != http.StatusOK { + t.Errorf("List did not get a 200 back %v", response.Status) + } + if len(hooks) < 1 { + t.Errorf("List should have at least 1 hook %d", len(hooks)) + } +} + +func TestCreateDeleteHooks(t *testing.T) { + if token == "" { + t.Skip("Skipping, Acceptance test") + } + client = azure.NewDefault(organization, project) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("Authorization", fmt.Sprintf("Basic %s", token)) + }, + }, + } + originalHooks, _, _ := client.Repositories.ListHooks(context.Background(), repoID, scm.ListOptions{}) + // create a new hook + inputHook := &scm.HookInput{ + Name: "web", + NativeEvents: []string{"git.push"}, + Target: "http://www.example.com/webhook", + } + outHook, createResponse, createErr := client.Repositories.CreateHook(context.Background(), repoID, inputHook) + if createErr != nil { + t.Errorf("Create got an error %v", createErr) + } + if createResponse.Status != http.StatusOK { + t.Errorf("Create did not get a 200 back %v", createResponse.Status) + } + if len(outHook.Events) != 1 { + t.Errorf("New hook has one event %d", len(outHook.Events)) + } + // get the hooks again, and make sure the new hook is there + afterCreate, _, _ := client.Repositories.ListHooks(context.Background(), repoID, scm.ListOptions{}) + if len(afterCreate) != len(originalHooks)+1 { + t.Errorf("After create, the number of hooks is not correct %d. It should be %d", len(afterCreate), len(originalHooks)+1) + } + // delete the hook we created + deleteResponse, deleteErr := client.Repositories.DeleteHook(context.Background(), repoID, outHook.ID) + if deleteErr != nil { + t.Errorf("Delete got an error %v", deleteErr) + } + if deleteResponse.Status != http.StatusNoContent { + t.Errorf("Delete did not get a 204 back, got %v", deleteResponse.Status) + } + // get the hooks again, and make sure the new hook is gone + afterDelete, _, _ := client.Repositories.ListHooks(context.Background(), repoID, scm.ListOptions{}) + if len(afterDelete) != len(originalHooks) { + t.Errorf("After Delete, the number of hooks is not correct %d. It should be %d", len(afterDelete), len(originalHooks)) + } +} diff --git a/scm/driver/azure/repo.go b/scm/driver/azure/repo.go index ba38be25b..5a86d6c46 100644 --- a/scm/driver/azure/repo.go +++ b/scm/driver/azure/repo.go @@ -44,7 +44,11 @@ func (s *RepositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* // ListHooks returns a list or repository hooks. func (s *RepositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + // https://docs.microsoft.com/en-us/rest/api/azure/devops/hooks/subscriptions/list?view=azure-devops-rest-6.0 + endpoint := fmt.Sprintf("%s/_apis/hooks/subscriptions?api-version=6.0", s.client.owner) + out := new(subscriptions) + res, err := s.client.do(ctx, "GET", endpoint, nil, &out) + return convertHookList(out.Value, repo), res, err } // ListStatus returns a list of commit statuses. @@ -54,7 +58,37 @@ func (s *RepositoryService) ListStatus(ctx context.Context, repo, ref string, op // CreateHook creates a new repository webhook. func (s *RepositoryService) CreateHook(ctx context.Context, repo string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + // https://docs.microsoft.com/en-us/rest/api/azure/devops/hooks/subscriptions/create?view=azure-devops-rest-6.0 + endpoint := fmt.Sprintf("%s/_apis/hooks/subscriptions?api-version=6.0", s.client.owner) + in := new(subscription) + in.Status = "enabled" + in.PublisherID = "tfs" + in.ResourceVersion = "1.0" + in.ConsumerID = "webHooks" + in.ConsumerActionID = "httpRequest" + // we do not support scm hookevents, only native events + if input.NativeEvents == nil { + return nil, nil, fmt.Errorf("CreateHook, You must pass at least one native event") + } + if len(input.NativeEvents) > 1 { + return nil, nil, fmt.Errorf("CreateHook, Azure only allows the creation of a single hook at a time %v", input.NativeEvents) + } + in.EventType = input.NativeEvents[0] + // publisher + projectID, projErr := s.getProjectIDFromProjectName(ctx, s.client.project) + if projErr != nil { + return nil, nil, fmt.Errorf("CreateHook was unable to look up the project's projectID, %s", projErr) + } + in.PublisherInputs.ProjectID = projectID + in.PublisherInputs.Repository = repo + // consumer + in.ConsumerInputs.URL = input.Target + if input.SkipVerify { + in.ConsumerInputs.AcceptUntrustedCerts = "enabled" + } + out := new(subscription) + res, err := s.client.do(ctx, "POST", endpoint, in, out) + return convertHook(out), res, err } // CreateStatus creates a new commit status. @@ -74,7 +108,38 @@ func (s *RepositoryService) UpdateHook(ctx context.Context, repo, id string, inp // DeleteHook deletes a repository webhook. func (s *RepositoryService) DeleteHook(ctx context.Context, repo, id string) (*scm.Response, error) { - return nil, scm.ErrNotSupported + // https://docs.microsoft.com/en-us/rest/api/azure/devops/hooks/subscriptions/delete?view=azure-devops-rest-6.0 + endpoint := fmt.Sprintf("%s/_apis/hooks/subscriptions/%s?api-version=6.0", s.client.owner, id) + return s.client.do(ctx, "DELETE", endpoint, nil, nil) +} + +// helper function to return the projectID from the project name +func (s *RepositoryService) getProjectIDFromProjectName(ctx context.Context, projectName string) (string, error) { + // https://docs.microsoft.com/en-us/rest/api/azure/devops/core/projects/list?view=azure-devops-rest-6.0 + endpoint := fmt.Sprintf("%s/_apis/projects?api-version=6.0", s.client.owner) + type projects struct { + Count int64 `json:"count"` + Value []struct { + Description string `json:"description"` + ID string `json:"id"` + Name string `json:"name"` + State string `json:"state"` + URL string `json:"url"` + } `json:"value"` + } + + out := new(projects) + response, err := s.client.do(ctx, "GET", endpoint, nil, &out) + if err != nil { + fmt.Println(response) + return "", fmt.Errorf("failed to list projects: %s", err) + } + for _, v := range out.Value { + if v.Name == projectName { + return v.ID, nil + } + } + return "", fmt.Errorf("failed to find project id for %s", projectName) } type repositories struct { @@ -96,6 +161,64 @@ type repository struct { URL string `json:"url"` } +type subscriptions struct { + Count int64 `json:"count"` + Value []*subscription `json:"value"` +} + +type subscription struct { + ActionDescription string `json:"actionDescription"` + ConsumerActionID string `json:"consumerActionId"` + ConsumerID string `json:"consumerId"` + ConsumerInputs struct { + AccountName string `json:"accountName,omitempty"` + AcceptUntrustedCerts string `json:"acceptUntrustedCerts,omitempty"` + AddToTop string `json:"addToTop,omitempty"` + APIToken string `json:"apiToken,omitempty"` + BoardID string `json:"boardId,omitempty"` + BuildName string `json:"buildName,omitempty"` + BuildParameterized string `json:"buildParameterized,omitempty"` + FeedID string `json:"feedId,omitempty"` + ListID string `json:"listId,omitempty"` + PackageSourceID string `json:"packageSourceId,omitempty"` + Password string `json:"password,omitempty"` + ServerBaseURL string `json:"serverBaseUrl,omitempty"` + URL string `json:"url,omitempty"` + UserToken string `json:"userToken,omitempty"` + Username string `json:"username,omitempty"` + } `json:"consumerInputs"` + CreatedBy struct { + ID string `json:"id"` + } `json:"createdBy"` + CreatedDate string `json:"createdDate"` + EventDescription string `json:"eventDescription"` + EventType string `json:"eventType"` + ID string `json:"id"` + ModifiedBy struct { + ID string `json:"id"` + } `json:"modifiedBy"` + ModifiedDate string `json:"modifiedDate"` + ProbationRetries int64 `json:"probationRetries"` + PublisherID string `json:"publisherId"` + PublisherInputs struct { + AreaPath string `json:"areaPath,omitempty"` + Branch string `json:"branch,omitempty"` + BuildStatus string `json:"buildStatus,omitempty"` + ChangedFields string `json:"changedFields,omitempty"` + CommentPattern string `json:"commentPattern,omitempty"` + DefinitionName string `json:"definitionName,omitempty"` + HostID string `json:"hostId,omitempty"` + Path string `json:"path,omitempty"` + ProjectID string `json:"projectId,omitempty"` + Repository string `json:"repository,omitempty"` + TfsSubscriptionID string `json:"tfsSubscriptionId,omitempty"` + WorkItemType string `json:"workItemType,omitempty"` + } `json:"publisherInputs"` + ResourceVersion string `json:"resourceVersion"` + Status string `json:"status"` + URL string `json:"url"` +} + // helper function to convert from the gogs repository list to // the common repository structure. func convertRepositoryList(from *repositories) []*scm.Repository { @@ -116,3 +239,26 @@ func convertRepository(from *repository) *scm.Repository { Branch: from.DefaultBranch, } } + +func convertHookList(from []*subscription, repositoryFilter string) []*scm.Hook { + to := []*scm.Hook{} + for _, v := range from { + if repositoryFilter != "" && repositoryFilter == v.PublisherInputs.Repository { + to = append(to, convertHook(v)) + } + } + return to +} + +func convertHook(from *subscription) *scm.Hook { + returnVal := &scm.Hook{ + ID: from.ID, + + Active: from.Status == "enabled", + Target: from.ConsumerInputs.URL, + Events: []string{from.EventType}, + SkipVerify: from.ConsumerInputs.AcceptUntrustedCerts == "true", + } + + return returnVal +} diff --git a/scm/driver/azure/repo_test.go b/scm/driver/azure/repo_test.go index 345f7cfb4..b159f6df9 100644 --- a/scm/driver/azure/repo_test.go +++ b/scm/driver/azure/repo_test.go @@ -44,3 +44,62 @@ func TestRepositoryList(t *testing.T) { t.Log(diff) } } + +func TestRepositoryHookCreate(t *testing.T) { + defer gock.Off() + + gock.New("https:/dev.azure.com/"). + Get("/ORG/_apis/projects"). + Reply(201). + Type("application/json"). + File("testdata/projects.json") + + gock.New("https:/dev.azure.com/"). + Post("/ORG/_apis/hooks/subscriptions"). + Reply(201). + Type("application/json"). + File("testdata/hook.json") + + in := &scm.HookInput{ + Name: "web", + NativeEvents: []string{"git.push"}, + Target: "http://www.example.com/webhook", + } + + client := NewDefault("ORG", "test_project") + got, _, err := client.Repositories.CreateHook(context.Background(), "test_project", in) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Hook) + raw, _ := ioutil.ReadFile("testdata/hook.json.golden") + _ = json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + +func TestRepositoryHookDelete(t *testing.T) { + defer gock.Off() + + gock.New("https:/dev.azure.com/"). + Delete("/ORG/_apis/hooks/subscriptions"). + Reply(204). + Type("application/json") + + client := NewDefault("ORG", "PROJ") + res, err := client.Repositories.DeleteHook(context.Background(), "", "test-project") + if err != nil { + t.Error(err) + return + } + + if got, want := res.Status, 204; got != want { + t.Errorf("Want response status %d, got %d", want, got) + } + +} diff --git a/scm/driver/azure/testdata/hook.json b/scm/driver/azure/testdata/hook.json new file mode 100644 index 000000000..ff8a2daea --- /dev/null +++ b/scm/driver/azure/testdata/hook.json @@ -0,0 +1,58 @@ +{ + "id": "d455cb11-20a0-4b15-b546-7e9fb9973cc6", + "url": "https://dev.azure.com/tphoney/_apis/hooks/subscriptions/d455cb11-20a0-4b15-b546-7e9fb9973cc6", + "status": "enabled", + "publisherId": "tfs", + "eventType": "git.pullrequest.created", + "subscriber": null, + "resourceVersion": "1.0", + "eventDescription": "Repository test_repo2", + "consumerId": "webHooks", + "consumerActionId": "httpRequest", + "actionDescription": "To host www.bla.com", + "probationRetries": 1, + "createdBy": { + "displayName": "tp", + "id": "3ff4a20f-306e-677e-8a01-57f35e71f109", + "uniqueName": "tp@harness.io", + "descriptor": "msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + }, + "createdDate": "2022-03-25T13:28:12.39Z", + "modifiedBy": { + "displayName": "tp", + "id": "3ff4a20f-306e-677e-8a01-57f35e71f109", + "uniqueName": "tp@harness.io", + "descriptor": "msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + }, + "modifiedDate": "2022-03-29T10:39:13.813Z", + "lastProbationRetryDate": "2022-03-28T10:44:51.093Z", + "publisherInputs": { + "branch": "", + "projectId": "d350c9c0-7749-4ff8-a78f-f9c1f0e56729", + "pullrequestCreatedBy": "", + "pullrequestReviewersContains": "", + "repository": "fde2d21f-13b9-4864-a995-83329045289a", + "tfsSubscriptionId": "4ce8d6c4-f655-418d-8eb6-9462dd01ff39" + }, + "consumerInputs": { + "acceptUntrustedCerts": "true", + "url": "http://www.bla.com" + }, + "_links": { + "self": { + "href": "https://dev.azure.com/tphoney/_apis/hooks/subscriptions/d455cb11-20a0-4b15-b546-7e9fb9973cc6" + }, + "consumer": { + "href": "https://dev.azure.com/tphoney/_apis/hooks/consumers/webHooks" + }, + "actions": { + "href": "https://dev.azure.com/tphoney/_apis/hooks/consumers/webHooks/actions" + }, + "notifications": { + "href": "https://dev.azure.com/tphoney/_apis/hooks/subscriptions/d455cb11-20a0-4b15-b546-7e9fb9973cc6/notifications" + }, + "publisher": { + "href": "https://dev.azure.com/tphoney/_apis/hooks/publishers/tfs" + } + } +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/hook.json.golden b/scm/driver/azure/testdata/hook.json.golden new file mode 100644 index 000000000..927ae8496 --- /dev/null +++ b/scm/driver/azure/testdata/hook.json.golden @@ -0,0 +1,10 @@ +{ + "ID": "d455cb11-20a0-4b15-b546-7e9fb9973cc6", + "Name": "", + "Target": "http://www.bla.com", + "Events": [ + "git.pullrequest.created" + ], + "Active": true, + "SkipVerify": true +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/projects.json b/scm/driver/azure/testdata/projects.json new file mode 100644 index 000000000..933b642be --- /dev/null +++ b/scm/driver/azure/testdata/projects.json @@ -0,0 +1,14 @@ +{ + "count": 1, + "value": [ + { + "id": "d350c9c0-7749-4ff8-a78f-f9c1f0e56729", + "name": "test_project", + "url": "https://dev.azure.com/tphoney/_apis/projects/d350c9c0-7749-4ff8-a78f-f9c1f0e56729", + "state": "wellFormed", + "revision": 11, + "visibility": "private", + "lastUpdateTime": "2022-02-24T15:31:27.89Z" + } + ] +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/webhooks/pr_merged.json b/scm/driver/azure/testdata/webhooks/pr_merged.json new file mode 100644 index 000000000..2cdd4a359 --- /dev/null +++ b/scm/driver/azure/testdata/webhooks/pr_merged.json @@ -0,0 +1,86 @@ +{ + "id": "6872ee8c-b333-4eff-bfb9-0d5274943566", + "eventType": "git.pullrequest.merged", + "publisherId": "tfs", + "scope": "all", + "message": { + "text": "Jamal Hartnett has created a pull request merge commit", + "html": "Jamal Hartnett has created a pull request merge commit", + "markdown": "Jamal Hartnett has created a pull request merge commit" + }, + "detailedMessage": { + "text": "Jamal Hartnett has created a pull request merge commit\r\n\r\n- Merge status: Succeeded\r\n- Merge commit: eef717(https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/eef717f69257a6333f221566c1c987dc94cc0d72)\r\n", + "html": "Jamal Hartnett has created a pull request merge commit\r\n
    \r\n
  • Merge status: Succeeded
  • \r\n
  • Merge commit: eef717
  • \r\n
", + "markdown": "Jamal Hartnett has created a pull request merge commit\r\n\r\n+ Merge status: Succeeded\r\n+ Merge commit: [eef717](https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/eef717f69257a6333f221566c1c987dc94cc0d72)\r\n" + }, + "resource": { + "repository": { + "id": "4bc14d40-c903-45e2-872e-0462c7748079", + "name": "Fabrikam", + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079", + "project": { + "id": "6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c", + "name": "Fabrikam", + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/projects/6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c", + "state": "wellFormed" + }, + "defaultBranch": "refs/heads/master", + "remoteUrl": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam" + }, + "pullRequestId": 1, + "status": "completed", + "createdBy": { + "id": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "displayName": "Jamal Hartnett", + "uniqueName": "fabrikamfiber4@hotmail.com", + "url": "https://vssps.dev.azure.com/fabrikam/_apis/Identities/54d125f7-69f7-4191-904f-c5b96b6261c8", + "imageUrl": "https://dev.azure.com/fabrikam/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8" + }, + "creationDate": "2014-06-17T16:55:46.589889Z", + "closedDate": "2014-06-30T18:59:12.3660573Z", + "title": "my first pull request", + "description": " - test2\r\n", + "sourceRefName": "refs/heads/mytopic", + "targetRefName": "refs/heads/master", + "mergeStatus": "succeeded", + "mergeId": "a10bb228-6ba6-4362-abd7-49ea21333dbd", + "lastMergeSourceCommit": { + "commitId": "53d54ac915144006c2c9e90d2c7d3880920db49c", + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/53d54ac915144006c2c9e90d2c7d3880920db49c" + }, + "lastMergeTargetCommit": { + "commitId": "a511f535b1ea495ee0c903badb68fbc83772c882", + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/a511f535b1ea495ee0c903badb68fbc83772c882" + }, + "lastMergeCommit": { + "commitId": "eef717f69257a6333f221566c1c987dc94cc0d72", + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/eef717f69257a6333f221566c1c987dc94cc0d72" + }, + "reviewers": [ + { + "reviewerUrl": null, + "vote": 0, + "id": "2ea2d095-48f9-4cd6-9966-62f6f574096c", + "displayName": "[Mobile]\\Mobile Team", + "uniqueName": "vstfs:///Classification/TeamProject/f0811a3b-8c8a-4e43-a3bf-9a049b4835bd\\Mobile Team", + "url": "https://vssps.dev.azure.com/fabrikam/_apis/Identities/2ea2d095-48f9-4cd6-9966-62f6f574096c", + "imageUrl": "https://dev.azure.com/fabrikam/DefaultCollection/_api/_common/identityImage?id=2ea2d095-48f9-4cd6-9966-62f6f574096c", + "isContainer": true + } + ], + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1" + }, + "resourceVersion": "1.0", + "resourceContainers": { + "collection": { + "id": "c12d0eb8-e382-443b-9f9c-c52cba5014c2" + }, + "account": { + "id": "f844ec47-a9db-4511-8281-8b63f4eaf94e" + }, + "project": { + "id": "be9b3917-87e6-42a4-a549-2bc06a7a878f" + } + }, + "createdDate": "2016-09-19T13:03:27.3156388Z" + } \ No newline at end of file diff --git a/scm/driver/azure/testdata/webhooks/pr_merged.json.golden b/scm/driver/azure/testdata/webhooks/pr_merged.json.golden new file mode 100644 index 000000000..0b9fcf117 --- /dev/null +++ b/scm/driver/azure/testdata/webhooks/pr_merged.json.golden @@ -0,0 +1,61 @@ +{ + "Action": "merged", + "Repo": { + "ID": "4bc14d40-c903-45e2-872e-0462c7748079", + "Namespace": "Fabrikam", + "Name": "4bc14d40-c903-45e2-872e-0462c7748079", + "Perm": null, + "Branch": "", + "Archived": false, + "Private": false, + "Visibility": 0, + "Clone": "", + "CloneSSH": "", + "Link": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 1, + "Title": "my first pull request", + "Body": " - test2\r\n", + "Sha": "a10bb228-6ba6-4362-abd7-49ea21333dbd", + "Ref": "refs/heads/mytopic", + "Source": "refs/heads/mytopic", + "Target": "refs/heads/master", + "Fork": "", + "Link": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1", + "Diff": "", + "Closed": false, + "Merged": false, + "Base": { + "Name": "", + "Path": "", + "Sha": "" + }, + "Head": { + "Name": "", + "Path": "", + "Sha": "" + }, + "Author": { + "Login": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "Name": "Jamal Hartnett", + "Email": "fabrikamfiber4@hotmail.com", + "Avatar": "https://dev.azure.com/fabrikam/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Created": "2014-06-17T16:55:46.589889Z", + "Updated": "0001-01-01T00:00:00Z", + "Labels": null + }, + "Sender": { + "Login": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "Name": "Jamal Hartnett", + "Email": "fabrikamfiber4@hotmail.com", + "Avatar": "https://dev.azure.com/fabrikam/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + } +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/webhooks/pr_updated.json b/scm/driver/azure/testdata/webhooks/pr_updated.json new file mode 100644 index 000000000..25115a743 --- /dev/null +++ b/scm/driver/azure/testdata/webhooks/pr_updated.json @@ -0,0 +1,92 @@ +{ + "id": "af07be1b-f3ad-44c8-a7f1-c4835f2df06b", + "eventType": "git.pullrequest.updated", + "publisherId": "tfs", + "scope": "all", + "message": { + "text": "Jamal Hartnett marked the pull request as completed", + "html": "Jamal Hartnett marked the pull request as completed", + "markdown": "Jamal Hartnett marked the pull request as completed" + }, + "detailedMessage": { + "text": "Jamal Hartnett marked the pull request as completed\r\n\r\n- Merge status: Succeeded\r\n- Merge commit: eef717(https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/eef717f69257a6333f221566c1c987dc94cc0d72)\r\n", + "html": "Jamal Hartnett marked the pull request as completed\r\n
    \r\n
  • Merge status: Succeeded
  • \r\n
  • Merge commit: eef717
  • \r\n
", + "markdown": "Jamal Hartnett marked the pull request as completed\r\n\r\n+ Merge status: Succeeded\r\n+ Merge commit: [eef717](https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/eef717f69257a6333f221566c1c987dc94cc0d72)\r\n" + }, + "resource": { + "repository": { + "id": "4bc14d40-c903-45e2-872e-0462c7748079", + "name": "Fabrikam", + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079", + "project": { + "id": "6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c", + "name": "Fabrikam", + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/projects/6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c", + "state": "wellFormed" + }, + "defaultBranch": "refs/heads/master", + "remoteUrl": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam" + }, + "pullRequestId": 1, + "status": "completed", + "createdBy": { + "id": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "displayName": "Jamal Hartnett", + "uniqueName": "fabrikamfiber4@hotmail.com", + "url": "https://vssps.dev.azure.com/fabrikam/_apis/Identities/54d125f7-69f7-4191-904f-c5b96b6261c8", + "imageUrl": "https://dev.azure.com/fabrikam/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8" + }, + "creationDate": "2014-06-17T16:55:46.589889Z", + "closedDate": "2014-06-30T18:59:12.3660573Z", + "title": "my first pull request", + "description": " - test2\r\n", + "sourceRefName": "refs/heads/mytopic", + "targetRefName": "refs/heads/master", + "mergeStatus": "succeeded", + "mergeId": "a10bb228-6ba6-4362-abd7-49ea21333dbd", + "lastMergeSourceCommit": { + "commitId": "53d54ac915144006c2c9e90d2c7d3880920db49c", + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/53d54ac915144006c2c9e90d2c7d3880920db49c" + }, + "lastMergeTargetCommit": { + "commitId": "a511f535b1ea495ee0c903badb68fbc83772c882", + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/a511f535b1ea495ee0c903badb68fbc83772c882" + }, + "lastMergeCommit": { + "commitId": "eef717f69257a6333f221566c1c987dc94cc0d72", + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/eef717f69257a6333f221566c1c987dc94cc0d72" + }, + "reviewers": [ + { + "reviewerUrl": null, + "vote": 0, + "id": "2ea2d095-48f9-4cd6-9966-62f6f574096c", + "displayName": "[Mobile]\\Mobile Team", + "uniqueName": "vstfs:///Classification/TeamProject/f0811a3b-8c8a-4e43-a3bf-9a049b4835bd\\Mobile Team", + "url": "https://vssps.dev.azure.com/fabrikam/_apis/Identities/2ea2d095-48f9-4cd6-9966-62f6f574096c", + "imageUrl": "https://dev.azure.com/fabrikam/DefaultCollection/_api/_common/identityImage?id=2ea2d095-48f9-4cd6-9966-62f6f574096c", + "isContainer": true + } + ], + "commits": [ + { + "commitId": "53d54ac915144006c2c9e90d2c7d3880920db49c", + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/53d54ac915144006c2c9e90d2c7d3880920db49c" + } + ], + "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1" + }, + "resourceVersion": "1.0", + "resourceContainers": { + "collection": { + "id": "c12d0eb8-e382-443b-9f9c-c52cba5014c2" + }, + "account": { + "id": "f844ec47-a9db-4511-8281-8b63f4eaf94e" + }, + "project": { + "id": "be9b3917-87e6-42a4-a549-2bc06a7a878f" + } + }, + "createdDate": "2016-09-19T13:03:27.2813828Z" +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/webhooks/pr_updated.json.golden b/scm/driver/azure/testdata/webhooks/pr_updated.json.golden new file mode 100644 index 000000000..aed341d44 --- /dev/null +++ b/scm/driver/azure/testdata/webhooks/pr_updated.json.golden @@ -0,0 +1,61 @@ +{ + "Action": "updated", + "Repo": { + "ID": "4bc14d40-c903-45e2-872e-0462c7748079", + "Namespace": "Fabrikam", + "Name": "4bc14d40-c903-45e2-872e-0462c7748079", + "Perm": null, + "Branch": "", + "Archived": false, + "Private": false, + "Visibility": 0, + "Clone": "", + "CloneSSH": "", + "Link": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 1, + "Title": "my first pull request", + "Body": " - test2\r\n", + "Sha": "a10bb228-6ba6-4362-abd7-49ea21333dbd", + "Ref": "refs/heads/mytopic", + "Source": "refs/heads/mytopic", + "Target": "refs/heads/master", + "Fork": "", + "Link": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1", + "Diff": "", + "Closed": false, + "Merged": false, + "Base": { + "Name": "", + "Path": "", + "Sha": "" + }, + "Head": { + "Name": "", + "Path": "", + "Sha": "" + }, + "Author": { + "Login": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "Name": "Jamal Hartnett", + "Email": "fabrikamfiber4@hotmail.com", + "Avatar": "https://dev.azure.com/fabrikam/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Created": "2014-06-17T16:55:46.589889Z", + "Updated": "0001-01-01T00:00:00Z", + "Labels": null + }, + "Sender": { + "Login": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "Name": "Jamal Hartnett", + "Email": "fabrikamfiber4@hotmail.com", + "Avatar": "https://dev.azure.com/fabrikam/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + } +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/webhooks/push.json b/scm/driver/azure/testdata/webhooks/push.json new file mode 100644 index 000000000..a5fc4d254 --- /dev/null +++ b/scm/driver/azure/testdata/webhooks/push.json @@ -0,0 +1,76 @@ +{ + "id": "03c164c2-8912-4d5e-8009-3707d5f83734", + "eventType": "git.push", + "publisherId": "tfs", + "scope": "all", + "message": { + "text": "Jamal Hartnett pushed updates to branch master of repository Fabrikam-Fiber-Git.", + "html": "Jamal Hartnett pushed updates to branch master of repository Fabrikam-Fiber-Git.", + "markdown": "Jamal Hartnett pushed updates to branch `master` of repository `Fabrikam-Fiber-Git`." + }, + "detailedMessage": { + "text": "Jamal Hartnett pushed 1 commit to branch master of repository Fabrikam-Fiber-Git.\n - Fixed bug in web.config file 33b55f7c", + "html": "Jamal Hartnett pushed 1 commit to branch master of repository Fabrikam-Fiber-Git.\n
    \n
  • Fixed bug in web.config file 33b55f7c\n
", + "markdown": "Jamal Hartnett pushed 1 commit to branch [master](https://dev.azure.com/fabrikam-fiber-inc/DefaultCollection/_git/Fabrikam-Fiber-Git/#version=GBmaster) of repository [Fabrikam-Fiber-Git](https://dev.azure.com/fabrikam-fiber-inc/DefaultCollection/_git/Fabrikam-Fiber-Git/).\n* Fixed bug in web.config file [33b55f7c](https://dev.azure.com/fabrikam-fiber-inc/DefaultCollection/_git/Fabrikam-Fiber-Git/commit/33b55f7cb7e7e245323987634f960cf4a6e6bc74)" + }, + "resource": { + "commits": [ + { + "commitId": "33b55f7cb7e7e245323987634f960cf4a6e6bc74", + "author": { + "name": "Jamal Hartnett", + "email": "fabrikamfiber4@hotmail.com", + "date": "2015-02-25T19:01:00Z" + }, + "committer": { + "name": "Jamal Hartnett", + "email": "fabrikamfiber4@hotmail.com", + "date": "2015-02-25T19:01:00Z" + }, + "comment": "Fixed bug in web.config file", + "url": "https://dev.azure.com/fabrikam-fiber-inc/DefaultCollection/_git/Fabrikam-Fiber-Git/commit/33b55f7cb7e7e245323987634f960cf4a6e6bc74" + } + ], + "refUpdates": [ + { + "name": "refs/heads/master", + "oldObjectId": "aad331d8d3b131fa9ae03cf5e53965b51942618a", + "newObjectId": "33b55f7cb7e7e245323987634f960cf4a6e6bc74" + } + ], + "repository": { + "id": "278d5cd2-584d-4b63-824a-2ba458937249", + "name": "Fabrikam-Fiber-Git", + "url": "https://dev.azure.com/fabrikam-fiber-inc/DefaultCollection/_apis/repos/git/repositories/278d5cd2-584d-4b63-824a-2ba458937249", + "project": { + "id": "6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c", + "name": "Fabrikam-Fiber-Git", + "url": "https://dev.azure.com/fabrikam-fiber-inc/DefaultCollection/_apis/projects/6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c", + "state": "wellFormed" + }, + "defaultBranch": "refs/heads/master", + "remoteUrl": "https://dev.azure.com/fabrikam-fiber-inc/DefaultCollection/_git/Fabrikam-Fiber-Git" + }, + "pushedBy": { + "id": "00067FFED5C7AF52@Live.com", + "displayName": "Jamal Hartnett", + "uniqueName": "Windows Live ID\\fabrikamfiber4@hotmail.com" + }, + "pushId": 14, + "date": "2014-05-02T19:17:13.3309587Z", + "url": "https://dev.azure.com/fabrikam-fiber-inc/DefaultCollection/_apis/repos/git/repositories/278d5cd2-584d-4b63-824a-2ba458937249/pushes/14" + }, + "resourceVersion": "1.0", + "resourceContainers": { + "collection": { + "id": "c12d0eb8-e382-443b-9f9c-c52cba5014c2" + }, + "account": { + "id": "f844ec47-a9db-4511-8281-8b63f4eaf94e" + }, + "project": { + "id": "be9b3917-87e6-42a4-a549-2bc06a7a878f" + } + }, + "createdDate": "2016-09-19T13:03:27.0379153Z" +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/webhooks/push.json.golden b/scm/driver/azure/testdata/webhooks/push.json.golden new file mode 100644 index 000000000..76073d237 --- /dev/null +++ b/scm/driver/azure/testdata/webhooks/push.json.golden @@ -0,0 +1,45 @@ +{ + "Ref": "refs/heads/master", + "Before": "aad331d8d3b131fa9ae03cf5e53965b51942618a", + "After": "33b55f7cb7e7e245323987634f960cf4a6e6bc74", + "Repo": { + "ID": "278d5cd2-584d-4b63-824a-2ba458937249", + "Namespace": "", + "Name": "Fabrikam-Fiber-Git", + "Perm": null, + "Branch": "", + "Private": false, + "Clone": "https://dev.azure.com/fabrikam-fiber-inc/DefaultCollection/_apis/repos/git/repositories/278d5cd2-584d-4b63-824a-2ba458937249", + "CloneSSH": "", + "Link": "", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Commits": [ + { + "Sha": "33b55f7cb7e7e245323987634f960cf4a6e6bc74", + "Message": "Fixed bug in web.config file", + "Author": { + "Name": "Jamal Hartnett", + "Email": "fabrikamfiber4@hotmail.com", + "Date": "2015-02-25T19:01:00-00:00", + "Login": "Jamal Hartnett", + "Avatar": "" + }, + "Committer": { + "Name": "Jamal Hartnett", + "Email": "fabrikamfiber4@hotmail.com", + "Date": "2015-02-25T19:01:00-00:00", + "Login": "Jamal Hartnett", + "Avatar": "" + }, + "Link": "https://dev.azure.com/fabrikam-fiber-inc/DefaultCollection/_git/Fabrikam-Fiber-Git/commit/33b55f7cb7e7e245323987634f960cf4a6e6bc74" + } + ], + "Sender": { + "Login": "", + "Name": "", + "Email": "", + "Avatar": "" + } +} \ No newline at end of file diff --git a/scm/driver/azure/webhook.go b/scm/driver/azure/webhook.go index c2c1168c7..94bafe10d 100644 --- a/scm/driver/azure/webhook.go +++ b/scm/driver/azure/webhook.go @@ -6,6 +6,7 @@ package azure import ( "encoding/json" + "fmt" "io" "io/ioutil" "net/http" @@ -25,37 +26,131 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo if err != nil { return nil, err } - - var hook scm.Webhook - // switch req.Header.Get("SOMETHING") { - // case "pull_request": - hook, err = s.parsePullRequest(data) - // default: - // return nil, scm.ErrUnknownEvent - // } - return hook, err -} - -func (s *webhookService) parsePullRequest(data []byte) (scm.Webhook, error) { - src := new(pullRequestHook) - err := json.Unmarshal(data, src) - if err != nil { - return nil, err + // we need to read the json data then look at the eventType + var unstructuredJSON map[string]interface{} + jsonErr := json.Unmarshal([]byte(data), &unstructuredJSON) + if jsonErr != nil { + return nil, fmt.Errorf("Error parsing JSON from webhook: %s", jsonErr) } - dst := convertPullRequestHook(src) - switch src.EventType { + eventType := unstructuredJSON["eventType"].(string) + + switch eventType { + case "git.push": + // https://docs.microsoft.com/en-us/azure/devops/service-hooks/events?view=azure-devops#git.push + src := new(pushHook) + err := json.Unmarshal(data, src) + if err != nil { + return nil, err + } + dst := convertPushHook(src) + return dst, nil case "git.pullrequest.created": + // https://docs.microsoft.com/en-us/azure/devops/service-hooks/events?view=azure-devops#git.pullrequest.created + src := new(createPullRequestHook) + err := json.Unmarshal(data, src) + if err != nil { + return nil, err + } + dst := convertCreatePullRequestHook(src) dst.Action = scm.ActionOpen + return dst, nil case "git.pullrequest.updated": + // https://docs.microsoft.com/en-us/azure/devops/service-hooks/events?view=azure-devops#git.pullrequest.updated + src := new(updatePullRequestHook) + err := json.Unmarshal(data, src) + if err != nil { + return nil, err + } + dst := convertUpdatePullRequestHook(src) dst.Action = scm.ActionUpdate + return dst, nil + case "git.pullrequest.merged": + // https://docs.microsoft.com/en-us/azure/devops/service-hooks/events?view=azure-devops#git.pullrequest.merged + src := new(mergePullRequestHook) + err := json.Unmarshal(data, src) + if err != nil { + return nil, err + } + dst := convertMergePullRequestHook(src) + dst.Action = scm.ActionMerge + return dst, nil default: - dst.Action = scm.ActionUnknown + return nil, scm.ErrUnknownEvent } +} - return dst, nil +func convertPushHook(src *pushHook) *scm.PushHook { + var commits []scm.Commit + for _, c := range src.Resource.Commits { + commits = append(commits, + scm.Commit{ + Sha: c.CommitID, + Message: c.Comment, + Link: c.URL, + Author: scm.Signature{ + Login: c.Author.Name, + Email: c.Author.Email, + Name: c.Author.Name, + Date: c.Author.Date, + }, + Committer: scm.Signature{ + Login: c.Committer.Name, + Email: c.Committer.Email, + Name: c.Committer.Name, + Date: c.Committer.Date, + }, + }) + } + dst := &scm.PushHook{ + Ref: src.Resource.RefUpdates[0].Name, + Before: src.Resource.RefUpdates[0].OldObjectID, + After: src.Resource.RefUpdates[0].NewObjectID, + Repo: scm.Repository{ + ID: src.Resource.Repository.ID, + Name: src.Resource.Repository.Name, + Clone: src.Resource.Repository.URL, + }, + Commits: commits, + } + return dst +} + +func convertCreatePullRequestHook(src *createPullRequestHook) (returnVal *scm.PullRequestHook) { + returnVal = &scm.PullRequestHook{ + PullRequest: scm.PullRequest{ + Number: src.Resource.PullRequestID, + Title: src.Resource.Title, + Body: src.Resource.Description, + Sha: src.Resource.MergeID, + Ref: src.Resource.SourceRefName, + Source: src.Resource.SourceRefName, + Target: src.Resource.TargetRefName, + Link: src.Resource.URL, + Author: scm.User{ + Login: src.Resource.CreatedBy.ID, + Name: src.Resource.CreatedBy.DisplayName, + Email: src.Resource.CreatedBy.UniqueName, + Avatar: src.Resource.CreatedBy.ImageURL, + }, + Created: src.Resource.CreationDate, + }, + Repo: scm.Repository{ + ID: src.Resource.Repository.ID, + Name: src.Resource.Repository.ID, + Namespace: src.Resource.Repository.Name, + Link: src.Resource.Repository.URL, + }, + Sender: scm.User{ + Login: src.Resource.CreatedBy.ID, + Name: src.Resource.CreatedBy.DisplayName, + Email: src.Resource.CreatedBy.UniqueName, + Avatar: src.Resource.CreatedBy.ImageURL, + }, + } + return returnVal } -func convertPullRequestHook(src *pullRequestHook) (returnVal *scm.PullRequestHook) { +func convertUpdatePullRequestHook(src *updatePullRequestHook) (returnVal *scm.PullRequestHook) { returnVal = &scm.PullRequestHook{ PullRequest: scm.PullRequest{ Number: src.Resource.PullRequestID, @@ -90,7 +185,115 @@ func convertPullRequestHook(src *pullRequestHook) (returnVal *scm.PullRequestHoo return returnVal } -type pullRequestHook struct { +func convertMergePullRequestHook(src *mergePullRequestHook) (returnVal *scm.PullRequestHook) { + returnVal = &scm.PullRequestHook{ + PullRequest: scm.PullRequest{ + Number: src.Resource.PullRequestID, + Title: src.Resource.Title, + Body: src.Resource.Description, + Sha: src.Resource.MergeID, + Ref: src.Resource.SourceRefName, + Source: src.Resource.SourceRefName, + Target: src.Resource.TargetRefName, + Link: src.Resource.URL, + Author: scm.User{ + Login: src.Resource.CreatedBy.ID, + Name: src.Resource.CreatedBy.DisplayName, + Email: src.Resource.CreatedBy.UniqueName, + Avatar: src.Resource.CreatedBy.ImageURL, + }, + Created: src.Resource.CreationDate, + }, + Repo: scm.Repository{ + ID: src.Resource.Repository.ID, + Name: src.Resource.Repository.ID, + Namespace: src.Resource.Repository.Name, + Link: src.Resource.Repository.URL, + }, + Sender: scm.User{ + Login: src.Resource.CreatedBy.ID, + Name: src.Resource.CreatedBy.DisplayName, + Email: src.Resource.CreatedBy.UniqueName, + Avatar: src.Resource.CreatedBy.ImageURL, + }, + } + return returnVal +} + +type pushHook struct { + CreatedDate string `json:"createdDate"` + DetailedMessage struct { + HTML string `json:"html"` + Markdown string `json:"markdown"` + Text string `json:"text"` + } `json:"detailedMessage"` + EventType string `json:"eventType"` + ID string `json:"id"` + Message struct { + HTML string `json:"html"` + Markdown string `json:"markdown"` + Text string `json:"text"` + } `json:"message"` + PublisherID string `json:"publisherId"` + Resource struct { + Commits []struct { + Author struct { + Date time.Time `json:"date"` + Email string `json:"email"` + Name string `json:"name"` + } `json:"author"` + Comment string `json:"comment"` + CommitID string `json:"commitId"` + Committer struct { + Date time.Time `json:"date"` + Email string `json:"email"` + Name string `json:"name"` + } `json:"committer"` + URL string `json:"url"` + } `json:"commits"` + Date string `json:"date"` + PushID int64 `json:"pushId"` + PushedBy struct { + DisplayName string `json:"displayName"` + ID string `json:"id"` + UniqueName string `json:"uniqueName"` + } `json:"pushedBy"` + RefUpdates []struct { + Name string `json:"name"` + NewObjectID string `json:"newObjectId"` + OldObjectID string `json:"oldObjectId"` + } `json:"refUpdates"` + Repository struct { + DefaultBranch string `json:"defaultBranch"` + ID string `json:"id"` + Name string `json:"name"` + Project struct { + ID string `json:"id"` + Name string `json:"name"` + State string `json:"state"` + URL string `json:"url"` + } `json:"project"` + RemoteURL string `json:"remoteUrl"` + URL string `json:"url"` + } `json:"repository"` + URL string `json:"url"` + } `json:"resource"` + ResourceContainers struct { + Account struct { + ID string `json:"id"` + } `json:"account"` + Collection struct { + ID string `json:"id"` + } `json:"collection"` + Project struct { + ID string `json:"id"` + } `json:"project"` + } `json:"resourceContainers"` + ResourceVersion string `json:"resourceVersion"` + Scope string `json:"scope"` +} + +type createPullRequestHook struct { ID string `json:"id"` EventType string `json:"eventType"` PublisherID string `json:"publisherId"` @@ -173,3 +376,177 @@ type pullRequestHook struct { } `json:"resourceContainers"` CreatedDate time.Time `json:"createdDate"` } + +type updatePullRequestHook struct { + CreatedDate string `json:"createdDate"` + DetailedMessage struct { + HTML string `json:"html"` + Markdown string `json:"markdown"` + Text string `json:"text"` + } `json:"detailedMessage"` + EventType string `json:"eventType"` + ID string `json:"id"` + Message struct { + HTML string `json:"html"` + Markdown string `json:"markdown"` + Text string `json:"text"` + } `json:"message"` + PublisherID string `json:"publisherId"` + Resource struct { + ClosedDate string `json:"closedDate"` + Commits []struct { + CommitID string `json:"commitId"` + URL string `json:"url"` + } `json:"commits"` + CreatedBy struct { + DisplayName string `json:"displayName"` + ID string `json:"id"` + ImageURL string `json:"imageUrl"` + UniqueName string `json:"uniqueName"` + URL string `json:"url"` + } `json:"createdBy"` + CreationDate time.Time `json:"creationDate"` + Description string `json:"description"` + LastMergeCommit struct { + CommitID string `json:"commitId"` + URL string `json:"url"` + } `json:"lastMergeCommit"` + LastMergeSourceCommit struct { + CommitID string `json:"commitId"` + URL string `json:"url"` + } `json:"lastMergeSourceCommit"` + LastMergeTargetCommit struct { + CommitID string `json:"commitId"` + URL string `json:"url"` + } `json:"lastMergeTargetCommit"` + MergeID string `json:"mergeId"` + MergeStatus string `json:"mergeStatus"` + PullRequestID int `json:"pullRequestId"` + Repository struct { + DefaultBranch string `json:"defaultBranch"` + ID string `json:"id"` + Name string `json:"name"` + Project struct { + ID string `json:"id"` + Name string `json:"name"` + State string `json:"state"` + URL string `json:"url"` + } `json:"project"` + RemoteURL string `json:"remoteUrl"` + URL string `json:"url"` + } `json:"repository"` + Reviewers []struct { + DisplayName string `json:"displayName"` + ID string `json:"id"` + ImageURL string `json:"imageUrl"` + IsContainer bool `json:"isContainer"` + ReviewerURL interface{} `json:"reviewerUrl"` + UniqueName string `json:"uniqueName"` + URL string `json:"url"` + Vote int64 `json:"vote"` + } `json:"reviewers"` + SourceRefName string `json:"sourceRefName"` + Status string `json:"status"` + TargetRefName string `json:"targetRefName"` + Title string `json:"title"` + URL string `json:"url"` + } `json:"resource"` + ResourceContainers struct { + Account struct { + ID string `json:"id"` + } `json:"account"` + Collection struct { + ID string `json:"id"` + } `json:"collection"` + Project struct { + ID string `json:"id"` + } `json:"project"` + } `json:"resourceContainers"` + ResourceVersion string `json:"resourceVersion"` + Scope string `json:"scope"` +} + +type mergePullRequestHook struct { + CreatedDate string `json:"createdDate"` + DetailedMessage struct { + HTML string `json:"html"` + Markdown string `json:"markdown"` + Text string `json:"text"` + } `json:"detailedMessage"` + EventType string `json:"eventType"` + ID string `json:"id"` + Message struct { + HTML string `json:"html"` + Markdown string `json:"markdown"` + Text string `json:"text"` + } `json:"message"` + PublisherID string `json:"publisherId"` + Resource struct { + ClosedDate string `json:"closedDate"` + CreatedBy struct { + DisplayName string `json:"displayName"` + ID string `json:"id"` + ImageURL string `json:"imageUrl"` + UniqueName string `json:"uniqueName"` + URL string `json:"url"` + } `json:"createdBy"` + CreationDate time.Time `json:"creationDate"` + Description string `json:"description"` + LastMergeCommit struct { + CommitID string `json:"commitId"` + URL string `json:"url"` + } `json:"lastMergeCommit"` + LastMergeSourceCommit struct { + CommitID string `json:"commitId"` + URL string `json:"url"` + } `json:"lastMergeSourceCommit"` + LastMergeTargetCommit struct { + CommitID string `json:"commitId"` + URL string `json:"url"` + } `json:"lastMergeTargetCommit"` + MergeID string `json:"mergeId"` + MergeStatus string `json:"mergeStatus"` + PullRequestID int `json:"pullRequestId"` + Repository struct { + DefaultBranch string `json:"defaultBranch"` + ID string `json:"id"` + Name string `json:"name"` + Project struct { + ID string `json:"id"` + Name string `json:"name"` + State string `json:"state"` + URL string `json:"url"` + } `json:"project"` + RemoteURL string `json:"remoteUrl"` + URL string `json:"url"` + } `json:"repository"` + Reviewers []struct { + DisplayName string `json:"displayName"` + ID string `json:"id"` + ImageURL string `json:"imageUrl"` + IsContainer bool `json:"isContainer"` + ReviewerURL interface{} `json:"reviewerUrl"` + UniqueName string `json:"uniqueName"` + URL string `json:"url"` + Vote int64 `json:"vote"` + } `json:"reviewers"` + SourceRefName string `json:"sourceRefName"` + Status string `json:"status"` + TargetRefName string `json:"targetRefName"` + Title string `json:"title"` + URL string `json:"url"` + } `json:"resource"` + ResourceContainers struct { + Account struct { + ID string `json:"id"` + } `json:"account"` + Collection struct { + ID string `json:"id"` + } `json:"collection"` + Project struct { + ID string `json:"id"` + } `json:"project"` + } `json:"resourceContainers"` + ResourceVersion string `json:"resourceVersion"` + Scope string `json:"scope"` +} diff --git a/scm/driver/azure/webhook_test.go b/scm/driver/azure/webhook_test.go index 9ee1028ff..7ea03870e 100644 --- a/scm/driver/azure/webhook_test.go +++ b/scm/driver/azure/webhook_test.go @@ -18,23 +18,35 @@ import ( func TestWebhooks(t *testing.T) { tests := []struct { - sig string - event string before string after string obj interface{} }{ - // + // push hook + { + before: "testdata/webhooks/push.json", + after: "testdata/webhooks/push.json.golden", + obj: new(scm.PushHook), + }, // pull request events - // // pull request created { - sig: "71295b197fa25f4356d2fb9965df3f2379d903d7", - event: "pullrequest:created", before: "testdata/webhooks/pr_created.json", after: "testdata/webhooks/pr_created.json.golden", obj: new(scm.PullRequestHook), }, + // pull request updated + { + before: "testdata/webhooks/pr_updated.json", + after: "testdata/webhooks/pr_updated.json.golden", + obj: new(scm.PullRequestHook), + }, + // pull request merged + { + before: "testdata/webhooks/pr_merged.json", + after: "testdata/webhooks/pr_merged.json.golden", + obj: new(scm.PullRequestHook), + }, } for _, test := range tests { @@ -51,7 +63,6 @@ func TestWebhooks(t *testing.T) { buf := bytes.NewBuffer(before) r, _ := http.NewRequest("GET", "/?secret=71295b197fa25f4356d2fb9965df3f2379d903d7", buf) - r.Header.Set("x-event-key", test.event) s := new(webhookService) o, err := s.Parse(r, secretFunc) From 4e58ae32d1b0a31248182b71ae3c97534e81d755 Mon Sep 17 00:00:00 2001 From: Satyam Goel Date: Mon, 4 Apr 2022 13:02:10 +0530 Subject: [PATCH 079/282] Add support for repositry find in azure --- scm/driver/azure/repo.go | 7 ++++- scm/driver/azure/repo_test.go | 30 ++++++++++++++++++++++ scm/driver/azure/testdata/repo.json | 20 +++++++++++++++ scm/driver/azure/testdata/repo.json.golden | 6 +++++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 scm/driver/azure/testdata/repo.json create mode 100644 scm/driver/azure/testdata/repo.json.golden diff --git a/scm/driver/azure/repo.go b/scm/driver/azure/repo.go index 5a86d6c46..c5fb10652 100644 --- a/scm/driver/azure/repo.go +++ b/scm/driver/azure/repo.go @@ -19,7 +19,12 @@ type RepositoryService struct { // Find returns the repository by name. func (s *RepositoryService) Find(ctx context.Context, repo string) (*scm.Repository, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/repositories/get?view=azure-devops-rest-4.1 + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s?api-version=6.0", s.client.owner, s.client.project, repo) + + out := new(repository) + res, err := s.client.do(ctx, "GET", endpoint, nil, &out) + return convertRepository(out), res, err } // FindHook returns a repository hook. diff --git a/scm/driver/azure/repo_test.go b/scm/driver/azure/repo_test.go index b159f6df9..48663e64c 100644 --- a/scm/driver/azure/repo_test.go +++ b/scm/driver/azure/repo_test.go @@ -103,3 +103,33 @@ func TestRepositoryHookDelete(t *testing.T) { } } + +func TestRepositoryFind(t *testing.T) { + defer gock.Off() + + gock.New("https:/dev.azure.com/"). + Get("/ORG/PROJ/_apis/git/repositories/test_project"). + Reply(200). + Type("application/json"). + File("testdata/repo.json") + + client := NewDefault("ORG", "PROJ") + got, _, err := client.Repositories.Find(context.Background(), "test_project") + if err != nil { + t.Error(err) + return + } + + want := new(scm.Repository) + raw, _ := ioutil.ReadFile("testdata/repo.json.golden") + jsonErr := json.Unmarshal(raw, &want) + if jsonErr != nil { + t.Error(jsonErr) + } + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + +} diff --git a/scm/driver/azure/testdata/repo.json b/scm/driver/azure/testdata/repo.json new file mode 100644 index 000000000..c21fec46a --- /dev/null +++ b/scm/driver/azure/testdata/repo.json @@ -0,0 +1,20 @@ +{ + "id": "91f0d4cb-4c36-49a5-b28d-2d72da089c4d", + "name": "test_project", + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/91f0d4cb-4c36-49a5-b28d-2d72da089c4d", + "project": { + "id": "d350c9c0-7749-4ff8-a78f-f9c1f0e56729", + "name": "test_project", + "url": "https://dev.azure.com/tphoney/_apis/projects/d350c9c0-7749-4ff8-a78f-f9c1f0e56729", + "state": "wellFormed", + "revision": 11, + "visibility": "private", + "lastUpdateTime": "2022-02-24T15:31:27.89Z" + }, + "defaultBranch": "refs/heads/main", + "size": 1232, + "remoteUrl": "https://tphoney@dev.azure.com/tphoney/test_project/_git/test_project", + "sshUrl": "git@ssh.dev.azure.com:v3/tphoney/test_project/test_project", + "webUrl": "https://dev.azure.com/tphoney/test_project/_git/test_project", + "isDisabled": false +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/repo.json.golden b/scm/driver/azure/testdata/repo.json.golden new file mode 100644 index 000000000..ab8efc4b1 --- /dev/null +++ b/scm/driver/azure/testdata/repo.json.golden @@ -0,0 +1,6 @@ +{ + "ID": "91f0d4cb-4c36-49a5-b28d-2d72da089c4d", + "Name": "test_project", + "Branch": "refs/heads/main", + "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/91f0d4cb-4c36-49a5-b28d-2d72da089c4d" +} \ No newline at end of file From a791b0d6e2f7ae7d270139fe185dfb8023bfedde Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Thu, 7 Apr 2022 12:08:33 -0400 Subject: [PATCH 080/282] capture blob id when listing blobs for gitea --- scm/driver/gitea/content.go | 3 +- scm/driver/gitea/testdata/content_list.json | 400 ------------------ .../gitea/testdata/content_list.json.golden | 92 +--- 3 files changed, 10 insertions(+), 485 deletions(-) diff --git a/scm/driver/gitea/content.go b/scm/driver/gitea/content.go index 06b3db195..d0c73ad5c 100644 --- a/scm/driver/gitea/content.go +++ b/scm/driver/gitea/content.go @@ -48,6 +48,7 @@ func (s *contentService) List(ctx context.Context, repo, path, ref string, _ scm type content struct { Path string `json:"path"` Type string `json:"type"` + Sha string `json:"sha"` } func convertContentInfoList(from []*content) []*scm.ContentInfo { @@ -59,7 +60,7 @@ func convertContentInfoList(from []*content) []*scm.ContentInfo { } func convertContentInfo(from *content) *scm.ContentInfo { - to := &scm.ContentInfo{Path: from.Path} + to := &scm.ContentInfo{Path: from.Path, BlobID: from.Sha} switch from.Type { case "file": to.Kind = scm.ContentKindFile diff --git a/scm/driver/gitea/testdata/content_list.json b/scm/driver/gitea/testdata/content_list.json index 87535a882..b7b2871a4 100644 --- a/scm/driver/gitea/testdata/content_list.json +++ b/scm/driver/gitea/testdata/content_list.json @@ -78,405 +78,5 @@ "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/8c43a4fb023735dfd026014bae92ad91414b88bd", "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/advanced" } - }, - { - "name": "features.en-us.md", - "path": "docs/content/doc/features.en-us.md", - "sha": "9cc90b46a0d17864e5ce1749dbd1609a0921f8f7", - "type": "file", - "size": 192, - "encoding": null, - "content": null, - "target": null, - "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features.en-us.md?ref=master", - "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features.en-us.md", - "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/9cc90b46a0d17864e5ce1749dbd1609a0921f8f7", - "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/features.en-us.md", - "submodule_git_url": null, - "_links": { - "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features.en-us.md?ref=master", - "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/9cc90b46a0d17864e5ce1749dbd1609a0921f8f7", - "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features.en-us.md" - } - }, - { - "name": "features.zh-cn.md", - "path": "docs/content/doc/features.zh-cn.md", - "sha": "68d2f71b11f6bb5b1ca31adad00bc0f6ed3e94d8", - "type": "file", - "size": 188, - "encoding": null, - "content": null, - "target": null, - "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features.zh-cn.md?ref=master", - "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features.zh-cn.md", - "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/68d2f71b11f6bb5b1ca31adad00bc0f6ed3e94d8", - "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/features.zh-cn.md", - "submodule_git_url": null, - "_links": { - "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features.zh-cn.md?ref=master", - "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/68d2f71b11f6bb5b1ca31adad00bc0f6ed3e94d8", - "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features.zh-cn.md" - } - }, - { - "name": "features.zh-tw.md", - "path": "docs/content/doc/features.zh-tw.md", - "sha": "889e0df88213a937914ba43bb52956d0e54b1c98", - "type": "file", - "size": 188, - "encoding": null, - "content": null, - "target": null, - "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features.zh-tw.md?ref=master", - "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features.zh-tw.md", - "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/889e0df88213a937914ba43bb52956d0e54b1c98", - "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/features.zh-tw.md", - "submodule_git_url": null, - "_links": { - "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features.zh-tw.md?ref=master", - "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/889e0df88213a937914ba43bb52956d0e54b1c98", - "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features.zh-tw.md" - } - }, - { - "name": "features", - "path": "docs/content/doc/features", - "sha": "e212486606cf756b3b626f0a5bb1dd386b83b698", - "type": "dir", - "size": 0, - "encoding": null, - "content": null, - "target": null, - "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features?ref=master", - "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features", - "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/e212486606cf756b3b626f0a5bb1dd386b83b698", - "download_url": null, - "submodule_git_url": null, - "_links": { - "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/features?ref=master", - "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/e212486606cf756b3b626f0a5bb1dd386b83b698", - "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/features" - } - }, - { - "name": "help.en-us.md", - "path": "docs/content/doc/help.en-us.md", - "sha": "5ad1dd7f1edb3b78a3e3fba2113ecd5b10625dc4", - "type": "file", - "size": 176, - "encoding": null, - "content": null, - "target": null, - "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/help.en-us.md?ref=master", - "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/help.en-us.md", - "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/5ad1dd7f1edb3b78a3e3fba2113ecd5b10625dc4", - "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/help.en-us.md", - "submodule_git_url": null, - "_links": { - "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/help.en-us.md?ref=master", - "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/5ad1dd7f1edb3b78a3e3fba2113ecd5b10625dc4", - "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/help.en-us.md" - } - }, - { - "name": "help.zh-cn.md", - "path": "docs/content/doc/help.zh-cn.md", - "sha": "6af7aa1719b99e35874b76911aff29b9ad4bbc68", - "type": "file", - "size": 180, - "encoding": null, - "content": null, - "target": null, - "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/help.zh-cn.md?ref=master", - "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/help.zh-cn.md", - "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/6af7aa1719b99e35874b76911aff29b9ad4bbc68", - "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/help.zh-cn.md", - "submodule_git_url": null, - "_links": { - "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/help.zh-cn.md?ref=master", - "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/6af7aa1719b99e35874b76911aff29b9ad4bbc68", - "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/help.zh-cn.md" - } - }, - { - "name": "help", - "path": "docs/content/doc/help", - "sha": "91adc879a877f6c44aab1f27453bfa2679e4c3a0", - "type": "dir", - "size": 0, - "encoding": null, - "content": null, - "target": null, - "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/help?ref=master", - "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/help", - "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/91adc879a877f6c44aab1f27453bfa2679e4c3a0", - "download_url": null, - "submodule_git_url": null, - "_links": { - "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/help?ref=master", - "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/91adc879a877f6c44aab1f27453bfa2679e4c3a0", - "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/help" - } - }, - { - "name": "installation.en-us.md", - "path": "docs/content/doc/installation.en-us.md", - "sha": "4257521d973b0d28a7040f9030f701bbd1bf7bef", - "type": "file", - "size": 208, - "encoding": null, - "content": null, - "target": null, - "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.en-us.md?ref=master", - "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.en-us.md", - "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/4257521d973b0d28a7040f9030f701bbd1bf7bef", - "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/installation.en-us.md", - "submodule_git_url": null, - "_links": { - "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.en-us.md?ref=master", - "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/4257521d973b0d28a7040f9030f701bbd1bf7bef", - "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.en-us.md" - } - }, - { - "name": "installation.fr-fr.md", - "path": "docs/content/doc/installation.fr-fr.md", - "sha": "55b48bda3eca4e459c12e44d54de9c4573d9b0b7", - "type": "file", - "size": 208, - "encoding": null, - "content": null, - "target": null, - "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.fr-fr.md?ref=master", - "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.fr-fr.md", - "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/55b48bda3eca4e459c12e44d54de9c4573d9b0b7", - "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/installation.fr-fr.md", - "submodule_git_url": null, - "_links": { - "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.fr-fr.md?ref=master", - "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/55b48bda3eca4e459c12e44d54de9c4573d9b0b7", - "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.fr-fr.md" - } - }, - { - "name": "installation.zh-cn.md", - "path": "docs/content/doc/installation.zh-cn.md", - "sha": "8f57e0f00c273619c1ce66f04f7536f62d830e88", - "type": "file", - "size": 196, - "encoding": null, - "content": null, - "target": null, - "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.zh-cn.md?ref=master", - "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.zh-cn.md", - "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/8f57e0f00c273619c1ce66f04f7536f62d830e88", - "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/installation.zh-cn.md", - "submodule_git_url": null, - "_links": { - "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.zh-cn.md?ref=master", - "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/8f57e0f00c273619c1ce66f04f7536f62d830e88", - "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.zh-cn.md" - } - }, - { - "name": "installation.zh-tw.md", - "path": "docs/content/doc/installation.zh-tw.md", - "sha": "f955e994ac09834f546212a6ec494978a4d10039", - "type": "file", - "size": 196, - "encoding": null, - "content": null, - "target": null, - "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.zh-tw.md?ref=master", - "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.zh-tw.md", - "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/f955e994ac09834f546212a6ec494978a4d10039", - "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/installation.zh-tw.md", - "submodule_git_url": null, - "_links": { - "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation.zh-tw.md?ref=master", - "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/f955e994ac09834f546212a6ec494978a4d10039", - "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation.zh-tw.md" - } - }, - { - "name": "installation", - "path": "docs/content/doc/installation", - "sha": "2a3ff66218ae980c07444b8c97b710b3d7b5b846", - "type": "dir", - "size": 0, - "encoding": null, - "content": null, - "target": null, - "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation?ref=master", - "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation", - "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/2a3ff66218ae980c07444b8c97b710b3d7b5b846", - "download_url": null, - "submodule_git_url": null, - "_links": { - "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/installation?ref=master", - "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/2a3ff66218ae980c07444b8c97b710b3d7b5b846", - "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/installation" - } - }, - { - "name": "upgrade.en-us.md", - "path": "docs/content/doc/upgrade.en-us.md", - "sha": "9623ff9f1eaf74e9ebc03f5869bc0b9d2b3372d3", - "type": "file", - "size": 188, - "encoding": null, - "content": null, - "target": null, - "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.en-us.md?ref=master", - "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.en-us.md", - "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/9623ff9f1eaf74e9ebc03f5869bc0b9d2b3372d3", - "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/upgrade.en-us.md", - "submodule_git_url": null, - "_links": { - "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.en-us.md?ref=master", - "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/9623ff9f1eaf74e9ebc03f5869bc0b9d2b3372d3", - "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.en-us.md" - } - }, - { - "name": "upgrade.fr-fr.md", - "path": "docs/content/doc/upgrade.fr-fr.md", - "sha": "ca08daf9c096bf027ba95a13b44c5fe4d0a47afe", - "type": "file", - "size": 198, - "encoding": null, - "content": null, - "target": null, - "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.fr-fr.md?ref=master", - "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.fr-fr.md", - "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/ca08daf9c096bf027ba95a13b44c5fe4d0a47afe", - "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/upgrade.fr-fr.md", - "submodule_git_url": null, - "_links": { - "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.fr-fr.md?ref=master", - "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/ca08daf9c096bf027ba95a13b44c5fe4d0a47afe", - "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.fr-fr.md" - } - }, - { - "name": "upgrade.zh-cn.md", - "path": "docs/content/doc/upgrade.zh-cn.md", - "sha": "d12e150b9cbce2c26acb64c724914cec8667bb5d", - "type": "file", - "size": 186, - "encoding": null, - "content": null, - "target": null, - "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.zh-cn.md?ref=master", - "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.zh-cn.md", - "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/d12e150b9cbce2c26acb64c724914cec8667bb5d", - "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/upgrade.zh-cn.md", - "submodule_git_url": null, - "_links": { - "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.zh-cn.md?ref=master", - "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/d12e150b9cbce2c26acb64c724914cec8667bb5d", - "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.zh-cn.md" - } - }, - { - "name": "upgrade.zh-tw.md", - "path": "docs/content/doc/upgrade.zh-tw.md", - "sha": "b57fccbdd578e9c981171838a9dd1e152f69bce9", - "type": "file", - "size": 186, - "encoding": null, - "content": null, - "target": null, - "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.zh-tw.md?ref=master", - "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.zh-tw.md", - "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/b57fccbdd578e9c981171838a9dd1e152f69bce9", - "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/upgrade.zh-tw.md", - "submodule_git_url": null, - "_links": { - "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade.zh-tw.md?ref=master", - "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/b57fccbdd578e9c981171838a9dd1e152f69bce9", - "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade.zh-tw.md" - } - }, - { - "name": "upgrade", - "path": "docs/content/doc/upgrade", - "sha": "ff064862ee6ca9aa7bfda908c5354c83fbac25a4", - "type": "dir", - "size": 0, - "encoding": null, - "content": null, - "target": null, - "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade?ref=master", - "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade", - "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/ff064862ee6ca9aa7bfda908c5354c83fbac25a4", - "download_url": null, - "submodule_git_url": null, - "_links": { - "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/upgrade?ref=master", - "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/ff064862ee6ca9aa7bfda908c5354c83fbac25a4", - "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/upgrade" - } - }, - { - "name": "usage.en-us.md", - "path": "docs/content/doc/usage.en-us.md", - "sha": "6be9769d64603f93e05e099a8b2dcbceae1e98df", - "type": "file", - "size": 180, - "encoding": null, - "content": null, - "target": null, - "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/usage.en-us.md?ref=master", - "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/usage.en-us.md", - "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/6be9769d64603f93e05e099a8b2dcbceae1e98df", - "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/usage.en-us.md", - "submodule_git_url": null, - "_links": { - "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/usage.en-us.md?ref=master", - "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/6be9769d64603f93e05e099a8b2dcbceae1e98df", - "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/usage.en-us.md" - } - }, - { - "name": "usage.zh-cn.md", - "path": "docs/content/doc/usage.zh-cn.md", - "sha": "c533df662481ea381cba02f0cb7996a3c1b377fd", - "type": "file", - "size": 194, - "encoding": null, - "content": null, - "target": null, - "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/usage.zh-cn.md?ref=master", - "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/usage.zh-cn.md", - "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/c533df662481ea381cba02f0cb7996a3c1b377fd", - "download_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/raw/branch/master/docs/content/doc/usage.zh-cn.md", - "submodule_git_url": null, - "_links": { - "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/usage.zh-cn.md?ref=master", - "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/c533df662481ea381cba02f0cb7996a3c1b377fd", - "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/usage.zh-cn.md" - } - }, - { - "name": "usage", - "path": "docs/content/doc/usage", - "sha": "ac7d00a3401c3299068e09da540badfaf29d5e58", - "type": "dir", - "size": 0, - "encoding": null, - "content": null, - "target": null, - "url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/usage?ref=master", - "html_url": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/usage", - "git_url": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/ac7d00a3401c3299068e09da540badfaf29d5e58", - "download_url": null, - "submodule_git_url": null, - "_links": { - "self": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/contents/docs/content/doc/usage?ref=master", - "git": "https://try.gitea.io/api/v1/repos/aaaaaz/go-gitea.gitea/git/blobs/ac7d00a3401c3299068e09da540badfaf29d5e58", - "html": "https://try.gitea.io/aaaaaz/go-gitea.gitea/src/branch/master/docs/content/doc/usage" - } } ] \ No newline at end of file diff --git a/scm/driver/gitea/testdata/content_list.json.golden b/scm/driver/gitea/testdata/content_list.json.golden index cc23f85ff..7b6547bab 100644 --- a/scm/driver/gitea/testdata/content_list.json.golden +++ b/scm/driver/gitea/testdata/content_list.json.golden @@ -1,98 +1,22 @@ [ { "path": "docs/content/doc/advanced.en-us.md", - "kind": "file" + "kind": "file", + "blobid": "de2bfeed6f2d3ea1d2f91e457e9450efc582bb31" }, { "path": "docs/content/doc/advanced.fr-fr.md", - "kind": "file" + "kind": "file", + "blobid": "04734a8f81f5641de2b6d738bc9b777c2cc541c6" }, { "path": "docs/content/doc/advanced.zh-cn.md", - "kind": "file" + "kind": "file", + "blobid": "1f7ebf81e723a0ba82a89eec18a2706ac1b0dace" }, { "path": "docs/content/doc/advanced", - "kind": "directory" - }, - { - "path": "docs/content/doc/features.en-us.md", - "kind": "file" - }, - { - "path": "docs/content/doc/features.zh-cn.md", - "kind": "file" - }, - { - "path": "docs/content/doc/features.zh-tw.md", - "kind": "file" - }, - { - "path": "docs/content/doc/features", - "kind": "directory" - }, - { - "path": "docs/content/doc/help.en-us.md", - "kind": "file" - }, - { - "path": "docs/content/doc/help.zh-cn.md", - "kind": "file" - }, - { - "path": "docs/content/doc/help", - "kind": "directory" - }, - { - "path": "docs/content/doc/installation.en-us.md", - "kind": "file" - }, - { - "path": "docs/content/doc/installation.fr-fr.md", - "kind": "file" - }, - { - "path": "docs/content/doc/installation.zh-cn.md", - "kind": "file" - }, - { - "path": "docs/content/doc/installation.zh-tw.md", - "kind": "file" - }, - { - "path": "docs/content/doc/installation", - "kind": "directory" - }, - { - "path": "docs/content/doc/upgrade.en-us.md", - "kind": "file" - }, - { - "path": "docs/content/doc/upgrade.fr-fr.md", - "kind": "file" - }, - { - "path": "docs/content/doc/upgrade.zh-cn.md", - "kind": "file" - }, - { - "path": "docs/content/doc/upgrade.zh-tw.md", - "kind": "file" - }, - { - "path": "docs/content/doc/upgrade", - "kind": "directory" - }, - { - "path": "docs/content/doc/usage.en-us.md", - "kind": "file" - }, - { - "path": "docs/content/doc/usage.zh-cn.md", - "kind": "file" - }, - { - "path": "docs/content/doc/usage", - "kind": "directory" + "kind": "directory", + "blobid": "8c43a4fb023735dfd026014bae92ad91414b88bd" } ] From f73f51e6556fb8636e34cb2ac45a33e7892e5f1d Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Thu, 7 Apr 2022 17:54:47 -0400 Subject: [PATCH 081/282] fix ContentKind file marshaling --- scm/const.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scm/const.go b/scm/const.go index 55bedf568..576290e70 100644 --- a/scm/const.go +++ b/scm/const.go @@ -201,6 +201,11 @@ func (k ContentKind) String() string { } } +// MarshalJSON returns the JSON-encoded Action. +func (k ContentKind) MarshalJSON() ([]byte, error) { + return json.Marshal(k.String()) +} + // UnmarshalJSON unmarshales the JSON-encoded ContentKind. func (k *ContentKind) UnmarshalJSON(data []byte) error { var s string From c16bee3f210f1c7e2f338639564b1732859521ea Mon Sep 17 00:00:00 2001 From: TP Honey Date: Fri, 22 Apr 2022 10:18:03 +0100 Subject: [PATCH 082/282] (fix) handle nil repos in github responses (#168) * (fix) handle nil repos in github responses * convertRepoList change and tests * add new line at end of test file * implement Brad's suggested changes Co-authored-by: Dan Wilson --- scm/driver/github/repo.go | 22 +++- scm/driver/github/repo_test.go | 75 ++++++++++++ scm/driver/github/testdata/reposWithNull.json | 113 ++++++++++++++++++ 3 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 scm/driver/github/testdata/reposWithNull.json diff --git a/scm/driver/github/repo.go b/scm/driver/github/repo.go index ce8049fde..501d9f113 100644 --- a/scm/driver/github/repo.go +++ b/scm/driver/github/repo.go @@ -6,6 +6,7 @@ package github import ( "context" + "errors" "fmt" "strconv" "time" @@ -63,6 +64,13 @@ func (s *RepositoryService) Find(ctx context.Context, repo string) (*scm.Reposit path := fmt.Sprintf("repos/%s", repo) out := new(repository) res, err := s.client.do(ctx, "GET", path, nil, out) + if err != nil { + return nil, res, err + } + convertedRepo := convertRepository(out) + if convertedRepo == nil { + return nil, res, errors.New("GitHub returned an unexpected null repository") + } return convertRepository(out), res, err } @@ -79,6 +87,13 @@ func (s *RepositoryService) FindPerms(ctx context.Context, repo string) (*scm.Pe path := fmt.Sprintf("repos/%s", repo) out := new(repository) res, err := s.client.do(ctx, "GET", path, nil, out) + if err != nil { + return nil, res, err + } + convertedRepo := convertRepository(out) + if convertedRepo == nil { + return nil, res, errors.New("GitHub returned an unexpected null repository") + } return convertRepository(out).Perm, res, err } @@ -187,7 +202,9 @@ func (s *RepositoryService) DeleteHook(ctx context.Context, repo, id string) (*s func convertRepositoryList(from []*repository) []*scm.Repository { to := []*scm.Repository{} for _, v := range from { - to = append(to, convertRepository(v)) + if repo := convertRepository(v); repo != nil { + to = append(to, repo) + } } return to } @@ -195,6 +212,9 @@ func convertRepositoryList(from []*repository) []*scm.Repository { // helper function to convert from the gogs repository structure // to the common repository structure. func convertRepository(from *repository) *scm.Repository { + if from == nil { + return nil + } return &scm.Repository{ ID: strconv.Itoa(from.ID), Name: from.Name, diff --git a/scm/driver/github/repo_test.go b/scm/driver/github/repo_test.go index 7fd992eac..caa93b45f 100644 --- a/scm/driver/github/repo_test.go +++ b/scm/driver/github/repo_test.go @@ -8,6 +8,7 @@ import ( "context" "encoding/json" "io/ioutil" + "reflect" "testing" "github.com/drone/go-scm/scm" @@ -528,3 +529,77 @@ func TestHookEvents(t *testing.T) { } } } + +func Test_convertRepository(t *testing.T) { + permissionsStruct := &repository{ + Name: "bla", + } + permissionsStruct.Permissions.Admin = true + tests := []struct { + name string + from *repository + want *scm.Repository + }{ + { + name: "Simple", + from: &repository{ + Name: "hello-world", + ID: 1, + Permissions: permissionsStruct.Permissions, + }, + want: &scm.Repository{ + Name: "hello-world", + ID: "1", + Perm: &scm.Perm{ + Admin: true, + }, + }, + }, + { + name: "null", + from: nil, + want: nil, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := convertRepository(tt.from); !reflect.DeepEqual(got, tt.want) { + t.Errorf("convertRepository() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestRepositoryListWithNull(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Get("/user/repos"). + MatchParam("page", "1"). + MatchParam("per_page", "30"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + SetHeaders(mockPageHeaders). + File("testdata/reposWithNull.json") + + client := NewDefault() + got, res, err := client.Repositories.List(context.Background(), scm.ListOptions{Page: 1, Size: 30}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Repository{} + raw, _ := ioutil.ReadFile("testdata/repos.json.golden") + _ = json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) + t.Run("Page", testPage(res)) +} diff --git a/scm/driver/github/testdata/reposWithNull.json b/scm/driver/github/testdata/reposWithNull.json new file mode 100644 index 000000000..bcd5c18c6 --- /dev/null +++ b/scm/driver/github/testdata/reposWithNull.json @@ -0,0 +1,113 @@ +[ + { + "id": 1296269, + "owner": { + "login": "octocat", + "id": 1, + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "name": "Hello-World", + "full_name": "octocat/Hello-World", + "description": "This your first repo!", + "private": true, + "fork": true, + "visibility": "public", + "url": "https://api.github.com/repos/octocat/Hello-World", + "html_url": "https://github.com/octocat/Hello-World", + "archive_url": "http://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", + "assignees_url": "http://api.github.com/repos/octocat/Hello-World/assignees{/user}", + "blobs_url": "http://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", + "branches_url": "http://api.github.com/repos/octocat/Hello-World/branches{/branch}", + "clone_url": "https://github.com/octocat/Hello-World.git", + "collaborators_url": "http://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", + "comments_url": "http://api.github.com/repos/octocat/Hello-World/comments{/number}", + "commits_url": "http://api.github.com/repos/octocat/Hello-World/commits{/sha}", + "compare_url": "http://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", + "contents_url": "http://api.github.com/repos/octocat/Hello-World/contents/{+path}", + "contributors_url": "http://api.github.com/repos/octocat/Hello-World/contributors", + "deployments_url": "http://api.github.com/repos/octocat/Hello-World/deployments", + "downloads_url": "http://api.github.com/repos/octocat/Hello-World/downloads", + "events_url": "http://api.github.com/repos/octocat/Hello-World/events", + "forks_url": "http://api.github.com/repos/octocat/Hello-World/forks", + "git_commits_url": "http://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", + "git_refs_url": "http://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", + "git_tags_url": "http://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", + "git_url": "git:github.com/octocat/Hello-World.git", + "hooks_url": "http://api.github.com/repos/octocat/Hello-World/hooks", + "issue_comment_url": "http://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", + "issue_events_url": "http://api.github.com/repos/octocat/Hello-World/issues/events{/number}", + "issues_url": "http://api.github.com/repos/octocat/Hello-World/issues{/number}", + "keys_url": "http://api.github.com/repos/octocat/Hello-World/keys{/key_id}", + "labels_url": "http://api.github.com/repos/octocat/Hello-World/labels{/name}", + "languages_url": "http://api.github.com/repos/octocat/Hello-World/languages", + "merges_url": "http://api.github.com/repos/octocat/Hello-World/merges", + "milestones_url": "http://api.github.com/repos/octocat/Hello-World/milestones{/number}", + "mirror_url": "git:git.example.com/octocat/Hello-World", + "notifications_url": "http://api.github.com/repos/octocat/Hello-World/notifications{?since, all, participating}", + "pulls_url": "http://api.github.com/repos/octocat/Hello-World/pulls{/number}", + "releases_url": "http://api.github.com/repos/octocat/Hello-World/releases{/id}", + "ssh_url": "git@github.com:octocat/Hello-World.git", + "stargazers_url": "http://api.github.com/repos/octocat/Hello-World/stargazers", + "statuses_url": "http://api.github.com/repos/octocat/Hello-World/statuses/{sha}", + "subscribers_url": "http://api.github.com/repos/octocat/Hello-World/subscribers", + "subscription_url": "http://api.github.com/repos/octocat/Hello-World/subscription", + "svn_url": "https://svn.github.com/octocat/Hello-World", + "tags_url": "http://api.github.com/repos/octocat/Hello-World/tags", + "teams_url": "http://api.github.com/repos/octocat/Hello-World/teams", + "trees_url": "http://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", + "homepage": "https://github.com", + "language": null, + "forks_count": 9, + "stargazers_count": 80, + "watchers_count": 80, + "size": 108, + "default_branch": "master", + "open_issues_count": 0, + "topics": [ + "octocat", + "atom", + "electron", + "API" + ], + "has_issues": true, + "has_wiki": true, + "has_pages": false, + "has_downloads": true, + "archived": false, + "pushed_at": "2011-01-26T19:06:43Z", + "created_at": "2011-01-26T19:01:12Z", + "updated_at": "2011-01-26T19:14:43Z", + "permissions": { + "admin": true, + "push": true, + "pull": true + }, + "allow_rebase_merge": true, + "allow_squash_merge": true, + "allow_merge_commit": true, + "subscribers_count": 42, + "network_count": 0, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "html_url": "http://choosealicense.com/licenses/mit/" + } + }, + null +] From ecb6c07893dd476c70917361354b7dca178ad64b Mon Sep 17 00:00:00 2001 From: Dan Wilson Date: Fri, 22 Apr 2022 13:52:24 +0100 Subject: [PATCH 083/282] (maint) release prep for 1.21.0 --- CHANGELOG.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3c835d85..d9bf6b005 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## [v1.21.0](https://github.com/drone/go-scm/tree/v1.21.0) (2022-04-22) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.20.0...v1.21.0) + +**Implemented enhancements:** + +- Add support for repository find in azure [\#164](https://github.com/drone/go-scm/pull/164) ([goelsatyam2](https://github.com/goelsatyam2)) +- \(feat\) add azure webhook parsing, creation deletion & list [\#163](https://github.com/drone/go-scm/pull/163) ([tphoney](https://github.com/tphoney)) +- \(DRON-242\) azure add compare commits,get commit,list repos [\#162](https://github.com/drone/go-scm/pull/162) ([tphoney](https://github.com/tphoney)) + +**Fixed bugs:** + +- \(fix\) handle nil repos in github responses [\#168](https://github.com/drone/go-scm/pull/168) ([tphoney](https://github.com/tphoney)) + +**Closed issues:** + +- When attempting to clone my git repo from GitLab drone hangs on git fetch. [\#161](https://github.com/drone/go-scm/issues/161) +- Fix dump response [\#119](https://github.com/drone/go-scm/issues/119) + ## [v1.20.0](https://github.com/drone/go-scm/tree/v1.20.0) (2022-03-08) [Full Changelog](https://github.com/drone/go-scm/compare/v1.19.1...v1.20.0) @@ -12,6 +31,10 @@ - fixed raw response dumping in client [\#159](https://github.com/drone/go-scm/pull/159) ([marko-gacesa](https://github.com/marko-gacesa)) +**Merged pull requests:** + +- \(maint\) release prep for 1.20.0 [\#160](https://github.com/drone/go-scm/pull/160) ([d1wilko](https://github.com/d1wilko)) + ## [v1.19.1](https://github.com/drone/go-scm/tree/v1.19.1) (2022-02-23) [Full Changelog](https://github.com/drone/go-scm/compare/v1.19.0...v1.19.1) From 50a50a8c4d1b97de76069d4ff2002a204cb7df77 Mon Sep 17 00:00:00 2001 From: Dan Wilson Date: Fri, 22 Apr 2022 14:21:04 +0100 Subject: [PATCH 084/282] remove double invocation of convertRepository --- scm/driver/github/repo.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scm/driver/github/repo.go b/scm/driver/github/repo.go index 501d9f113..f5a9c5140 100644 --- a/scm/driver/github/repo.go +++ b/scm/driver/github/repo.go @@ -71,7 +71,7 @@ func (s *RepositoryService) Find(ctx context.Context, repo string) (*scm.Reposit if convertedRepo == nil { return nil, res, errors.New("GitHub returned an unexpected null repository") } - return convertRepository(out), res, err + return convertedRepo, res, err } // FindHook returns a repository hook. @@ -94,7 +94,7 @@ func (s *RepositoryService) FindPerms(ctx context.Context, repo string) (*scm.Pe if convertedRepo == nil { return nil, res, errors.New("GitHub returned an unexpected null repository") } - return convertRepository(out).Perm, res, err + return convertedRepo.Perm, res, err } // List returns the user repository list. From f11f79ca538f4fac2a57bd93668fd31b61fd88aa Mon Sep 17 00:00:00 2001 From: Dan Wilson Date: Fri, 22 Apr 2022 15:01:10 +0100 Subject: [PATCH 085/282] (maint) release prep for 1.21.1 (#171) --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9bf6b005..721833536 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [v1.21.1](https://github.com/drone/go-scm/tree/v1.21.1) (2022-04-22) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.21.0...v1.21.1) + +**Fixed bugs:** + +- remove double invocation of convertRepository [\#170](https://github.com/drone/go-scm/pull/170) ([d1wilko](https://github.com/d1wilko)) + ## [v1.21.0](https://github.com/drone/go-scm/tree/v1.21.0) (2022-04-22) [Full Changelog](https://github.com/drone/go-scm/compare/v1.20.0...v1.21.0) @@ -19,6 +27,10 @@ - When attempting to clone my git repo from GitLab drone hangs on git fetch. [\#161](https://github.com/drone/go-scm/issues/161) - Fix dump response [\#119](https://github.com/drone/go-scm/issues/119) +**Merged pull requests:** + +- \(maint\) release prep for 1.21.0 [\#169](https://github.com/drone/go-scm/pull/169) ([d1wilko](https://github.com/d1wilko)) + ## [v1.20.0](https://github.com/drone/go-scm/tree/v1.20.0) (2022-03-08) [Full Changelog](https://github.com/drone/go-scm/compare/v1.19.1...v1.20.0) From 7539f6d51342875ebcd029b138d775ff7410742c Mon Sep 17 00:00:00 2001 From: kit101 Date: Thu, 28 Apr 2022 16:22:23 +0800 Subject: [PATCH 086/282] fixbug: gitee populatePageValues (#167) --- scm/driver/gitee/gitee.go | 47 ++++++++++++++++++++++------------ scm/driver/gitee/gitee_test.go | 4 +-- scm/driver/gitee/issue.go | 17 ------------ 3 files changed, 32 insertions(+), 36 deletions(-) diff --git a/scm/driver/gitee/gitee.go b/scm/driver/gitee/gitee.go index 1403a7fe4..9bf40fd29 100644 --- a/scm/driver/gitee/gitee.go +++ b/scm/driver/gitee/gitee.go @@ -126,29 +126,42 @@ func websiteAddress(u *url.URL) string { // Response. // response header: total_page, total_count func populatePageValues(req *scm.Request, resp *scm.Response) { + // get last last, totalError := strconv.Atoi(resp.Header.Get("total_page")) + if totalError != nil { + return + } + // get curren page reqURL, err := url.Parse(req.Path) if err != nil { return } - current, currentError := strconv.Atoi(reqURL.Query().Get("page")) - if totalError != nil && currentError != nil { - return + currentPageStr := reqURL.Query().Get("page") + var current int + if currentPageStr == "" { + current = 1 + } else { + currentPage, currentError := strconv.Atoi(currentPageStr) + if currentError != nil { + return + } + current = currentPage } - resp.Page.First = 1 - if last != 0 { - resp.Page.Last = last + + // first, prev + if current <= 1 { + resp.Page.First = 0 + resp.Page.Prev = 0 + } else { + resp.Page.First = 1 + resp.Page.Prev = current - 1 } - if current != 0 { - if current < resp.Page.Last { - resp.Page.Next = current + 1 - } else { - resp.Page.Next = resp.Page.Last - } - if current > resp.Page.First { - resp.Page.Prev = current - 1 - } else { - resp.Page.Prev = resp.Page.First - } + // last, next + if current >= last { + resp.Page.Last = 0 + resp.Page.Next = 0 + } else { + resp.Page.Last = last + resp.Page.Next = current + 1 } } diff --git a/scm/driver/gitee/gitee_test.go b/scm/driver/gitee/gitee_test.go index df990b06d..7547de351 100644 --- a/scm/driver/gitee/gitee_test.go +++ b/scm/driver/gitee/gitee_test.go @@ -56,7 +56,7 @@ func TestClient_Error(t *testing.T) { func testPage(res *scm.Response) func(t *testing.T) { return func(t *testing.T) { - if got, want := res.Page.Prev, 1; got != want { + if got, want := res.Page.Prev, 0; got != want { t.Errorf("Want prev page %d, got %d", want, got) } if got, want := res.Page.Next, 2; got != want { @@ -65,7 +65,7 @@ func testPage(res *scm.Response) func(t *testing.T) { if got, want := res.Page.Last, 3; got != want { t.Errorf("Want last page %d, got %d", want, got) } - if got, want := res.Page.First, 1; got != want { + if got, want := res.Page.First, 0; got != want { t.Errorf("Want first page %d, got %d", want, got) } } diff --git a/scm/driver/gitee/issue.go b/scm/driver/gitee/issue.go index a5fe52a3f..4d06350a6 100644 --- a/scm/driver/gitee/issue.go +++ b/scm/driver/gitee/issue.go @@ -35,23 +35,6 @@ func (s *issueService) List(ctx context.Context, repo string, opts scm.IssueList path := fmt.Sprintf("repos/%s/issues?%s", repo, encodeIssueListOptions(opts)) out := []*issue{} res, err := s.client.do(ctx, "GET", path, nil, &out) - if err != nil { - res.Page.First = 1 - if opts.Page-1 < 1 { - res.Page.Prev = 1 - } else { - res.Page.Prev = opts.Page - 1 - } - totalPage, perr := strconv.Atoi(res.Header.Get("total_page")) - if perr != nil { - res.Page.Last = totalPage - if opts.Page+1 > totalPage { - res.Page.Next = totalPage - } else { - res.Page.Next = opts.Page + 1 - } - } - } return convertIssueList(out), res, err } From c98fdb3c1ca0f481afb8e184de42a02d3c929a93 Mon Sep 17 00:00:00 2001 From: Deepak Patankar Date: Fri, 29 Apr 2022 14:20:24 +0530 Subject: [PATCH 087/282] [fix]: [PL-24880]: Trim the ref when fetching default branch in get Repo API (#172) * [fix]: [PL-24880]: Trim the ref when fetching default branch --- scm/driver/azure/repo.go | 2 +- scm/driver/azure/testdata/repo.json.golden | 2 +- scm/driver/azure/testdata/repos.json.golden | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scm/driver/azure/repo.go b/scm/driver/azure/repo.go index c5fb10652..74f572e90 100644 --- a/scm/driver/azure/repo.go +++ b/scm/driver/azure/repo.go @@ -241,7 +241,7 @@ func convertRepository(from *repository) *scm.Repository { ID: from.ID, Name: from.Name, Link: from.URL, - Branch: from.DefaultBranch, + Branch: scm.TrimRef(from.DefaultBranch), } } diff --git a/scm/driver/azure/testdata/repo.json.golden b/scm/driver/azure/testdata/repo.json.golden index ab8efc4b1..92f3b874a 100644 --- a/scm/driver/azure/testdata/repo.json.golden +++ b/scm/driver/azure/testdata/repo.json.golden @@ -1,6 +1,6 @@ { "ID": "91f0d4cb-4c36-49a5-b28d-2d72da089c4d", "Name": "test_project", - "Branch": "refs/heads/main", + "Branch": "main", "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/91f0d4cb-4c36-49a5-b28d-2d72da089c4d" } \ No newline at end of file diff --git a/scm/driver/azure/testdata/repos.json.golden b/scm/driver/azure/testdata/repos.json.golden index cf0a77b5d..cbe9d840d 100644 --- a/scm/driver/azure/testdata/repos.json.golden +++ b/scm/driver/azure/testdata/repos.json.golden @@ -2,13 +2,13 @@ { "ID": "91f0d4cb-4c36-49a5-b28d-2d72da089c4d", "Name": "test_project", - "Branch": "refs/heads/main", + "Branch": "main", "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/91f0d4cb-4c36-49a5-b28d-2d72da089c4d" }, { "ID": "fde2d21f-13b9-4864-a995-83329045289a", "Name": "test_repo2", - "Branch": "refs/heads/main", + "Branch": "main", "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a" } ] \ No newline at end of file From 6d77e8582467a368223331c45c8a4f0d5776af96 Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Mon, 2 May 2022 16:27:33 -0400 Subject: [PATCH 088/282] add helper function fetch all repos --- scm/enrich/doc.go | 3 +++ scm/enrich/webhook.go | 17 +++++++++++++++++ scm/enrich/webhook_test.go | 5 +++++ scm/traverse/doc.go | 3 +++ scm/traverse/repos.go | 36 ++++++++++++++++++++++++++++++++++++ scm/traverse/repos_test.go | 5 +++++ 6 files changed, 69 insertions(+) create mode 100644 scm/enrich/doc.go create mode 100644 scm/enrich/webhook.go create mode 100644 scm/enrich/webhook_test.go create mode 100644 scm/traverse/doc.go create mode 100644 scm/traverse/repos.go create mode 100644 scm/traverse/repos_test.go diff --git a/scm/enrich/doc.go b/scm/enrich/doc.go new file mode 100644 index 000000000..4792e6e14 --- /dev/null +++ b/scm/enrich/doc.go @@ -0,0 +1,3 @@ +// Package normalize provides facilities for enriching +// data structures with missing information. +package enrich diff --git a/scm/enrich/webhook.go b/scm/enrich/webhook.go new file mode 100644 index 000000000..2dde306d2 --- /dev/null +++ b/scm/enrich/webhook.go @@ -0,0 +1,17 @@ +// Copyright 2022 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package enrich + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +// Webhook enriches the webhook payload with missing +// information not included in the webhook payload. +func Webhook(ctx context.Context, client *scm.Client, webhook *scm.Webhook) error { + return nil // TODO +} diff --git a/scm/enrich/webhook_test.go b/scm/enrich/webhook_test.go new file mode 100644 index 000000000..94fe1bca4 --- /dev/null +++ b/scm/enrich/webhook_test.go @@ -0,0 +1,5 @@ +// Copyright 2022 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package enrich diff --git a/scm/traverse/doc.go b/scm/traverse/doc.go new file mode 100644 index 000000000..845da57c3 --- /dev/null +++ b/scm/traverse/doc.go @@ -0,0 +1,3 @@ +// Package traverse provides facilities for traversing +// and combining the paginated results. +package traverse diff --git a/scm/traverse/repos.go b/scm/traverse/repos.go new file mode 100644 index 000000000..7b1b5e982 --- /dev/null +++ b/scm/traverse/repos.go @@ -0,0 +1,36 @@ +// Copyright 2022 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package traverse + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +// Repos returns the full repository list, traversing and +// combining paginated responses if necessary. +func Repos(ctx context.Context, client *scm.Client, webhook *scm.Webhook) ([]*scm.Repository, error) { + list := []*scm.Repository{} + opts := scm.ListOptions{Size: 100} + for { + result, meta, err := client.Repositories.List(ctx, opts) + if err != nil { + return nil, err + } + for _, src := range result { + if src != nil { + list = append(list, result...) + } + } + opts.Page = meta.Page.Next + opts.URL = meta.Page.NextURL + + if opts.Page == 0 && opts.URL == "" { + break + } + } + return list, nil +} diff --git a/scm/traverse/repos_test.go b/scm/traverse/repos_test.go new file mode 100644 index 000000000..63cf67f35 --- /dev/null +++ b/scm/traverse/repos_test.go @@ -0,0 +1,5 @@ +// Copyright 2022 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package traverse From 6e8f06a69ff8f3f5147f1da38f44fac1e8a48f71 Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Mon, 2 May 2022 17:34:24 -0400 Subject: [PATCH 089/282] fix issue #133 --- scm/driver/bitbucket/git.go | 13 +++++++-- scm/driver/bitbucket/git_test.go | 31 +++++++++++++++++++++ scm/util.go | 11 ++++++++ scm/util_test.go | 46 ++++++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+), 2 deletions(-) diff --git a/scm/driver/bitbucket/git.go b/scm/driver/bitbucket/git.go index 059cc89cf..03093c5bc 100644 --- a/scm/driver/bitbucket/git.go +++ b/scm/driver/bitbucket/git.go @@ -35,6 +35,15 @@ func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Re } func (s *gitService) FindCommit(ctx context.Context, repo, ref string) (*scm.Commit, *scm.Response, error) { + // github and gitlab permit fetching a commit by sha + // or branch. This code emulates the github and gitlab + // behavior for bitbucket by fetching the commit sha + // for the branch and using in the subsequent API call. + if scm.IsHash(ref) == false { + if branch, _, err := s.FindBranch(ctx, repo, scm.TrimRef(ref)); err == nil { + ref = branch.Sha // replace ref with sha + } + } path := fmt.Sprintf("2.0/repositories/%s/commit/%s", repo, ref) out := new(commit) res, err := s.client.do(ctx, "GET", path, nil, out) @@ -217,9 +226,9 @@ func convertDiffstat(from *diffstat) *scm.Change { Deleted: from.Status == "removed", } - if (response.Renamed) { + if response.Renamed { response.PrevFilePath = from.Old.Path - } else if (response.Deleted) { + } else if response.Deleted { response.Path = from.Old.Path } diff --git a/scm/driver/bitbucket/git_test.go b/scm/driver/bitbucket/git_test.go index 9cc19c2b6..7e666772c 100644 --- a/scm/driver/bitbucket/git_test.go +++ b/scm/driver/bitbucket/git_test.go @@ -41,6 +41,37 @@ func TestGitFindCommit(t *testing.T) { } } +func TestGitFindCommitForBranch(t *testing.T) { + defer gock.Off() + + gock.New("https://api.bitbucket.org"). + Get("/2.0/repositories/atlassian/stash-example-plugin/commit/a6e5e7d797edf751cbd839d6bd4aef86c941eec9"). + Reply(200). + Type("application/json"). + File("testdata/commit.json") + + gock.New("https://api.bitbucket.org"). + Get("/2.0/repositories/atlassian/stash-example-plugin/refs/branches/master"). + Reply(200). + Type("application/json"). + File("testdata/branch.json") + + client, _ := New("https://api.bitbucket.org") + got, _, err := client.Git.FindCommit(context.Background(), "atlassian/stash-example-plugin", "master") + if err != nil { + t.Error(err) + } + + want := new(scm.Commit) + raw, _ := ioutil.ReadFile("testdata/commit.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + func TestGitCreateBranch(t *testing.T) { defer gock.Off() diff --git a/scm/util.go b/scm/util.go index 02da73a65..0a8c3a2ca 100644 --- a/scm/util.go +++ b/scm/util.go @@ -14,6 +14,13 @@ import ( // from the git ref (e.g. refs/pulls/{d}/head) var re = regexp.MustCompile("\\d+") +// regular expressions to test whether or not a string is +// a sha1 or sha256 commit hash. +var ( + sha1 = regexp.MustCompile("^([a-f0-9]{40})$") + sha256 = regexp.MustCompile("^([a-f0-9]{64})$") +) + // Split splits the full repository name into segments. func Split(s string) (owner, name string) { parts := strings.SplitN(s, "/", 2) @@ -78,3 +85,7 @@ func IsPullRequest(ref string) bool { strings.HasPrefix(ref, "refs/merge-requests/") } +// IsHash returns true if the string is a commit hash. +func IsHash(s string) bool { + return sha1.MatchString(s) || sha256.MatchString(s) +} diff --git a/scm/util_test.go b/scm/util_test.go index 44b0ba181..41332276d 100644 --- a/scm/util_test.go +++ b/scm/util_test.go @@ -193,3 +193,49 @@ func TestExtractPullRequest(t *testing.T) { } } } + +func TestIsHash(t *testing.T) { + tests := []struct { + name string + tag bool + }{ + { + name: "aacad6eca956c3a340ae5cd5856aa9c4a3755408", + tag: true, + }, + { + name: "3da541559918a808c2402bba5012f6c60b27661c", + tag: true, + }, + { + name: "f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b", + tag: true, + }, + // not a sha + { + name: "aacad6e", + tag: false, + }, + { + name: "master", + tag: false, + }, + { + name: "refs/heads/master", + tag: false, + }, + { + name: "issue/42", + tag: false, + }, + { + name: "feature/foo", + tag: false, + }, + } + for _, test := range tests { + if got, want := IsHash(test.name), test.tag; got != want { + t.Errorf("Got IsHash %v, want %v", got, want) + } + } +} From 1bb3f504dbdb1f0c2d190f28cde076bbe6309cab Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Mon, 2 May 2022 17:41:21 -0400 Subject: [PATCH 090/282] helper to traverse repository pagination --- scm/traverse/repos.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/traverse/repos.go b/scm/traverse/repos.go index 7b1b5e982..dcad3ddd6 100644 --- a/scm/traverse/repos.go +++ b/scm/traverse/repos.go @@ -12,7 +12,7 @@ import ( // Repos returns the full repository list, traversing and // combining paginated responses if necessary. -func Repos(ctx context.Context, client *scm.Client, webhook *scm.Webhook) ([]*scm.Repository, error) { +func Repos(ctx context.Context, client *scm.Client) ([]*scm.Repository, error) { list := []*scm.Repository{} opts := scm.ListOptions{Size: 100} for { From c608194ffb75380d1d49823e0f6cbdd5767475e9 Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Mon, 2 May 2022 18:20:54 -0400 Subject: [PATCH 091/282] support for user email lists --- scm/driver/azure/user.go | 4 +++ scm/driver/bitbucket/user.go | 4 +++ scm/driver/gitea/user.go | 4 +++ scm/driver/gitee/user.go | 4 +++ scm/driver/github/testdata/emails.json | 8 +++++ scm/driver/github/testdata/emails.json.golden | 7 ++++ scm/driver/github/user.go | 33 ++++++++++++++++++ scm/driver/github/user_test.go | 34 +++++++++++++++++++ scm/driver/gitlab/testdata/emails.json | 12 +++++++ scm/driver/gitlab/testdata/emails.json.golden | 12 +++++++ scm/driver/gitlab/user.go | 33 ++++++++++++++++++ scm/driver/gitlab/user_test.go | 34 +++++++++++++++++++ scm/driver/gogs/user.go | 4 +++ scm/driver/stash/user.go | 4 +++ scm/user.go | 10 ++++++ 15 files changed, 207 insertions(+) create mode 100644 scm/driver/github/testdata/emails.json create mode 100644 scm/driver/github/testdata/emails.json.golden create mode 100644 scm/driver/gitlab/testdata/emails.json create mode 100644 scm/driver/gitlab/testdata/emails.json.golden diff --git a/scm/driver/azure/user.go b/scm/driver/azure/user.go index 78bfbe2e1..711edd848 100644 --- a/scm/driver/azure/user.go +++ b/scm/driver/azure/user.go @@ -25,3 +25,7 @@ func (s *userService) FindLogin(ctx context.Context, login string) (*scm.User, * func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, error) { return "", nil, scm.ErrNotSupported } + +func (s *userService) ListEmail(context.Context, scm.ListOptions) ([]*scm.Email, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} diff --git a/scm/driver/bitbucket/user.go b/scm/driver/bitbucket/user.go index d5ad1e4b8..b349cb5c1 100644 --- a/scm/driver/bitbucket/user.go +++ b/scm/driver/bitbucket/user.go @@ -32,6 +32,10 @@ func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, err return "", nil, scm.ErrNotSupported } +func (s *userService) ListEmail(context.Context, scm.ListOptions) ([]*scm.Email, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + type user struct { // The `username` field is no longer available after 29 April 2019 in // accordance with GDPR regulations. See: diff --git a/scm/driver/gitea/user.go b/scm/driver/gitea/user.go index 09b9e9399..38ab64acc 100644 --- a/scm/driver/gitea/user.go +++ b/scm/driver/gitea/user.go @@ -33,6 +33,10 @@ func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, err return user.Email, res, err } +func (s *userService) ListEmail(context.Context, scm.ListOptions) ([]*scm.Email, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + // // native data structures // diff --git a/scm/driver/gitee/user.go b/scm/driver/gitee/user.go index d893908de..3221e15b1 100644 --- a/scm/driver/gitee/user.go +++ b/scm/driver/gitee/user.go @@ -37,6 +37,10 @@ func (s *userService) FindLogin(ctx context.Context, login string) (*scm.User, * return convertUser(out), res, err } +func (s *userService) ListEmail(context.Context, scm.ListOptions) ([]*scm.Email, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + type user struct { ID int `json:"id"` Login string `json:"login"` diff --git a/scm/driver/github/testdata/emails.json b/scm/driver/github/testdata/emails.json new file mode 100644 index 000000000..b251b370e --- /dev/null +++ b/scm/driver/github/testdata/emails.json @@ -0,0 +1,8 @@ +[ + { + "email": "octocat@github.com", + "verified": true, + "primary": true, + "visibility": "public" + } +] \ No newline at end of file diff --git a/scm/driver/github/testdata/emails.json.golden b/scm/driver/github/testdata/emails.json.golden new file mode 100644 index 000000000..dc0613ac5 --- /dev/null +++ b/scm/driver/github/testdata/emails.json.golden @@ -0,0 +1,7 @@ +[ + { + "Value": "octocat@github.com", + "verified": true, + "primary": true + } +] \ No newline at end of file diff --git a/scm/driver/github/user.go b/scm/driver/github/user.go index 4b04b38a8..fd6243e13 100644 --- a/scm/driver/github/user.go +++ b/scm/driver/github/user.go @@ -35,6 +35,13 @@ func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, err return user.Email, res, err } +func (s *userService) ListEmail(ctx context.Context, opts scm.ListOptions) ([]*scm.Email, *scm.Response, error) { + path := fmt.Sprintf("user/emails?%s", encodeListOptions(opts)) + out := []*email{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertEmailList(out), res, err +} + type user struct { ID int `json:"id"` Login string `json:"login"` @@ -45,6 +52,12 @@ type user struct { Updated time.Time `json:"updated_at"` } +type email struct { + Email string `json:"email"` + Primary bool `json:"primary"` + Verified bool `json:"verified"` +} + func convertUser(from *user) *scm.User { return &scm.User{ Avatar: from.Avatar, @@ -55,3 +68,23 @@ func convertUser(from *user) *scm.User { Updated: from.Updated, } } + +// helper function to convert from the github email list to +// the common email structure. +func convertEmailList(from []*email) []*scm.Email { + to := []*scm.Email{} + for _, v := range from { + to = append(to, convertEmail(v)) + } + return to +} + +// helper function to convert from the github email structure to +// the common email structure. +func convertEmail(from *email) *scm.Email { + return &scm.Email{ + Value: from.Email, + Primary: from.Primary, + Verified: from.Verified, + } +} diff --git a/scm/driver/github/user_test.go b/scm/driver/github/user_test.go index 2eb6fea8e..e2fd64bad 100644 --- a/scm/driver/github/user_test.go +++ b/scm/driver/github/user_test.go @@ -108,3 +108,37 @@ func TestUserEmailFind(t *testing.T) { t.Run("Request", testRequest(res)) t.Run("Rate", testRate(res)) } + +func TestUserEmailList(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Get("/user/emails"). + MatchParam("page", "1"). + MatchParam("per_page", "30"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + SetHeaders(mockPageHeaders). + File("testdata/emails.json") + + client := NewDefault() + got, res, err := client.Users.ListEmail(context.Background(), scm.ListOptions{Size: 30, Page: 1}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Email{} + raw, _ := ioutil.ReadFile("testdata/emails.json.golden") + _ = json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) + t.Run("Page", testPage(res)) +} diff --git a/scm/driver/gitlab/testdata/emails.json b/scm/driver/gitlab/testdata/emails.json new file mode 100644 index 000000000..15ff44bab --- /dev/null +++ b/scm/driver/gitlab/testdata/emails.json @@ -0,0 +1,12 @@ +[ + { + "id": 1, + "email": "john@company.com", + "confirmed_at": "2021-03-26T19:07:56.248Z" + }, + { + "id": 3, + "email": "jane@company.com", + "confirmed_at": null + } +] \ No newline at end of file diff --git a/scm/driver/gitlab/testdata/emails.json.golden b/scm/driver/gitlab/testdata/emails.json.golden new file mode 100644 index 000000000..595eea801 --- /dev/null +++ b/scm/driver/gitlab/testdata/emails.json.golden @@ -0,0 +1,12 @@ +[ + { + "Value": "john@company.com", + "verified": true, + "primary": false + }, + { + "Value": "jane@company.com", + "verified": false, + "primary": false + } +] \ No newline at end of file diff --git a/scm/driver/gitlab/user.go b/scm/driver/gitlab/user.go index 454aea5c7..fa8c2f9c1 100644 --- a/scm/driver/gitlab/user.go +++ b/scm/driver/gitlab/user.go @@ -41,6 +41,13 @@ func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, err return user.Email, res, err } +func (s *userService) ListEmail(ctx context.Context, opts scm.ListOptions) ([]*scm.Email, *scm.Response, error) { + path := fmt.Sprintf("api/v4/user/emails?%s", encodeListOptions(opts)) + out := []*email{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertEmailList(out), res, err +} + type user struct { Username string `json:"username"` Name string `json:"name"` @@ -48,6 +55,13 @@ type user struct { Avatar string `json:"avatar_url"` } +type email struct { + Email string `json:"email"` + Confirmed null.String `json:"confirmed_at"` +} + +// helper function to convert from the gitlab user structure to +// the common user structure. func convertUser(from *user) *scm.User { return &scm.User{ Avatar: from.Avatar, @@ -56,3 +70,22 @@ func convertUser(from *user) *scm.User { Name: from.Name, } } + +// helper function to convert from the gitlab email list to +// the common email structure. +func convertEmailList(from []*email) []*scm.Email { + to := []*scm.Email{} + for _, v := range from { + to = append(to, convertEmail(v)) + } + return to +} + +// helper function to convert from the gitlab email structure to +// the common email structure. +func convertEmail(from *email) *scm.Email { + return &scm.Email{ + Value: from.Email, + Verified: !from.Confirmed.IsZero(), + } +} diff --git a/scm/driver/gitlab/user_test.go b/scm/driver/gitlab/user_test.go index 7729592ef..217ae319c 100644 --- a/scm/driver/gitlab/user_test.go +++ b/scm/driver/gitlab/user_test.go @@ -143,3 +143,37 @@ func TestUserEmailFind(t *testing.T) { t.Run("Request", testRequest(res)) t.Run("Rate", testRate(res)) } + +func TestUserEmailList(t *testing.T) { + defer gock.Off() + + gock.New("https://gitlab.com"). + Get("/api/v4/user/emails"). + MatchParam("page", "1"). + MatchParam("per_page", "30"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + SetHeaders(mockPageHeaders). + File("testdata/emails.json") + + client := NewDefault() + got, res, err := client.Users.ListEmail(context.Background(), scm.ListOptions{Size: 30, Page: 1}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Email{} + raw, _ := ioutil.ReadFile("testdata/emails.json.golden") + _ = json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) + t.Run("Page", testPage(res)) +} diff --git a/scm/driver/gogs/user.go b/scm/driver/gogs/user.go index 77abd3c76..fa0618c92 100644 --- a/scm/driver/gogs/user.go +++ b/scm/driver/gogs/user.go @@ -33,6 +33,10 @@ func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, err return user.Email, res, err } +func (s *userService) ListEmail(context.Context, scm.ListOptions) ([]*scm.Email, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + // // native data structures // diff --git a/scm/driver/stash/user.go b/scm/driver/stash/user.go index 3bcade3e1..aeab588be 100644 --- a/scm/driver/stash/user.go +++ b/scm/driver/stash/user.go @@ -78,6 +78,10 @@ func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, err return email, res, err } +func (s *userService) ListEmail(context.Context, scm.ListOptions) ([]*scm.Email, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + type user struct { Name string `json:"name"` EmailAddress string `json:"emailAddress"` diff --git a/scm/user.go b/scm/user.go index 93c40c469..e1ea08fa5 100644 --- a/scm/user.go +++ b/scm/user.go @@ -20,6 +20,13 @@ type ( Updated time.Time } + // Email represents a user email. + Email struct { + Value string + Primary bool + Verified bool + } + // UserService provides access to user account resources. UserService interface { // Find returns the authenticated user. @@ -30,5 +37,8 @@ type ( // FindLogin returns the user account by username. FindLogin(context.Context, string) (*User, *Response, error) + + // ListEmail returns the user email list. + ListEmail(context.Context, ListOptions) ([]*Email, *Response, error) } ) From 985a17351f9673eae7bd49ca57e47dc424a12583 Mon Sep 17 00:00:00 2001 From: Deepak Patankar Date: Wed, 4 May 2022 14:53:49 +0530 Subject: [PATCH 092/282] [feat]: [PL-24915]: Add the support for create branches in bitbucket server (#174) * [PL-24915]: Add the support for creating a branch in bitbucker server --- scm/driver/stash/git.go | 14 +++++++- scm/driver/stash/git_test.go | 25 +++++++++++++ scm/driver/stash/integration/git_test.go | 37 ++++++++++++++++++++ scm/driver/stash/integration/testSettings.go | 16 +++++++++ scm/driver/stash/testdata/branch_create.json | 10 ++++++ 5 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 scm/driver/stash/integration/git_test.go create mode 100644 scm/driver/stash/integration/testSettings.go create mode 100644 scm/driver/stash/testdata/branch_create.json diff --git a/scm/driver/stash/git.go b/scm/driver/stash/git.go index eae5a9942..a06f74909 100644 --- a/scm/driver/stash/git.go +++ b/scm/driver/stash/git.go @@ -20,7 +20,14 @@ type gitService struct { } func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.CreateBranch) (*scm.Response, error) { - return nil, scm.ErrNotSupported + namespace, repoName := scm.Split(repo) + path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/branches", namespace, repoName) + in := &createBranch{ + Name: params.Name, + StartPoint: params.Sha, + } + return s.client.do(ctx, "POST", path, in, nil) + } func (s *gitService) FindBranch(ctx context.Context, repo, branch string) (*scm.Reference, *scm.Response, error) { @@ -156,6 +163,11 @@ type diffstat struct { } `json:"properties"` } +type createBranch struct { + Name string `json:"name"` + StartPoint string `json:"startPoint"` +} + type commit struct { ID string `json:"id"` DisplayID string `json:"displayId"` diff --git a/scm/driver/stash/git_test.go b/scm/driver/stash/git_test.go index 04ad8b8d3..dfa37bfba 100644 --- a/scm/driver/stash/git_test.go +++ b/scm/driver/stash/git_test.go @@ -227,3 +227,28 @@ func TestGitCompareChanges(t *testing.T) { t.Log(diff) } } + +func TestCreateBranch(t *testing.T) { + defer gock.Off() + + gock.New("http://example.com:7990"). + Post("/rest/api/1.0/projects/PRJ/repos/my-repo/branches"). + Reply(201). + Type("application/json"). + File("testdata/branch_create.json") + + client, _ := New("http://example.com:7990") + params := &scm.CreateBranch{ + Name: "Hello", + Sha: "312797ba52425353dec56871a255e2a36fc96344", + } + res, err := client.Git.CreateBranch(context.Background(), "PRJ/my-repo", params) + + if err != nil { + t.Errorf("Encountered err while creating branch " + err.Error()) + } + + if res.Status != 201 { + t.Errorf("The error response of branch creation is not 201") + } +} diff --git a/scm/driver/stash/integration/git_test.go b/scm/driver/stash/integration/git_test.go new file mode 100644 index 000000000..a211df4d1 --- /dev/null +++ b/scm/driver/stash/integration/git_test.go @@ -0,0 +1,37 @@ +package integration + +import ( + "context" + "net/http" + "testing" + + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/stash" + "github.com/drone/go-scm/scm/transport" +) + +func TestCreateBranch(t *testing.T) { + if token == "" { + t.Skip("Skipping, Acceptance test") + } + client, _ = stash.New(endpoint) + client.Client = &http.Client{ + Transport: &transport.BasicAuth{ + Username: username, + Password: token, + }, + } + + input := &scm.CreateBranch{ + Name: "test_branch", + Sha: commitId, + } + response, listerr := client.Git.CreateBranch(context.Background(), repoID, input) + if listerr != nil { + t.Errorf("CreateBranch got an error %v", listerr) + } + if response.Status != http.StatusOK { + t.Errorf("CreateBranch did not get a 200 back %v", response.Status) + } + +} diff --git a/scm/driver/stash/integration/testSettings.go b/scm/driver/stash/integration/testSettings.go new file mode 100644 index 000000000..e034d24f3 --- /dev/null +++ b/scm/driver/stash/integration/testSettings.go @@ -0,0 +1,16 @@ +package integration + +import ( + "os" + + "github.com/drone/go-scm/scm" +) + +var ( + client *scm.Client + token = os.Getenv("BITBUCKET_SERVER_TOKEN") + endpoint = "https://bitbucket.dev.harness.io/" + repoID = "har/scm-integration-test-repo" + username = "harnessadmin" + commitId = "f675c4b55841908d7c338c500c8f4cb844fd9be7" +) diff --git a/scm/driver/stash/testdata/branch_create.json b/scm/driver/stash/testdata/branch_create.json new file mode 100644 index 000000000..90f12b96a --- /dev/null +++ b/scm/driver/stash/testdata/branch_create.json @@ -0,0 +1,10 @@ +{ + "ref": "refs/heads/Hello", + "node_id": "MDM6UmVmMzQ0NDI5MDA5OnJlZnMvaGVhZHMvSGVsbG8=", + "url": "https://api.github.com/repos/tphoney/scm-test/git/refs/heads/Hello", + "object": { + "sha": "312797ba52425353dec56871a255e2a36fc96344", + "type": "commit", + "url": "https://api.github.com/repos/tphoney/scm-test/git/commits/312797ba52425353dec56871a255e2a36fc96344" + } +} \ No newline at end of file From 30f8094b0f088709d2c9023dfae26c215cfa7cac Mon Sep 17 00:00:00 2001 From: Deepak Patankar Date: Fri, 6 May 2022 17:01:55 +0530 Subject: [PATCH 093/282] [PL-24911]: Make project name as optional param in Azure Repo APIs (#173) * [fix]: [PL-24880]: Trim the ref when fetching default branch * [PL-24911]: Make the project id as optional param --- scm/driver/azure/azure.go | 4 ++-- scm/driver/azure/azure_test.go | 4 ++-- scm/driver/azure/repo.go | 7 ++++++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/scm/driver/azure/azure.go b/scm/driver/azure/azure.go index ab61f1126..9fefd4425 100644 --- a/scm/driver/azure/azure.go +++ b/scm/driver/azure/azure.go @@ -25,8 +25,8 @@ func New(uri, owner, project string) (*scm.Client, error) { if !strings.HasSuffix(base.Path, "/") { base.Path = base.Path + "/" } - if owner == "" || project == "" { - return nil, fmt.Errorf("azure owner and azure project are required") + if owner == "" { + return nil, fmt.Errorf("azure owner is required") } client := &wrapper{ new(scm.Client), diff --git a/scm/driver/azure/azure_test.go b/scm/driver/azure/azure_test.go index 0347567a9..0a4334374 100644 --- a/scm/driver/azure/azure_test.go +++ b/scm/driver/azure/azure_test.go @@ -28,8 +28,8 @@ func TestClient_Default(t *testing.T) { func TestClient_azure_special(t *testing.T) { client, _ := New("https://dev.azure.com", "org", "") - if client != nil { - t.Errorf("Want nil client, got %v", client) + if got, want := client.BaseURL.String(), "https://dev.azure.com/"; got != want { + t.Errorf("Want Client URL %q, got %q", want, got) } client2, _ := New("https://dev.azure.com", "", "proj") if client2 != nil { diff --git a/scm/driver/azure/repo.go b/scm/driver/azure/repo.go index 74f572e90..82cac7977 100644 --- a/scm/driver/azure/repo.go +++ b/scm/driver/azure/repo.go @@ -40,7 +40,12 @@ func (s *RepositoryService) FindPerms(ctx context.Context, repo string) (*scm.Pe // List returns the user repository list. func (s *RepositoryService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/repositories/list?view=azure-devops-rest-6.0 - endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories?api-version=6.0", s.client.owner, s.client.project) + var endpoint string + if s.client.project == "" { + endpoint = fmt.Sprintf("%s/_apis/git/repositories?api-version=6.0", s.client.owner) + } else { + endpoint = fmt.Sprintf("%s/%s/_apis/git/repositories?api-version=6.0", s.client.owner, s.client.project) + } out := new(repositories) res, err := s.client.do(ctx, "GET", endpoint, nil, &out) From 78b5e763f6cd368a16aecfca6c391c13e0c26017 Mon Sep 17 00:00:00 2001 From: Deepak Patankar Date: Mon, 9 May 2022 16:37:57 +0530 Subject: [PATCH 094/282] [feat]: [PL-24913]: Add the support for create and update file in bitbucket server (#177) * [PL-24913]: Add the support for create and update api in bitbucket server * [PL-24913]: Add the tests for create and update of file in bitbucket server --- scm/driver/stash/content.go | 26 ++++++- scm/driver/stash/content_test.go | 73 +++++++++++++++++-- scm/driver/stash/integration/content_test.go | 62 ++++++++++++++++ scm/driver/stash/integration/testSettings.go | 14 +++- scm/driver/stash/stash.go | 36 ++++++++- scm/driver/stash/testdata/content_create.json | 21 ++++++ scm/driver/stash/testdata/content_update.json | 21 ++++++ 7 files changed, 237 insertions(+), 16 deletions(-) create mode 100644 scm/driver/stash/integration/content_test.go create mode 100644 scm/driver/stash/testdata/content_create.json create mode 100644 scm/driver/stash/testdata/content_update.json diff --git a/scm/driver/stash/content.go b/scm/driver/stash/content.go index 52e2ef425..f03b6b1bc 100644 --- a/scm/driver/stash/content.go +++ b/scm/driver/stash/content.go @@ -28,11 +28,26 @@ func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm } func (s *contentService) Create(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { - return nil, scm.ErrNotSupported + namespace, repoName := scm.Split(repo) + endpoint := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/browse/%s", namespace, repoName, path) + in := &contentCreateUpdate{ + Message: params.Message, + Branch: params.Branch, + Content: params.Data, + } + return s.client.do(ctx, "PUT", endpoint, in, nil) } func (s *contentService) Update(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { - return nil, scm.ErrNotSupported + namespace, repoName := scm.Split(repo) + endpoint := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/browse/%s", namespace, repoName, path) + in := &contentCreateUpdate{ + Message: params.Message, + Branch: params.Branch, + Content: params.Data, + Sha: params.Sha, + } + return s.client.do(ctx, "PUT", endpoint, in, nil) } func (s *contentService) Delete(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { @@ -53,6 +68,13 @@ type contents struct { Values []string `json:"values"` } +type contentCreateUpdate struct { + Branch string `json:"branch"` + Message string `json:"message"` + Content []byte `json:"content"` + Sha string `json:"sourceCommitId"` +} + func convertContentInfoList(from *contents) []*scm.ContentInfo { to := []*scm.ContentInfo{} for _, v := range from.Values { diff --git a/scm/driver/stash/content_test.go b/scm/driver/stash/content_test.go index 43ca8c15c..f5ff36965 100644 --- a/scm/driver/stash/content_test.go +++ b/scm/driver/stash/content_test.go @@ -43,18 +43,75 @@ func TestContentFind(t *testing.T) { } func TestContentCreate(t *testing.T) { - content := new(contentService) - _, err := content.Create(context.Background(), "atlassian/atlaskit", "README", nil) - if err != scm.ErrNotSupported { - t.Errorf("Expect Not Supported error") + defer gock.Off() + + gock.New("http://localhost:7990"). + Put("/rest/api/1.0/projects/octocat/repos/hello-world/browse/README"). + Reply(200). + Type("application/json"). + File("testdata/content_create.json") + + params := &scm.ContentParams{ + Message: "my commit message", + Data: []byte("bXkgbmV3IGZpbGUgY29udGVudHM="), + Signature: scm.Signature{ + Name: "Monalisa Octocat", + Email: "octocat@github.com", + }, + } + + client := NewDefault() + res, err := client.Contents.Create( + context.Background(), + "octocat/hello-world", + "README", + params, + ) + + if err != nil { + t.Error(err) + return + } + + if res.Status != 200 { + t.Errorf("Unexpected Results") } } func TestContentUpdate(t *testing.T) { - content := new(contentService) - _, err := content.Update(context.Background(), "atlassian/atlaskit", "README", nil) - if err != scm.ErrNotSupported { - t.Errorf("Expect Not Supported error") + defer gock.Off() + + gock.New("http://localhost:7990"). + Put("/rest/api/1.0/projects/octocat/repos/hello-world/browse/README"). + Reply(200). + Type("application/json"). + File("testdata/content_update.json") + + params := &scm.ContentParams{ + Message: "a new commit message", + Data: []byte("bXkgdXBkYXRlZCBmaWxlIGNvbnRlbnRz"), + BlobID: "95b966ae1c166bd92f8ae7d1c313e738c731dfc3", + Signature: scm.Signature{ + Name: "Monalisa Octocat", + Email: "octocat@github.com", + }, + } + + client := NewDefault() + res, err := client.Contents.Update( + context.Background(), + "octocat/hello-world", + "README", + params, + ) + + if err != nil { + t.Error(err) + return + } + + if res.Status != 200 { + t.Errorf("Unexpected Results") } } diff --git a/scm/driver/stash/integration/content_test.go b/scm/driver/stash/integration/content_test.go new file mode 100644 index 000000000..a65b1b838 --- /dev/null +++ b/scm/driver/stash/integration/content_test.go @@ -0,0 +1,62 @@ +package integration + +import ( + "context" + "net/http" + "testing" + + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/stash" + "github.com/drone/go-scm/scm/transport" +) + +func TestCreateUpdateDeleteFileStash(t *testing.T) { + if token == "" { + t.Skip("Skipping, Acceptance test") + } + client, _ = stash.New(endpoint) + client.Client = &http.Client{ + Transport: &transport.BasicAuth{ + Username: username, + Password: token, + }, + } + // get latest commit first + currentCommit, commitErr := GetCurrentCommitOfBranch(client, "master") + if commitErr != nil { + t.Errorf("we got an error %v", commitErr) + } + // create a new file + createParams := scm.ContentParams{ + Message: "go-scm create crud file", + Data: []byte("hello"), + Branch: "master", + Sha: currentCommit, + } + createResponse, createErr := client.Contents.Create(context.Background(), repoID, "README5", &createParams) + if createErr != nil { + t.Errorf("Contents.Create we got an error %v", createErr) + } + if createResponse.Status != http.StatusOK { + t.Errorf("Contents.Create we did not get a 201 back %v", createResponse.Status) + } + // get latest commit first + currentCommit, commitErr = GetCurrentCommitOfBranch(client, "main") + if commitErr != nil { + t.Errorf("we got an error %v", commitErr) + } + // update the file + updateParams := scm.ContentParams{ + Message: "go-scm update crud file", + Data: []byte("updated test data"), + Branch: "master", + Sha: currentCommit, + } + updateResponse, updateErr := client.Contents.Update(context.Background(), repoID, "README5", &updateParams) + if updateErr != nil { + t.Errorf("Contents.Update we got an error %v", updateErr) + } + if updateResponse.Status != http.StatusOK { + t.Errorf("Contents.Update we did not get a 201 back %v", updateResponse.Status) + } +} diff --git a/scm/driver/stash/integration/testSettings.go b/scm/driver/stash/integration/testSettings.go index e034d24f3..4696ba86f 100644 --- a/scm/driver/stash/integration/testSettings.go +++ b/scm/driver/stash/integration/testSettings.go @@ -1,16 +1,26 @@ package integration import ( + "context" "os" "github.com/drone/go-scm/scm" ) var ( - client *scm.Client - token = os.Getenv("BITBUCKET_SERVER_TOKEN") + client *scm.Client + token = os.Getenv("BITBUCKET_SERVER_TOKEN") + endpoint = "https://bitbucket.dev.harness.io/" repoID = "har/scm-integration-test-repo" username = "harnessadmin" commitId = "f675c4b55841908d7c338c500c8f4cb844fd9be7" ) + +func GetCurrentCommitOfBranch(client *scm.Client, branch string) (string, error) { + commits, _, err := client.Git.ListCommits(context.Background(), repoID, scm.CommitListOptions{Ref: branch}) + if err != nil { + return "", err + } + return commits[0].Sha, nil +} diff --git a/scm/driver/stash/stash.go b/scm/driver/stash/stash.go index 17244d456..ae57fe4dd 100644 --- a/scm/driver/stash/stash.go +++ b/scm/driver/stash/stash.go @@ -11,6 +11,7 @@ import ( "encoding/json" "fmt" "io" + "mime/multipart" "net/url" "strings" @@ -74,10 +75,37 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface // if we are posting or putting data, we need to // write it to the body of the request. if in != nil { - buf := new(bytes.Buffer) - json.NewEncoder(buf).Encode(in) - req.Header["Content-Type"] = []string{"application/json"} - req.Body = buf + switch content := in.(type) { + case *contentCreateUpdate: + // add the content to the multipart + var b bytes.Buffer + w := multipart.NewWriter(&b) + // add the other fields + if content.Message != "" { + _ = w.WriteField("content", string(content.Content)) + } + if content.Message != "" { + _ = w.WriteField("message", content.Message) + } + if content.Branch != "" { + _ = w.WriteField("branch", content.Branch) + } + if content.Sha != "" { + _ = w.WriteField("sourceCommitId", content.Sha) + } + w.Close() + // write the multipart response to the body + req.Body = &b + // write the content type that contains the length of the multipart + req.Header = map[string][]string{ + "Content-Type": {w.FormDataContentType()}, + } + default: + buf := new(bytes.Buffer) + json.NewEncoder(buf).Encode(in) + req.Header["Content-Type"] = []string{"application/json"} + req.Body = buf + } } // execute the http request diff --git a/scm/driver/stash/testdata/content_create.json b/scm/driver/stash/testdata/content_create.json new file mode 100644 index 000000000..7188f36c5 --- /dev/null +++ b/scm/driver/stash/testdata/content_create.json @@ -0,0 +1,21 @@ +{ + "id": "abcdef0123abcdef4567abcdef8987abcdef6543", + "displayId": "abcdef0123a", + "author": { + "name": "charlie", + "emailAddress": "charlie@example.com" + }, + "authorTimestamp": 1636089306104, + "committer": { + "name": "charlie", + "emailAddress": "charlie@example.com" + }, + "committerTimestamp": 1636089306104, + "message": "WIP on feature 1", + "parents": [ + { + "id": "abcdef0123abcdef4567abcdef8987abcdef6543", + "displayId": "abcdef0" + } + ] +} \ No newline at end of file diff --git a/scm/driver/stash/testdata/content_update.json b/scm/driver/stash/testdata/content_update.json new file mode 100644 index 000000000..7188f36c5 --- /dev/null +++ b/scm/driver/stash/testdata/content_update.json @@ -0,0 +1,21 @@ +{ + "id": "abcdef0123abcdef4567abcdef8987abcdef6543", + "displayId": "abcdef0123a", + "author": { + "name": "charlie", + "emailAddress": "charlie@example.com" + }, + "authorTimestamp": 1636089306104, + "committer": { + "name": "charlie", + "emailAddress": "charlie@example.com" + }, + "committerTimestamp": 1636089306104, + "message": "WIP on feature 1", + "parents": [ + { + "id": "abcdef0123abcdef4567abcdef8987abcdef6543", + "displayId": "abcdef0" + } + ] +} \ No newline at end of file From dbbf69f1dc8e86ee958ffd93f62805b3ee038ad8 Mon Sep 17 00:00:00 2001 From: Mankrit Singh Date: Tue, 10 May 2022 17:44:28 +0530 Subject: [PATCH 095/282] [feat]: [PL-25025]: Updated Project validation for Azure API (#179) * [PL-25025]: Project Validation changes for Azure --- scm/driver/azure/azure.go | 5 +++++ scm/driver/azure/content.go | 15 +++++++++++++++ scm/driver/azure/git.go | 18 ++++++++++++++++++ scm/driver/azure/repo.go | 12 ++++++++++++ 4 files changed, 50 insertions(+) diff --git a/scm/driver/azure/azure.go b/scm/driver/azure/azure.go index 9fefd4425..1832e568d 100644 --- a/scm/driver/azure/azure.go +++ b/scm/driver/azure/azure.go @@ -9,6 +9,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "net/url" "strings" @@ -116,6 +117,10 @@ func (e *Error) Error() string { return e.Message } +func ProjectRequiredError() error { + return errors.New("This API endpoint requires a project to be specified") +} + func SanitizeBranchName(name string) string { if strings.Contains(name, "/") { return name diff --git a/scm/driver/azure/content.go b/scm/driver/azure/content.go index 4acd84848..18cd0402a 100644 --- a/scm/driver/azure/content.go +++ b/scm/driver/azure/content.go @@ -18,6 +18,9 @@ type contentService struct { func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm.Content, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/items/get?view=azure-devops-rest-6.0 + if s.client.project == "" { + return nil, nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/items?path=%s&includeContent=true&$format=json", s.client.owner, s.client.project, repo, path) endpoint += generateURIFromRef(ref) endpoint += "&api-version=6.0" @@ -33,6 +36,9 @@ func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm } func (s *contentService) Create(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { + if s.client.project == "" { + return nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/pushes?api-version=6.0", s.client.owner, s.client.project, repo) ref := refUpdate{ Name: SanitizeBranchName(params.Branch), @@ -59,6 +65,9 @@ func (s *contentService) Create(ctx context.Context, repo, path string, params * } func (s *contentService) Update(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { + if s.client.project == "" { + return nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/pushes?api-version=6.0", s.client.owner, s.client.project, repo) ref := refUpdate{ Name: SanitizeBranchName(params.Branch), @@ -85,6 +94,9 @@ func (s *contentService) Update(ctx context.Context, repo, path string, params * } func (s *contentService) Delete(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { + if s.client.project == "" { + return nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/pushes?api-version=6.0", s.client.owner, s.client.project, repo) ref := refUpdate{ Name: SanitizeBranchName(params.Branch), @@ -109,6 +121,9 @@ func (s *contentService) Delete(ctx context.Context, repo, path string, params * func (s *contentService) List(ctx context.Context, repo, path, ref string, _ scm.ListOptions) ([]*scm.ContentInfo, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/items/list?view=azure-devops-rest-6.0 + if s.client.project == "" { + return nil, nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/items?path=%s&recursionLevel=Full&$format=json", s.client.owner, s.client.project, repo, path) endpoint += generateURIFromRef(ref) out := new(contentList) diff --git a/scm/driver/azure/git.go b/scm/driver/azure/git.go index 0e28cb24d..e61ec6236 100644 --- a/scm/driver/azure/git.go +++ b/scm/driver/azure/git.go @@ -18,6 +18,9 @@ type gitService struct { func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.CreateBranch) (*scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/refs/update-refs?view=azure-devops-rest-6.0 + if s.client.project == "" { + return nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/refs?api-version=6.0", s.client.owner, s.client.project, repo) in := make(crudBranch, 1) @@ -28,11 +31,17 @@ func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm. } func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { + if s.client.project == "" { + return nil, nil, ProjectRequiredError() + } return nil, nil, scm.ErrNotSupported } func (s *gitService) FindCommit(ctx context.Context, repo, ref string) (*scm.Commit, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/commits/get?view=azure-devops-rest-6.0#get-by-id + if s.client.project == "" { + return nil, nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/commits/%s?api-version=6.0", s.client.owner, s.client.project, repo, ref) out := new(gitCommit) res, err := s.client.do(ctx, "GET", endpoint, nil, out) @@ -45,6 +54,9 @@ func (s *gitService) FindTag(ctx context.Context, repo, name string) (*scm.Refer func (s *gitService) ListBranches(ctx context.Context, repo string, _ scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/refs/list?view=azure-devops-rest-6.0 + if s.client.project == "" { + return nil, nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/refs?api-version=6.0", s.client.owner, s.client.project, repo) out := new(branchList) res, err := s.client.do(ctx, "GET", endpoint, nil, &out) @@ -53,6 +65,9 @@ func (s *gitService) ListBranches(ctx context.Context, repo string, _ scm.ListOp func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/commits/get-commits?view=azure-devops-rest-6.0 + if s.client.project == "" { + return nil, nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/commits?", s.client.owner, s.client.project, repo) if opts.Ref != "" { endpoint += fmt.Sprintf("searchCriteria.itemVersion.version=%s&", opts.Ref) @@ -77,6 +92,9 @@ func (s *gitService) ListChanges(ctx context.Context, repo, ref string, _ scm.Li func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/diffs/get?view=azure-devops-rest-6.0 + if s.client.project == "" { + return nil, nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/diffs/commits?", s.client.owner, s.client.project, repo) // add base endpoint += fmt.Sprintf("baseVersion=%s&baseVersionType=commit&", source) diff --git a/scm/driver/azure/repo.go b/scm/driver/azure/repo.go index 82cac7977..3e729b336 100644 --- a/scm/driver/azure/repo.go +++ b/scm/driver/azure/repo.go @@ -20,6 +20,9 @@ type RepositoryService struct { // Find returns the repository by name. func (s *RepositoryService) Find(ctx context.Context, repo string) (*scm.Repository, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/repositories/get?view=azure-devops-rest-4.1 + if s.client.project == "" { + return nil, nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s?api-version=6.0", s.client.owner, s.client.project, repo) out := new(repository) @@ -55,6 +58,9 @@ func (s *RepositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* // ListHooks returns a list or repository hooks. func (s *RepositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/hooks/subscriptions/list?view=azure-devops-rest-6.0 + if s.client.project == "" { + return nil, nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/_apis/hooks/subscriptions?api-version=6.0", s.client.owner) out := new(subscriptions) res, err := s.client.do(ctx, "GET", endpoint, nil, &out) @@ -69,6 +75,9 @@ func (s *RepositoryService) ListStatus(ctx context.Context, repo, ref string, op // CreateHook creates a new repository webhook. func (s *RepositoryService) CreateHook(ctx context.Context, repo string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/hooks/subscriptions/create?view=azure-devops-rest-6.0 + if s.client.project == "" { + return nil, nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/_apis/hooks/subscriptions?api-version=6.0", s.client.owner) in := new(subscription) in.Status = "enabled" @@ -119,6 +128,9 @@ func (s *RepositoryService) UpdateHook(ctx context.Context, repo, id string, inp // DeleteHook deletes a repository webhook. func (s *RepositoryService) DeleteHook(ctx context.Context, repo, id string) (*scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/hooks/subscriptions/delete?view=azure-devops-rest-6.0 + if s.client.project == "" { + return nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/_apis/hooks/subscriptions/%s?api-version=6.0", s.client.owner, id) return s.client.do(ctx, "DELETE", endpoint, nil, nil) } From 5a5c5ca5c58b5b8314b302500e80ea1fd7c20c8f Mon Sep 17 00:00:00 2001 From: Mankrit Singh Date: Tue, 10 May 2022 18:07:12 +0530 Subject: [PATCH 096/282] [feat]: [PL-25025]: Changelog Updated to v1.22.0 (#180) * [PL-25025]: Changelog updated to v1.22.0 --- CHANGELOG.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 721833536..f4f193d81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## [v1.22.0](https://github.com/drone/go-scm/tree/v1.22.0) (2022-05-10) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.21.1...v1.22.0) + +**Implemented enhancements:** + +- \[feat\]: \[PL-24913\]: Add the support for create and update file in bitbucket server [\#177](https://github.com/drone/go-scm/pull/177) ([DeepakPatankar](https://github.com/DeepakPatankar)) +- \[feat\]: \[PL-24915\]: Add the support for create branches in bitbucket server [\#174](https://github.com/drone/go-scm/pull/174) ([DeepakPatankar](https://github.com/DeepakPatankar)) +- \[PL-24911\]: Make project name as optional param in Azure Repo APIs [\#173](https://github.com/drone/go-scm/pull/173) ([DeepakPatankar](https://github.com/DeepakPatankar)) + +**Fixed bugs:** + +- \[feat\]: \[PL-25025\]: Updated Project validation for Azure API [\#179](https://github.com/drone/go-scm/pull/179) ([mankrit-singh](https://github.com/mankrit-singh)) +- \[fix\]: \[PL-24880\]: Trim the ref when fetching default branch in get Repo API [\#172](https://github.com/drone/go-scm/pull/172) ([DeepakPatankar](https://github.com/DeepakPatankar)) +- fixbug: gitee populatePageValues [\#167](https://github.com/drone/go-scm/pull/167) ([kit101](https://github.com/kit101)) + +**Closed issues:** + +- gitea find commit [\#125](https://github.com/drone/go-scm/issues/125) + ## [v1.21.1](https://github.com/drone/go-scm/tree/v1.21.1) (2022-04-22) [Full Changelog](https://github.com/drone/go-scm/compare/v1.21.0...v1.21.1) @@ -8,6 +28,10 @@ - remove double invocation of convertRepository [\#170](https://github.com/drone/go-scm/pull/170) ([d1wilko](https://github.com/d1wilko)) +**Merged pull requests:** + +- \(maint\) release prep for 1.21.1 [\#171](https://github.com/drone/go-scm/pull/171) ([d1wilko](https://github.com/d1wilko)) + ## [v1.21.0](https://github.com/drone/go-scm/tree/v1.21.0) (2022-04-22) [Full Changelog](https://github.com/drone/go-scm/compare/v1.20.0...v1.21.0) From 766414330d77aa62abbb2e3c951ebdd06a237718 Mon Sep 17 00:00:00 2001 From: Deepak Patankar Date: Thu, 12 May 2022 19:21:50 +0530 Subject: [PATCH 097/282] [PL-24913]: Handle the error raised while creating a multipart input (#181) --- scm/driver/stash/integration/git_test.go | 1 + scm/driver/stash/integration/testSettings.go | 1 - scm/driver/stash/multipart.go | 26 ++++++++++++++++++++ scm/driver/stash/stash.go | 24 ++++++++---------- 4 files changed, 37 insertions(+), 15 deletions(-) create mode 100644 scm/driver/stash/multipart.go diff --git a/scm/driver/stash/integration/git_test.go b/scm/driver/stash/integration/git_test.go index a211df4d1..d03277fee 100644 --- a/scm/driver/stash/integration/git_test.go +++ b/scm/driver/stash/integration/git_test.go @@ -22,6 +22,7 @@ func TestCreateBranch(t *testing.T) { }, } + commitId, _ := GetCurrentCommitOfBranch(client, "master") input := &scm.CreateBranch{ Name: "test_branch", Sha: commitId, diff --git a/scm/driver/stash/integration/testSettings.go b/scm/driver/stash/integration/testSettings.go index 4696ba86f..7a3dfce71 100644 --- a/scm/driver/stash/integration/testSettings.go +++ b/scm/driver/stash/integration/testSettings.go @@ -14,7 +14,6 @@ var ( endpoint = "https://bitbucket.dev.harness.io/" repoID = "har/scm-integration-test-repo" username = "harnessadmin" - commitId = "f675c4b55841908d7c338c500c8f4cb844fd9be7" ) func GetCurrentCommitOfBranch(client *scm.Client, branch string) (string, error) { diff --git a/scm/driver/stash/multipart.go b/scm/driver/stash/multipart.go new file mode 100644 index 000000000..4da89fdb7 --- /dev/null +++ b/scm/driver/stash/multipart.go @@ -0,0 +1,26 @@ +package stash + +import "mime/multipart" + +type MultipartWriter struct { + Writer *multipart.Writer + Error error +} + +func (mw *MultipartWriter) Write(f, v string) { + if mw.Error != nil { + return + } + if v == "" { + return + } + mw.Error = mw.Writer.WriteField(f, v) +} + +func (mw *MultipartWriter) Close() { + mw.Writer.Close() +} + +func (mw *MultipartWriter) FormDataContentType() string { + return mw.Writer.FormDataContentType() +} diff --git a/scm/driver/stash/stash.go b/scm/driver/stash/stash.go index ae57fe4dd..440cf3844 100644 --- a/scm/driver/stash/stash.go +++ b/scm/driver/stash/stash.go @@ -79,26 +79,22 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface case *contentCreateUpdate: // add the content to the multipart var b bytes.Buffer - w := multipart.NewWriter(&b) + mw := &MultipartWriter{Writer: multipart.NewWriter(&b)} // add the other fields - if content.Message != "" { - _ = w.WriteField("content", string(content.Content)) + // The Write function doesn't write the string value to multipart if it is Empty + mw.Write("content", string(content.Content)) + mw.Write("message", content.Message) + mw.Write("branch", content.Branch) + mw.Write("sourceCommitId", content.Sha) + if mw.Error != nil { + return nil, fmt.Errorf("error writing multipart-content. err: %s", mw.Error) } - if content.Message != "" { - _ = w.WriteField("message", content.Message) - } - if content.Branch != "" { - _ = w.WriteField("branch", content.Branch) - } - if content.Sha != "" { - _ = w.WriteField("sourceCommitId", content.Sha) - } - w.Close() + mw.Close() // write the multipart response to the body req.Body = &b // write the content type that contains the length of the multipart req.Header = map[string][]string{ - "Content-Type": {w.FormDataContentType()}, + "Content-Type": {mw.FormDataContentType()}, } default: buf := new(bytes.Buffer) From 1ff5fea1a4598410eb408e598c95e15a21f163e2 Mon Sep 17 00:00:00 2001 From: DeepakPatankar Date: Mon, 16 May 2022 15:45:22 +0530 Subject: [PATCH 098/282] Add the support to fetch commit of a file --- scm/driver/stash/git.go | 9 ++++++-- scm/driver/stash/integration/git_test.go | 26 ++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/scm/driver/stash/git.go b/scm/driver/stash/git.go index a06f74909..2c38c4cd4 100644 --- a/scm/driver/stash/git.go +++ b/scm/driver/stash/git.go @@ -81,9 +81,14 @@ func (s *gitService) ListBranches(ctx context.Context, repo string, opts scm.Lis func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { namespace, name := scm.Split(repo) - path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/commits", namespace, name) + var requestPath string + if opts.Path != "" { + requestPath = fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/commits?path=%s", namespace, name, opts.Path) + } else { + requestPath = fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/commits", namespace, name) + } out := new(commits) - res, err := s.client.do(ctx, "GET", path, nil, out) + res, err := s.client.do(ctx, "GET", requestPath, nil, out) copyPagination(out.pagination, res) return convertCommitList(out), res, err } diff --git a/scm/driver/stash/integration/git_test.go b/scm/driver/stash/integration/git_test.go index d03277fee..bd5933f25 100644 --- a/scm/driver/stash/integration/git_test.go +++ b/scm/driver/stash/integration/git_test.go @@ -34,5 +34,31 @@ func TestCreateBranch(t *testing.T) { if response.Status != http.StatusOK { t.Errorf("CreateBranch did not get a 200 back %v", response.Status) } +} +func TestGetLatestCommitOfBranch(t *testing.T) { + if token == "" { + t.Skip("Skipping, Acceptance test") + } + client, _ = stash.New(endpoint) + client.Client = &http.Client{ + Transport: &transport.BasicAuth{ + Username: username, + Password: token, + }, + } + + commits, response, err := client.Git.ListCommits(context.Background(), repoID, scm.CommitListOptions{Ref: "master", Path: "README"}) + + if err != nil { + t.Errorf("GetLatestCommitOfFile got an error %v", err) + } else { + if response.Status != http.StatusOK { + t.Errorf("GetLatestCommitOfFile did not get a 200 back %v", response.Status) + } + + if commits[0].Sha != "2cc4dbe084f0d66761318b305c408cb0ea300c9a" { + t.Errorf("Got the commitId %s instead of the top commit of the file", commits[0].Sha) + } + } } From a262104f3ca712b9cc04b37f6e07e55a551989de Mon Sep 17 00:00:00 2001 From: DeepakPatankar Date: Tue, 17 May 2022 10:35:02 +0530 Subject: [PATCH 099/282] Remove the null value de-reference issue --- scm/driver/stash/integration/repo_test.go | 37 +++++++++++++++++++++++ scm/driver/stash/repo.go | 4 +-- 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 scm/driver/stash/integration/repo_test.go diff --git a/scm/driver/stash/integration/repo_test.go b/scm/driver/stash/integration/repo_test.go new file mode 100644 index 000000000..927d4e85e --- /dev/null +++ b/scm/driver/stash/integration/repo_test.go @@ -0,0 +1,37 @@ +package integration + +import ( + "context" + "net/http" + "testing" + + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/stash" + "github.com/drone/go-scm/scm/transport" +) + +func TestListRepos(t *testing.T) { + if token == "" { + t.Skip("Skipping, Acceptance test") + } + client, _ = stash.New(endpoint) + client.Client = &http.Client{ + Transport: &transport.BasicAuth{ + Username: username, + Password: token, + }, + } + + repos, response, listerr := client.Repositories.List(context.Background(), scm.ListOptions{}) + if listerr != nil { + t.Errorf("List Repos got an error %v", listerr) + } + if response.Status != http.StatusOK { + t.Errorf("List Repos did not get a 200 back %v", response.Status) + } + + if len(repos) == 0 { + t.Errorf("Got Empty repo list") + } + +} diff --git a/scm/driver/stash/repo.go b/scm/driver/stash/repo.go index e7754b459..c44fd661f 100644 --- a/scm/driver/stash/repo.go +++ b/scm/driver/stash/repo.go @@ -161,7 +161,7 @@ func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* path := fmt.Sprintf("rest/api/1.0/repos?%s", encodeListRoleOptions(opts)) out := new(repositories) res, err := s.client.do(ctx, "GET", path, nil, &out) - if !out.pagination.LastPage.Bool { + if res != nil && !out.pagination.LastPage.Bool { res.Page.First = 1 res.Page.Next = opts.Page + 1 } @@ -183,7 +183,7 @@ func (s *repositoryService) ListHooks(ctx context.Context, repo string, opts scm path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/webhooks?%s", namespace, name, encodeListOptions(opts)) out := new(hooks) res, err := s.client.do(ctx, "GET", path, nil, out) - if !out.pagination.LastPage.Bool { + if res != nil && !out.pagination.LastPage.Bool { res.Page.First = 1 res.Page.Next = opts.Page + 1 } From d651af57012b0fd77adb76c8a9bb1bac86bc5aab Mon Sep 17 00:00:00 2001 From: DeepakPatankar Date: Mon, 23 May 2022 18:39:02 +0530 Subject: [PATCH 100/282] Upgrade the scm version --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4f193d81..1e0bc4f5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [v1.23.0](https://github.com/drone/go-scm/tree/v1.23.0) (2022-05-23) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.22.0...v1.23.0) + +**Implemented enhancements:** + +- Add the support to fetch commit of a particular file [\#182](https://github.com/drone/go-scm/pull/182) ([DeepakPatankar](https://github.com/DeepakPatankar)) + +**Fixed bugs:** + +- Remove the null value de-reference issue when the bitbucket server url is nil [\#183](https://github.com/drone/go-scm/pull/183) ([DeepakPatankar](https://github.com/DeepakPatankar)) +- \[PL-24913\]: Handle the error raised while creating a multipart input [\#181](https://github.com/drone/go-scm/pull/181) ([DeepakPatankar](https://github.com/DeepakPatankar)) + ## [v1.22.0](https://github.com/drone/go-scm/tree/v1.22.0) (2022-05-10) [Full Changelog](https://github.com/drone/go-scm/compare/v1.21.1...v1.22.0) @@ -20,6 +33,10 @@ - gitea find commit [\#125](https://github.com/drone/go-scm/issues/125) +**Merged pull requests:** + +- \[feat\]: \[PL-25025\]: Changelog Updated/New Version [\#180](https://github.com/drone/go-scm/pull/180) ([mankrit-singh](https://github.com/mankrit-singh)) + ## [v1.21.1](https://github.com/drone/go-scm/tree/v1.21.1) (2022-04-22) [Full Changelog](https://github.com/drone/go-scm/compare/v1.21.0...v1.21.1) From 9acf83b318465a6842e02a6b4fcecaee08b0f490 Mon Sep 17 00:00:00 2001 From: raghavharness Date: Wed, 1 Jun 2022 17:38:13 +0530 Subject: [PATCH 101/282] [CI-4621]: Added PR find and listCommits API support in go-scm --- scm/driver/azure/integration/pr_test.go | 51 ++++++++++++++++++++++++ scm/driver/azure/pr.go | 14 ++++++- scm/driver/azure/pr_test.go | 53 +++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 2 deletions(-) diff --git a/scm/driver/azure/integration/pr_test.go b/scm/driver/azure/integration/pr_test.go index 941b30526..ea755f04f 100644 --- a/scm/driver/azure/integration/pr_test.go +++ b/scm/driver/azure/integration/pr_test.go @@ -40,3 +40,54 @@ func TestCreatePR(t *testing.T) { t.Errorf("PullRequests.Create does not have the correct title %v", outputPR.Title) } } + +func TestPullRequestFind(t *testing.T) { + if token == "" { + t.Skip("Skipping, Acceptance test") + } + client = azure.NewDefault(organization, project) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("Authorization", fmt.Sprintf("Basic %s", token)) + }, + }, + } + outputPR, response, err := client.PullRequests.Find(context.Background(), repoID, 1) + if err != nil { + t.Errorf("PullRequests.Find got an error %v", err) + } + if response.Status != http.StatusOK { + t.Errorf("PullRequests.Find did not get a 200 back %v", response.Status) + } + if outputPR.Title != "test_pr" { + t.Errorf("PullRequests.Find does not have the correct title %v", outputPR.Title) + } +} + +func TestPullRequestCommits(t *testing.T) { + if token == "" { + t.Skip("Skipping, Acceptance test") + } + client = azure.NewDefault(organization, project) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("Authorization", fmt.Sprintf("Basic %s", token)) + }, + }, + } + commits, response, err := client.PullRequests.ListCommits(context.Background(), repoID, 1, scm.ListOptions{}) + if err != nil { + t.Errorf("PullRequests.ListCommits got an error %v", err) + } + if response.Status != http.StatusOK { + t.Errorf("PullRequests.ListCommits did not get a 200 back %v", response.Status) + } + if len(commits) < 1 { + t.Errorf("PullRequests.ListCommits there should be at least 1 commit %d", len(commits)) + } + if commits[0].Sha == "" { + t.Errorf("PullRequests.ListCommits first entry did not get a sha back %v", commits[0].Sha) + } +} \ No newline at end of file diff --git a/scm/driver/azure/pr.go b/scm/driver/azure/pr.go index 647332899..0a221b117 100644 --- a/scm/driver/azure/pr.go +++ b/scm/driver/azure/pr.go @@ -17,7 +17,12 @@ type pullService struct { } func (s *pullService) Find(ctx context.Context, repo string, number int) (*scm.PullRequest, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/pull-requests/get-pull-request?view=azure-devops-rest-6.0 + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/pullrequests/%d?api-version=6.0", + s.client.owner, s.client.project, repo, number) + out := new(pr) + res, err := s.client.do(ctx, "GET", endpoint, nil, out) + return convertPullRequest(out), res, err } func (s *pullService) List(ctx context.Context, repo string, opts scm.PullRequestListOptions) ([]*scm.PullRequest, *scm.Response, error) { @@ -29,7 +34,12 @@ func (s *pullService) ListChanges(ctx context.Context, repo string, number int, } func (s *pullService) ListCommits(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Commit, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/pull-request-commits/get-pull-request-commits?view=azure-devops-rest-6.0 + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/pullRequests/%d/commits?api-version=6.0", + s.client.owner, s.client.project, repo, number) + out := new(commitList) + res, err := s.client.do(ctx, "GET", endpoint, nil, out) + return convertCommitList(out.Value), res, err } func (s *pullService) Merge(ctx context.Context, repo string, number int) (*scm.Response, error) { diff --git a/scm/driver/azure/pr_test.go b/scm/driver/azure/pr_test.go index afddc8da7..a54031cd2 100644 --- a/scm/driver/azure/pr_test.go +++ b/scm/driver/azure/pr_test.go @@ -48,3 +48,56 @@ func TestPullCreate(t *testing.T) { t.Log(diff) } } + +func TestPullFind(t *testing.T) { + defer gock.Off() + + gock.New("https:/dev.azure.com/"). + Get("/ORG/PROJ/_apis/git/repositories/REPOID/pullrequests/1"). + Reply(200). + Type("application/json"). + File("testdata/pr.json") + + + client := NewDefault("ORG", "PROJ") + got, _, err := client.PullRequests.Find(context.Background(), "REPOID", 1) + if err != nil { + t.Error(err) + return + } + + want := new(scm.PullRequest) + raw, _ := ioutil.ReadFile("testdata/pr.json.golden") + _ = json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + +func TestPullListCommits(t *testing.T) { + defer gock.Off() + + gock.New("https:/dev.azure.com/"). + Get("/ORG/PROJ/_apis/git/repositories/REPOID/pullRequests/1/commits"). + Reply(200). + Type("application/json"). + File("testdata/commits.json") + + client := NewDefault("ORG", "PROJ") + got, _, err := client.PullRequests.ListCommits(context.Background(), "REPOID", 1, scm.ListOptions{}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Commit{} + raw, _ := ioutil.ReadFile("testdata/commits.json.golden") + _ = json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} \ No newline at end of file From 2cc03ad3449d20ddd3d41e6eb2e2e3833b4214f1 Mon Sep 17 00:00:00 2001 From: raghavharness Date: Wed, 1 Jun 2022 19:25:45 +0530 Subject: [PATCH 102/282] [CI-4621]: go mod change --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 1a7e7c5ea..0bf3fae57 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/drone/go-scm +module github.com/raghavharness/go-scm require ( github.com/google/go-cmp v0.2.0 From 71867bca7c8e56aa1123dee5307631e588d87be8 Mon Sep 17 00:00:00 2001 From: raghavharness Date: Thu, 2 Jun 2022 11:39:51 +0530 Subject: [PATCH 103/282] revert --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 0bf3fae57..1a7e7c5ea 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/raghavharness/go-scm +module github.com/drone/go-scm require ( github.com/google/go-cmp v0.2.0 From 0dd92782c45468f27c0a05f0a1c1de13bf043c23 Mon Sep 17 00:00:00 2001 From: raghavharness Date: Thu, 2 Jun 2022 12:41:29 +0530 Subject: [PATCH 104/282] go fmt --- scm/driver/azure/integration/pr_test.go | 2 +- scm/driver/azure/pr.go | 8 ++++---- scm/driver/azure/pr_test.go | 3 +-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/scm/driver/azure/integration/pr_test.go b/scm/driver/azure/integration/pr_test.go index ea755f04f..b82307340 100644 --- a/scm/driver/azure/integration/pr_test.go +++ b/scm/driver/azure/integration/pr_test.go @@ -90,4 +90,4 @@ func TestPullRequestCommits(t *testing.T) { if commits[0].Sha == "" { t.Errorf("PullRequests.ListCommits first entry did not get a sha back %v", commits[0].Sha) } -} \ No newline at end of file +} diff --git a/scm/driver/azure/pr.go b/scm/driver/azure/pr.go index 0a221b117..2d9282892 100644 --- a/scm/driver/azure/pr.go +++ b/scm/driver/azure/pr.go @@ -18,8 +18,8 @@ type pullService struct { func (s *pullService) Find(ctx context.Context, repo string, number int) (*scm.PullRequest, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/pull-requests/get-pull-request?view=azure-devops-rest-6.0 - endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/pullrequests/%d?api-version=6.0", - s.client.owner, s.client.project, repo, number) + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/pullrequests/%d?api-version=6.0", + s.client.owner, s.client.project, repo, number) out := new(pr) res, err := s.client.do(ctx, "GET", endpoint, nil, out) return convertPullRequest(out), res, err @@ -35,8 +35,8 @@ func (s *pullService) ListChanges(ctx context.Context, repo string, number int, func (s *pullService) ListCommits(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Commit, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/pull-request-commits/get-pull-request-commits?view=azure-devops-rest-6.0 - endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/pullRequests/%d/commits?api-version=6.0", - s.client.owner, s.client.project, repo, number) + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/pullRequests/%d/commits?api-version=6.0", + s.client.owner, s.client.project, repo, number) out := new(commitList) res, err := s.client.do(ctx, "GET", endpoint, nil, out) return convertCommitList(out.Value), res, err diff --git a/scm/driver/azure/pr_test.go b/scm/driver/azure/pr_test.go index a54031cd2..42b60dfe7 100644 --- a/scm/driver/azure/pr_test.go +++ b/scm/driver/azure/pr_test.go @@ -58,7 +58,6 @@ func TestPullFind(t *testing.T) { Type("application/json"). File("testdata/pr.json") - client := NewDefault("ORG", "PROJ") got, _, err := client.PullRequests.Find(context.Background(), "REPOID", 1) if err != nil { @@ -100,4 +99,4 @@ func TestPullListCommits(t *testing.T) { t.Errorf("Unexpected Results") t.Log(diff) } -} \ No newline at end of file +} From 74701d04a2c01775b4edf5c126015916b9578982 Mon Sep 17 00:00:00 2001 From: Aman Singh Date: Sun, 5 Jun 2022 20:45:10 +0530 Subject: [PATCH 105/282] remove slash from list commits api --- scm/driver/github/pr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/driver/github/pr.go b/scm/driver/github/pr.go index 2dc083b4c..74da3bbf2 100644 --- a/scm/driver/github/pr.go +++ b/scm/driver/github/pr.go @@ -39,7 +39,7 @@ func (s *pullService) ListChanges(ctx context.Context, repo string, number int, } func (s *pullService) ListCommits(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Commit, *scm.Response, error) { - path := fmt.Sprintf("/repos/%s/pulls/%d/commits?%s", repo, number, encodeListOptions(opts)) + path := fmt.Sprintf("repos/%s/pulls/%d/commits?%s", repo, number, encodeListOptions(opts)) out := []*commit{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertCommitList(out), res, err From 4c30731be442baccbbfd47bfd974f711d4b9788c Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Sun, 5 Jun 2022 12:02:26 -0400 Subject: [PATCH 106/282] fix dupes in pagination --- scm/traverse/repos.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/traverse/repos.go b/scm/traverse/repos.go index dcad3ddd6..c417d2704 100644 --- a/scm/traverse/repos.go +++ b/scm/traverse/repos.go @@ -22,7 +22,7 @@ func Repos(ctx context.Context, client *scm.Client) ([]*scm.Repository, error) { } for _, src := range result { if src != nil { - list = append(list, result...) + list = append(list, src) } } opts.Page = meta.Page.Next From 63b6fb0f3b3e982075110c73270f3de14486d41f Mon Sep 17 00:00:00 2001 From: Raghav Date: Mon, 6 Jun 2022 13:38:10 +0530 Subject: [PATCH 107/282] Using target commit instead of source in base info for azure (#189) * Using target commit instead of source in base info * added pr status information for azure --- scm/driver/azure/git.go | 2 ++ scm/driver/azure/pr.go | 25 +++++++++++-------- scm/driver/azure/testdata/commit.json.golden | 4 +-- scm/driver/azure/testdata/commits.json.golden | 12 ++++----- scm/driver/azure/testdata/pr.json | 3 ++- scm/driver/azure/testdata/pr.json.golden | 11 ++++---- 6 files changed, 33 insertions(+), 24 deletions(-) diff --git a/scm/driver/azure/git.go b/scm/driver/azure/git.go index e61ec6236..435023ab9 100644 --- a/scm/driver/azure/git.go +++ b/scm/driver/azure/git.go @@ -221,11 +221,13 @@ func convertCommit(from *gitCommit) *scm.Commit { Sha: from.CommitID, Link: from.URL, Author: scm.Signature{ + Login: from.Author.Name, Name: from.Author.Name, Email: from.Author.Email, Date: from.Author.Date, }, Committer: scm.Signature{ + Login: from.Committer.Name, Name: from.Committer.Name, Email: from.Committer.Email, Date: from.Committer.Date, diff --git a/scm/driver/azure/pr.go b/scm/driver/azure/pr.go index 2d9282892..a5bb93479 100644 --- a/scm/driver/azure/pr.go +++ b/scm/driver/azure/pr.go @@ -10,6 +10,7 @@ import ( "time" "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/internal/null" ) type pullService struct { @@ -99,13 +100,14 @@ type pr struct { URL string `json:"url"` ImageURL string `json:"imageUrl"` } `json:"createdBy"` - CreationDate time.Time `json:"creationDate"` - Title string `json:"title"` - Description string `json:"description"` - SourceRefName string `json:"sourceRefName"` - TargetRefName string `json:"targetRefName"` - MergeStatus string `json:"mergeStatus"` - MergeID string `json:"mergeId"` + CreationDate time.Time `json:"creationDate"` + ClosedDate null.String `json:"closedDate"` + Title string `json:"title"` + Description string `json:"description"` + SourceRefName string `json:"sourceRefName"` + TargetRefName string `json:"targetRefName"` + MergeStatus string `json:"mergeStatus"` + MergeID string `json:"mergeId"` LastMergeSourceCommit struct { CommitID string `json:"commitId"` URL string `json:"url"` @@ -163,15 +165,18 @@ func convertPullRequest(from *pr) *scm.PullRequest { Title: from.Title, Body: from.Description, Sha: from.LastMergeSourceCommit.CommitID, - Source: from.SourceRefName, - Target: from.TargetRefName, + Source: scm.TrimRef(from.SourceRefName), + Target: scm.TrimRef(from.TargetRefName), Link: from.URL, + Closed: from.ClosedDate.Valid, + Merged: from.Status == "completed", + Ref: fmt.Sprintf("refs/pull/%d/merge", from.PullRequestID), Head: scm.Reference{ Sha: from.LastMergeSourceCommit.CommitID, }, Base: scm.Reference{ - Sha: from.LastMergeSourceCommit.CommitID, + Sha: from.LastMergeTargetCommit.CommitID, }, Author: scm.User{ Login: from.CreatedBy.UniqueName, diff --git a/scm/driver/azure/testdata/commit.json.golden b/scm/driver/azure/testdata/commit.json.golden index 36b73b3cf..1659822a9 100644 --- a/scm/driver/azure/testdata/commit.json.golden +++ b/scm/driver/azure/testdata/commit.json.golden @@ -5,14 +5,14 @@ "Name": "tp", "Email": "tp@harness.io", "Date": "2022-03-15T17:08:22Z", - "Login": "", + "Login": "tp", "Avatar": "" }, "Committer": { "Name": "tp", "Email": "tp@harness.io", "Date": "2022-03-15T17:08:22Z", - "Login": "", + "Login": "tp", "Avatar": "" }, "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/14897f4465d2d63508242b5cbf68aa2865f693e7" diff --git a/scm/driver/azure/testdata/commits.json.golden b/scm/driver/azure/testdata/commits.json.golden index 7f2eb4a47..a42699cf2 100644 --- a/scm/driver/azure/testdata/commits.json.golden +++ b/scm/driver/azure/testdata/commits.json.golden @@ -6,14 +6,14 @@ "Name": "tp", "Email": "tp@harness.io", "Date": "2022-03-04T12:19:58Z", - "Login": "", + "Login": "tp", "Avatar": "" }, "Committer": { "Name": "tp", "Email": "tp@harness.io", "Date": "2022-03-04T12:19:58Z", - "Login": "", + "Login": "tp", "Avatar": "" }, "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/e0aee6aa543294d62520fb906689da6710af149c" @@ -25,14 +25,14 @@ "Name": "tp", "Email": "tp@harness.io", "Date": "2022-03-04T12:19:57Z", - "Login": "", + "Login": "tp", "Avatar": "" }, "Committer": { "Name": "tp", "Email": "tp@harness.io", "Date": "2022-03-04T12:19:57Z", - "Login": "", + "Login": "tp", "Avatar": "" }, "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/1fe456794debece7c4125b9e283b601c974977a9" @@ -44,14 +44,14 @@ "Name": "tp", "Email": "tp@harness.io", "Date": "2022-03-04T12:19:56Z", - "Login": "", + "Login": "tp", "Avatar": "" }, "Committer": { "Name": "tp", "Email": "tp@harness.io", "Date": "2022-03-04T12:19:56Z", - "Login": "", + "Login": "tp", "Avatar": "" }, "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/commits/dc49e8e6e22bb3456366a09365ce9e72912f26b5" diff --git a/scm/driver/azure/testdata/pr.json b/scm/driver/azure/testdata/pr.json index b721e0dae..e419af010 100644 --- a/scm/driver/azure/testdata/pr.json +++ b/scm/driver/azure/testdata/pr.json @@ -15,7 +15,7 @@ }, "pullRequestId": 19, "codeReviewId": 19, - "status": "active", + "status": "completed", "createdBy": { "id": "3ff4a20f-306e-677e-8a01-57f35e71f109", "displayName": "tp", @@ -24,6 +24,7 @@ "imageUrl": "https://dev.azure.com/tphoney/_api/_common/identityImage?id=3ff4a20f-306e-677e-8a01-57f35e71f109" }, "creationDate": "2022-03-04T13:34:54.3177724Z", + "closedDate": "2022-06-03T06:33:42.2405472Z", "title": "test_pr", "description": "test_pr_body", "sourceRefName": "refs/heads/pr_branch", diff --git a/scm/driver/azure/testdata/pr.json.golden b/scm/driver/azure/testdata/pr.json.golden index 291b6f063..5e59c583b 100644 --- a/scm/driver/azure/testdata/pr.json.golden +++ b/scm/driver/azure/testdata/pr.json.golden @@ -4,17 +4,18 @@ "Body": "test_pr_body", "Sha": "01768d964c03e97260af0bd8cd9e5cd1f9ac6356", "Ref": "", - "Source": "refs/heads/pr_branch", - "Target": "refs/heads/main", + "Source": "pr_branch", + "Target": "main", + "Ref": "refs/pull/19/merge", "Fork": "", "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/pullRequests/19", "Diff": "", - "Closed": false, - "Merged": false, + "Closed": true, + "Merged": true, "Base": { "Name": "", "Path": "", - "Sha": "01768d964c03e97260af0bd8cd9e5cd1f9ac6356" + "Sha": "b748ab7eb49b8627214f22f631f878c4af9893b5" }, "Head": { "Name": "", From 424d106097528828e40ca749aaafdcc5bf833836 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Tue, 7 Jun 2022 13:06:23 +0100 Subject: [PATCH 108/282] release_prep_v1.24.0 --- CHANGELOG.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e0bc4f5c..cdb448dfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## [v1.24.0](https://github.com/drone/go-scm/tree/v1.24.0) (2022-06-07) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.23.0...v1.24.0) + +**Implemented enhancements:** + +- Added PR find and listCommit API support for Azure [\#188](https://github.com/drone/go-scm/pull/188) ([raghavharness](https://github.com/raghavharness)) + +**Fixed bugs:** + +- remove redundant slash from list commits api [\#190](https://github.com/drone/go-scm/pull/190) ([aman-harness](https://github.com/aman-harness)) +- Using target commit instead of source in base info for azure [\#189](https://github.com/drone/go-scm/pull/189) ([raghavharness](https://github.com/raghavharness)) + +**Closed issues:** + +- gitee client pagination bug [\#187](https://github.com/drone/go-scm/issues/187) + ## [v1.23.0](https://github.com/drone/go-scm/tree/v1.23.0) (2022-05-23) [Full Changelog](https://github.com/drone/go-scm/compare/v1.22.0...v1.23.0) @@ -13,6 +30,10 @@ - Remove the null value de-reference issue when the bitbucket server url is nil [\#183](https://github.com/drone/go-scm/pull/183) ([DeepakPatankar](https://github.com/DeepakPatankar)) - \[PL-24913\]: Handle the error raised while creating a multipart input [\#181](https://github.com/drone/go-scm/pull/181) ([DeepakPatankar](https://github.com/DeepakPatankar)) +**Merged pull requests:** + +- Upgrade the scm version [\#185](https://github.com/drone/go-scm/pull/185) ([DeepakPatankar](https://github.com/DeepakPatankar)) + ## [v1.22.0](https://github.com/drone/go-scm/tree/v1.22.0) (2022-05-10) [Full Changelog](https://github.com/drone/go-scm/compare/v1.21.1...v1.22.0) From 5c53bd59c4bab4c85a10723089c1f56c980600cd Mon Sep 17 00:00:00 2001 From: raghavharness Date: Sat, 11 Jun 2022 14:04:18 +0530 Subject: [PATCH 109/282] [CI-4622]: Added projectFilter for ListHooks API for Azure --- scm/driver/azure/repo.go | 26 +++-- scm/driver/azure/repo_test.go | 37 ++++++ scm/driver/azure/testdata/hooks.json | 121 ++++++++++++++++++++ scm/driver/azure/testdata/hooks.json.golden | 22 ++++ 4 files changed, 195 insertions(+), 11 deletions(-) create mode 100644 scm/driver/azure/testdata/hooks.json create mode 100644 scm/driver/azure/testdata/hooks.json.golden diff --git a/scm/driver/azure/repo.go b/scm/driver/azure/repo.go index 3e729b336..a590bffee 100644 --- a/scm/driver/azure/repo.go +++ b/scm/driver/azure/repo.go @@ -21,8 +21,8 @@ type RepositoryService struct { func (s *RepositoryService) Find(ctx context.Context, repo string) (*scm.Repository, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/repositories/get?view=azure-devops-rest-4.1 if s.client.project == "" { - return nil, nil, ProjectRequiredError() - } + return nil, nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s?api-version=6.0", s.client.owner, s.client.project, repo) out := new(repository) @@ -59,12 +59,16 @@ func (s *RepositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* func (s *RepositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/hooks/subscriptions/list?view=azure-devops-rest-6.0 if s.client.project == "" { - return nil, nil, ProjectRequiredError() - } + return nil, nil, ProjectRequiredError() + } + projectID, projErr := s.getProjectIDFromProjectName(ctx, s.client.project) + if projErr != nil { + return nil, nil, fmt.Errorf("ListHooks was unable to look up the project's projectID, %s", projErr) + } endpoint := fmt.Sprintf("%s/_apis/hooks/subscriptions?api-version=6.0", s.client.owner) out := new(subscriptions) res, err := s.client.do(ctx, "GET", endpoint, nil, &out) - return convertHookList(out.Value, repo), res, err + return convertHookList(out.Value, projectID, repo), res, err } // ListStatus returns a list of commit statuses. @@ -76,8 +80,8 @@ func (s *RepositoryService) ListStatus(ctx context.Context, repo, ref string, op func (s *RepositoryService) CreateHook(ctx context.Context, repo string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/hooks/subscriptions/create?view=azure-devops-rest-6.0 if s.client.project == "" { - return nil, nil, ProjectRequiredError() - } + return nil, nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/_apis/hooks/subscriptions?api-version=6.0", s.client.owner) in := new(subscription) in.Status = "enabled" @@ -129,8 +133,8 @@ func (s *RepositoryService) UpdateHook(ctx context.Context, repo, id string, inp func (s *RepositoryService) DeleteHook(ctx context.Context, repo, id string) (*scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/hooks/subscriptions/delete?view=azure-devops-rest-6.0 if s.client.project == "" { - return nil, ProjectRequiredError() - } + return nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/_apis/hooks/subscriptions/%s?api-version=6.0", s.client.owner, id) return s.client.do(ctx, "DELETE", endpoint, nil, nil) } @@ -262,10 +266,10 @@ func convertRepository(from *repository) *scm.Repository { } } -func convertHookList(from []*subscription, repositoryFilter string) []*scm.Hook { +func convertHookList(from []*subscription, projectFilter string, repositoryFilter string) []*scm.Hook { to := []*scm.Hook{} for _, v := range from { - if repositoryFilter != "" && repositoryFilter == v.PublisherInputs.Repository { + if repositoryFilter != "" && projectFilter == v.PublisherInputs.ProjectID && repositoryFilter == v.PublisherInputs.Repository { to = append(to, convertHook(v)) } } diff --git a/scm/driver/azure/repo_test.go b/scm/driver/azure/repo_test.go index 48663e64c..f2bd509db 100644 --- a/scm/driver/azure/repo_test.go +++ b/scm/driver/azure/repo_test.go @@ -83,6 +83,43 @@ func TestRepositoryHookCreate(t *testing.T) { } } +func TestHooksList(t *testing.T) { + defer gock.Off() + + gock.New("https:/dev.azure.com/"). + Get("/ORG/_apis/projects"). + Reply(201). + Type("application/json"). + File("testdata/projects.json") + + gock.New("https:/dev.azure.com/"). + Get("/ORG/_apis/hooks/subscriptions"). + Reply(200). + Type("application/json"). + File("testdata/hooks.json") + + client := NewDefault("ORG", "test_project") + repoID := "fde2d21f-13b9-4864-a995-83329045289a" + + got, _, err := client.Repositories.ListHooks(context.Background(), repoID, scm.ListOptions{}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Hook{} + raw, _ := ioutil.ReadFile("testdata/hooks.json.golden") + jsonErr := json.Unmarshal(raw, &want) + if jsonErr != nil { + t.Error(jsonErr) + } + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + func TestRepositoryHookDelete(t *testing.T) { defer gock.Off() diff --git a/scm/driver/azure/testdata/hooks.json b/scm/driver/azure/testdata/hooks.json new file mode 100644 index 000000000..76efd534c --- /dev/null +++ b/scm/driver/azure/testdata/hooks.json @@ -0,0 +1,121 @@ +{ + "count": 2, + "value": [ + { + "id": "d455cb11-20a0-4b15-b546-7e9fb9973cc6", + "url": "https://dev.azure.com/tphoney/_apis/hooks/subscriptions/d455cb11-20a0-4b15-b546-7e9fb9973cc6", + "status": "enabled", + "publisherId": "tfs", + "eventType": "git.pullrequest.created", + "subscriber": null, + "resourceVersion": "1.0", + "eventDescription": "Repository test_repo2", + "consumerId": "webHooks", + "consumerActionId": "httpRequest", + "actionDescription": "To host www.bla.com", + "probationRetries": 1, + "createdBy": { + "displayName": "tp", + "id": "3ff4a20f-306e-677e-8a01-57f35e71f109", + "uniqueName": "tp@harness.io", + "descriptor": "msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + }, + "createdDate": "2022-03-25T13:28:12.39Z", + "modifiedBy": { + "displayName": "tp", + "id": "3ff4a20f-306e-677e-8a01-57f35e71f109", + "uniqueName": "tp@harness.io", + "descriptor": "msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + }, + "modifiedDate": "2022-03-29T10:39:13.813Z", + "lastProbationRetryDate": "2022-03-28T10:44:51.093Z", + "publisherInputs": { + "branch": "", + "projectId": "d350c9c0-7749-4ff8-a78f-f9c1f0e56729", + "pullrequestCreatedBy": "", + "pullrequestReviewersContains": "", + "repository": "fde2d21f-13b9-4864-a995-83329045289a", + "tfsSubscriptionId": "4ce8d6c4-f655-418d-8eb6-9462dd01ff39" + }, + "consumerInputs": { + "acceptUntrustedCerts": "true", + "url": "http://www.bla.com" + }, + "_links": { + "self": { + "href": "https://dev.azure.com/tphoney/_apis/hooks/subscriptions/d455cb11-20a0-4b15-b546-7e9fb9973cc6" + }, + "consumer": { + "href": "https://dev.azure.com/tphoney/_apis/hooks/consumers/webHooks" + }, + "actions": { + "href": "https://dev.azure.com/tphoney/_apis/hooks/consumers/webHooks/actions" + }, + "notifications": { + "href": "https://dev.azure.com/tphoney/_apis/hooks/subscriptions/d455cb11-20a0-4b15-b546-7e9fb9973cc6/notifications" + }, + "publisher": { + "href": "https://dev.azure.com/tphoney/_apis/hooks/publishers/tfs" + } + } + }, + { + "id": "d455cb11-20a0-4b15-b546-7e9fb9973cc7", + "url": "https://dev.azure.com/tphoney/_apis/hooks/subscriptions/d455cb11-20a0-4b15-b546-7e9fb9973cc7", + "status": "enabled", + "publisherId": "tfs", + "eventType": "git.pullrequest.merged", + "subscriber": null, + "resourceVersion": "1.0", + "eventDescription": "Repository test_repo2", + "consumerId": "webHooks", + "consumerActionId": "httpRequest", + "actionDescription": "To host www.bla.com", + "probationRetries": 1, + "createdBy": { + "displayName": "tp", + "id": "3ff4a20f-306e-677e-8a01-57f35e71f109", + "uniqueName": "tp@harness.io", + "descriptor": "msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + }, + "createdDate": "2022-03-25T13:28:12.39Z", + "modifiedBy": { + "displayName": "tp", + "id": "3ff4a20f-306e-677e-8a01-57f35e71f109", + "uniqueName": "tp@harness.io", + "descriptor": "msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + }, + "modifiedDate": "2022-03-29T10:39:13.813Z", + "lastProbationRetryDate": "2022-03-28T10:44:51.093Z", + "publisherInputs": { + "branch": "", + "projectId": "d350c9c0-7749-4ff8-a78f-f9c1f0e56729", + "pullrequestCreatedBy": "", + "pullrequestReviewersContains": "", + "repository": "fde2d21f-13b9-4864-a995-83329045289a", + "tfsSubscriptionId": "4ce8d6c4-f655-418d-8eb6-9462dd01ff39" + }, + "consumerInputs": { + "acceptUntrustedCerts": "true", + "url": "http://www.bla.com" + }, + "_links": { + "self": { + "href": "https://dev.azure.com/tphoney/_apis/hooks/subscriptions/d455cb11-20a0-4b15-b546-7e9fb9973cc7" + }, + "consumer": { + "href": "https://dev.azure.com/tphoney/_apis/hooks/consumers/webHooks" + }, + "actions": { + "href": "https://dev.azure.com/tphoney/_apis/hooks/consumers/webHooks/actions" + }, + "notifications": { + "href": "https://dev.azure.com/tphoney/_apis/hooks/subscriptions/d455cb11-20a0-4b15-b546-7e9fb9973cc7/notifications" + }, + "publisher": { + "href": "https://dev.azure.com/tphoney/_apis/hooks/publishers/tfs" + } + } + } + ] +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/hooks.json.golden b/scm/driver/azure/testdata/hooks.json.golden new file mode 100644 index 000000000..78d873eb2 --- /dev/null +++ b/scm/driver/azure/testdata/hooks.json.golden @@ -0,0 +1,22 @@ +[ + { + "ID": "d455cb11-20a0-4b15-b546-7e9fb9973cc6", + "Name": "", + "Target": "http://www.bla.com", + "Events": [ + "git.pullrequest.created" + ], + "Active": true, + "SkipVerify": true + }, + { + "ID": "d455cb11-20a0-4b15-b546-7e9fb9973cc7", + "Name": "", + "Target": "http://www.bla.com", + "Events": [ + "git.pullrequest.merged" + ], + "Active": true, + "SkipVerify": true + } +] \ No newline at end of file From f5cea0ee897ce9ed2a7ea445958636ccae7c8303 Mon Sep 17 00:00:00 2001 From: Bhavya Agrawal Date: Wed, 15 Jun 2022 12:24:37 +0530 Subject: [PATCH 110/282] [PL-25889]: fix list branches Azure API --- scm/driver/azure/git.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/scm/driver/azure/git.go b/scm/driver/azure/git.go index 435023ab9..5aa41b07f 100644 --- a/scm/driver/azure/git.go +++ b/scm/driver/azure/git.go @@ -19,8 +19,8 @@ type gitService struct { func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.CreateBranch) (*scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/refs/update-refs?view=azure-devops-rest-6.0 if s.client.project == "" { - return nil, ProjectRequiredError() - } + return nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/refs?api-version=6.0", s.client.owner, s.client.project, repo) in := make(crudBranch, 1) @@ -32,16 +32,16 @@ func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm. func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { if s.client.project == "" { - return nil, nil, ProjectRequiredError() - } + return nil, nil, ProjectRequiredError() + } return nil, nil, scm.ErrNotSupported } func (s *gitService) FindCommit(ctx context.Context, repo, ref string) (*scm.Commit, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/commits/get?view=azure-devops-rest-6.0#get-by-id if s.client.project == "" { - return nil, nil, ProjectRequiredError() - } + return nil, nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/commits/%s?api-version=6.0", s.client.owner, s.client.project, repo, ref) out := new(gitCommit) res, err := s.client.do(ctx, "GET", endpoint, nil, out) @@ -55,9 +55,9 @@ func (s *gitService) FindTag(ctx context.Context, repo, name string) (*scm.Refer func (s *gitService) ListBranches(ctx context.Context, repo string, _ scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/refs/list?view=azure-devops-rest-6.0 if s.client.project == "" { - return nil, nil, ProjectRequiredError() - } - endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/refs?api-version=6.0", s.client.owner, s.client.project, repo) + return nil, nil, ProjectRequiredError() + } + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/refs?includeMyBranches=true&api-version=6.0", s.client.owner, s.client.project, repo) out := new(branchList) res, err := s.client.do(ctx, "GET", endpoint, nil, &out) return convertBranchList(out.Value), res, err @@ -66,8 +66,8 @@ func (s *gitService) ListBranches(ctx context.Context, repo string, _ scm.ListOp func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/commits/get-commits?view=azure-devops-rest-6.0 if s.client.project == "" { - return nil, nil, ProjectRequiredError() - } + return nil, nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/commits?", s.client.owner, s.client.project, repo) if opts.Ref != "" { endpoint += fmt.Sprintf("searchCriteria.itemVersion.version=%s&", opts.Ref) @@ -93,8 +93,8 @@ func (s *gitService) ListChanges(ctx context.Context, repo, ref string, _ scm.Li func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/diffs/get?view=azure-devops-rest-6.0 if s.client.project == "" { - return nil, nil, ProjectRequiredError() - } + return nil, nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/diffs/commits?", s.client.owner, s.client.project, repo) // add base endpoint += fmt.Sprintf("baseVersion=%s&baseVersionType=commit&", source) From b62b9fc45b290836a777ac17b46ef25b8484387b Mon Sep 17 00:00:00 2001 From: Rutvij Mehta Date: Tue, 14 Jun 2022 11:21:48 -0700 Subject: [PATCH 111/282] Support parsing Gitlab Note Hook event --- ...json => merge_request_comment_create.json} | 0 .../merge_request_comment_create.json.golden | 94 ++++++ .../pull_request_comment_create.json.golden | 0 scm/driver/gitlab/user.go | 1 + scm/driver/gitlab/webhook.go | 271 ++++++++++++------ scm/driver/gitlab/webhook_test.go | 14 +- 6 files changed, 279 insertions(+), 101 deletions(-) rename scm/driver/gitlab/testdata/webhooks/{pull_request_comment_create.json => merge_request_comment_create.json} (100%) create mode 100644 scm/driver/gitlab/testdata/webhooks/merge_request_comment_create.json.golden delete mode 100644 scm/driver/gitlab/testdata/webhooks/pull_request_comment_create.json.golden diff --git a/scm/driver/gitlab/testdata/webhooks/pull_request_comment_create.json b/scm/driver/gitlab/testdata/webhooks/merge_request_comment_create.json similarity index 100% rename from scm/driver/gitlab/testdata/webhooks/pull_request_comment_create.json rename to scm/driver/gitlab/testdata/webhooks/merge_request_comment_create.json diff --git a/scm/driver/gitlab/testdata/webhooks/merge_request_comment_create.json.golden b/scm/driver/gitlab/testdata/webhooks/merge_request_comment_create.json.golden new file mode 100644 index 000000000..3b84d1116 --- /dev/null +++ b/scm/driver/gitlab/testdata/webhooks/merge_request_comment_create.json.golden @@ -0,0 +1,94 @@ +{ + "Action": "created", + "Repo": { + "ID": "4861503", + "Namespace": "gitlab-org", + "Name": "hello-world", + "Perm": null, + "Branch": "master", + "Archived": false, + "Private": false, + "Visibility": 0, + "Clone": "https://gitlab.com/gitlab-org/hello-world.git", + "CloneSSH": "git@gitlab.com:gitlab-org/hello-world.git", + "Link": "https://gitlab.com/gitlab-org/hello-world", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Issue": { + "Number": 1, + "Title": "update readme", + "Body": "update readme", + "Link": "https://gitlab.com/gitlab-org/hello-world", + "Labels": null, + "Closed": false, + "Locked": false, + "Author": { + "Login": "sytses", + "Name": "Sid Sijbrandij", + "Email": "", + "Avatar": "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87?s=80\u0026d=identicon", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 1, + "Title": "update readme", + "Body": "adding build instructions to readme", + "Sha": "c4c79227ed610f1151f05bbc5be33b4f340d39c8", + "Ref": "refs/merge-requests/1/head", + "Source": "feature", + "Target": "master", + "Fork": "", + "Link": "https://gitlab.com/gitlab-org/hello-world", + "Diff": "", + "Closed": false, + "Merged": false, + "Base": { + "Name": "", + "Path": "", + "Sha": "" + }, + "Head": { + "Name": "", + "Path": "", + "Sha": "" + }, + "Author": { + "Login": "sytses", + "Name": "Sid Sijbrandij", + "Email": "", + "Avatar": "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87?s=80\u0026d=identicon", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Created": "2017-12-10T17:01:11Z", + "Updated": "2017-12-10T17:05:14Z", + "Labels": null + }, + "Created": "2017-12-10T17:05:14Z", + "Updated": "2017-12-10T17:05:14Z" + }, + "Comment": { + "ID": 50772616, + "Body": "lgtm", + "Author": { + "Login": "sytses", + "Name": "Sid Sijbrandij", + "Email": "", + "Avatar": "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87?s=80\u0026d=identicon", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Created": "2017-12-10T17:05:14Z", + "Updated": "2017-12-10T17:05:14Z" + }, + "Sender": { + "Login": "sytses", + "Name": "Sid Sijbrandij", + "Email": "", + "Avatar": "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87?s=80\u0026d=identicon", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + } +} \ No newline at end of file diff --git a/scm/driver/gitlab/testdata/webhooks/pull_request_comment_create.json.golden b/scm/driver/gitlab/testdata/webhooks/pull_request_comment_create.json.golden deleted file mode 100644 index e69de29bb..000000000 diff --git a/scm/driver/gitlab/user.go b/scm/driver/gitlab/user.go index fa8c2f9c1..7f182bfca 100644 --- a/scm/driver/gitlab/user.go +++ b/scm/driver/gitlab/user.go @@ -49,6 +49,7 @@ func (s *userService) ListEmail(ctx context.Context, opts scm.ListOptions) ([]*s } type user struct { + ID int `json:"id"` Username string `json:"username"` Name string `json:"name"` Email null.String `json:"email"` diff --git a/scm/driver/gitlab/webhook.go b/scm/driver/gitlab/webhook.go index e3ee5ad73..b50f8d904 100644 --- a/scm/driver/gitlab/webhook.go +++ b/scm/driver/gitlab/webhook.go @@ -11,6 +11,7 @@ import ( "io/ioutil" "net/http" "strconv" + "time" "github.com/drone/go-scm/scm" ) @@ -35,6 +36,8 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo return nil, scm.ErrUnknownEvent case "Merge Request Hook": hook, err = parsePullRequestHook(data) + case "Note Hook": + hook, err = parseIssueCommentHook(data) default: return nil, scm.ErrUnknownEvent } @@ -59,6 +62,19 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo return hook, nil } +func parseIssueCommentHook(data []byte) (scm.Webhook, error) { + src := new(commentHook) + err := json.Unmarshal(data, src) + if err != nil { + return nil, err + } + dst, err := convertCommentHook(src) + if err != nil { + return nil, err + } + return dst, nil +} + func parsePushHook(data []byte) (scm.Webhook, error) { src := new(pushHook) err := json.Unmarshal(data, src) @@ -202,6 +218,77 @@ func converBranchHook(src *pushHook) *scm.BranchHook { } } +func convertCommentHook(src *commentHook) (*scm.IssueCommentHook, error) { + var issue scm.Issue + var comment scm.Comment + + switch src.ObjectAttributes.NoteableType { + case "Commit", "Issue", "Snippet": + return nil, scm.ErrUnknownEvent + case "MergeRequest": + pr := scm.PullRequest{ + Number: src.MergeRequest.Iid, + Title: src.MergeRequest.Title, + Body: src.MergeRequest.Description, + Sha: src.MergeRequest.LastCommit.ID, + Ref: fmt.Sprintf("refs/merge-requests/%d/head", src.MergeRequest.Iid), + Source: src.MergeRequest.SourceBranch, + Target: src.MergeRequest.TargetBranch, + Link: src.Project.WebURL, + Closed: src.MergeRequest.State != "opened", + Merged: src.MergeRequest.State == "merged", + Author: *convertUser(&src.User), + Created: parseTimeString(src.MergeRequest.CreatedAt), + Updated: parseTimeString(src.MergeRequest.UpdatedAt), + } + for _, l := range src.MergeRequest.Labels { + label := scm.Label { + Name: l.Title, + Color: l.Color, + } + pr.Labels = append(pr.Labels, label) + } + issue = scm.Issue{ + Number: src.MergeRequest.Iid, + Title: src.MergeRequest.Title, + Body: src.MergeRequest.Title, + Link: src.Project.WebURL, + Author: *convertUser(&src.User), + PullRequest: pr, + Created: parseTimeString(src.ObjectAttributes.CreatedAt), + Updated: parseTimeString(src.ObjectAttributes.UpdatedAt), + } + comment = scm.Comment{ + ID: src.ObjectAttributes.ID, + Body: src.ObjectAttributes.Note, + Author: *convertUser(&src.User), + Created: parseTimeString(src.ObjectAttributes.CreatedAt), + Updated: parseTimeString(src.ObjectAttributes.UpdatedAt), + } + default: + return nil, scm.ErrUnknownEvent + } + + namespace, _ := scm.Split(src.Project.PathWithNamespace) + dst := scm.IssueCommentHook{ + Action: scm.ActionCreate, + Repo: scm.Repository{ + ID: strconv.Itoa(src.Project.ID), + Namespace: namespace, + Name: src.Repository.Name, + Clone: src.Project.GitHTTPURL, + CloneSSH: src.Project.GitSSHURL, + Link: src.Project.WebURL, + Branch: src.Project.DefaultBranch, + Private: false, // TODO how do we correctly set Private vs Public? + }, + Issue: issue, + Comment: comment, + Sender: *convertUser(&src.User), + } + return &dst, nil +} + func convertTagHook(src *pushHook) *scm.TagHook { action := scm.ActionCreate commit := src.After @@ -296,6 +383,13 @@ func convertPullRequestHook(src *pullRequestHook) *scm.PullRequestHook { } } +func parseTimeString(timeString string) (time.Time) { + layout := "2006-01-02 15:04:05 UTC" + // Returns zero value of time in case of an error 0001-01-01 00:00:00 +0000 UTC + t, _ := time.Parse(layout, timeString) + return t +} + type ( pushHook struct { ObjectKind string `json:"object_kind"` @@ -356,13 +450,10 @@ type ( commentHook struct { ObjectKind string `json:"object_kind"` - User struct { - Name string `json:"name"` - Username string `json:"username"` - AvatarURL string `json:"avatar_url"` - } `json:"user"` - ProjectID int `json:"project_id"` - Project struct { + EventType string `json:"event_type"` + User user `json:"user"` + ProjectID int `json:"project_id"` + Project struct { ID int `json:"id"` Name string `json:"name"` Description string `json:"description"` @@ -380,93 +471,76 @@ type ( SSHURL string `json:"ssh_url"` HTTPURL string `json:"http_url"` } `json:"project"` - ObjectAttributes struct { - ID int `json:"id"` - Note string `json:"note"` - NoteableType string `json:"noteable_type"` - AuthorID int `json:"author_id"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` - ProjectID int `json:"project_id"` - Attachment interface{} `json:"attachment"` - LineCode string `json:"line_code"` - CommitID string `json:"commit_id"` - NoteableID int `json:"noteable_id"` - StDiff interface{} `json:"st_diff"` - System bool `json:"system"` - UpdatedByID interface{} `json:"updated_by_id"` - Type string `json:"type"` - Position struct { - BaseSha string `json:"base_sha"` - StartSha string `json:"start_sha"` - HeadSha string `json:"head_sha"` - OldPath string `json:"old_path"` - NewPath string `json:"new_path"` - PositionType string `json:"position_type"` - OldLine interface{} `json:"old_line"` - NewLine int `json:"new_line"` - } `json:"position"` - OriginalPosition struct { - BaseSha string `json:"base_sha"` - StartSha string `json:"start_sha"` - HeadSha string `json:"head_sha"` - OldPath string `json:"old_path"` - NewPath string `json:"new_path"` - PositionType string `json:"position_type"` - OldLine interface{} `json:"old_line"` - NewLine int `json:"new_line"` - } `json:"original_position"` - ResolvedAt interface{} `json:"resolved_at"` - ResolvedByID interface{} `json:"resolved_by_id"` - DiscussionID string `json:"discussion_id"` - ChangePosition struct { - BaseSha interface{} `json:"base_sha"` - StartSha interface{} `json:"start_sha"` - HeadSha interface{} `json:"head_sha"` - OldPath interface{} `json:"old_path"` - NewPath interface{} `json:"new_path"` - PositionType string `json:"position_type"` - OldLine interface{} `json:"old_line"` - NewLine interface{} `json:"new_line"` - } `json:"change_position"` - ResolvedByPush interface{} `json:"resolved_by_push"` - URL string `json:"url"` + ObjectAttributes struct { + ID int `json:"id"` + Note string `json:"note"` + NoteableType string `json:"noteable_type"` + AuthorID int `json:"author_id"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + ProjectID int `json:"project_id"` + Attachment interface{} `json:"attachment"` + LineCode string `json:"line_code"` + CommitID string `json:"commit_id"` + NoteableID int `json:"noteable_id"` + StDiff interface{} `json:"st_diff"` + System bool `json:"system"` + ResolvedAt interface{} `json:"resolved_at"` + ResolvedByID interface{} `json:"resolved_by_id"` + ResolvedByPush interface{} `json:"resolved_by_push"` + DiscussionID string `json:"discussion_id"` + URL string `json:"url"` + Position interface{} `json:"position"` + OriginalPosition interface{} `json:"original_position"` + ChangePosition interface{} `json:"change_position"` + Type interface{} `json:"type"` + Description string `json:"description"` } `json:"object_attributes"` - Repository struct { + Repository struct { Name string `json:"name"` URL string `json:"url"` Description string `json:"description"` Homepage string `json:"homepage"` } `json:"repository"` - MergeRequest struct { - AssigneeID interface{} `json:"assignee_id"` - AuthorID int `json:"author_id"` - CreatedAt string `json:"created_at"` - DeletedAt interface{} `json:"deleted_at"` - Description string `json:"description"` - HeadPipelineID interface{} `json:"head_pipeline_id"` - ID int `json:"id"` - Iid int `json:"iid"` - LastEditedAt interface{} `json:"last_edited_at"` - LastEditedByID interface{} `json:"last_edited_by_id"` - MergeCommitSha interface{} `json:"merge_commit_sha"` - MergeError interface{} `json:"merge_error"` - MergeParams interface{} `json:"-"` - MergeStatus string `json:"merge_status"` - MergeUserID interface{} `json:"merge_user_id"` - MergeWhenPipelineSucceeds bool `json:"merge_when_pipeline_succeeds"` - MilestoneID interface{} `json:"milestone_id"` - SourceBranch string `json:"source_branch"` - SourceProjectID int `json:"source_project_id"` - State string `json:"state"` - TargetBranch string `json:"target_branch"` - TargetProjectID int `json:"target_project_id"` - TimeEstimate int `json:"time_estimate"` - Title string `json:"title"` - UpdatedAt string `json:"updated_at"` - UpdatedByID interface{} `json:"updated_by_id"` - URL string `json:"url"` - Source struct { + MergeRequest struct { + AssigneeID interface{} `json:"assignee_id"` + AuthorID int `json:"author_id"` + CreatedAt string `json:"created_at"` + DeletedAt interface{} `json:"deleted_at"` + Description string `json:"description"` + HeadPipelineID interface{} `json:"head_pipeline_id"` + ID int `json:"id"` + Iid int `json:"iid"` + LastEditedAt interface{} `json:"last_edited_at"` + LastEditedByID interface{} `json:"last_edited_by_id"` + MergeCommitSha interface{} `json:"merge_commit_sha"` + MergeError interface{} `json:"merge_error"` + MergeParams interface{} `json:"-"` + MergeStatus string `json:"merge_status"` + MergeUserID interface{} `json:"merge_user_id"` + MergeWhenPipelineSucceeds bool `json:"merge_when_pipeline_succeeds"` + MilestoneID interface{} `json:"milestone_id"` + SourceBranch string `json:"source_branch"` + SourceProjectID int `json:"source_project_id"` + StateID int `json:"state_id"` + State string `json:"state"` + TargetBranch string `json:"target_branch"` + TargetProjectID int `json:"target_project_id"` + TimeEstimate int `json:"time_estimate"` + Title string `json:"title"` + UpdatedAt string `json:"updated_at"` + UpdatedByID interface{} `json:"updated_by_id"` + URL string `json:"url"` + WorkInProgress bool `json:"work_in_progress"` + TimeChange int `json:"time_change"` + HumanTimeChange int `json:"human_time_change"` + TotalTimeSpent int `json:"total_time_spent"` + HumanTotalTimeSpent interface{} `json:"human_total_time_spent"` + HumanTimeEstimate interface{} `json:"human_time_estimate"` + Action string `json:"action"` + AssigneeIDs interface{} `json:"assignee_ids"` + BlockingDiscussionResolved bool `json:"blocking_discussions_resolved"` + Source struct { ID int `json:"id"` Name string `json:"name"` Description string `json:"description"` @@ -484,7 +558,7 @@ type ( SSHURL string `json:"ssh_url"` HTTPURL string `json:"http_url"` } `json:"source"` - Target struct { + Target struct { ID int `json:"id"` Name string `json:"name"` Description string `json:"description"` @@ -502,7 +576,7 @@ type ( SSHURL string `json:"ssh_url"` HTTPURL string `json:"http_url"` } `json:"target"` - LastCommit struct { + LastCommit struct { ID string `json:"id"` Message string `json:"message"` Timestamp string `json:"timestamp"` @@ -512,10 +586,19 @@ type ( Email string `json:"email"` } `json:"author"` } `json:"last_commit"` - WorkInProgress bool `json:"work_in_progress"` - TotalTimeSpent int `json:"total_time_spent"` - HumanTotalTimeSpent interface{} `json:"human_total_time_spent"` - HumanTimeEstimate interface{} `json:"human_time_estimate"` + Labels []struct { + ID int `json:"id"` + Title string `json:"title"` + Color string `json:"color"` + ProjectID int `json:"project_id"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` + Template bool `json:"template"` + Description string `json:"description"` + Type string `json:"type"` + GroupID interface{} `json:"group_id"` + } `json:"labels"` + } `json:"merge_request"` } diff --git a/scm/driver/gitlab/webhook_test.go b/scm/driver/gitlab/webhook_test.go index 1f153f20d..1eb6cf527 100644 --- a/scm/driver/gitlab/webhook_test.go +++ b/scm/driver/gitlab/webhook_test.go @@ -109,13 +109,13 @@ func TestWebhooks(t *testing.T) { after: "testdata/webhooks/pull_request_merge.json.golden", obj: new(scm.PullRequestHook), }, - // // pull request comment hooks - // { - // event: "issue_comment", - // before: "testdata/webhooks/pull_request_comment_created.json", - // after: "testdata/webhooks/pull_request_comment_created.json.golden", - // obj: new(scm.PullRequestCommentHook), - // }, + // Note hook for Gitlab Merge Request comment + { + event: "Note Hook", + before: "testdata/webhooks/merge_request_comment_create.json", + after: "testdata/webhooks/merge_request_comment_create.json.golden", + obj: new(scm.IssueCommentHook), + }, } for _, test := range tests { From c9023cd2de44b91acf2b2295a38e98a9be08812c Mon Sep 17 00:00:00 2001 From: Rutvij Mehta Date: Thu, 16 Jun 2022 03:43:35 -0700 Subject: [PATCH 112/282] Update scm version 1.25.0 --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdb448dfd..642d37d15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [v1.25.0](https://github.com/drone/go-scm/tree/v1.25.0) (2022-06-16) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.24.0...v1.25.0) + +**Implemented enhancements:** + +- Support parsing Gitlab Note Hook event [\#194](https://github.com/drone/go-scm/pull/194) ([rutvijmehta-harness](https://github.com/rutvijmehta-harness)) + +**Fixed bugs:** + +- \[PL-25889\]: fix list branches Azure API [\#195](https://github.com/drone/go-scm/pull/195) ([bhavya181](https://github.com/bhavya181)) +- Return project specific hooks only in ListHooks API for Azure. [\#192](https://github.com/drone/go-scm/pull/192) ([raghavharness](https://github.com/raghavharness)) + ## [v1.24.0](https://github.com/drone/go-scm/tree/v1.24.0) (2022-06-07) [Full Changelog](https://github.com/drone/go-scm/compare/v1.23.0...v1.24.0) @@ -17,6 +30,10 @@ - gitee client pagination bug [\#187](https://github.com/drone/go-scm/issues/187) +**Merged pull requests:** + +- release\_prep\_v1.24.0 [\#191](https://github.com/drone/go-scm/pull/191) ([tphoney](https://github.com/tphoney)) + ## [v1.23.0](https://github.com/drone/go-scm/tree/v1.23.0) (2022-05-23) [Full Changelog](https://github.com/drone/go-scm/compare/v1.22.0...v1.23.0) From c7f09d3e2a5c85978b0fbebe222bcb7e85077607 Mon Sep 17 00:00:00 2001 From: raghavharness Date: Sun, 19 Jun 2022 12:29:24 +0530 Subject: [PATCH 113/282] [CI-4623] - Azure webhook parseAPI changes --- .../azure/testdata/webhooks/pr_created.json | 3 +- .../testdata/webhooks/pr_created.json.golden | 18 ++-- .../azure/testdata/webhooks/pr_merged.json | 3 +- .../testdata/webhooks/pr_merged.json.golden | 18 ++-- .../azure/testdata/webhooks/pr_updated.json | 3 +- .../testdata/webhooks/pr_updated.json.golden | 18 ++-- .../azure/testdata/webhooks/push.json.golden | 31 ++++-- scm/driver/azure/webhook.go | 98 ++++++++++++++----- 8 files changed, 129 insertions(+), 63 deletions(-) diff --git a/scm/driver/azure/testdata/webhooks/pr_created.json b/scm/driver/azure/testdata/webhooks/pr_created.json index 746cacec8..9b544c962 100644 --- a/scm/driver/azure/testdata/webhooks/pr_created.json +++ b/scm/driver/azure/testdata/webhooks/pr_created.json @@ -24,7 +24,8 @@ "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/projects/6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c", "state": "wellFormed" }, - "defaultBranch": "refs/heads/master", + "sshUrl": "git@ssh.dev.azure.com:v3/fabrikam/DefaultCollection/Fabrikam", + "webUrl": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam", "remoteUrl": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam" }, "pullRequestId": 1, diff --git a/scm/driver/azure/testdata/webhooks/pr_created.json.golden b/scm/driver/azure/testdata/webhooks/pr_created.json.golden index 3ca595b6c..e081e85fa 100644 --- a/scm/driver/azure/testdata/webhooks/pr_created.json.golden +++ b/scm/driver/azure/testdata/webhooks/pr_created.json.golden @@ -1,17 +1,17 @@ { - "Action": "opened", + "Action": "created", "Repo": { "ID": "4bc14d40-c903-45e2-872e-0462c7748079", "Namespace": "Fabrikam", - "Name": "4bc14d40-c903-45e2-872e-0462c7748079", + "Name": "Fabrikam", "Perm": null, "Branch": "", "Archived": false, "Private": false, "Visibility": 0, - "Clone": "", - "CloneSSH": "", - "Link": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079", + "Clone": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam", + "CloneSSH": "git@ssh.dev.azure.com:v3/fabrikam/DefaultCollection/Fabrikam", + "Link": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam", "Created": "0001-01-01T00:00:00Z", "Updated": "0001-01-01T00:00:00Z" }, @@ -19,10 +19,10 @@ "Number": 1, "Title": "my first pull request", "Body": " - test2\r\n", - "Sha": "a10bb228-6ba6-4362-abd7-49ea21333dbd", + "Sha": "53d54ac915144006c2c9e90d2c7d3880920db49c", "Ref": "refs/heads/mytopic", - "Source": "refs/heads/mytopic", - "Target": "refs/heads/master", + "Source": "mytopic", + "Target": "master", "Fork": "", "Link": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1", "Diff": "", @@ -39,7 +39,7 @@ "Sha": "" }, "Author": { - "Login": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "Login": "Jamal Hartnett", "Name": "Jamal Hartnett", "Email": "fabrikamfiber4@hotmail.com", "Avatar": "https://dev.azure.com/fabrikam/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8", diff --git a/scm/driver/azure/testdata/webhooks/pr_merged.json b/scm/driver/azure/testdata/webhooks/pr_merged.json index 2cdd4a359..15537ac3e 100644 --- a/scm/driver/azure/testdata/webhooks/pr_merged.json +++ b/scm/driver/azure/testdata/webhooks/pr_merged.json @@ -24,7 +24,8 @@ "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/projects/6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c", "state": "wellFormed" }, - "defaultBranch": "refs/heads/master", + "sshUrl": "git@ssh.dev.azure.com:v3/fabrikam/DefaultCollection/Fabrikam", + "webUrl": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam", "remoteUrl": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam" }, "pullRequestId": 1, diff --git a/scm/driver/azure/testdata/webhooks/pr_merged.json.golden b/scm/driver/azure/testdata/webhooks/pr_merged.json.golden index 0b9fcf117..844d14542 100644 --- a/scm/driver/azure/testdata/webhooks/pr_merged.json.golden +++ b/scm/driver/azure/testdata/webhooks/pr_merged.json.golden @@ -3,15 +3,15 @@ "Repo": { "ID": "4bc14d40-c903-45e2-872e-0462c7748079", "Namespace": "Fabrikam", - "Name": "4bc14d40-c903-45e2-872e-0462c7748079", + "Name": "Fabrikam", "Perm": null, "Branch": "", "Archived": false, "Private": false, "Visibility": 0, - "Clone": "", - "CloneSSH": "", - "Link": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079", + "Clone": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam", + "CloneSSH": "git@ssh.dev.azure.com:v3/fabrikam/DefaultCollection/Fabrikam", + "Link": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam", "Created": "0001-01-01T00:00:00Z", "Updated": "0001-01-01T00:00:00Z" }, @@ -19,15 +19,15 @@ "Number": 1, "Title": "my first pull request", "Body": " - test2\r\n", - "Sha": "a10bb228-6ba6-4362-abd7-49ea21333dbd", + "Sha": "53d54ac915144006c2c9e90d2c7d3880920db49c", "Ref": "refs/heads/mytopic", - "Source": "refs/heads/mytopic", - "Target": "refs/heads/master", + "Source": "mytopic", + "Target": "master", "Fork": "", "Link": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1", "Diff": "", "Closed": false, - "Merged": false, + "Merged": true, "Base": { "Name": "", "Path": "", @@ -39,7 +39,7 @@ "Sha": "" }, "Author": { - "Login": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "Login": "Jamal Hartnett", "Name": "Jamal Hartnett", "Email": "fabrikamfiber4@hotmail.com", "Avatar": "https://dev.azure.com/fabrikam/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8", diff --git a/scm/driver/azure/testdata/webhooks/pr_updated.json b/scm/driver/azure/testdata/webhooks/pr_updated.json index 25115a743..ac0f7f1ac 100644 --- a/scm/driver/azure/testdata/webhooks/pr_updated.json +++ b/scm/driver/azure/testdata/webhooks/pr_updated.json @@ -24,7 +24,8 @@ "url": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/projects/6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c", "state": "wellFormed" }, - "defaultBranch": "refs/heads/master", + "sshUrl": "git@ssh.dev.azure.com:v3/fabrikam/DefaultCollection/Fabrikam", + "webUrl": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam", "remoteUrl": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam" }, "pullRequestId": 1, diff --git a/scm/driver/azure/testdata/webhooks/pr_updated.json.golden b/scm/driver/azure/testdata/webhooks/pr_updated.json.golden index aed341d44..ae36b5d5b 100644 --- a/scm/driver/azure/testdata/webhooks/pr_updated.json.golden +++ b/scm/driver/azure/testdata/webhooks/pr_updated.json.golden @@ -3,15 +3,15 @@ "Repo": { "ID": "4bc14d40-c903-45e2-872e-0462c7748079", "Namespace": "Fabrikam", - "Name": "4bc14d40-c903-45e2-872e-0462c7748079", + "Name": "Fabrikam", "Perm": null, "Branch": "", "Archived": false, "Private": false, "Visibility": 0, - "Clone": "", - "CloneSSH": "", - "Link": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079", + "Clone": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam", + "CloneSSH": "git@ssh.dev.azure.com:v3/fabrikam/DefaultCollection/Fabrikam", + "Link": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam", "Created": "0001-01-01T00:00:00Z", "Updated": "0001-01-01T00:00:00Z" }, @@ -19,14 +19,14 @@ "Number": 1, "Title": "my first pull request", "Body": " - test2\r\n", - "Sha": "a10bb228-6ba6-4362-abd7-49ea21333dbd", + "Sha": "53d54ac915144006c2c9e90d2c7d3880920db49c", "Ref": "refs/heads/mytopic", - "Source": "refs/heads/mytopic", - "Target": "refs/heads/master", + "Source": "mytopic", + "Target": "master", "Fork": "", "Link": "https://dev.azure.com/fabrikam/DefaultCollection/_apis/repos/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1", "Diff": "", - "Closed": false, + "Closed": true, "Merged": false, "Base": { "Name": "", @@ -39,7 +39,7 @@ "Sha": "" }, "Author": { - "Login": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "Login": "Jamal Hartnett", "Name": "Jamal Hartnett", "Email": "fabrikamfiber4@hotmail.com", "Avatar": "https://dev.azure.com/fabrikam/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8", diff --git a/scm/driver/azure/testdata/webhooks/push.json.golden b/scm/driver/azure/testdata/webhooks/push.json.golden index 76073d237..59fae065b 100644 --- a/scm/driver/azure/testdata/webhooks/push.json.golden +++ b/scm/driver/azure/testdata/webhooks/push.json.golden @@ -4,14 +4,14 @@ "After": "33b55f7cb7e7e245323987634f960cf4a6e6bc74", "Repo": { "ID": "278d5cd2-584d-4b63-824a-2ba458937249", - "Namespace": "", + "Namespace": "Fabrikam-Fiber-Git", "Name": "Fabrikam-Fiber-Git", "Perm": null, - "Branch": "", + "Branch": "master", "Private": false, - "Clone": "https://dev.azure.com/fabrikam-fiber-inc/DefaultCollection/_apis/repos/git/repositories/278d5cd2-584d-4b63-824a-2ba458937249", + "Clone": "https://dev.azure.com/fabrikam-fiber-inc/DefaultCollection/_git/Fabrikam-Fiber-Git", "CloneSSH": "", - "Link": "", + "Link": "https://dev.azure.com/fabrikam-fiber-inc/DefaultCollection/_git/Fabrikam-Fiber-Git", "Created": "0001-01-01T00:00:00Z", "Updated": "0001-01-01T00:00:00Z" }, @@ -37,9 +37,26 @@ } ], "Sender": { - "Login": "", - "Name": "", - "Email": "", + "Login": "00067FFED5C7AF52@Live.com", + "Name": "Jamal Hartnett", + "Email": "Windows Live ID\\fabrikamfiber4@hotmail.com", "Avatar": "" + }, + "Commit": { + "Sha": "33b55f7cb7e7e245323987634f960cf4a6e6bc74", + "Message": "", + "Author": { + "Login": "00067FFED5C7AF52@Live.com", + "Name": "Jamal Hartnett", + "Email": "Windows Live ID\\fabrikamfiber4@hotmail.com", + "Avatar": "" + }, + "Committer": { + "Login": "00067FFED5C7AF52@Live.com", + "Name": "Jamal Hartnett", + "Email": "Windows Live ID\\fabrikamfiber4@hotmail.com", + "Avatar": "" + }, + "Link": "" } } \ No newline at end of file diff --git a/scm/driver/azure/webhook.go b/scm/driver/azure/webhook.go index 94bafe10d..ff73ab99c 100644 --- a/scm/driver/azure/webhook.go +++ b/scm/driver/azure/webhook.go @@ -13,6 +13,7 @@ import ( "time" "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/internal/null" ) type webhookService struct { @@ -52,7 +53,7 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo return nil, err } dst := convertCreatePullRequestHook(src) - dst.Action = scm.ActionOpen + dst.Action = scm.ActionCreate return dst, nil case "git.pullrequest.updated": // https://docs.microsoft.com/en-us/azure/devops/service-hooks/events?view=azure-devops#git.pullrequest.updated @@ -102,13 +103,39 @@ func convertPushHook(src *pushHook) *scm.PushHook { }) } dst := &scm.PushHook{ + Commit: scm.Commit{ + Sha: src.Resource.RefUpdates[0].NewObjectID, + Message: "", + Author: scm.Signature{ + Login: src.Resource.PushedBy.ID, + Name: src.Resource.PushedBy.DisplayName, + Email: src.Resource.PushedBy.UniqueName, + Avatar: src.Resource.PushedBy.ImageURL, + }, + Committer: scm.Signature{ + Login: src.Resource.PushedBy.ID, + Name: src.Resource.PushedBy.DisplayName, + Email: src.Resource.PushedBy.UniqueName, + Avatar: src.Resource.PushedBy.ImageURL, + }, + Link: "", + }, Ref: src.Resource.RefUpdates[0].Name, Before: src.Resource.RefUpdates[0].OldObjectID, After: src.Resource.RefUpdates[0].NewObjectID, + Sender: scm.User{ + Login: src.Resource.PushedBy.ID, + Name: src.Resource.PushedBy.DisplayName, + Email: src.Resource.PushedBy.UniqueName, + Avatar: src.Resource.PushedBy.ImageURL, + }, Repo: scm.Repository{ - ID: src.Resource.Repository.ID, - Name: src.Resource.Repository.Name, - Clone: src.Resource.Repository.URL, + ID: src.Resource.Repository.ID, + Branch: scm.TrimRef(src.Resource.Repository.DefaultBranch), + Name: src.Resource.Repository.Name, + Namespace: src.Resource.Repository.Project.Name, + Clone: src.Resource.Repository.RemoteURL, + Link: src.Resource.Repository.RemoteURL, }, Commits: commits, } @@ -121,13 +148,15 @@ func convertCreatePullRequestHook(src *createPullRequestHook) (returnVal *scm.Pu Number: src.Resource.PullRequestID, Title: src.Resource.Title, Body: src.Resource.Description, - Sha: src.Resource.MergeID, + Sha: src.Resource.LastMergeSourceCommit.CommitID, Ref: src.Resource.SourceRefName, - Source: src.Resource.SourceRefName, - Target: src.Resource.TargetRefName, + Source: scm.TrimRef(src.Resource.SourceRefName), + Target: scm.TrimRef(src.Resource.TargetRefName), Link: src.Resource.URL, + Closed: false, + Merged: false, Author: scm.User{ - Login: src.Resource.CreatedBy.ID, + Login: src.Resource.CreatedBy.DisplayName, Name: src.Resource.CreatedBy.DisplayName, Email: src.Resource.CreatedBy.UniqueName, Avatar: src.Resource.CreatedBy.ImageURL, @@ -136,9 +165,11 @@ func convertCreatePullRequestHook(src *createPullRequestHook) (returnVal *scm.Pu }, Repo: scm.Repository{ ID: src.Resource.Repository.ID, - Name: src.Resource.Repository.ID, - Namespace: src.Resource.Repository.Name, - Link: src.Resource.Repository.URL, + Name: src.Resource.Repository.Name, + Namespace: src.Resource.Repository.Project.Name, + Link: src.Resource.Repository.WebURL, + Clone: src.Resource.Repository.WebURL, + CloneSSH: src.Resource.Repository.SSHURL, }, Sender: scm.User{ Login: src.Resource.CreatedBy.ID, @@ -156,13 +187,15 @@ func convertUpdatePullRequestHook(src *updatePullRequestHook) (returnVal *scm.Pu Number: src.Resource.PullRequestID, Title: src.Resource.Title, Body: src.Resource.Description, - Sha: src.Resource.MergeID, + Sha: src.Resource.LastMergeSourceCommit.CommitID, Ref: src.Resource.SourceRefName, - Source: src.Resource.SourceRefName, - Target: src.Resource.TargetRefName, + Source: scm.TrimRef(src.Resource.SourceRefName), + Target: scm.TrimRef(src.Resource.TargetRefName), Link: src.Resource.URL, + Closed: src.Resource.ClosedDate.Valid, + Merged: false, Author: scm.User{ - Login: src.Resource.CreatedBy.ID, + Login: src.Resource.CreatedBy.DisplayName, Name: src.Resource.CreatedBy.DisplayName, Email: src.Resource.CreatedBy.UniqueName, Avatar: src.Resource.CreatedBy.ImageURL, @@ -171,9 +204,11 @@ func convertUpdatePullRequestHook(src *updatePullRequestHook) (returnVal *scm.Pu }, Repo: scm.Repository{ ID: src.Resource.Repository.ID, - Name: src.Resource.Repository.ID, - Namespace: src.Resource.Repository.Name, - Link: src.Resource.Repository.URL, + Name: src.Resource.Repository.Name, + Namespace: src.Resource.Repository.Project.Name, + Link: src.Resource.Repository.WebURL, + Clone: src.Resource.Repository.WebURL, + CloneSSH: src.Resource.Repository.SSHURL, }, Sender: scm.User{ Login: src.Resource.CreatedBy.ID, @@ -191,13 +226,15 @@ func convertMergePullRequestHook(src *mergePullRequestHook) (returnVal *scm.Pull Number: src.Resource.PullRequestID, Title: src.Resource.Title, Body: src.Resource.Description, - Sha: src.Resource.MergeID, + Sha: src.Resource.LastMergeSourceCommit.CommitID, Ref: src.Resource.SourceRefName, - Source: src.Resource.SourceRefName, - Target: src.Resource.TargetRefName, + Source: scm.TrimRef(src.Resource.SourceRefName), + Target: scm.TrimRef(src.Resource.TargetRefName), Link: src.Resource.URL, + Closed: false, + Merged: true, Author: scm.User{ - Login: src.Resource.CreatedBy.ID, + Login: src.Resource.CreatedBy.DisplayName, Name: src.Resource.CreatedBy.DisplayName, Email: src.Resource.CreatedBy.UniqueName, Avatar: src.Resource.CreatedBy.ImageURL, @@ -206,9 +243,11 @@ func convertMergePullRequestHook(src *mergePullRequestHook) (returnVal *scm.Pull }, Repo: scm.Repository{ ID: src.Resource.Repository.ID, - Name: src.Resource.Repository.ID, - Namespace: src.Resource.Repository.Name, - Link: src.Resource.Repository.URL, + Name: src.Resource.Repository.Name, + Namespace: src.Resource.Repository.Project.Name, + Link: src.Resource.Repository.WebURL, + Clone: src.Resource.Repository.WebURL, + CloneSSH: src.Resource.Repository.SSHURL, }, Sender: scm.User{ Login: src.Resource.CreatedBy.ID, @@ -257,6 +296,7 @@ type pushHook struct { DisplayName string `json:"displayName"` ID string `json:"id"` UniqueName string `json:"uniqueName"` + ImageURL string `json:"imageUrl"` } `json:"pushedBy"` RefUpdates []struct { Name string `json:"name"` @@ -313,6 +353,8 @@ type createPullRequestHook struct { ID string `json:"id"` Name string `json:"name"` URL string `json:"url"` + WebURL string `json:"webUrl"` + SSHURL string `json:"sshUrl"` Project struct { ID string `json:"id"` Name string `json:"name"` @@ -393,7 +435,7 @@ type updatePullRequestHook struct { } `json:"message"` PublisherID string `json:"publisherId"` Resource struct { - ClosedDate string `json:"closedDate"` + ClosedDate null.String `json:"closedDate"` Commits []struct { CommitID string `json:"commitId"` URL string `json:"url"` @@ -434,6 +476,8 @@ type updatePullRequestHook struct { } `json:"project"` RemoteURL string `json:"remoteUrl"` URL string `json:"url"` + WebURL string `json:"webUrl"` + SSHURL string `json:"sshUrl"` } `json:"repository"` Reviewers []struct { DisplayName string `json:"displayName"` @@ -519,6 +563,8 @@ type mergePullRequestHook struct { } `json:"project"` RemoteURL string `json:"remoteUrl"` URL string `json:"url"` + WebURL string `json:"webUrl"` + SSHURL string `json:"sshUrl"` } `json:"repository"` Reviewers []struct { DisplayName string `json:"displayName"` From cc265c122bc0edfd118dab4ef6a6b8e0bba5a736 Mon Sep 17 00:00:00 2001 From: Hemanth Mantri Date: Mon, 20 Jun 2022 11:39:23 -0700 Subject: [PATCH 114/282] Fixed formatting in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7ada651d4..a95de0461 100644 --- a/README.md +++ b/README.md @@ -163,7 +163,7 @@ comment, _, err := client.Issues.CreateComment(ctx, "octocat/Hello-World", 1, in Here are some useful links to providers API documentation: -- [Azure DevOps](https://docs.microsoft.com/en-us/rest/api/azure/devops/git/?view=azure-devops-rest-6.0)) +- [Azure DevOps](https://docs.microsoft.com/en-us/rest/api/azure/devops/git/?view=azure-devops-rest-6.0) - [Bitbucket cloud API](https://developer.atlassian.com/cloud/bitbucket/rest/intro/) - [Bitbucket server/Stash API](https://docs.atlassian.com/bitbucket-server/rest/5.16.0/bitbucket-rest.html) - [Gitea API](https://gitea.com/api/swagger/#/) From 71ecc3b1545f257f51207ad6c8d7f373bbf05636 Mon Sep 17 00:00:00 2001 From: Raghav Date: Tue, 28 Jun 2022 16:12:00 +0530 Subject: [PATCH 115/282] added issue comment hook support for Azure (#200) * added issue comment hook support for Azure * added supported actions --- scm/const.go | 4 + .../testdata/webhooks/issue_comment.json | 132 ++++++++++++ .../webhooks/issue_comment.json.golden | 88 ++++++++ .../webhooks/issue_comment_delete.json | 133 ++++++++++++ .../webhooks/issue_comment_delete.json.golden | 88 ++++++++ .../testdata/webhooks/issue_comment_edit.json | 132 ++++++++++++ .../webhooks/issue_comment_edit.json.golden | 88 ++++++++ scm/driver/azure/webhook.go | 192 ++++++++++++++++++ scm/driver/azure/webhook_test.go | 18 ++ 9 files changed, 875 insertions(+) create mode 100644 scm/driver/azure/testdata/webhooks/issue_comment.json create mode 100644 scm/driver/azure/testdata/webhooks/issue_comment.json.golden create mode 100644 scm/driver/azure/testdata/webhooks/issue_comment_delete.json create mode 100644 scm/driver/azure/testdata/webhooks/issue_comment_delete.json.golden create mode 100644 scm/driver/azure/testdata/webhooks/issue_comment_edit.json create mode 100644 scm/driver/azure/testdata/webhooks/issue_comment_edit.json.golden diff --git a/scm/const.go b/scm/const.go index 576290e70..690202cb5 100644 --- a/scm/const.go +++ b/scm/const.go @@ -67,6 +67,8 @@ func (a Action) String() (s string) { return "synchronized" case ActionMerge: return "merged" + case ActionEdit: + return "edited" default: return } @@ -104,6 +106,8 @@ func (a *Action) UnmarshalJSON(data []byte) error { *a = ActionSync case "merged": *a = ActionMerge + case "edited": + *a = ActionEdit } return nil } diff --git a/scm/driver/azure/testdata/webhooks/issue_comment.json b/scm/driver/azure/testdata/webhooks/issue_comment.json new file mode 100644 index 000000000..33cd10cad --- /dev/null +++ b/scm/driver/azure/testdata/webhooks/issue_comment.json @@ -0,0 +1,132 @@ +{ + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "notificationId": 2, + "id": "af07be1b-f3ad-44c8-a7f1-c4835f2df06b", + "eventType": "ms.vss-code.git-pullrequest-comment-event", + "publisherId": "tfs", + "message": { + "text": "Jamal Hartnett has edited a pull request comment", + "html": "Jamal Hartnett has edited a pull request comment", + "markdown": "Jamal Hartnett has [edited](https://fabrikam.visualstudio.com/DefaultCollection/_git/Fabrikam/pullrequest/1?discussionId=5) a pull request comment" + }, + "detailedMessage": { + "text": "Jamal Hartnett has edited a pull request comment\r\nThis is my comment.\r\n", + "html": "Jamal Hartnett has edited a pull request comment

This is my comment.

", + "markdown": "Jamal Hartnett has [edited](https://fabrikam.visualstudio.com/DefaultCollection/_git/Fabrikam/pullrequest/1?discussionId=5) a pull request comment\r\nThis is my comment.\r\n" + }, + "resource": { + "comment": { + "id": 2, + "parentCommentId": 1, + "author": { + "displayName": "Jamal Hartnett", + "url": "https://fabrikam.vssps.visualstudio.com/_apis/Identities/54d125f7-69f7-4191-904f-c5b96b6261c8", + "id": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "uniqueName": "fabrikamfiber4@hotmail.com", + "imageUrl": "https://fabrikam.visualstudio.com/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8" + }, + "content": "This is my comment.", + "publishedDate": "2014-06-17T16:55:46.589889Z", + "lastUpdatedDate": "2014-06-17T16:55:46.589889Z", + "lastContentUpdatedDate": "2014-06-17T16:58:33.123889Z", + "commentType": "text", + "_links": { + "self": { + "href": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1/threads/5/comments/2" + }, + "repository": { + "href": "http://joscol2/DefaultCollection/ebed510c-62eb-474b-965f-fd151ebb82e4/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079" + }, + "threads": { + "href": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1/threads/5" + } + } + }, + "pullRequest": { + "repository": { + "id": "4bc14d40-c903-45e2-872e-0462c7748079", + "name": "Fabrikam", + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079", + "project": { + "id": "6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c", + "name": "Fabrikam", + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/projects/6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c", + "state": "wellFormed", + "visibility": "unchanged", + "lastUpdateTime": "0001-01-01T00:00:00" + }, + "sshUrl": "git@ssh.dev.azure.com:v3/fabrikam/DefaultCollection/Fabrikam", + "webUrl": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam", + "remoteUrl": "https://fabrikam.visualstudio.com/DefaultCollection/_git/Fabrikam" + }, + "pullRequestId": 1, + "status": "active", + "createdBy": { + "displayName": "Jamal Hartnett", + "url": "https://fabrikam.vssps.visualstudio.com/_apis/Identities/54d125f7-69f7-4191-904f-c5b96b6261c8", + "id": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "uniqueName": "fabrikamfiber4@hotmail.com", + "imageUrl": "https://fabrikam.visualstudio.com/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8" + }, + "creationDate": "2014-06-17T16:55:46.589889Z", + "title": "my first pull request", + "description": " - test2\r\n", + "sourceRefName": "refs/heads/mytopic", + "targetRefName": "refs/heads/master", + "mergeStatus": "succeeded", + "mergeId": "a10bb228-6ba6-4362-abd7-49ea21333dbd", + "lastMergeSourceCommit": { + "commitId": "53d54ac915144006c2c9e90d2c7d3880920db49c", + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/53d54ac915144006c2c9e90d2c7d3880920db49c" + }, + "lastMergeTargetCommit": { + "commitId": "a511f535b1ea495ee0c903badb68fbc83772c882", + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/a511f535b1ea495ee0c903badb68fbc83772c882" + }, + "lastMergeCommit": { + "commitId": "eef717f69257a6333f221566c1c987dc94cc0d72", + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/eef717f69257a6333f221566c1c987dc94cc0d72" + }, + "reviewers": [ + { + "reviewerUrl": null, + "vote": 0, + "displayName": "[Mobile]\\Mobile Team", + "url": "https://fabrikam.vssps.visualstudio.com/_apis/Identities/2ea2d095-48f9-4cd6-9966-62f6f574096c", + "id": "2ea2d095-48f9-4cd6-9966-62f6f574096c", + "uniqueName": "vstfs:///Classification/TeamProject/f0811a3b-8c8a-4e43-a3bf-9a049b4835bd\\Mobile Team", + "imageUrl": "https://fabrikam.visualstudio.com/DefaultCollection/_api/_common/identityImage?id=2ea2d095-48f9-4cd6-9966-62f6f574096c", + "isContainer": true + } + ], + "commits": [ + { + "commitId": "53d54ac915144006c2c9e90d2c7d3880920db49c", + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/53d54ac915144006c2c9e90d2c7d3880920db49c" + } + ], + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1", + "_links": { + "web": { + "href": "https://fabrikam.visualstudio.com/DefaultCollection/_git/Fabrikam/pullrequest/1#view=discussion" + }, + "statuses": { + "href": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1/statuses" + } + } + } + }, + "resourceVersion": "2.0", + "resourceContainers": { + "collection": { + "id": "c12d0eb8-e382-443b-9f9c-c52cba5014c2" + }, + "account": { + "id": "f844ec47-a9db-4511-8281-8b63f4eaf94e" + }, + "project": { + "id": "be9b3917-87e6-42a4-a549-2bc06a7a878f" + } + }, + "createdDate": "2022-06-21T13:03:20.480894Z" + } \ No newline at end of file diff --git a/scm/driver/azure/testdata/webhooks/issue_comment.json.golden b/scm/driver/azure/testdata/webhooks/issue_comment.json.golden new file mode 100644 index 000000000..70b4da243 --- /dev/null +++ b/scm/driver/azure/testdata/webhooks/issue_comment.json.golden @@ -0,0 +1,88 @@ +{ + "Action": "created", + "Repo": { + "ID": "4bc14d40-c903-45e2-872e-0462c7748079", + "Namespace": "Fabrikam", + "Name": "Fabrikam", + "Perm": null, + "Branch": "mytopic", + "Archived": false, + "Private": false, + "Visibility": 0, + "Clone": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam", + "CloneSSH": "git@ssh.dev.azure.com:v3/fabrikam/DefaultCollection/Fabrikam", + "Link": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Issue": { + "Number": 1, + "Title": "my first pull request", + "Body": " - test2\r\n", + "Link": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1", + "Author": { + "Login": "Jamal Hartnett", + "Name": "Jamal Hartnett", + "Email": "fabrikamfiber4@hotmail.com", + "Avatar": "https://fabrikam.visualstudio.com/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 1, + "Title": "my first pull request", + "Body": " - test2\r\n", + "Sha": "53d54ac915144006c2c9e90d2c7d3880920db49c", + "Ref": "refs/heads/mytopic", + "Source": "mytopic", + "Target": "master", + "Fork": "", + "Link": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1", + "Diff": "", + "Closed": false, + "Merged": false, + "Base": { + "Name": "", + "Path": "", + "Sha": "" + }, + "Head": { + "Name": "", + "Path": "", + "Sha": "" + }, + "Author": { + "Login": "Jamal Hartnett", + "Name": "Jamal Hartnett", + "Email": "fabrikamfiber4@hotmail.com", + "Avatar": "https://fabrikam.visualstudio.com/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Created": "2014-06-17T16:55:46.589889Z", + "Updated": "0001-01-01T00:00:00Z", + "Labels": null + }, + "Created": "2014-06-17T16:55:46.589889Z" + }, + "Comment": { + "ID": 2, + "Body": "This is my comment.", + "Author": { + "Login": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "Name": "Jamal Hartnett", + "Email": "fabrikamfiber4@hotmail.com", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Created": "2014-06-17T16:55:46.589889Z", + "Updated": "2014-06-17T16:55:46.589889Z" + }, + "Sender": { + "Login": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "Name": "Jamal Hartnett", + "Email": "fabrikamfiber4@hotmail.com", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + } +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/webhooks/issue_comment_delete.json b/scm/driver/azure/testdata/webhooks/issue_comment_delete.json new file mode 100644 index 000000000..5b154f7b3 --- /dev/null +++ b/scm/driver/azure/testdata/webhooks/issue_comment_delete.json @@ -0,0 +1,133 @@ +{ + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "notificationId": 2, + "id": "af07be1b-f3ad-44c8-a7f1-c4835f2df06b", + "eventType": "ms.vss-code.git-pullrequest-comment-event", + "publisherId": "tfs", + "message": { + "text": "Jamal Hartnett has edited a pull request comment", + "html": "Jamal Hartnett has edited a pull request comment", + "markdown": "Jamal Hartnett has [edited](https://fabrikam.visualstudio.com/DefaultCollection/_git/Fabrikam/pullrequest/1?discussionId=5) a pull request comment" + }, + "detailedMessage": { + "text": "Jamal Hartnett has edited a pull request comment\r\nThis is my comment.\r\n", + "html": "Jamal Hartnett has edited a pull request comment

This is my comment.

", + "markdown": "Jamal Hartnett has [edited](https://fabrikam.visualstudio.com/DefaultCollection/_git/Fabrikam/pullrequest/1?discussionId=5) a pull request comment\r\nThis is my comment.\r\n" + }, + "resource": { + "comment": { + "id": 2, + "parentCommentId": 1, + "author": { + "displayName": "Jamal Hartnett", + "url": "https://fabrikam.vssps.visualstudio.com/_apis/Identities/54d125f7-69f7-4191-904f-c5b96b6261c8", + "id": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "uniqueName": "fabrikamfiber4@hotmail.com", + "imageUrl": "https://fabrikam.visualstudio.com/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8" + }, + "content": "This is my comment.", + "publishedDate": "2014-06-17T16:55:46.589889Z", + "lastUpdatedDate": "2014-06-17T16:58:33.123889Z", + "lastContentUpdatedDate": "2014-06-17T16:58:33.123889Z", + "commentType": "text", + "isDeleted": true, + "_links": { + "self": { + "href": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1/threads/5/comments/2" + }, + "repository": { + "href": "http://joscol2/DefaultCollection/ebed510c-62eb-474b-965f-fd151ebb82e4/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079" + }, + "threads": { + "href": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1/threads/5" + } + } + }, + "pullRequest": { + "repository": { + "id": "4bc14d40-c903-45e2-872e-0462c7748079", + "name": "Fabrikam", + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079", + "project": { + "id": "6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c", + "name": "Fabrikam", + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/projects/6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c", + "state": "wellFormed", + "visibility": "unchanged", + "lastUpdateTime": "0001-01-01T00:00:00" + }, + "sshUrl": "git@ssh.dev.azure.com:v3/fabrikam/DefaultCollection/Fabrikam", + "webUrl": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam", + "remoteUrl": "https://fabrikam.visualstudio.com/DefaultCollection/_git/Fabrikam" + }, + "pullRequestId": 1, + "status": "active", + "createdBy": { + "displayName": "Jamal Hartnett", + "url": "https://fabrikam.vssps.visualstudio.com/_apis/Identities/54d125f7-69f7-4191-904f-c5b96b6261c8", + "id": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "uniqueName": "fabrikamfiber4@hotmail.com", + "imageUrl": "https://fabrikam.visualstudio.com/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8" + }, + "creationDate": "2014-06-17T16:55:46.589889Z", + "title": "my first pull request", + "description": " - test2\r\n", + "sourceRefName": "refs/heads/mytopic", + "targetRefName": "refs/heads/master", + "mergeStatus": "succeeded", + "mergeId": "a10bb228-6ba6-4362-abd7-49ea21333dbd", + "lastMergeSourceCommit": { + "commitId": "53d54ac915144006c2c9e90d2c7d3880920db49c", + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/53d54ac915144006c2c9e90d2c7d3880920db49c" + }, + "lastMergeTargetCommit": { + "commitId": "a511f535b1ea495ee0c903badb68fbc83772c882", + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/a511f535b1ea495ee0c903badb68fbc83772c882" + }, + "lastMergeCommit": { + "commitId": "eef717f69257a6333f221566c1c987dc94cc0d72", + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/eef717f69257a6333f221566c1c987dc94cc0d72" + }, + "reviewers": [ + { + "reviewerUrl": null, + "vote": 0, + "displayName": "[Mobile]\\Mobile Team", + "url": "https://fabrikam.vssps.visualstudio.com/_apis/Identities/2ea2d095-48f9-4cd6-9966-62f6f574096c", + "id": "2ea2d095-48f9-4cd6-9966-62f6f574096c", + "uniqueName": "vstfs:///Classification/TeamProject/f0811a3b-8c8a-4e43-a3bf-9a049b4835bd\\Mobile Team", + "imageUrl": "https://fabrikam.visualstudio.com/DefaultCollection/_api/_common/identityImage?id=2ea2d095-48f9-4cd6-9966-62f6f574096c", + "isContainer": true + } + ], + "commits": [ + { + "commitId": "53d54ac915144006c2c9e90d2c7d3880920db49c", + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/53d54ac915144006c2c9e90d2c7d3880920db49c" + } + ], + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1", + "_links": { + "web": { + "href": "https://fabrikam.visualstudio.com/DefaultCollection/_git/Fabrikam/pullrequest/1#view=discussion" + }, + "statuses": { + "href": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1/statuses" + } + } + } + }, + "resourceVersion": "2.0", + "resourceContainers": { + "collection": { + "id": "c12d0eb8-e382-443b-9f9c-c52cba5014c2" + }, + "account": { + "id": "f844ec47-a9db-4511-8281-8b63f4eaf94e" + }, + "project": { + "id": "be9b3917-87e6-42a4-a549-2bc06a7a878f" + } + }, + "createdDate": "2022-06-21T13:03:20.480894Z" + } \ No newline at end of file diff --git a/scm/driver/azure/testdata/webhooks/issue_comment_delete.json.golden b/scm/driver/azure/testdata/webhooks/issue_comment_delete.json.golden new file mode 100644 index 000000000..cd1e33741 --- /dev/null +++ b/scm/driver/azure/testdata/webhooks/issue_comment_delete.json.golden @@ -0,0 +1,88 @@ +{ + "Action": "deleted", + "Repo": { + "ID": "4bc14d40-c903-45e2-872e-0462c7748079", + "Namespace": "Fabrikam", + "Name": "Fabrikam", + "Perm": null, + "Branch": "mytopic", + "Archived": false, + "Private": false, + "Visibility": 0, + "Clone": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam", + "CloneSSH": "git@ssh.dev.azure.com:v3/fabrikam/DefaultCollection/Fabrikam", + "Link": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Issue": { + "Number": 1, + "Title": "my first pull request", + "Body": " - test2\r\n", + "Link": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1", + "Author": { + "Login": "Jamal Hartnett", + "Name": "Jamal Hartnett", + "Email": "fabrikamfiber4@hotmail.com", + "Avatar": "https://fabrikam.visualstudio.com/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 1, + "Title": "my first pull request", + "Body": " - test2\r\n", + "Sha": "53d54ac915144006c2c9e90d2c7d3880920db49c", + "Ref": "refs/heads/mytopic", + "Source": "mytopic", + "Target": "master", + "Fork": "", + "Link": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1", + "Diff": "", + "Closed": false, + "Merged": false, + "Base": { + "Name": "", + "Path": "", + "Sha": "" + }, + "Head": { + "Name": "", + "Path": "", + "Sha": "" + }, + "Author": { + "Login": "Jamal Hartnett", + "Name": "Jamal Hartnett", + "Email": "fabrikamfiber4@hotmail.com", + "Avatar": "https://fabrikam.visualstudio.com/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Created": "2014-06-17T16:55:46.589889Z", + "Updated": "0001-01-01T00:00:00Z", + "Labels": null + }, + "Created": "2014-06-17T16:55:46.589889Z" + }, + "Comment": { + "ID": 2, + "Body": "This is my comment.", + "Author": { + "Login": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "Name": "Jamal Hartnett", + "Email": "fabrikamfiber4@hotmail.com", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Created": "2014-06-17T16:55:46.589889Z", + "Updated": "2014-06-17T16:58:33.123889Z" + }, + "Sender": { + "Login": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "Name": "Jamal Hartnett", + "Email": "fabrikamfiber4@hotmail.com", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + } +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/webhooks/issue_comment_edit.json b/scm/driver/azure/testdata/webhooks/issue_comment_edit.json new file mode 100644 index 000000000..971daae0d --- /dev/null +++ b/scm/driver/azure/testdata/webhooks/issue_comment_edit.json @@ -0,0 +1,132 @@ +{ + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "notificationId": 2, + "id": "af07be1b-f3ad-44c8-a7f1-c4835f2df06b", + "eventType": "ms.vss-code.git-pullrequest-comment-event", + "publisherId": "tfs", + "message": { + "text": "Jamal Hartnett has edited a pull request comment", + "html": "Jamal Hartnett has edited a pull request comment", + "markdown": "Jamal Hartnett has [edited](https://fabrikam.visualstudio.com/DefaultCollection/_git/Fabrikam/pullrequest/1?discussionId=5) a pull request comment" + }, + "detailedMessage": { + "text": "Jamal Hartnett has edited a pull request comment\r\nThis is my comment.\r\n", + "html": "Jamal Hartnett has edited a pull request comment

This is my comment.

", + "markdown": "Jamal Hartnett has [edited](https://fabrikam.visualstudio.com/DefaultCollection/_git/Fabrikam/pullrequest/1?discussionId=5) a pull request comment\r\nThis is my comment.\r\n" + }, + "resource": { + "comment": { + "id": 2, + "parentCommentId": 1, + "author": { + "displayName": "Jamal Hartnett", + "url": "https://fabrikam.vssps.visualstudio.com/_apis/Identities/54d125f7-69f7-4191-904f-c5b96b6261c8", + "id": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "uniqueName": "fabrikamfiber4@hotmail.com", + "imageUrl": "https://fabrikam.visualstudio.com/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8" + }, + "content": "This is my comment.", + "publishedDate": "2014-06-17T16:55:46.589889Z", + "lastUpdatedDate": "2014-06-17T16:58:33.123889Z", + "lastContentUpdatedDate": "2014-06-17T16:58:33.123889Z", + "commentType": "text", + "_links": { + "self": { + "href": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1/threads/5/comments/2" + }, + "repository": { + "href": "http://joscol2/DefaultCollection/ebed510c-62eb-474b-965f-fd151ebb82e4/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079" + }, + "threads": { + "href": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1/threads/5" + } + } + }, + "pullRequest": { + "repository": { + "id": "4bc14d40-c903-45e2-872e-0462c7748079", + "name": "Fabrikam", + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079", + "project": { + "id": "6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c", + "name": "Fabrikam", + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/projects/6ce954b1-ce1f-45d1-b94d-e6bf2464ba2c", + "state": "wellFormed", + "visibility": "unchanged", + "lastUpdateTime": "0001-01-01T00:00:00" + }, + "sshUrl": "git@ssh.dev.azure.com:v3/fabrikam/DefaultCollection/Fabrikam", + "webUrl": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam", + "remoteUrl": "https://fabrikam.visualstudio.com/DefaultCollection/_git/Fabrikam" + }, + "pullRequestId": 1, + "status": "active", + "createdBy": { + "displayName": "Jamal Hartnett", + "url": "https://fabrikam.vssps.visualstudio.com/_apis/Identities/54d125f7-69f7-4191-904f-c5b96b6261c8", + "id": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "uniqueName": "fabrikamfiber4@hotmail.com", + "imageUrl": "https://fabrikam.visualstudio.com/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8" + }, + "creationDate": "2014-06-17T16:55:46.589889Z", + "title": "my first pull request", + "description": " - test2\r\n", + "sourceRefName": "refs/heads/mytopic", + "targetRefName": "refs/heads/master", + "mergeStatus": "succeeded", + "mergeId": "a10bb228-6ba6-4362-abd7-49ea21333dbd", + "lastMergeSourceCommit": { + "commitId": "53d54ac915144006c2c9e90d2c7d3880920db49c", + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/53d54ac915144006c2c9e90d2c7d3880920db49c" + }, + "lastMergeTargetCommit": { + "commitId": "a511f535b1ea495ee0c903badb68fbc83772c882", + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/a511f535b1ea495ee0c903badb68fbc83772c882" + }, + "lastMergeCommit": { + "commitId": "eef717f69257a6333f221566c1c987dc94cc0d72", + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/eef717f69257a6333f221566c1c987dc94cc0d72" + }, + "reviewers": [ + { + "reviewerUrl": null, + "vote": 0, + "displayName": "[Mobile]\\Mobile Team", + "url": "https://fabrikam.vssps.visualstudio.com/_apis/Identities/2ea2d095-48f9-4cd6-9966-62f6f574096c", + "id": "2ea2d095-48f9-4cd6-9966-62f6f574096c", + "uniqueName": "vstfs:///Classification/TeamProject/f0811a3b-8c8a-4e43-a3bf-9a049b4835bd\\Mobile Team", + "imageUrl": "https://fabrikam.visualstudio.com/DefaultCollection/_api/_common/identityImage?id=2ea2d095-48f9-4cd6-9966-62f6f574096c", + "isContainer": true + } + ], + "commits": [ + { + "commitId": "53d54ac915144006c2c9e90d2c7d3880920db49c", + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/commits/53d54ac915144006c2c9e90d2c7d3880920db49c" + } + ], + "url": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1", + "_links": { + "web": { + "href": "https://fabrikam.visualstudio.com/DefaultCollection/_git/Fabrikam/pullrequest/1#view=discussion" + }, + "statuses": { + "href": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1/statuses" + } + } + } + }, + "resourceVersion": "2.0", + "resourceContainers": { + "collection": { + "id": "c12d0eb8-e382-443b-9f9c-c52cba5014c2" + }, + "account": { + "id": "f844ec47-a9db-4511-8281-8b63f4eaf94e" + }, + "project": { + "id": "be9b3917-87e6-42a4-a549-2bc06a7a878f" + } + }, + "createdDate": "2022-06-21T13:03:20.480894Z" + } \ No newline at end of file diff --git a/scm/driver/azure/testdata/webhooks/issue_comment_edit.json.golden b/scm/driver/azure/testdata/webhooks/issue_comment_edit.json.golden new file mode 100644 index 000000000..4ae2669fb --- /dev/null +++ b/scm/driver/azure/testdata/webhooks/issue_comment_edit.json.golden @@ -0,0 +1,88 @@ +{ + "Action": "edited", + "Repo": { + "ID": "4bc14d40-c903-45e2-872e-0462c7748079", + "Namespace": "Fabrikam", + "Name": "Fabrikam", + "Perm": null, + "Branch": "mytopic", + "Archived": false, + "Private": false, + "Visibility": 0, + "Clone": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam", + "CloneSSH": "git@ssh.dev.azure.com:v3/fabrikam/DefaultCollection/Fabrikam", + "Link": "https://dev.azure.com/fabrikam/DefaultCollection/_git/Fabrikam", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Issue": { + "Number": 1, + "Title": "my first pull request", + "Body": " - test2\r\n", + "Link": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1", + "Author": { + "Login": "Jamal Hartnett", + "Name": "Jamal Hartnett", + "Email": "fabrikamfiber4@hotmail.com", + "Avatar": "https://fabrikam.visualstudio.com/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 1, + "Title": "my first pull request", + "Body": " - test2\r\n", + "Sha": "53d54ac915144006c2c9e90d2c7d3880920db49c", + "Ref": "refs/heads/mytopic", + "Source": "mytopic", + "Target": "master", + "Fork": "", + "Link": "https://fabrikam.visualstudio.com/DefaultCollection/_apis/git/repositories/4bc14d40-c903-45e2-872e-0462c7748079/pullRequests/1", + "Diff": "", + "Closed": false, + "Merged": false, + "Base": { + "Name": "", + "Path": "", + "Sha": "" + }, + "Head": { + "Name": "", + "Path": "", + "Sha": "" + }, + "Author": { + "Login": "Jamal Hartnett", + "Name": "Jamal Hartnett", + "Email": "fabrikamfiber4@hotmail.com", + "Avatar": "https://fabrikam.visualstudio.com/DefaultCollection/_api/_common/identityImage?id=54d125f7-69f7-4191-904f-c5b96b6261c8", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Created": "2014-06-17T16:55:46.589889Z", + "Updated": "0001-01-01T00:00:00Z", + "Labels": null + }, + "Created": "2014-06-17T16:55:46.589889Z" + }, + "Comment": { + "ID": 2, + "Body": "This is my comment.", + "Author": { + "Login": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "Name": "Jamal Hartnett", + "Email": "fabrikamfiber4@hotmail.com", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Created": "2014-06-17T16:55:46.589889Z", + "Updated": "2014-06-17T16:58:33.123889Z" + }, + "Sender": { + "Login": "54d125f7-69f7-4191-904f-c5b96b6261c8", + "Name": "Jamal Hartnett", + "Email": "fabrikamfiber4@hotmail.com", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + } +} \ No newline at end of file diff --git a/scm/driver/azure/webhook.go b/scm/driver/azure/webhook.go index ff73ab99c..9e17da18f 100644 --- a/scm/driver/azure/webhook.go +++ b/scm/driver/azure/webhook.go @@ -75,11 +75,30 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo dst := convertMergePullRequestHook(src) dst.Action = scm.ActionMerge return dst, nil + case "ms.vss-code.git-pullrequest-comment-event": + src := new(issueCommentPullRequestHook) + err := json.Unmarshal(data, src) + if err != nil { + return nil, err + } + dst := convertIssueCommentHook(src) + dst.Action = getIssueCommentAction(src) + return dst, nil default: return nil, scm.ErrUnknownEvent } } +func getIssueCommentAction(src *issueCommentPullRequestHook) scm.Action { + if src.Resource.Comment.IsDeleted { + return scm.ActionDelete + } else if src.Resource.Comment.PublishedDate.Equal(src.Resource.Comment.LastUpdatedDate) { + return scm.ActionCreate + } else { + return scm.ActionEdit + } +} + func convertPushHook(src *pushHook) *scm.PushHook { var commits []scm.Commit for _, c := range src.Resource.Commits { @@ -259,6 +278,70 @@ func convertMergePullRequestHook(src *mergePullRequestHook) (returnVal *scm.Pull return returnVal } +func convertIssueCommentHook(src *issueCommentPullRequestHook) *scm.IssueCommentHook { + dst := &scm.IssueCommentHook{ + Repo: scm.Repository{ + ID: src.Resource.PullRequest.Repository.ID, + Namespace: src.Resource.PullRequest.Repository.Project.Name, + Name: src.Resource.PullRequest.Repository.Name, + Branch: scm.TrimRef(src.Resource.PullRequest.SourceRefName), + Private: false, + Clone: src.Resource.PullRequest.Repository.WebURL, + CloneSSH: src.Resource.PullRequest.Repository.SSHURL, + Link: src.Resource.PullRequest.Repository.WebURL, + }, + Issue: scm.Issue{ + Number: src.Resource.PullRequest.PullRequestID, + Title: src.Resource.PullRequest.Title, + Body: src.Resource.PullRequest.Description, + Link: src.Resource.PullRequest.URL, + Author: scm.User{ + Login: src.Resource.PullRequest.CreatedBy.DisplayName, + Name: src.Resource.PullRequest.CreatedBy.DisplayName, + Email: src.Resource.PullRequest.CreatedBy.UniqueName, + Avatar: src.Resource.PullRequest.CreatedBy.ImageURL, + }, + PullRequest: scm.PullRequest{ + Number: src.Resource.PullRequest.PullRequestID, + Title: src.Resource.PullRequest.Title, + Body: src.Resource.PullRequest.Description, + Sha: src.Resource.PullRequest.LastMergeSourceCommit.CommitID, + Ref: src.Resource.PullRequest.SourceRefName, + Source: scm.TrimRef(src.Resource.PullRequest.SourceRefName), + Target: scm.TrimRef(src.Resource.PullRequest.TargetRefName), + Link: src.Resource.PullRequest.URL, + Closed: false, + Merged: false, + Author: scm.User{ + Login: src.Resource.PullRequest.CreatedBy.DisplayName, + Name: src.Resource.PullRequest.CreatedBy.DisplayName, + Email: src.Resource.PullRequest.CreatedBy.UniqueName, + Avatar: src.Resource.PullRequest.CreatedBy.ImageURL, + }, + Created: src.Resource.PullRequest.CreationDate, + }, + Created: src.Resource.PullRequest.CreationDate, + }, + Comment: scm.Comment{ + ID: src.Resource.Comment.ID, + Body: src.Resource.Comment.Content, + Author: scm.User{ + Email: src.Resource.Comment.Author.UniqueName, + Login: src.Resource.Comment.Author.ID, + Name: src.Resource.Comment.Author.DisplayName, + }, + Created: src.Resource.Comment.PublishedDate, + Updated: src.Resource.Comment.LastUpdatedDate, + }, + Sender: scm.User{ + Email: src.Resource.Comment.Author.UniqueName, + Login: src.Resource.Comment.Author.ID, + Name: src.Resource.Comment.Author.DisplayName, + }, + } + return dst +} + type pushHook struct { CreatedDate string `json:"createdDate"` DetailedMessage struct { @@ -596,3 +679,112 @@ type mergePullRequestHook struct { ResourceVersion string `json:"resourceVersion"` Scope string `json:"scope"` } + +type issueCommentPullRequestHook struct { + CreatedDate string `json:"createdDate"` + DetailedMessage struct { + HTML string `json:"html"` + Markdown string `json:"markdown"` + Text string `json:"text"` + } `json:"detailedMessage"` + EventType string `json:"eventType"` + ID string `json:"id"` + Message struct { + HTML string `json:"html"` + Markdown string `json:"markdown"` + Text string `json:"text"` + } `json:"message"` + PublisherID string `json:"publisherId"` + Resource struct { + PullRequest struct { + CreatedBy struct { + DisplayName string `json:"displayName"` + ID string `json:"id"` + ImageURL string `json:"imageUrl"` + UniqueName string `json:"uniqueName"` + URL string `json:"url"` + } `json:"createdBy"` + CreationDate time.Time `json:"creationDate"` + Description string `json:"description"` + LastMergeCommit struct { + CommitID string `json:"commitId"` + Author struct { + Date time.Time `json:"date"` + Email string `json:"email"` + Name string `json:"name"` + } `json:"author"` + URL string `json:"url"` + } `json:"lastMergeCommit"` + LastMergeSourceCommit struct { + CommitID string `json:"commitId"` + URL string `json:"url"` + } `json:"lastMergeSourceCommit"` + LastMergeTargetCommit struct { + CommitID string `json:"commitId"` + URL string `json:"url"` + } `json:"lastMergeTargetCommit"` + MergeID string `json:"mergeId"` + MergeStatus string `json:"mergeStatus"` + PullRequestID int `json:"pullRequestId"` + Repository struct { + ID string `json:"id"` + Name string `json:"name"` + Project struct { + ID string `json:"id"` + Name string `json:"name"` + State string `json:"state"` + URL string `json:"url"` + } `json:"project"` + RemoteURL string `json:"remoteUrl"` + URL string `json:"url"` + WebURL string `json:"webUrl"` + SSHURL string `json:"sshUrl"` + } `json:"repository"` + Reviewers []struct { + DisplayName string `json:"displayName"` + ID string `json:"id"` + ImageURL string `json:"imageUrl"` + IsContainer bool `json:"isContainer"` + ReviewerURL interface{} `json:"reviewerUrl"` + UniqueName string `json:"uniqueName"` + URL string `json:"url"` + Vote int64 `json:"vote"` + } `json:"reviewers"` + SourceRefName string `json:"sourceRefName"` + Status string `json:"status"` + TargetRefName string `json:"targetRefName"` + Title string `json:"title"` + URL string `json:"url"` + } `json:"pullRequest"` + Comment struct { + ID int `json:"id"` + ParentCommentId int `json:"parentCommentId"` + Content string `json:"content"` + PublishedDate time.Time `json:"publishedDate"` + LastUpdatedDate time.Time `json:"lastUpdatedDate"` + LastContentUpdatedDate time.Time `json:"lastContentUpdatedDate"` + CommentType string `json:"commentType"` + IsDeleted bool `json:"isDeleted"` + Author struct { + DisplayName string `json:"displayName"` + ID string `json:"id"` + ImageURL string `json:"imageUrl"` + UniqueName string `json:"uniqueName"` + URL string `json:"url"` + } `json:"author"` + } `json:"comment"` + } `json:"resource"` + ResourceContainers struct { + Account struct { + ID string `json:"id"` + } `json:"account"` + Collection struct { + ID string `json:"id"` + } `json:"collection"` + Project struct { + ID string `json:"id"` + } `json:"project"` + } `json:"resourceContainers"` + ResourceVersion string `json:"resourceVersion"` + Scope string `json:"scope"` +} \ No newline at end of file diff --git a/scm/driver/azure/webhook_test.go b/scm/driver/azure/webhook_test.go index 7ea03870e..d4024c2f8 100644 --- a/scm/driver/azure/webhook_test.go +++ b/scm/driver/azure/webhook_test.go @@ -47,6 +47,24 @@ func TestWebhooks(t *testing.T) { after: "testdata/webhooks/pr_merged.json.golden", obj: new(scm.PullRequestHook), }, + // issue comment create + { + before: "testdata/webhooks/issue_comment.json", + after: "testdata/webhooks/issue_comment.json.golden", + obj: new(scm.IssueCommentHook), + }, + // issue comment edit + { + before: "testdata/webhooks/issue_comment_edit.json", + after: "testdata/webhooks/issue_comment_edit.json.golden", + obj: new(scm.IssueCommentHook), + }, + // issue comment delete + { + before: "testdata/webhooks/issue_comment_delete.json", + after: "testdata/webhooks/issue_comment_delete.json.golden", + obj: new(scm.IssueCommentHook), + }, } for _, test := range tests { From 152fbb89839c65c859b065ec7e40156521651ed4 Mon Sep 17 00:00:00 2001 From: Rutvij Mehta Date: Thu, 23 Jun 2022 18:50:48 -0700 Subject: [PATCH 116/282] Support parsing PR comment events for Bitbucket Cloud --- .../testdata/webhooks/pr_comment_created.json | 331 ++++++++++++++++++ .../webhooks/pr_comment_created.json.golden | 96 +++++ .../testdata/webhooks/pr_comment_deleted.json | 305 ++++++++++++++++ .../webhooks/pr_comment_deleted.json.golden | 96 +++++ scm/driver/bitbucket/webhook.go | 279 +++++++++++++++ scm/driver/bitbucket/webhook_test.go | 14 + scm/user.go | 1 + 7 files changed, 1122 insertions(+) create mode 100644 scm/driver/bitbucket/testdata/webhooks/pr_comment_created.json create mode 100644 scm/driver/bitbucket/testdata/webhooks/pr_comment_created.json.golden create mode 100644 scm/driver/bitbucket/testdata/webhooks/pr_comment_deleted.json create mode 100644 scm/driver/bitbucket/testdata/webhooks/pr_comment_deleted.json.golden diff --git a/scm/driver/bitbucket/testdata/webhooks/pr_comment_created.json b/scm/driver/bitbucket/testdata/webhooks/pr_comment_created.json new file mode 100644 index 000000000..b13056f91 --- /dev/null +++ b/scm/driver/bitbucket/testdata/webhooks/pr_comment_created.json @@ -0,0 +1,331 @@ +{ + "comment": { + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1/comments/311512047" + }, + "html": { + "href": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba/pull-requests/1/_/diff#comment-311512047" + } + }, + "deleted": false, + "pullrequest": { + "type": "pullrequest", + "id": 1, + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1" + }, + "html": { + "href": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba/pull-requests/1" + } + }, + "title": "Update pom.xml" + }, + "content": { + "raw": "test comment", + "markup": "markdown", + "html": "

test comment

", + "type": "rendered" + }, + "created_on": "2022-06-23T22:10:09.939925+00:00", + "user": { + "display_name": "Rutvij Mehta", + "uuid": "{145a94da-035e-42d6-bf85-296cea8005ba}", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B145a94da-035e-42d6-bf85-296cea8005ba%7D" + }, + "html": { + "href": "https://bitbucket.org/%7B145a94da-035e-42d6-bf85-296cea8005ba%7D/" + }, + "avatar": { + "href": "https://secure.gravatar.com/avatar/1bf4d1258f18330b314d2737db430cb0?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FRM-5.png" + } + }, + "type": "user", + "nickname": "Rutvij Mehta", + "account_id": "624de6f6fd5e450070486936" + }, + "updated_on": "2022-06-23T22:10:09.939978+00:00", + "type": "pullrequest_comment", + "id": 311512047 + }, + "pullrequest": { + "rendered": { + "description": { + "raw": "Test", + "markup": "markdown", + "html": "

Test

", + "type": "rendered" + }, + "title": { + "raw": "Update pom.xml", + "markup": "markdown", + "html": "

Update pom.xml

", + "type": "rendered" + } + }, + "type": "pullrequest", + "description": "Test", + "links": { + "decline": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1/decline" + }, + "diffstat": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/diffstat/rutvijmehta-harness/spring-cloud-alibaba:b9437f32dddd%0Dcfd2d864e389?from_pullrequest_id=1&topic=true" + }, + "commits": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1/commits" + }, + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1" + }, + "comments": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1/comments" + }, + "merge": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1/merge" + }, + "html": { + "href": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba/pull-requests/1" + }, + "activity": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1/activity" + }, + "request-changes": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1/request-changes" + }, + "diff": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/diff/rutvijmehta-harness/spring-cloud-alibaba:b9437f32dddd%0Dcfd2d864e389?from_pullrequest_id=1&topic=true" + }, + "approve": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1/approve" + }, + "statuses": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1/statuses" + } + }, + "title": "Update pom.xml", + "close_source_branch": false, + "reviewers": [], + "id": 1, + "destination": { + "commit": { + "hash": "cfd2d864e389", + "type": "commit", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/commit/cfd2d864e389" + }, + "html": { + "href": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba/commits/cfd2d864e389" + } + } + }, + "repository": { + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba" + }, + "html": { + "href": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7B4402cbae-7790-453a-b29e-5fcab61a84df%7D?ts=default" + } + }, + "type": "repository", + "name": "spring-cloud-alibaba", + "full_name": "rutvijmehta-harness/spring-cloud-alibaba", + "uuid": "{4402cbae-7790-453a-b29e-5fcab61a84df}" + }, + "branch": { + "name": "2021.x" + } + }, + "created_on": "2022-06-23T19:27:25.443049+00:00", + "summary": { + "raw": "Test", + "markup": "markdown", + "html": "

Test

", + "type": "rendered" + }, + "source": { + "commit": { + "hash": "b9437f32dddd", + "type": "commit", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/commit/b9437f32dddd" + }, + "html": { + "href": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba/commits/b9437f32dddd" + } + } + }, + "repository": { + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba" + }, + "html": { + "href": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7B4402cbae-7790-453a-b29e-5fcab61a84df%7D?ts=default" + } + }, + "type": "repository", + "name": "spring-cloud-alibaba", + "full_name": "rutvijmehta-harness/spring-cloud-alibaba", + "uuid": "{4402cbae-7790-453a-b29e-5fcab61a84df}" + }, + "branch": { + "name": "tiwhitepaper-rutvij" + } + }, + "comment_count": 1, + "state": "OPEN", + "task_count": 0, + "participants": [ + { + "participated_on": "2022-06-23T22:10:09.939978+00:00", + "state": null, + "role": "PARTICIPANT", + "user": { + "display_name": "Rutvij Mehta", + "uuid": "{145a94da-035e-42d6-bf85-296cea8005ba}", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B145a94da-035e-42d6-bf85-296cea8005ba%7D" + }, + "html": { + "href": "https://bitbucket.org/%7B145a94da-035e-42d6-bf85-296cea8005ba%7D/" + }, + "avatar": { + "href": "https://secure.gravatar.com/avatar/1bf4d1258f18330b314d2737db430cb0?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FRM-5.png" + } + }, + "type": "user", + "nickname": "Rutvij Mehta", + "account_id": "624de6f6fd5e450070486936" + }, + "type": "participant", + "approved": false + } + ], + "reason": "", + "updated_on": "2022-06-23T22:10:09.939978+00:00", + "author": { + "display_name": "Rutvij Mehta", + "uuid": "{145a94da-035e-42d6-bf85-296cea8005ba}", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B145a94da-035e-42d6-bf85-296cea8005ba%7D" + }, + "html": { + "href": "https://bitbucket.org/%7B145a94da-035e-42d6-bf85-296cea8005ba%7D/" + }, + "avatar": { + "href": "https://secure.gravatar.com/avatar/1bf4d1258f18330b314d2737db430cb0?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FRM-5.png" + } + }, + "type": "user", + "nickname": "Rutvij Mehta", + "account_id": "624de6f6fd5e450070486936" + }, + "merge_commit": null, + "closed_by": null + }, + "repository": { + "scm": "git", + "website": null, + "uuid": "{4402cbae-7790-453a-b29e-5fcab61a84df}", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba" + }, + "html": { + "href": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7B4402cbae-7790-453a-b29e-5fcab61a84df%7D?ts=default" + } + }, + "project": { + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/workspaces/rutvijmehta-harness/projects/TEST" + }, + "html": { + "href": "https://bitbucket.org/rutvijmehta-harness/workspace/projects/TEST" + }, + "avatar": { + "href": "https://bitbucket.org/account/user/rutvijmehta-harness/projects/TEST/avatar/32?ts=1655023274" + } + }, + "type": "project", + "name": "Test", + "key": "TEST", + "uuid": "{aa857cae-daad-4fbd-93ef-503cc3d6c3d6}" + }, + "full_name": "rutvijmehta-harness/spring-cloud-alibaba", + "owner": { + "display_name": "Rutvij Mehta", + "uuid": "{145a94da-035e-42d6-bf85-296cea8005ba}", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B145a94da-035e-42d6-bf85-296cea8005ba%7D" + }, + "html": { + "href": "https://bitbucket.org/%7B145a94da-035e-42d6-bf85-296cea8005ba%7D/" + }, + "avatar": { + "href": "https://secure.gravatar.com/avatar/1bf4d1258f18330b314d2737db430cb0?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FRM-5.png" + } + }, + "type": "user", + "nickname": "Rutvij Mehta", + "account_id": "624de6f6fd5e450070486936" + }, + "workspace": { + "slug": "rutvijmehta-harness", + "type": "workspace", + "name": "Rutvij Mehta", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/workspaces/rutvijmehta-harness" + }, + "html": { + "href": "https://bitbucket.org/rutvijmehta-harness/" + }, + "avatar": { + "href": "https://bitbucket.org/workspaces/rutvijmehta-harness/avatar/?ts=1655023237" + } + }, + "uuid": "{145a94da-035e-42d6-bf85-296cea8005ba}" + }, + "type": "repository", + "is_private": false, + "name": "spring-cloud-alibaba" + }, + "actor": { + "display_name": "Rutvij Mehta", + "uuid": "{145a94da-035e-42d6-bf85-296cea8005ba}", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B145a94da-035e-42d6-bf85-296cea8005ba%7D" + }, + "html": { + "href": "https://bitbucket.org/%7B145a94da-035e-42d6-bf85-296cea8005ba%7D/" + }, + "avatar": { + "href": "https://secure.gravatar.com/avatar/1bf4d1258f18330b314d2737db430cb0?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FRM-5.png" + } + }, + "type": "user", + "nickname": "Rutvij Mehta", + "account_id": "624de6f6fd5e450070486936" + } +} \ No newline at end of file diff --git a/scm/driver/bitbucket/testdata/webhooks/pr_comment_created.json.golden b/scm/driver/bitbucket/testdata/webhooks/pr_comment_created.json.golden new file mode 100644 index 000000000..f4b06fb9d --- /dev/null +++ b/scm/driver/bitbucket/testdata/webhooks/pr_comment_created.json.golden @@ -0,0 +1,96 @@ +{ + "Action": "created", + "Repo": { + "ID": "{4402cbae-7790-453a-b29e-5fcab61a84df}", + "Namespace": "rutvijmehta-harness", + "Name": "spring-cloud-alibaba", + "Perm": null, + "Branch": "", + "Archived": false, + "Private": false, + "Visibility": 0, + "Clone": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba.git", + "CloneSSH": "git@bitbucket.org:rutvijmehta-harness/spring-cloud-alibaba.git", + "Link": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Issue": { + "Number": 1, + "Title": "Update pom.xml", + "Body": "Test", + "Link": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba/pull-requests/1", + "Labels": null, + "Closed": false, + "Locked": false, + "Author": { + "Login": "", + "Name": "Rutvij Mehta", + "Email": "", + "Avatar": "https://secure.gravatar.com/avatar/1bf4d1258f18330b314d2737db430cb0?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FRM-5.png", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 1, + "Title": "Update pom.xml", + "Body": "Test", + "Sha": "b9437f32dddd", + "Ref": "refs/pull-requests/1/from", + "Source": "tiwhitepaper-rutvij", + "Target": "2021.x", + "Fork": "rutvijmehta-harness/spring-cloud-alibaba", + "Link": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba/pull-requests/1", + "Diff": "", + "Closed": false, + "Merged": false, + "Base": { + "Name": "", + "Path": "", + "Sha": "" + }, + "Head": { + "Name": "", + "Path": "", + "Sha": "" + }, + "Author": { + "Login": "", + "Name": "Rutvij Mehta", + "Email": "", + "Avatar": "https://secure.gravatar.com/avatar/1bf4d1258f18330b314d2737db430cb0?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FRM-5.png", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Created": "2022-06-23T19:27:25.443049Z", + "Updated": "2022-06-23T22:10:09.939978Z", + "Labels": null + }, + "Created": "2022-06-23T19:27:25.443049Z", + "Updated": "2022-06-23T22:10:09.939978Z" + }, + "Comment": { + "ID": 311512047, + "Body": "test comment", + "Author": { + "ID": "{145a94da-035e-42d6-bf85-296cea8005ba}", + "Login": "", + "Name": "Rutvij Mehta", + "Email": "", + "Avatar": "https://secure.gravatar.com/avatar/1bf4d1258f18330b314d2737db430cb0?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FRM-5.png", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Created": "2022-06-23T22:10:09.939925Z", + "Updated": "2022-06-23T22:10:09.939978Z" + }, + "Sender": { + "ID": "{145a94da-035e-42d6-bf85-296cea8005ba}", + "Login": "", + "Name": "Rutvij Mehta", + "Email": "", + "Avatar": "https://secure.gravatar.com/avatar/1bf4d1258f18330b314d2737db430cb0?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FRM-5.png", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + } +} \ No newline at end of file diff --git a/scm/driver/bitbucket/testdata/webhooks/pr_comment_deleted.json b/scm/driver/bitbucket/testdata/webhooks/pr_comment_deleted.json new file mode 100644 index 000000000..23b3f0e3b --- /dev/null +++ b/scm/driver/bitbucket/testdata/webhooks/pr_comment_deleted.json @@ -0,0 +1,305 @@ +{ + "comment": { + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1/comments/311512047" + }, + "html": { + "href": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba/pull-requests/1/_/diff#comment-311512047" + } + }, + "deleted": true, + "pullrequest": { + "type": "pullrequest", + "id": 1, + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1" + }, + "html": { + "href": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba/pull-requests/1" + } + }, + "title": "Update pom.xml" + }, + "content": { + "raw": "", + "markup": "markdown", + "html": "", + "type": "rendered" + }, + "created_on": "2022-06-23T22:10:09.939925+00:00", + "user": { + "display_name": "Rutvij Mehta", + "uuid": "{145a94da-035e-42d6-bf85-296cea8005ba}", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B145a94da-035e-42d6-bf85-296cea8005ba%7D" + }, + "html": { + "href": "https://bitbucket.org/%7B145a94da-035e-42d6-bf85-296cea8005ba%7D/" + }, + "avatar": { + "href": "https://secure.gravatar.com/avatar/1bf4d1258f18330b314d2737db430cb0?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FRM-5.png" + } + }, + "type": "user", + "nickname": "Rutvij Mehta", + "account_id": "624de6f6fd5e450070486936" + }, + "updated_on": "2022-06-24T01:38:47.831843+00:00", + "type": "pullrequest_comment", + "id": 311512047 + }, + "pullrequest": { + "rendered": { + "description": { + "raw": "Test", + "markup": "markdown", + "html": "

Test

", + "type": "rendered" + }, + "title": { + "raw": "Update pom.xml", + "markup": "markdown", + "html": "

Update pom.xml

", + "type": "rendered" + } + }, + "type": "pullrequest", + "description": "Test", + "links": { + "decline": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1/decline" + }, + "diffstat": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/diffstat/rutvijmehta-harness/spring-cloud-alibaba:b9437f32dddd%0Dcfd2d864e389?from_pullrequest_id=1&topic=true" + }, + "commits": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1/commits" + }, + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1" + }, + "comments": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1/comments" + }, + "merge": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1/merge" + }, + "html": { + "href": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba/pull-requests/1" + }, + "activity": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1/activity" + }, + "request-changes": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1/request-changes" + }, + "diff": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/diff/rutvijmehta-harness/spring-cloud-alibaba:b9437f32dddd%0Dcfd2d864e389?from_pullrequest_id=1&topic=true" + }, + "approve": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1/approve" + }, + "statuses": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/pullrequests/1/statuses" + } + }, + "title": "Update pom.xml", + "close_source_branch": false, + "reviewers": [], + "id": 1, + "destination": { + "commit": { + "hash": "cfd2d864e389", + "type": "commit", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/commit/cfd2d864e389" + }, + "html": { + "href": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba/commits/cfd2d864e389" + } + } + }, + "repository": { + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba" + }, + "html": { + "href": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7B4402cbae-7790-453a-b29e-5fcab61a84df%7D?ts=default" + } + }, + "type": "repository", + "name": "spring-cloud-alibaba", + "full_name": "rutvijmehta-harness/spring-cloud-alibaba", + "uuid": "{4402cbae-7790-453a-b29e-5fcab61a84df}" + }, + "branch": { + "name": "2021.x" + } + }, + "created_on": "2022-06-23T19:27:25.443049+00:00", + "summary": { + "raw": "Test", + "markup": "markdown", + "html": "

Test

", + "type": "rendered" + }, + "source": { + "commit": { + "hash": "b9437f32dddd", + "type": "commit", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba/commit/b9437f32dddd" + }, + "html": { + "href": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba/commits/b9437f32dddd" + } + } + }, + "repository": { + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba" + }, + "html": { + "href": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7B4402cbae-7790-453a-b29e-5fcab61a84df%7D?ts=default" + } + }, + "type": "repository", + "name": "spring-cloud-alibaba", + "full_name": "rutvijmehta-harness/spring-cloud-alibaba", + "uuid": "{4402cbae-7790-453a-b29e-5fcab61a84df}" + }, + "branch": { + "name": "tiwhitepaper-rutvij" + } + }, + "comment_count": 0, + "state": "OPEN", + "task_count": 0, + "participants": [], + "reason": "", + "updated_on": "2022-06-24T01:40:18.667126+00:00", + "author": { + "display_name": "Rutvij Mehta", + "uuid": "{145a94da-035e-42d6-bf85-296cea8005ba}", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B145a94da-035e-42d6-bf85-296cea8005ba%7D" + }, + "html": { + "href": "https://bitbucket.org/%7B145a94da-035e-42d6-bf85-296cea8005ba%7D/" + }, + "avatar": { + "href": "https://secure.gravatar.com/avatar/1bf4d1258f18330b314d2737db430cb0?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FRM-5.png" + } + }, + "type": "user", + "nickname": "Rutvij Mehta", + "account_id": "624de6f6fd5e450070486936" + }, + "merge_commit": null, + "closed_by": null + }, + "repository": { + "scm": "git", + "website": null, + "uuid": "{4402cbae-7790-453a-b29e-5fcab61a84df}", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/repositories/rutvijmehta-harness/spring-cloud-alibaba" + }, + "html": { + "href": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba" + }, + "avatar": { + "href": "https://bytebucket.org/ravatar/%7B4402cbae-7790-453a-b29e-5fcab61a84df%7D?ts=default" + } + }, + "project": { + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/workspaces/rutvijmehta-harness/projects/TEST" + }, + "html": { + "href": "https://bitbucket.org/rutvijmehta-harness/workspace/projects/TEST" + }, + "avatar": { + "href": "https://bitbucket.org/account/user/rutvijmehta-harness/projects/TEST/avatar/32?ts=1655023274" + } + }, + "type": "project", + "name": "Test", + "key": "TEST", + "uuid": "{aa857cae-daad-4fbd-93ef-503cc3d6c3d6}" + }, + "full_name": "rutvijmehta-harness/spring-cloud-alibaba", + "owner": { + "display_name": "Rutvij Mehta", + "uuid": "{145a94da-035e-42d6-bf85-296cea8005ba}", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B145a94da-035e-42d6-bf85-296cea8005ba%7D" + }, + "html": { + "href": "https://bitbucket.org/%7B145a94da-035e-42d6-bf85-296cea8005ba%7D/" + }, + "avatar": { + "href": "https://secure.gravatar.com/avatar/1bf4d1258f18330b314d2737db430cb0?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FRM-5.png" + } + }, + "type": "user", + "nickname": "Rutvij Mehta", + "account_id": "624de6f6fd5e450070486936" + }, + "workspace": { + "slug": "rutvijmehta-harness", + "type": "workspace", + "name": "Rutvij Mehta", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/workspaces/rutvijmehta-harness" + }, + "html": { + "href": "https://bitbucket.org/rutvijmehta-harness/" + }, + "avatar": { + "href": "https://bitbucket.org/workspaces/rutvijmehta-harness/avatar/?ts=1655023237" + } + }, + "uuid": "{145a94da-035e-42d6-bf85-296cea8005ba}" + }, + "type": "repository", + "is_private": false, + "name": "spring-cloud-alibaba" + }, + "actor": { + "display_name": "Rutvij Mehta", + "uuid": "{145a94da-035e-42d6-bf85-296cea8005ba}", + "links": { + "self": { + "href": "https://api.bitbucket.org/2.0/users/%7B145a94da-035e-42d6-bf85-296cea8005ba%7D" + }, + "html": { + "href": "https://bitbucket.org/%7B145a94da-035e-42d6-bf85-296cea8005ba%7D/" + }, + "avatar": { + "href": "https://secure.gravatar.com/avatar/1bf4d1258f18330b314d2737db430cb0?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FRM-5.png" + } + }, + "type": "user", + "nickname": "Rutvij Mehta", + "account_id": "624de6f6fd5e450070486936" + } +} \ No newline at end of file diff --git a/scm/driver/bitbucket/testdata/webhooks/pr_comment_deleted.json.golden b/scm/driver/bitbucket/testdata/webhooks/pr_comment_deleted.json.golden new file mode 100644 index 000000000..7190b1ff7 --- /dev/null +++ b/scm/driver/bitbucket/testdata/webhooks/pr_comment_deleted.json.golden @@ -0,0 +1,96 @@ +{ + "Action": "deleted", + "Repo": { + "ID": "{4402cbae-7790-453a-b29e-5fcab61a84df}", + "Namespace": "rutvijmehta-harness", + "Name": "spring-cloud-alibaba", + "Perm": null, + "Branch": "", + "Archived": false, + "Private": false, + "Visibility": 0, + "Clone": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba.git", + "CloneSSH": "git@bitbucket.org:rutvijmehta-harness/spring-cloud-alibaba.git", + "Link": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Issue": { + "Number": 1, + "Title": "Update pom.xml", + "Body": "Test", + "Link": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba/pull-requests/1", + "Labels": null, + "Closed": false, + "Locked": false, + "Author": { + "Login": "", + "Name": "Rutvij Mehta", + "Email": "", + "Avatar": "https://secure.gravatar.com/avatar/1bf4d1258f18330b314d2737db430cb0?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FRM-5.png", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 1, + "Title": "Update pom.xml", + "Body": "Test", + "Sha": "b9437f32dddd", + "Ref": "refs/pull-requests/1/from", + "Source": "tiwhitepaper-rutvij", + "Target": "2021.x", + "Fork": "rutvijmehta-harness/spring-cloud-alibaba", + "Link": "https://bitbucket.org/rutvijmehta-harness/spring-cloud-alibaba/pull-requests/1", + "Diff": "", + "Closed": false, + "Merged": false, + "Base": { + "Name": "", + "Path": "", + "Sha": "" + }, + "Head": { + "Name": "", + "Path": "", + "Sha": "" + }, + "Author": { + "Login": "", + "Name": "Rutvij Mehta", + "Email": "", + "Avatar": "https://secure.gravatar.com/avatar/1bf4d1258f18330b314d2737db430cb0?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FRM-5.png", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Created": "2022-06-23T19:27:25.443049Z", + "Updated": "2022-06-24T01:40:18.667126Z", + "Labels": null + }, + "Created": "2022-06-23T19:27:25.443049Z", + "Updated": "2022-06-24T01:40:18.667126Z" + }, + "Comment": { + "ID": 311512047, + "Body": "", + "Author": { + "ID": "{145a94da-035e-42d6-bf85-296cea8005ba}", + "Login": "", + "Name": "Rutvij Mehta", + "Email": "", + "Avatar": "https://secure.gravatar.com/avatar/1bf4d1258f18330b314d2737db430cb0?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FRM-5.png", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Created": "2022-06-23T22:10:09.939925Z", + "Updated": "2022-06-24T01:38:47.831843Z" + }, + "Sender": { + "ID": "{145a94da-035e-42d6-bf85-296cea8005ba}", + "Login": "", + "Name": "Rutvij Mehta", + "Email": "", + "Avatar": "https://secure.gravatar.com/avatar/1bf4d1258f18330b314d2737db430cb0?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FRM-5.png", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + } +} \ No newline at end of file diff --git a/scm/driver/bitbucket/webhook.go b/scm/driver/bitbucket/webhook.go index da62ba876..c567e565f 100644 --- a/scm/driver/bitbucket/webhook.go +++ b/scm/driver/bitbucket/webhook.go @@ -53,6 +53,23 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo if hook != nil { hook.(*scm.PullRequestHook).Action = scm.ActionClose } + case "pullrequest:comment_created": + hook, err = s.parsePullRequestCommentHook(data) + if hook != nil { + hook.(*scm.IssueCommentHook).Action = scm.ActionCreate + } + case "pullrequest:comment_updated": + // Bitbucket PR Comment Update is unreliable and does not send events + // most of the time https://github.com/iterative/cml/issues/817 + hook, err = s.parsePullRequestCommentHook(data) + if hook != nil { + hook.(*scm.IssueCommentHook).Action = scm.ActionEdit + } + case "pullrequest:comment_deleted": + hook, err = s.parsePullRequestCommentHook(data) + if hook != nil { + hook.(*scm.IssueCommentHook).Action = scm.ActionDelete + } } if err != nil { return nil, err @@ -78,6 +95,12 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo return hook, nil } +func (s *webhookService) parsePullRequestCommentHook(data []byte) (scm.Webhook, error) { + dst := new(prCommentHook) + err := json.Unmarshal(data, dst) + return convertPrCommentHook(dst), err +} + func (s *webhookService) parsePushHook(data []byte) (scm.Webhook, error) { dst := new(pushHook) err := json.Unmarshal(data, dst) @@ -381,6 +404,194 @@ type ( } `json:"links"` UUID string `json:"uuid"` } + + prComment struct { + Links struct { + Self link `json:"self"` + HTML link `json:"html"` + } `json:"links"` + Deleted bool `json:"deleted"` + PullRequest struct { + Type string `json:"type"` + ID int `json:"id"` + Links struct { + Self link `json:"self"` + HTML link `json:"html"` + } `json:"links"` + Title string `json:"title"` + } + Content struct { + Raw string `json:"raw"` + Markup string `json:"markup"` + Html string `json:"html"` + Type string `json:"type"` + } + CreatedOn time.Time `json:"created_on"` + User prCommentHookUser `json:"user"` + UpdatedOn time.Time `json:"updated_on"` + Type string `json:"type"` + ID int `json:"id"` + } + + prCommentHookRepo struct { + Scm string `json:"scm"` + Website string `json:"website"` + UUID string `json:"uuid"` + Links struct { + Self link `json:"self"` + HTML link `json:"html"` + Avatar link `json:"avatar"` + } `json:"links"` + Project struct { + Links struct { + Self link `json:"self"` + HTML link `json:"html"` + Avatar link `json:"avatar"` + } `json:"links"` + Type string `json:"type"` + Name string `json:"name"` + Key string `json:"key"` + UUID string `json:"uuid"` + } `json:"project"` + FullName string `json:"full_name"` + Owner prCommentHookUser `json:"owner"` + Workspace struct { + Slug string `json:"slugg"` + Type string `json:"type"` + Name string `json:"name"` + Links struct { + Self link `json:"self"` + HTML link `json:"html"` + Avatar link `json:"avatar"` + } `json:"links"` + UUID string `json:"uuid"` + } `json:"workspace"` + Type string `json:"type"` + IsPrivate bool `json:"is_private"` + Name string `json:"name"` + } + + prCommentHookUser struct { + Username string `json:"username"` + DisplayName string `json:"display_name"` + UUID string `json:"uuid"` + Links struct { + Self link `json:"self"` + HTML link `json:"html"` + Avatar link `json:"avatar"` + } `json:"links"` + Type string `json:"type"` + Nickname string `json:"nickname"` + AccountID string `json:"account_id"` + } + + prCommentHookPullRequest struct { + Rendered struct { + Description struct { + Raw string `json:"raw"` + Markup string `json:"markup"` + Html string `json:"html"` + Type string `json:"type"` + } `json:"description"` + Title struct { + Raw string `json:"raw"` + Markup string `json:"markup"` + Html string `json:"html"` + Type string `json:"type"` + } `json:"title"` + } `json:"rendered"` + Type string `json:"type"` + Description string `json:"description"` + Links struct { + Decline link `json:"decline"` + Diffstat link `json:"diffstat"` + Commits link `json:"commits"` + Self link `json:"self"` + Comments link `json:"comments"` + Merge link `json:"merge"` + Html link `json:"html"` + Activity link `json:"activity"` + RequestChanges link `json:"request-changes"` + Diff link `json:"diff"` + Approve link `json:"approve"` + Statuses link `json:"statuses"` + } `json:"links"` + Title string `json:"title"` + CloseSourceBranch bool `json:"close_source_branch"` + Reviewers []interface{} `json:"reviewers"` + ID int `json:"id"` + Destination struct { + Commit struct { + Hash string `json:"hash"` + Type string `json:"type"` + Links struct { + Self link `json:"self"` + HTML link `json:"html"` + } `json:"links"` + } + Repository struct { + Links struct { + Self link `json:"self"` + HTML link `json:"html"` + Avatar link `json:"avatar"` + } `json:"links"` + Type string `json:"type"` + Name string `json:"name"` + FullName string `json:"full_name"` + UUID string `json:"uuid"` + } `json:"repository"` + Branch struct { + Name string `json:"name"` + } `json:"branch"` + } `json:"destination"` + CreatedOn time.Time `json:"created_on"` + Summary struct { + Raw string `json:"raw"` + Markup string `json:"markup"` + Html string `json:"html"` + Type string `json:"type"` + } `json:"summary"` + Source struct { + Commit struct { + Hash string `json:"hash"` + Type string `json:"type"` + Links struct { + Self link `json:"self"` + HTML link `json:"html"` + } `json:"links"` + } + Repository struct { + Links struct { + Self link `json:"self"` + HTML link `json:"html"` + Avatar link `json:"avatar"` + } `json:"links"` + Type string `json:"type"` + Name string `json:"name"` + FullName string `json:"full_name"` + UUID string `json:"uuid"` + } `json:"repository"` + Branch struct { + Name string `json:"name"` + } `json:"branch"` + } `json:"source"` + CommentCount int `json:"comment_count"` + State string `json:"state"` + TaskCount int `json:"task_count"` + Participants []interface{} `json:"participants"` + Reason string `json:"reason"` + UpdatedOn time.Time `json:"updated_on"` + Author prCommentHookUser `json:"author"` + MergeCommit interface{} `json:"merge_commit"` + ClosedBy interface{} `json:"closed_by"` + } + + prCommentHook struct { + Comment prComment `json:"comment"` + PullRequest prCommentHookPullRequest `json:"pullRequest"` + Repository prCommentHookRepo `json:"repository"` + Actor prCommentHookUser `json:"actor"` + } ) // @@ -610,3 +821,71 @@ func convertPullRequestHook(src *webhook) *scm.PullRequestHook { }, } } + +func convertPrCommentHook(src *prCommentHook) *scm.IssueCommentHook { + namespace, _ := scm.Split(src.Repository.FullName) + dst := scm.IssueCommentHook{ + Repo: scm.Repository{ + ID: src.Repository.UUID, + Namespace: namespace, + Name: src.Repository.Name, + Clone: fmt.Sprintf("https://bitbucket.org/%s.git", src.Repository.FullName), + CloneSSH: fmt.Sprintf("git@bitbucket.org:%s.git", src.Repository.FullName), + Link: src.Repository.Links.HTML.Href, + Private: src.Repository.IsPrivate, + }, + Issue: scm.Issue{ + Number: src.PullRequest.ID, + Title: src.PullRequest.Title, + Body: src.PullRequest.Description, + Link: src.PullRequest.Links.Html.Href, + Author: scm.User{ + Login: src.PullRequest.Author.Username, + Name: src.PullRequest.Author.DisplayName, + Avatar: src.PullRequest.Author.Links.Avatar.Href, + }, + PullRequest: scm.PullRequest{ + Number: src.PullRequest.ID, + Title: src.PullRequest.Title, + Body: src.PullRequest.Description, + Sha: src.PullRequest.Source.Commit.Hash, + // Bitbucket does not support PR Refs: https://jira.atlassian.com/browse/BCLOUD-5814 + Ref: fmt.Sprintf("refs/pull-requests/%d/from", src.PullRequest.ID), + Source: src.PullRequest.Source.Branch.Name, + Target: src.PullRequest.Destination.Branch.Name, + Fork: src.PullRequest.Source.Repository.FullName, + Link: src.PullRequest.Links.Html.Href, + Closed: src.PullRequest.State != "OPEN", + Merged: src.PullRequest.State == "MERGED", + Author: scm.User{ + Login: src.PullRequest.Author.Username, + Name: src.PullRequest.Author.DisplayName, + Avatar: src.PullRequest.Author.Links.Avatar.Href, + }, + Created: src.PullRequest.CreatedOn, + Updated: src.PullRequest.UpdatedOn, + }, + Created: src.PullRequest.CreatedOn, + Updated: src.PullRequest.UpdatedOn, + }, + Comment: scm.Comment{ + ID: src.Comment.ID, + Body: src.Comment.Content.Raw, + Author: scm.User{ + ID: src.Comment.User.UUID, + Login: src.Comment.User.Username, + Name: src.Comment.User.DisplayName, + Avatar: src.Comment.User.Links.Avatar.Href, + }, + Created: src.Comment.CreatedOn, + Updated: src.Comment.UpdatedOn, + }, + Sender: scm.User{ + ID: src.Actor.UUID, + Login: src.Actor.Username, + Name: src.Actor.DisplayName, + Avatar: src.Actor.Links.Avatar.Href, + }, + } + return &dst +} diff --git a/scm/driver/bitbucket/webhook_test.go b/scm/driver/bitbucket/webhook_test.go index 9e633ed23..e72e096ff 100644 --- a/scm/driver/bitbucket/webhook_test.go +++ b/scm/driver/bitbucket/webhook_test.go @@ -132,6 +132,20 @@ func TestWebhooks(t *testing.T) { // after: "samples/pr_unlabeled.json.golden", // obj: new(scm.PullRequestHook), // }, + { + sig: "71295b197fa25f4356d2fb9965df3f2379d903d7", + event: "pullrequest:comment_created", + before: "testdata/webhooks/pr_comment_created.json", + after: "testdata/webhooks/pr_comment_created.json.golden", + obj: new(scm.IssueCommentHook), + }, + { + sig: "71295b197fa25f4356d2fb9965df3f2379d903d7", + event: "pullrequest:comment_deleted", + before: "testdata/webhooks/pr_comment_deleted.json", + after: "testdata/webhooks/pr_comment_deleted.json.golden", + obj: new(scm.IssueCommentHook), + }, } for _, test := range tests { diff --git a/scm/user.go b/scm/user.go index e1ea08fa5..fd448770a 100644 --- a/scm/user.go +++ b/scm/user.go @@ -12,6 +12,7 @@ import ( type ( // User represents a user account. User struct { + ID string Login string Name string Email string From 5f245ea841e985bef2cc34c456e73328cd95451c Mon Sep 17 00:00:00 2001 From: Rutvij Mehta Date: Thu, 30 Jun 2022 02:20:00 -0700 Subject: [PATCH 117/282] Update scm version 1.26.0 (#203) --- CHANGELOG.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 642d37d15..8bc4f787f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## [v1.26.0](https://github.com/drone/go-scm/tree/v1.26.0) (2022-07-01) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.25.0...v1.26.0) + +**Implemented enhancements:** + +- Support parsing PR comment events for Bitbucket Cloud [\#202](https://github.com/drone/go-scm/pull/202) ([rutvijmehta-harness](https://github.com/rutvijmehta-harness)) +- added issue comment hook support for Azure [\#200](https://github.com/drone/go-scm/pull/200) ([raghavharness](https://github.com/raghavharness)) + +**Fixed bugs:** + +- \[CI-4623\] - Azure webhook parseAPI changes [\#198](https://github.com/drone/go-scm/pull/198) ([raghavharness](https://github.com/raghavharness)) + +**Merged pull requests:** + +- Update scm version 1.26.0 [\#203](https://github.com/drone/go-scm/pull/203) ([rutvijmehta-harness](https://github.com/rutvijmehta-harness)) +- Fixed formatting in README.md [\#199](https://github.com/drone/go-scm/pull/199) ([hemanthmantri](https://github.com/hemanthmantri)) + ## [v1.25.0](https://github.com/drone/go-scm/tree/v1.25.0) (2022-06-16) [Full Changelog](https://github.com/drone/go-scm/compare/v1.24.0...v1.25.0) @@ -13,6 +31,10 @@ - \[PL-25889\]: fix list branches Azure API [\#195](https://github.com/drone/go-scm/pull/195) ([bhavya181](https://github.com/bhavya181)) - Return project specific hooks only in ListHooks API for Azure. [\#192](https://github.com/drone/go-scm/pull/192) ([raghavharness](https://github.com/raghavharness)) +**Merged pull requests:** + +- Update scm version 1.25.0 [\#197](https://github.com/drone/go-scm/pull/197) ([rutvijmehta-harness](https://github.com/rutvijmehta-harness)) + ## [v1.24.0](https://github.com/drone/go-scm/tree/v1.24.0) (2022-06-07) [Full Changelog](https://github.com/drone/go-scm/compare/v1.23.0...v1.24.0) From 9b81b04a4df2d9aa7ad8dd5d7127fe0a862c8899 Mon Sep 17 00:00:00 2001 From: raghavharness Date: Thu, 14 Jul 2022 19:13:11 +0530 Subject: [PATCH 118/282] using resource version 2.0 for Azure --- scm/driver/azure/repo.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scm/driver/azure/repo.go b/scm/driver/azure/repo.go index a590bffee..f46ede285 100644 --- a/scm/driver/azure/repo.go +++ b/scm/driver/azure/repo.go @@ -109,6 +109,10 @@ func (s *RepositoryService) CreateHook(ctx context.Context, repo string, input * if input.SkipVerify { in.ConsumerInputs.AcceptUntrustedCerts = "enabled" } + // with version 1.0, azure provides incomplete data for issue-comment + if in.EventType == "ms.vss-code.git-pullrequest-comment-event" { + in.ResourceVersion = "2.0" + } out := new(subscription) res, err := s.client.do(ctx, "POST", endpoint, in, out) return convertHook(out), res, err From 65018053d4317c83058a483ff815d2137092da09 Mon Sep 17 00:00:00 2001 From: Raghav Date: Tue, 19 Jul 2022 14:34:34 +0530 Subject: [PATCH 119/282] Update scm version 1.27.0 (#206) --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bc4f787f..2ccb06957 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [v1.27.0](https://github.com/drone/go-scm/tree/v1.27.0) (2022-07-18) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.26.0...v1.27.0) + +**Merged pull requests:** + +- Using resource version 2.0 for Azure [\#205](https://github.com/drone/go-scm/pull/205) ([raghavharness](https://github.com/raghavharness)) + ## [v1.26.0](https://github.com/drone/go-scm/tree/v1.26.0) (2022-07-01) [Full Changelog](https://github.com/drone/go-scm/compare/v1.25.0...v1.26.0) @@ -15,7 +23,6 @@ **Merged pull requests:** -- Update scm version 1.26.0 [\#203](https://github.com/drone/go-scm/pull/203) ([rutvijmehta-harness](https://github.com/rutvijmehta-harness)) - Fixed formatting in README.md [\#199](https://github.com/drone/go-scm/pull/199) ([hemanthmantri](https://github.com/hemanthmantri)) ## [v1.25.0](https://github.com/drone/go-scm/tree/v1.25.0) (2022-06-16) From 07b069c7f79af40bf6cdb2bd91022591477be0a6 Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Sun, 24 Jul 2022 17:36:52 -0400 Subject: [PATCH 120/282] gogs find commit for branch --- scm/driver/gogs/git.go | 9 +++++++++ scm/driver/gogs/git_test.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/scm/driver/gogs/git.go b/scm/driver/gogs/git.go index 2cb3c687e..1ab6dd8a2 100644 --- a/scm/driver/gogs/git.go +++ b/scm/driver/gogs/git.go @@ -28,6 +28,15 @@ func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Re } func (s *gitService) FindCommit(ctx context.Context, repo, ref string) (*scm.Commit, *scm.Response, error) { + // github and gitlab permit fetching a commit by sha + // or branch. This code emulates the github and gitlab + // behavior for gogs by fetching the commit sha for the + // branch and using in the subsequent API call. + if scm.IsHash(ref) == false { + if branch, _, err := s.FindBranch(ctx, repo, scm.TrimRef(ref)); err == nil { + ref = branch.Sha // replace ref with sha + } + } path := fmt.Sprintf("api/v1/repos/%s/commits/%s", repo, ref) out := new(commitDetail) res, err := s.client.do(ctx, "GET", path, nil, out) diff --git a/scm/driver/gogs/git_test.go b/scm/driver/gogs/git_test.go index 5b226e1db..9fe8d1322 100644 --- a/scm/driver/gogs/git_test.go +++ b/scm/driver/gogs/git_test.go @@ -44,6 +44,40 @@ func TestCommitFind(t *testing.T) { } } +func TestCommitFindBranch(t *testing.T) { + defer gock.Off() + + gock.New("https://try.gogs.io"). + Get("/api/v1/repos/gogits/gogs/branches/master"). + Reply(200). + Type("application/json"). + File("testdata/branch.json") + + gock.New("https://try.gogs.io"). + Get("/api/v1/repos/gogits/gogs/commits/f05f642b892d59a0a9ef6a31f6c905a24b5db13a"). + Reply(200). + Type("application/json"). + File("testdata/commits.json") + + client, _ := New("https://try.gogs.io") + got, _, err := client.Git.FindCommit( + context.Background(), + "gogits/gogs", + "master", + ) + if err != nil { + t.Error(err) + } + want := new(scm.Commit) + raw, _ := ioutil.ReadFile("testdata/commits.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + func TestCommitList(t *testing.T) { client, _ := New("https://try.gogs.io") _, _, err := client.Git.ListCommits(context.Background(), "gogits/gogs", scm.CommitListOptions{}) From c29b3f1156cd6fb200364177aa6accc631e74082 Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Sun, 24 Jul 2022 17:45:05 -0400 Subject: [PATCH 121/282] escape forward slashes in gitlab branch name --- scm/driver/gitlab/git.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scm/driver/gitlab/git.go b/scm/driver/gitlab/git.go index e9a1cffef..739621288 100644 --- a/scm/driver/gitlab/git.go +++ b/scm/driver/gitlab/git.go @@ -7,6 +7,8 @@ package gitlab import ( "context" "fmt" + "net/url" + "strings" "time" "github.com/drone/go-scm/scm" @@ -33,6 +35,11 @@ func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Re } func (s *gitService) FindCommit(ctx context.Context, repo, ref string) (*scm.Commit, *scm.Response, error) { + // if the reference is a branch, ensure forward slashes + // in the branch name are escaped. + if strings.Contains("ref", "/") { + ref = url.PathEscape(ref) + } path := fmt.Sprintf("api/v4/projects/%s/repository/commits/%s", encode(repo), scm.TrimRef(ref)) out := new(commit) res, err := s.client.do(ctx, "GET", path, nil, out) From 99b9843dc4d6ad9a033a3c160f4e143a90637b98 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Tue, 26 Jul 2022 11:00:18 +0100 Subject: [PATCH 122/282] (maint) fixing naming and add more go best practice --- .drone.yml | 33 ++++- .golangci.yml | 130 ++++++++++++++++++ .../{testSettings.go => integration.go} | 0 .../{testSettings.go => integration.go} | 0 4 files changed, 159 insertions(+), 4 deletions(-) create mode 100644 .golangci.yml rename scm/driver/azure/integration/{testSettings.go => integration.go} (100%) rename scm/driver/stash/integration/{testSettings.go => integration.go} (100%) diff --git a/.drone.yml b/.drone.yml index 6636d8200..2c3b73492 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,11 +1,10 @@ --- kind: pipeline -type: docker +type: vm name: default -platform: - os: linux - arch: amd64 +pool: + use: ubuntu steps: - name: vet @@ -15,6 +14,8 @@ steps: volumes: - name: gopath path: /go + depends_on: + - clone - name: test image: golang:1.15 @@ -23,6 +24,30 @@ steps: volumes: - name: gopath path: /go + depends_on: + - vet + +- name: check go.mod is up to date + image: golang:1.15 + commands: + - cp go.mod go.mod.bak + - go mod tidy + - diff go.mod go.mod.bak || (echo "go.mod is not up to date" && exit 1) + volumes: + - name: gopath + path: /go + depends_on: + - vet + +- name: golangci-lint + image: golangci/golangci-lint + commands: + - golangci-lint run --timeout 500s --new-from-rev=HEAD~ + volumes: + - name: gopath + path: /go + depends_on: + - clone volumes: - name: gopath diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 000000000..1ca20e4a8 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,130 @@ +linters-settings: + dupl: + threshold: 100 + funlen: + lines: 400 + statements: 100 + gci: + local-prefixes: github.com/golangci/golangci-lint + goconst: + min-len: 3 + min-occurrences: 3 + gocritic: + enabled-tags: + - diagnostic + - experimental + - opinionated + - performance + - style + disabled-checks: + - dupImport # https://github.com/go-critic/go-critic/issues/845 + - ifElseChain + - octalLiteral + - whyNoLint + - wrapperFunc + gocyclo: + min-complexity: 25 + goimports: + local-prefixes: github.com/golangci/golangci-lint + gomnd: + settings: + mnd: + # don't include the "operation" and "assign" + checks: argument,case,condition,return + govet: + check-shadowing: true + settings: + printf: + funcs: + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf + lll: + line-length: 200 + maligned: + suggest-new: true + misspell: + locale: US + nolintlint: + allow-leading-space: true # don't require machine-readable nolint directives (i.e. with no leading space) + allow-unused: false # report any unused nolint directives + require-explanation: false # don't require an explanation for nolint directives + require-specific: false # don't require nolint directives to be specific about which linter is being skipped + nakedret: + max-func-lines: 100 + +linters: + # please, do not use `enable-all`: it's deprecated and will be removed soon. + # inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint + disable-all: true + enable: + - bodyclose + - deadcode + - depguard + - dogsled + - errcheck + - exportloopref + - exhaustive + - funlen + - gochecknoinits + - goconst + - gocritic + - gocyclo + - gofmt + - goimports + - gomnd + - goprintffuncname + - gosec + - gosimple + - govet + - ineffassign + - lll + - misspell + - nakedret + - noctx + - nolintlint + - revive + - rowserrcheck + - staticcheck + - structcheck + - stylecheck + - typecheck + - unconvert + - unparam + - unused + - varcheck + - whitespace + + # don't enable: + # - asciicheck + # - dupl + # - scopelint + # - gochecknoglobals + # - gocognit + # - godot + # - godox + # - goerr113 + # - interfacer + # - maligned + # - nestif + # - prealloc + # - testpackage + # - revive + # - wsl + +issues: + # Excluding configuration per-path, per-linter, per-text and per-source + exclude-rules: + - path: _test\.go + linters: + - gomnd + + # https://github.com/go-critic/go-critic/issues/926 + - linters: + - gocritic + text: "unnecessaryDefer:" + +run: + skip-files: + - _gen\.go diff --git a/scm/driver/azure/integration/testSettings.go b/scm/driver/azure/integration/integration.go similarity index 100% rename from scm/driver/azure/integration/testSettings.go rename to scm/driver/azure/integration/integration.go diff --git a/scm/driver/stash/integration/testSettings.go b/scm/driver/stash/integration/integration.go similarity index 100% rename from scm/driver/stash/integration/testSettings.go rename to scm/driver/stash/integration/integration.go From 6024f33534850c0a9c6f03a90d8d8139aa18f480 Mon Sep 17 00:00:00 2001 From: Bhavya Agrawal Date: Thu, 4 Aug 2022 19:44:57 +0530 Subject: [PATCH 123/282] [PL-26239]: added api to list installation for github app --- scm/driver/github/repo.go | 8 ++++++++ scm/driver/github/repo_test.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/scm/driver/github/repo.go b/scm/driver/github/repo.go index f5a9c5140..9a38e9071 100644 --- a/scm/driver/github/repo.go +++ b/scm/driver/github/repo.go @@ -105,6 +105,14 @@ func (s *RepositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* return convertRepositoryList(out), res, err } +// List returns the githubapp installation list. +func (s *RepositoryService) ListAppInstallations(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { + path := fmt.Sprintf("installation/repositories?%s", encodeListOptions(opts)) + out := []*repository{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertRepositoryList(out), res, err +} + // ListHooks returns a list or repository hooks. func (s *RepositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { path := fmt.Sprintf("repos/%s/hooks?%s", repo, encodeListOptions(opts)) diff --git a/scm/driver/github/repo_test.go b/scm/driver/github/repo_test.go index caa93b45f..0131e89f9 100644 --- a/scm/driver/github/repo_test.go +++ b/scm/driver/github/repo_test.go @@ -131,6 +131,40 @@ func TestRepositoryList(t *testing.T) { t.Run("Page", testPage(res)) } +func TestGithubAppInstallationList(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Get("/installation/repositories"). + MatchParam("page", "1"). + MatchParam("per_page", "30"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + SetHeaders(mockPageHeaders). + File("testdata/repos.json") + + client := NewDefault() + got, res, err := client.Repositories.(*RepositoryService).ListAppInstallations(context.Background(), scm.ListOptions{Page: 1, Size: 30}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Repository{} + raw, _ := ioutil.ReadFile("testdata/repos.json.golden") + _ = json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) + t.Run("Page", testPage(res)) +} + func TestStatusList(t *testing.T) { defer gock.Off() From f481597b5e2a727112c912b58c94bf4e70801aa8 Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Sun, 7 Aug 2022 13:00:21 -0400 Subject: [PATCH 124/282] adopt golangci config from Rancher project --- .golangci.json | 51 +++++++++++++++++++ .golangci.yml | 130 ------------------------------------------------- 2 files changed, 51 insertions(+), 130 deletions(-) create mode 100644 .golangci.json delete mode 100644 .golangci.yml diff --git a/.golangci.json b/.golangci.json new file mode 100644 index 000000000..dc836dacc --- /dev/null +++ b/.golangci.json @@ -0,0 +1,51 @@ +{ + "linters": { + "disable-all": true, + "enable": [ + "govet", + "revive", + "goimports", + "misspell", + "ineffassign", + "gofmt" + ] + }, + "linters-settings": { + "govet": { + "check-shadowing": false + }, + "gofmt": { + "simplify": false + } + }, + "run": { + "skip-dirs": [ + "vendor", + "tests", + "pkg/client", + "pkg/generated" + ], + "tests": false, + "timeout": "10m" + }, + "issues": { + "exclude-rules": [ + { + "linters": "govet", + "text": "^(nilness|structtag)" + }, + { + "linters": "revive", + "text": "should have comment" + }, + { + "linters": "revive", + "text": "should be of the form" + }, + { + "linters": "typecheck", + "text": "imported but not used as apierrors" + } + ] + } +} diff --git a/.golangci.yml b/.golangci.yml deleted file mode 100644 index 1ca20e4a8..000000000 --- a/.golangci.yml +++ /dev/null @@ -1,130 +0,0 @@ -linters-settings: - dupl: - threshold: 100 - funlen: - lines: 400 - statements: 100 - gci: - local-prefixes: github.com/golangci/golangci-lint - goconst: - min-len: 3 - min-occurrences: 3 - gocritic: - enabled-tags: - - diagnostic - - experimental - - opinionated - - performance - - style - disabled-checks: - - dupImport # https://github.com/go-critic/go-critic/issues/845 - - ifElseChain - - octalLiteral - - whyNoLint - - wrapperFunc - gocyclo: - min-complexity: 25 - goimports: - local-prefixes: github.com/golangci/golangci-lint - gomnd: - settings: - mnd: - # don't include the "operation" and "assign" - checks: argument,case,condition,return - govet: - check-shadowing: true - settings: - printf: - funcs: - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf - - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf - lll: - line-length: 200 - maligned: - suggest-new: true - misspell: - locale: US - nolintlint: - allow-leading-space: true # don't require machine-readable nolint directives (i.e. with no leading space) - allow-unused: false # report any unused nolint directives - require-explanation: false # don't require an explanation for nolint directives - require-specific: false # don't require nolint directives to be specific about which linter is being skipped - nakedret: - max-func-lines: 100 - -linters: - # please, do not use `enable-all`: it's deprecated and will be removed soon. - # inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint - disable-all: true - enable: - - bodyclose - - deadcode - - depguard - - dogsled - - errcheck - - exportloopref - - exhaustive - - funlen - - gochecknoinits - - goconst - - gocritic - - gocyclo - - gofmt - - goimports - - gomnd - - goprintffuncname - - gosec - - gosimple - - govet - - ineffassign - - lll - - misspell - - nakedret - - noctx - - nolintlint - - revive - - rowserrcheck - - staticcheck - - structcheck - - stylecheck - - typecheck - - unconvert - - unparam - - unused - - varcheck - - whitespace - - # don't enable: - # - asciicheck - # - dupl - # - scopelint - # - gochecknoglobals - # - gocognit - # - godot - # - godox - # - goerr113 - # - interfacer - # - maligned - # - nestif - # - prealloc - # - testpackage - # - revive - # - wsl - -issues: - # Excluding configuration per-path, per-linter, per-text and per-source - exclude-rules: - - path: _test\.go - linters: - - gomnd - - # https://github.com/go-critic/go-critic/issues/926 - - linters: - - gocritic - text: "unnecessaryDefer:" - -run: - skip-files: - - _gen\.go From b9de5f548dc9d9d644f6bd9dc8fb279859150355 Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Sun, 7 Aug 2022 13:06:30 -0400 Subject: [PATCH 125/282] pin golangci version to use image from docker cache --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 2c3b73492..74ace6a27 100644 --- a/.drone.yml +++ b/.drone.yml @@ -40,7 +40,7 @@ steps: - vet - name: golangci-lint - image: golangci/golangci-lint + image: golangci/golangci-lint:v1.48-alpine commands: - golangci-lint run --timeout 500s --new-from-rev=HEAD~ volumes: From 3edbe5560fdc172e093e6214196ee37ce516152d Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Sun, 7 Aug 2022 13:12:09 -0400 Subject: [PATCH 126/282] upate function to match convention List[By] where By is singular --- scm/driver/github/repo.go | 4 ++-- scm/driver/github/repo_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scm/driver/github/repo.go b/scm/driver/github/repo.go index 9a38e9071..965b91253 100644 --- a/scm/driver/github/repo.go +++ b/scm/driver/github/repo.go @@ -105,8 +105,8 @@ func (s *RepositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* return convertRepositoryList(out), res, err } -// List returns the githubapp installation list. -func (s *RepositoryService) ListAppInstallations(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { +// List returns the github app installation repository list. +func (s *RepositoryService) ListInstallation(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { path := fmt.Sprintf("installation/repositories?%s", encodeListOptions(opts)) out := []*repository{} res, err := s.client.do(ctx, "GET", path, nil, &out) diff --git a/scm/driver/github/repo_test.go b/scm/driver/github/repo_test.go index 0131e89f9..439a8797f 100644 --- a/scm/driver/github/repo_test.go +++ b/scm/driver/github/repo_test.go @@ -145,7 +145,7 @@ func TestGithubAppInstallationList(t *testing.T) { File("testdata/repos.json") client := NewDefault() - got, res, err := client.Repositories.(*RepositoryService).ListAppInstallations(context.Background(), scm.ListOptions{Page: 1, Size: 30}) + got, res, err := client.Repositories.(*RepositoryService).ListInstallation(context.Background(), scm.ListOptions{Page: 1, Size: 30}) if err != nil { t.Error(err) return From 43b3e0a4fc1adf61ff946c8790cc11451d521871 Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Sun, 7 Aug 2022 23:49:16 -0400 Subject: [PATCH 127/282] update list (by) installation name --- scm/driver/github/repo.go | 2 +- scm/driver/github/repo_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scm/driver/github/repo.go b/scm/driver/github/repo.go index 965b91253..b1cdc7290 100644 --- a/scm/driver/github/repo.go +++ b/scm/driver/github/repo.go @@ -106,7 +106,7 @@ func (s *RepositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* } // List returns the github app installation repository list. -func (s *RepositoryService) ListInstallation(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { +func (s *RepositoryService) ListByInstallation(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { path := fmt.Sprintf("installation/repositories?%s", encodeListOptions(opts)) out := []*repository{} res, err := s.client.do(ctx, "GET", path, nil, &out) diff --git a/scm/driver/github/repo_test.go b/scm/driver/github/repo_test.go index 439a8797f..67cbec69a 100644 --- a/scm/driver/github/repo_test.go +++ b/scm/driver/github/repo_test.go @@ -145,7 +145,7 @@ func TestGithubAppInstallationList(t *testing.T) { File("testdata/repos.json") client := NewDefault() - got, res, err := client.Repositories.(*RepositoryService).ListInstallation(context.Background(), scm.ListOptions{Page: 1, Size: 30}) + got, res, err := client.Repositories.(*RepositoryService).ListByInstallation(context.Background(), scm.ListOptions{Page: 1, Size: 30}) if err != nil { t.Error(err) return From 09a4fde5917cd635f693534d742ea605fcc5de56 Mon Sep 17 00:00:00 2001 From: Mohit Garg Date: Wed, 17 Aug 2022 21:32:04 +0530 Subject: [PATCH 128/282] Added support for branch in list commits bb onprem API (#215) * added support for branch in list commits bb onprem API --- scm/driver/stash/git.go | 4 +- scm/driver/stash/git_test.go | 1 + scm/driver/stash/integration/git_test.go | 54 ++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/scm/driver/stash/git.go b/scm/driver/stash/git.go index 2c38c4cd4..c3576c1f0 100644 --- a/scm/driver/stash/git.go +++ b/scm/driver/stash/git.go @@ -83,9 +83,9 @@ func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.Comm namespace, name := scm.Split(repo) var requestPath string if opts.Path != "" { - requestPath = fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/commits?path=%s", namespace, name, opts.Path) + requestPath = fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/commits?until=%s&path=%s", namespace, name, opts.Ref, opts.Path) } else { - requestPath = fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/commits", namespace, name) + requestPath = fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/commits?until=%s", namespace, name, opts.Ref) } out := new(commits) res, err := s.client.do(ctx, "GET", requestPath, nil, out) diff --git a/scm/driver/stash/git_test.go b/scm/driver/stash/git_test.go index dfa37bfba..bf4d8e990 100644 --- a/scm/driver/stash/git_test.go +++ b/scm/driver/stash/git_test.go @@ -98,6 +98,7 @@ func TestGitListCommits(t *testing.T) { gock.New("http://example.com:7990"). Get("/rest/api/1.0/projects/PRJ/repos/my-repo/commits"). + MatchParam("until", ""). Reply(200). Type("application/json"). File("testdata/commits.json") diff --git a/scm/driver/stash/integration/git_test.go b/scm/driver/stash/integration/git_test.go index bd5933f25..6b4c18b82 100644 --- a/scm/driver/stash/integration/git_test.go +++ b/scm/driver/stash/integration/git_test.go @@ -62,3 +62,57 @@ func TestGetLatestCommitOfBranch(t *testing.T) { } } } + +func TestGetLatestCommitOfNonDefaultBranch(t *testing.T) { + if token == "" { + t.Skip("Skipping, Acceptance test") + } + client, _ = stash.New(endpoint) + client.Client = &http.Client{ + Transport: &transport.BasicAuth{ + Username: username, + Password: token, + }, + } + + commits, response, err := client.Git.ListCommits(context.Background(), repoID, scm.CommitListOptions{Ref: "main", Path: "do-not-touch.txt"}) + + if err != nil { + t.Errorf("GetLatestCommitOfFile got an error %v", err) + } else { + if response.Status != http.StatusOK { + t.Errorf("GetLatestCommitOfFile did not get a 200 back %v", response.Status) + } + + if commits[0].Sha != "76fb1762048a277596d3fa330b3da140cd12d361" { + t.Errorf("Got the commitId %s instead of the top commit of the file", commits[0].Sha) + } + } +} + +func TestGetLatestCommitOfBranchWhenNoRefPassed(t *testing.T) { + if token == "" { + t.Skip("Skipping, Acceptance test") + } + client, _ = stash.New(endpoint) + client.Client = &http.Client{ + Transport: &transport.BasicAuth{ + Username: username, + Password: token, + }, + } + + commits, response, err := client.Git.ListCommits(context.Background(), repoID, scm.CommitListOptions{Path: "README"}) + + if err != nil { + t.Errorf("GetLatestCommitOfFile got an error %v", err) + } else { + if response.Status != http.StatusOK { + t.Errorf("GetLatestCommitOfFile did not get a 200 back %v", response.Status) + } + + if commits[0].Sha != "2cc4dbe084f0d66761318b305c408cb0ea300c9a" { + t.Errorf("Got the commitId %s instead of the top commit of the file", commits[0].Sha) + } + } +} \ No newline at end of file From b83308fa5a3bb9ab72da898661d57cf7b55c9694 Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Tue, 23 Aug 2022 11:49:39 -0400 Subject: [PATCH 129/282] fix naming convention for CreateBranch Input --- scm/driver/azure/git.go | 2 +- scm/driver/azure/git_test.go | 2 +- scm/driver/azure/integration/git_test.go | 2 +- scm/driver/bitbucket/git.go | 2 +- scm/driver/bitbucket/git_test.go | 2 +- scm/driver/gitea/git.go | 2 +- scm/driver/gitee/git.go | 2 +- scm/driver/gitee/git_test.go | 2 +- scm/driver/github/git.go | 2 +- scm/driver/github/git_test.go | 2 +- scm/driver/gitlab/git.go | 2 +- scm/driver/gitlab/git_test.go | 2 +- scm/driver/gogs/git.go | 2 +- scm/driver/stash/git.go | 2 +- scm/driver/stash/git_test.go | 2 +- scm/driver/stash/integration/git_test.go | 4 ++-- scm/git.go | 16 ++++++++++------ 17 files changed, 27 insertions(+), 23 deletions(-) diff --git a/scm/driver/azure/git.go b/scm/driver/azure/git.go index 5aa41b07f..b23a0f7d7 100644 --- a/scm/driver/azure/git.go +++ b/scm/driver/azure/git.go @@ -16,7 +16,7 @@ type gitService struct { client *wrapper } -func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.CreateBranch) (*scm.Response, error) { +func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.ReferenceInput) (*scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/refs/update-refs?view=azure-devops-rest-6.0 if s.client.project == "" { return nil, ProjectRequiredError() diff --git a/scm/driver/azure/git_test.go b/scm/driver/azure/git_test.go index 0e652eca2..d5faf0ef7 100644 --- a/scm/driver/azure/git_test.go +++ b/scm/driver/azure/git_test.go @@ -53,7 +53,7 @@ func TestGitCreateBranch(t *testing.T) { Type("application/json"). File("testdata/branch_create.json") - params := &scm.CreateBranch{ + params := &scm.ReferenceInput{ Name: "test_branch", Sha: "312797ba52425353dec56871a255e2a36fc96344", } diff --git a/scm/driver/azure/integration/git_test.go b/scm/driver/azure/integration/git_test.go index ce9eefca6..aeb9f41b8 100644 --- a/scm/driver/azure/integration/git_test.go +++ b/scm/driver/azure/integration/git_test.go @@ -54,7 +54,7 @@ func TestCreateBranch(t *testing.T) { if commitErr != nil { t.Errorf("we got an error %v", commitErr) } - input := &scm.CreateBranch{ + input := &scm.ReferenceInput{ Name: "test_branch", Sha: currentCommit, } diff --git a/scm/driver/bitbucket/git.go b/scm/driver/bitbucket/git.go index 03093c5bc..4a2298d59 100644 --- a/scm/driver/bitbucket/git.go +++ b/scm/driver/bitbucket/git.go @@ -16,7 +16,7 @@ type gitService struct { client *wrapper } -func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.CreateBranch) (*scm.Response, error) { +func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.ReferenceInput) (*scm.Response, error) { path := fmt.Sprintf("2.0/repositories/%s/refs/branches", repo) in := &createBranch{ Name: params.Name, diff --git a/scm/driver/bitbucket/git_test.go b/scm/driver/bitbucket/git_test.go index 7e666772c..ec3b49f43 100644 --- a/scm/driver/bitbucket/git_test.go +++ b/scm/driver/bitbucket/git_test.go @@ -81,7 +81,7 @@ func TestGitCreateBranch(t *testing.T) { Type("application/json"). File("testdata/branch_create.json") - params := &scm.CreateBranch{ + params := &scm.ReferenceInput{ Name: "yooo", Sha: "2e684d13a43afd86cb48ea36d9f40f43e791fae9", } diff --git a/scm/driver/gitea/git.go b/scm/driver/gitea/git.go index 8382b8cad..60de87bec 100644 --- a/scm/driver/gitea/git.go +++ b/scm/driver/gitea/git.go @@ -17,7 +17,7 @@ type gitService struct { client *wrapper } -func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.CreateBranch) (*scm.Response, error) { +func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.ReferenceInput) (*scm.Response, error) { return nil, scm.ErrNotSupported } diff --git a/scm/driver/gitee/git.go b/scm/driver/gitee/git.go index 6b2933b67..ffbd5c0e2 100644 --- a/scm/driver/gitee/git.go +++ b/scm/driver/gitee/git.go @@ -16,7 +16,7 @@ type gitService struct { client *wrapper } -func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.CreateBranch) (*scm.Response, error) { +func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.ReferenceInput) (*scm.Response, error) { path := fmt.Sprintf("repos/%s/branches", repo) in := &branchCreate{ Refs: params.Sha, diff --git a/scm/driver/gitee/git_test.go b/scm/driver/gitee/git_test.go index b62cd951c..bdceb7634 100644 --- a/scm/driver/gitee/git_test.go +++ b/scm/driver/gitee/git_test.go @@ -26,7 +26,7 @@ func TestGitCreateBranch(t *testing.T) { SetHeaders(mockHeaders) client := NewDefault() - input := scm.CreateBranch{ + input := scm.ReferenceInput{ Name: "create-by-api", Sha: "b72a4c4a2d838d96a545a42d41d7776ae5566f4a", } diff --git a/scm/driver/github/git.go b/scm/driver/github/git.go index 0ef94db44..5a5829f4d 100644 --- a/scm/driver/github/git.go +++ b/scm/driver/github/git.go @@ -16,7 +16,7 @@ type gitService struct { client *wrapper } -func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.CreateBranch) (*scm.Response, error) { +func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.ReferenceInput) (*scm.Response, error) { path := fmt.Sprintf("repos/%s/git/refs", repo) in := &createBranch{ Ref: scm.ExpandRef(params.Name, "refs/heads"), diff --git a/scm/driver/github/git_test.go b/scm/driver/github/git_test.go index 65c2562c9..36e18e77f 100644 --- a/scm/driver/github/git_test.go +++ b/scm/driver/github/git_test.go @@ -116,7 +116,7 @@ func TestGitCreateBranch(t *testing.T) { SetHeaders(mockHeaders). File("testdata/branch_create.json") - params := &scm.CreateBranch{ + params := &scm.ReferenceInput{ Name: "Hello", Sha: "312797ba52425353dec56871a255e2a36fc96344", } diff --git a/scm/driver/gitlab/git.go b/scm/driver/gitlab/git.go index 739621288..ebada6c99 100644 --- a/scm/driver/gitlab/git.go +++ b/scm/driver/gitlab/git.go @@ -18,7 +18,7 @@ type gitService struct { client *wrapper } -func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.CreateBranch) (*scm.Response, error) { +func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.ReferenceInput) (*scm.Response, error) { path := fmt.Sprintf("api/v4/projects/%s/repository/branches", encode(repo)) in := &createBranch{ Branch: params.Name, diff --git a/scm/driver/gitlab/git_test.go b/scm/driver/gitlab/git_test.go index 6315b85b9..32d58f6f2 100644 --- a/scm/driver/gitlab/git_test.go +++ b/scm/driver/gitlab/git_test.go @@ -90,7 +90,7 @@ func TestGitCreateBranch(t *testing.T) { SetHeaders(mockHeaders). File("testdata/branch_create.json") - params := &scm.CreateBranch{ + params := &scm.ReferenceInput{ Name: "yooo", Sha: "0efb1bed7c6a4871cb4ddb862ecc2111e11f31ee", } diff --git a/scm/driver/gogs/git.go b/scm/driver/gogs/git.go index 1ab6dd8a2..aaf6a0616 100644 --- a/scm/driver/gogs/git.go +++ b/scm/driver/gogs/git.go @@ -16,7 +16,7 @@ type gitService struct { client *wrapper } -func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.CreateBranch) (*scm.Response, error) { +func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.ReferenceInput) (*scm.Response, error) { return nil, scm.ErrNotSupported } diff --git a/scm/driver/stash/git.go b/scm/driver/stash/git.go index c3576c1f0..dece5d940 100644 --- a/scm/driver/stash/git.go +++ b/scm/driver/stash/git.go @@ -19,7 +19,7 @@ type gitService struct { client *wrapper } -func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.CreateBranch) (*scm.Response, error) { +func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.ReferenceInput) (*scm.Response, error) { namespace, repoName := scm.Split(repo) path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/branches", namespace, repoName) in := &createBranch{ diff --git a/scm/driver/stash/git_test.go b/scm/driver/stash/git_test.go index bf4d8e990..4d92fec4e 100644 --- a/scm/driver/stash/git_test.go +++ b/scm/driver/stash/git_test.go @@ -239,7 +239,7 @@ func TestCreateBranch(t *testing.T) { File("testdata/branch_create.json") client, _ := New("http://example.com:7990") - params := &scm.CreateBranch{ + params := &scm.ReferenceInput{ Name: "Hello", Sha: "312797ba52425353dec56871a255e2a36fc96344", } diff --git a/scm/driver/stash/integration/git_test.go b/scm/driver/stash/integration/git_test.go index 6b4c18b82..6ef33fee7 100644 --- a/scm/driver/stash/integration/git_test.go +++ b/scm/driver/stash/integration/git_test.go @@ -23,7 +23,7 @@ func TestCreateBranch(t *testing.T) { } commitId, _ := GetCurrentCommitOfBranch(client, "master") - input := &scm.CreateBranch{ + input := &scm.ReferenceInput{ Name: "test_branch", Sha: commitId, } @@ -115,4 +115,4 @@ func TestGetLatestCommitOfBranchWhenNoRefPassed(t *testing.T) { t.Errorf("Got the commitId %s instead of the top commit of the file", commits[0].Sha) } } -} \ No newline at end of file +} diff --git a/scm/git.go b/scm/git.go index 07811b1fc..eff476038 100644 --- a/scm/git.go +++ b/scm/git.go @@ -13,16 +13,16 @@ import ( const EmptyCommit = "0000000000000000000000000000000000000000" type ( - // CreateBranch provides a SHA for creating a branch. - CreateBranch struct { + // Reference represents a git reference. + Reference struct { Name string + Path string Sha string } - // Reference represents a git reference. - Reference struct { + // ReferenceInput provides a SHA for creating a reference. + ReferenceInput struct { Name string - Path string Sha string } @@ -59,7 +59,7 @@ type ( // GitService provides access to git resources. GitService interface { // CreateBranch creates a git branch by name given a sha. - CreateBranch(ctx context.Context, repo string, params *CreateBranch) (*Response, error) + CreateBranch(ctx context.Context, repo string, params *ReferenceInput) (*Response, error) // FindBranch finds a git branch by name. FindBranch(ctx context.Context, repo, name string) (*Reference, *Response, error) @@ -88,4 +88,8 @@ type ( // return a 2-way or 3-way diff changeset. CompareChanges(ctx context.Context, repo, source, target string, opts ListOptions) ([]*Change, *Response, error) } + + // CreateBranch is a type alias for upstream projects + // that use the previous CreateBranch type name. + CreateBranch = ReferenceInput ) From f4a311024d4ece31370f2bd1bf90d0248852e57a Mon Sep 17 00:00:00 2001 From: Bhavya Agrawal Date: Fri, 26 Aug 2022 16:12:21 +0530 Subject: [PATCH 130/282] [PL-26239]: fix for list response (#218) * [PL-26239]: fix for list response --- scm/driver/github/repo.go | 11 +- scm/driver/github/repo_test.go | 2 +- .../github/testdata/github_app_repos.json | 115 ++++++++++++++++++ 3 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 scm/driver/github/testdata/github_app_repos.json diff --git a/scm/driver/github/repo.go b/scm/driver/github/repo.go index b1cdc7290..cc781cb92 100644 --- a/scm/driver/github/repo.go +++ b/scm/driver/github/repo.go @@ -53,6 +53,11 @@ type hook struct { } `json:"config"` } +type repositoryList struct { + TotalCount int `json:"total_count"` + Repositories []*repository `json:"repositories"` +} + // RepositoryService implements the repository service for // the GitHub driver. type RepositoryService struct { @@ -108,9 +113,9 @@ func (s *RepositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* // List returns the github app installation repository list. func (s *RepositoryService) ListByInstallation(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { path := fmt.Sprintf("installation/repositories?%s", encodeListOptions(opts)) - out := []*repository{} - res, err := s.client.do(ctx, "GET", path, nil, &out) - return convertRepositoryList(out), res, err + out := new(repositoryList) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertRepositoryList(out.Repositories), res, err } // ListHooks returns a list or repository hooks. diff --git a/scm/driver/github/repo_test.go b/scm/driver/github/repo_test.go index 67cbec69a..cd1d7f8b3 100644 --- a/scm/driver/github/repo_test.go +++ b/scm/driver/github/repo_test.go @@ -142,7 +142,7 @@ func TestGithubAppInstallationList(t *testing.T) { Type("application/json"). SetHeaders(mockHeaders). SetHeaders(mockPageHeaders). - File("testdata/repos.json") + File("testdata/github_app_repos.json") client := NewDefault() got, res, err := client.Repositories.(*RepositoryService).ListByInstallation(context.Background(), scm.ListOptions{Page: 1, Size: 30}) diff --git a/scm/driver/github/testdata/github_app_repos.json b/scm/driver/github/testdata/github_app_repos.json new file mode 100644 index 000000000..2526a4000 --- /dev/null +++ b/scm/driver/github/testdata/github_app_repos.json @@ -0,0 +1,115 @@ +{ + "total_count": 1, + "repositories": [ + { + "id": 1296269, + "owner": { + "login": "octocat", + "id": 1, + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "name": "Hello-World", + "full_name": "octocat/Hello-World", + "description": "This your first repo!", + "private": true, + "fork": true, + "visibility": "public", + "url": "https://api.github.com/repos/octocat/Hello-World", + "html_url": "https://github.com/octocat/Hello-World", + "archive_url": "http://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", + "assignees_url": "http://api.github.com/repos/octocat/Hello-World/assignees{/user}", + "blobs_url": "http://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", + "branches_url": "http://api.github.com/repos/octocat/Hello-World/branches{/branch}", + "clone_url": "https://github.com/octocat/Hello-World.git", + "collaborators_url": "http://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", + "comments_url": "http://api.github.com/repos/octocat/Hello-World/comments{/number}", + "commits_url": "http://api.github.com/repos/octocat/Hello-World/commits{/sha}", + "compare_url": "http://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", + "contents_url": "http://api.github.com/repos/octocat/Hello-World/contents/{+path}", + "contributors_url": "http://api.github.com/repos/octocat/Hello-World/contributors", + "deployments_url": "http://api.github.com/repos/octocat/Hello-World/deployments", + "downloads_url": "http://api.github.com/repos/octocat/Hello-World/downloads", + "events_url": "http://api.github.com/repos/octocat/Hello-World/events", + "forks_url": "http://api.github.com/repos/octocat/Hello-World/forks", + "git_commits_url": "http://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", + "git_refs_url": "http://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", + "git_tags_url": "http://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", + "git_url": "git:github.com/octocat/Hello-World.git", + "hooks_url": "http://api.github.com/repos/octocat/Hello-World/hooks", + "issue_comment_url": "http://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", + "issue_events_url": "http://api.github.com/repos/octocat/Hello-World/issues/events{/number}", + "issues_url": "http://api.github.com/repos/octocat/Hello-World/issues{/number}", + "keys_url": "http://api.github.com/repos/octocat/Hello-World/keys{/key_id}", + "labels_url": "http://api.github.com/repos/octocat/Hello-World/labels{/name}", + "languages_url": "http://api.github.com/repos/octocat/Hello-World/languages", + "merges_url": "http://api.github.com/repos/octocat/Hello-World/merges", + "milestones_url": "http://api.github.com/repos/octocat/Hello-World/milestones{/number}", + "mirror_url": "git:git.example.com/octocat/Hello-World", + "notifications_url": "http://api.github.com/repos/octocat/Hello-World/notifications{?since, all, participating}", + "pulls_url": "http://api.github.com/repos/octocat/Hello-World/pulls{/number}", + "releases_url": "http://api.github.com/repos/octocat/Hello-World/releases{/id}", + "ssh_url": "git@github.com:octocat/Hello-World.git", + "stargazers_url": "http://api.github.com/repos/octocat/Hello-World/stargazers", + "statuses_url": "http://api.github.com/repos/octocat/Hello-World/statuses/{sha}", + "subscribers_url": "http://api.github.com/repos/octocat/Hello-World/subscribers", + "subscription_url": "http://api.github.com/repos/octocat/Hello-World/subscription", + "svn_url": "https://svn.github.com/octocat/Hello-World", + "tags_url": "http://api.github.com/repos/octocat/Hello-World/tags", + "teams_url": "http://api.github.com/repos/octocat/Hello-World/teams", + "trees_url": "http://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", + "homepage": "https://github.com", + "language": null, + "forks_count": 9, + "stargazers_count": 80, + "watchers_count": 80, + "size": 108, + "default_branch": "master", + "open_issues_count": 0, + "topics": [ + "octocat", + "atom", + "electron", + "API" + ], + "has_issues": true, + "has_wiki": true, + "has_pages": false, + "has_downloads": true, + "archived": false, + "pushed_at": "2011-01-26T19:06:43Z", + "created_at": "2011-01-26T19:01:12Z", + "updated_at": "2011-01-26T19:14:43Z", + "permissions": { + "admin": true, + "push": true, + "pull": true + }, + "allow_rebase_merge": true, + "allow_squash_merge": true, + "allow_merge_commit": true, + "subscribers_count": 42, + "network_count": 0, + "license": { + "key": "mit", + "name": "MIT License", + "spdx_id": "MIT", + "url": "https://api.github.com/licenses/mit", + "html_url": "http://choosealicense.com/licenses/mit/" + } + } + ] +} \ No newline at end of file From c43e9f0b54ad9b669a7b36283efc9a53dcd35767 Mon Sep 17 00:00:00 2001 From: Raghav Date: Mon, 5 Sep 2022 15:59:42 +0530 Subject: [PATCH 131/282] added date info for commits in push hook (#223) * added date info for commits in push hook --- .../testdata/webhooks/branch_create.json | 2 +- .../webhooks/branch_create.json.golden | 4 +- scm/driver/gitlab/testdata/webhooks/push.json | 2 +- .../gitlab/testdata/webhooks/push.json.golden | 4 +- .../gitlab/testdata/webhooks/tag_create.json | 2 +- .../testdata/webhooks/tag_create.json.golden | 4 +- scm/driver/gitlab/webhook.go | 52 ++++++++++--------- 7 files changed, 36 insertions(+), 34 deletions(-) diff --git a/scm/driver/gitlab/testdata/webhooks/branch_create.json b/scm/driver/gitlab/testdata/webhooks/branch_create.json index 9abeda061..9c99d83b2 100644 --- a/scm/driver/gitlab/testdata/webhooks/branch_create.json +++ b/scm/driver/gitlab/testdata/webhooks/branch_create.json @@ -34,7 +34,7 @@ { "id": "c4c79227ed610f1151f05bbc5be33b4f340d39c8", "message": "update readme\n", - "timestamp": "2017-12-10T08:28:36-08:00", + "timestamp": "2017-12-10T08:28:36+00:00", "url": "https://gitlab.com/gitlab-org/hello-world/commit/c4c79227ed610f1151f05bbc5be33b4f340d39c8", "author": { "name": "Sid Sijbrandij", diff --git a/scm/driver/gitlab/testdata/webhooks/branch_create.json.golden b/scm/driver/gitlab/testdata/webhooks/branch_create.json.golden index 010c28001..1a618b2a9 100644 --- a/scm/driver/gitlab/testdata/webhooks/branch_create.json.golden +++ b/scm/driver/gitlab/testdata/webhooks/branch_create.json.golden @@ -41,14 +41,14 @@ "Author": { "Name": "Sid Sijbrandij", "Email": "noreply@gitlab.com", - "Date": "0001-01-01T00:00:00Z", + "Date": "2017-12-10T08:28:36Z", "Login": "", "Avatar": "" }, "Committer": { "Name": "Sid Sijbrandij", "Email": "noreply@gitlab.com", - "Date": "0001-01-01T00:00:00Z", + "Date": "2017-12-10T08:28:36Z", "Login": "", "Avatar": "" }, diff --git a/scm/driver/gitlab/testdata/webhooks/push.json b/scm/driver/gitlab/testdata/webhooks/push.json index dde1a9a84..40801e1d4 100644 --- a/scm/driver/gitlab/testdata/webhooks/push.json +++ b/scm/driver/gitlab/testdata/webhooks/push.json @@ -34,7 +34,7 @@ { "id": "2adc9465c4edfc33834e173fe89436a7cb899a1d", "message": "added readme\n", - "timestamp": "2017-12-10T08:26:38-08:00", + "timestamp": "2017-12-10T08:26:38+00:00", "url": "https://gitlab.com/gitlab-org/hello-world/commit/2adc9465c4edfc33834e173fe89436a7cb899a1d", "author": { "name": "Sid Sijbrandij", diff --git a/scm/driver/gitlab/testdata/webhooks/push.json.golden b/scm/driver/gitlab/testdata/webhooks/push.json.golden index 2b6863cbb..8c8bbf9e8 100644 --- a/scm/driver/gitlab/testdata/webhooks/push.json.golden +++ b/scm/driver/gitlab/testdata/webhooks/push.json.golden @@ -41,14 +41,14 @@ "Author": { "Name": "Sid Sijbrandij", "Email": "noreply@gitlab.com", - "Date": "0001-01-01T00:00:00Z", + "Date": "2017-12-10T08:26:38Z", "Login": "", "Avatar": "" }, "Committer": { "Name": "Sid Sijbrandij", "Email": "noreply@gitlab.com", - "Date": "0001-01-01T00:00:00Z", + "Date": "2017-12-10T08:26:38Z", "Login": "", "Avatar": "" }, diff --git a/scm/driver/gitlab/testdata/webhooks/tag_create.json b/scm/driver/gitlab/testdata/webhooks/tag_create.json index f28bdc160..4544eec7c 100644 --- a/scm/driver/gitlab/testdata/webhooks/tag_create.json +++ b/scm/driver/gitlab/testdata/webhooks/tag_create.json @@ -34,7 +34,7 @@ { "id": "2adc9465c4edfc33834e173fe89436a7cb899a1d", "message": "added readme\n", - "timestamp": "2017-12-10T08:26:38-08:00", + "timestamp": "2017-12-10T08:26:38+00:00", "url": "https://gitlab.com/gitlab-org/hello-world/commit/2adc9465c4edfc33834e173fe89436a7cb899a1d", "author": { "name": "Sid Sijbrandij", diff --git a/scm/driver/gitlab/testdata/webhooks/tag_create.json.golden b/scm/driver/gitlab/testdata/webhooks/tag_create.json.golden index b96828528..963085c35 100644 --- a/scm/driver/gitlab/testdata/webhooks/tag_create.json.golden +++ b/scm/driver/gitlab/testdata/webhooks/tag_create.json.golden @@ -41,14 +41,14 @@ "Author": { "Name": "Sid Sijbrandij", "Email": "noreply@gitlab.com", - "Date": "0001-01-01T00:00:00Z", + "Date": "2017-12-10T08:26:38Z", "Login": "", "Avatar": "" }, "Committer": { "Name": "Sid Sijbrandij", "Email": "noreply@gitlab.com", - "Date": "0001-01-01T00:00:00Z", + "Date": "2017-12-10T08:26:38Z", "Login": "", "Avatar": "" }, diff --git a/scm/driver/gitlab/webhook.go b/scm/driver/gitlab/webhook.go index b50f8d904..b0a519739 100644 --- a/scm/driver/gitlab/webhook.go +++ b/scm/driver/gitlab/webhook.go @@ -14,6 +14,7 @@ import ( "time" "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/internal/null" ) type webhookService struct { @@ -130,10 +131,12 @@ func convertPushHook(src *pushHook) *scm.PushHook { Author: scm.Signature{ Name: c.Author.Name, Email: c.Author.Email, + Date: c.Timestamp.ValueOrZero(), }, Committer: scm.Signature{ Name: c.Author.Name, Email: c.Author.Email, + Date: c.Timestamp.ValueOrZero(), }, }) } @@ -219,8 +222,8 @@ func converBranchHook(src *pushHook) *scm.BranchHook { } func convertCommentHook(src *commentHook) (*scm.IssueCommentHook, error) { - var issue scm.Issue - var comment scm.Comment + var issue scm.Issue + var comment scm.Comment switch src.ObjectAttributes.NoteableType { case "Commit", "Issue", "Snippet": @@ -242,7 +245,7 @@ func convertCommentHook(src *commentHook) (*scm.IssueCommentHook, error) { Updated: parseTimeString(src.MergeRequest.UpdatedAt), } for _, l := range src.MergeRequest.Labels { - label := scm.Label { + label := scm.Label{ Name: l.Title, Color: l.Color, } @@ -271,16 +274,16 @@ func convertCommentHook(src *commentHook) (*scm.IssueCommentHook, error) { namespace, _ := scm.Split(src.Project.PathWithNamespace) dst := scm.IssueCommentHook{ - Action: scm.ActionCreate, - Repo: scm.Repository{ - ID: strconv.Itoa(src.Project.ID), - Namespace: namespace, - Name: src.Repository.Name, - Clone: src.Project.GitHTTPURL, - CloneSSH: src.Project.GitSSHURL, - Link: src.Project.WebURL, - Branch: src.Project.DefaultBranch, - Private: false, // TODO how do we correctly set Private vs Public? + Action: scm.ActionCreate, + Repo: scm.Repository{ + ID: strconv.Itoa(src.Project.ID), + Namespace: namespace, + Name: src.Repository.Name, + Clone: src.Project.GitHTTPURL, + CloneSSH: src.Project.GitSSHURL, + Link: src.Project.WebURL, + Branch: src.Project.DefaultBranch, + Private: false, // TODO how do we correctly set Private vs Public? }, Issue: issue, Comment: comment, @@ -383,7 +386,7 @@ func convertPullRequestHook(src *pullRequestHook) *scm.PullRequestHook { } } -func parseTimeString(timeString string) (time.Time) { +func parseTimeString(timeString string) time.Time { layout := "2006-01-02 15:04:05 UTC" // Returns zero value of time in case of an error 0001-01-01 00:00:00 +0000 UTC t, _ := time.Parse(layout, timeString) @@ -424,10 +427,10 @@ type ( HTTPURL string `json:"http_url"` } `json:"project"` Commits []struct { - ID string `json:"id"` - Message string `json:"message"` - Timestamp string `json:"timestamp"` - URL string `json:"url"` + ID string `json:"id"` + Message string `json:"message"` + Timestamp null.Time `json:"timestamp"` + URL string `json:"url"` Author struct { Name string `json:"name"` Email string `json:"email"` @@ -471,7 +474,7 @@ type ( SSHURL string `json:"ssh_url"` HTTPURL string `json:"http_url"` } `json:"project"` - ObjectAttributes struct { + ObjectAttributes struct { ID int `json:"id"` Note string `json:"note"` NoteableType string `json:"noteable_type"` @@ -496,13 +499,13 @@ type ( Type interface{} `json:"type"` Description string `json:"description"` } `json:"object_attributes"` - Repository struct { + Repository struct { Name string `json:"name"` URL string `json:"url"` Description string `json:"description"` Homepage string `json:"homepage"` } `json:"repository"` - MergeRequest struct { + MergeRequest struct { AssigneeID interface{} `json:"assignee_id"` AuthorID int `json:"author_id"` CreatedAt string `json:"created_at"` @@ -558,7 +561,7 @@ type ( SSHURL string `json:"ssh_url"` HTTPURL string `json:"http_url"` } `json:"source"` - Target struct { + Target struct { ID int `json:"id"` Name string `json:"name"` Description string `json:"description"` @@ -576,7 +579,7 @@ type ( SSHURL string `json:"ssh_url"` HTTPURL string `json:"http_url"` } `json:"target"` - LastCommit struct { + LastCommit struct { ID string `json:"id"` Message string `json:"message"` Timestamp string `json:"timestamp"` @@ -586,7 +589,7 @@ type ( Email string `json:"email"` } `json:"author"` } `json:"last_commit"` - Labels []struct { + Labels []struct { ID int `json:"id"` Title string `json:"title"` Color string `json:"color"` @@ -598,7 +601,6 @@ type ( Type string `json:"type"` GroupID interface{} `json:"group_id"` } `json:"labels"` - } `json:"merge_request"` } From 531cb95bd122b8e23b4e43e99e3399bbeb53a612 Mon Sep 17 00:00:00 2001 From: Raghav Date: Mon, 5 Sep 2022 16:01:06 +0530 Subject: [PATCH 132/282] added omitempty annotation for secret (#221) --- scm/driver/stash/repo.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/driver/stash/repo.go b/scm/driver/stash/repo.go index c44fd661f..70f4c01de 100644 --- a/scm/driver/stash/repo.go +++ b/scm/driver/stash/repo.go @@ -81,7 +81,7 @@ type hookInput struct { URL string `json:"url"` Active bool `json:"active"` Config struct { - Secret string `json:"secret"` + Secret string `json:"secret,omitempty"` } `json:"configuration"` } From 7ee0aa5806a55868aeb7573f1de4478b1e15ee1f Mon Sep 17 00:00:00 2001 From: Raghav Date: Thu, 8 Sep 2022 14:35:41 +0530 Subject: [PATCH 133/282] decoding projectName for azure repo (#224) --- scm/driver/azure/repo.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scm/driver/azure/repo.go b/scm/driver/azure/repo.go index f46ede285..5d0427fa4 100644 --- a/scm/driver/azure/repo.go +++ b/scm/driver/azure/repo.go @@ -7,6 +7,7 @@ package azure import ( "context" "fmt" + "net/url" "github.com/drone/go-scm/scm" ) @@ -146,6 +147,11 @@ func (s *RepositoryService) DeleteHook(ctx context.Context, repo, id string) (*s // helper function to return the projectID from the project name func (s *RepositoryService) getProjectIDFromProjectName(ctx context.Context, projectName string) (string, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/core/projects/list?view=azure-devops-rest-6.0 + projectName, err := url.PathUnescape(projectName) + if err != nil { + return "", fmt.Errorf("unable to unscape project: %s", projectName) + } + endpoint := fmt.Sprintf("%s/_apis/projects?api-version=6.0", s.client.owner) type projects struct { Count int64 `json:"count"` From 32e680098bb1e96ae0d2a5d05378bc54db37d575 Mon Sep 17 00:00:00 2001 From: raghavharness Date: Tue, 13 Sep 2022 17:27:33 +0530 Subject: [PATCH 134/282] use merge commit sha if pull request is merged for bitbucket --- scm/driver/bitbucket/pr.go | 11 ++++++++++- .../testdata/webhooks/pr_fulfilled.json.golden | 2 +- scm/driver/bitbucket/webhook.go | 7 ++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/scm/driver/bitbucket/pr.go b/scm/driver/bitbucket/pr.go index 20dc31441..033860f85 100644 --- a/scm/driver/bitbucket/pr.go +++ b/scm/driver/bitbucket/pr.go @@ -108,6 +108,10 @@ type pr struct { HTML string `json:"html"` Type string `json:"type"` } `json:"summary"` + MergeCommit struct { + Type string `json:"type"` + Hash string `json:"hash"` + } `json:"merge_commit"` Source reference `json:"source"` State string `json:"state"` Author user `json:"author"` @@ -144,11 +148,16 @@ func convertPullRequests(from *prs) []*scm.PullRequest { } func convertPullRequest(from *pr) *scm.PullRequest { + sha := from.Source.Commit.Hash + // if pr is merged, use the merge commit + if from.MergeCommit.Hash != "" { + sha = from.MergeCommit.Hash + } return &scm.PullRequest{ Number: from.ID, Title: from.Title, Body: from.Description, - Sha: from.Source.Commit.Hash, + Sha: sha, Source: from.Source.Branch.Name, Target: from.Destination.Branch.Name, Fork: from.Source.Repository.FullName, diff --git a/scm/driver/bitbucket/testdata/webhooks/pr_fulfilled.json.golden b/scm/driver/bitbucket/testdata/webhooks/pr_fulfilled.json.golden index 1cc60a2f0..6b03b80fd 100644 --- a/scm/driver/bitbucket/testdata/webhooks/pr_fulfilled.json.golden +++ b/scm/driver/bitbucket/testdata/webhooks/pr_fulfilled.json.golden @@ -17,7 +17,7 @@ "Number": 1, "Title": "Awesome new feature", "Body": "made some changes", - "Sha": "0704fc5beccc", + "Sha": "4f8f6de9d0ff", "Ref": "refs/pull-requests/1/from", "Source": "develop", "Target": "master", diff --git a/scm/driver/bitbucket/webhook.go b/scm/driver/bitbucket/webhook.go index c567e565f..51f2c3f48 100644 --- a/scm/driver/bitbucket/webhook.go +++ b/scm/driver/bitbucket/webhook.go @@ -782,6 +782,11 @@ func convertTagDeleteHook(src *pushHook) *scm.TagHook { // func convertPullRequestHook(src *webhook) *scm.PullRequestHook { + sha := src.PullRequest.Source.Commit.Hash + // if pr is merged, use the merge commit + if src.PullRequest.MergeCommit.Hash != "" { + sha = src.PullRequest.MergeCommit.Hash + } namespace, name := scm.Split(src.Repository.FullName) return &scm.PullRequestHook{ Action: scm.ActionOpen, @@ -789,7 +794,7 @@ func convertPullRequestHook(src *webhook) *scm.PullRequestHook { Number: src.PullRequest.ID, Title: src.PullRequest.Title, Body: src.PullRequest.Description, - Sha: src.PullRequest.Source.Commit.Hash, + Sha: sha, Ref: fmt.Sprintf("refs/pull-requests/%d/from", src.PullRequest.ID), Source: src.PullRequest.Source.Branch.Name, Target: src.PullRequest.Destination.Branch.Name, From cfb5ca9937b25722f9a35832b66e463731a6f66d Mon Sep 17 00:00:00 2001 From: raghavharness Date: Wed, 14 Sep 2022 13:42:38 +0530 Subject: [PATCH 135/282] changes for stash --- scm/driver/stash/pr.go | 14 +++++++++++++- .../stash/testdata/webhooks/pr_merged.json.golden | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/scm/driver/stash/pr.go b/scm/driver/stash/pr.go index 836c5392b..e7607b859 100644 --- a/scm/driver/stash/pr.go +++ b/scm/driver/stash/pr.go @@ -173,6 +173,12 @@ type pr struct { Links struct { Self []link `json:"self"` } `json:"links"` + Properties struct { + MergeCommit struct { + ID string `json:"id"` + DisplayID string `json:"displayId"` + } `json:"mergeCommit"` + } `json:"properties"` } type prs struct { @@ -212,6 +218,12 @@ func convertPullRequests(from *prs) []*scm.PullRequest { } func convertPullRequest(from *pr) *scm.PullRequest { + sha := from.FromRef.LatestCommit + // if pr is merged, use the merge commit + if from.Properties.MergeCommit.ID != "" { + sha = from.Properties.MergeCommit.ID + } + fork := scm.Join( from.FromRef.Repository.Project.Key, from.FromRef.Repository.Slug, @@ -220,7 +232,7 @@ func convertPullRequest(from *pr) *scm.PullRequest { Number: from.ID, Title: from.Title, Body: from.Description, - Sha: from.FromRef.LatestCommit, + Sha: sha, Ref: fmt.Sprintf("refs/pull-requests/%d/from", from.ID), Source: from.FromRef.DisplayID, Target: from.ToRef.DisplayID, diff --git a/scm/driver/stash/testdata/webhooks/pr_merged.json.golden b/scm/driver/stash/testdata/webhooks/pr_merged.json.golden index 344032d2c..f4ab41c57 100644 --- a/scm/driver/stash/testdata/webhooks/pr_merged.json.golden +++ b/scm/driver/stash/testdata/webhooks/pr_merged.json.golden @@ -17,7 +17,7 @@ "Number": 3, "Title": "Develop", "Body": "* added LICENSE\r\n* add COPYING file", - "Sha": "b9eaed50a03c073b20dfa82e5e753d295e7f0e56", + "Sha": "83f836ca538dc4f43d29fda46a5b85ea49f1b8e7", "Ref": "refs/pull-requests/3/from", "Source": "develop", "Target": "master", From e073dbfa2bde20ab73068b47dfb9af69129b22be Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Wed, 14 Sep 2022 08:42:14 -0400 Subject: [PATCH 136/282] Add field to capture merge sha --- scm/pr.go | 1 + 1 file changed, 1 insertion(+) diff --git a/scm/pr.go b/scm/pr.go index b36254a34..1fd2e5a5b 100644 --- a/scm/pr.go +++ b/scm/pr.go @@ -24,6 +24,7 @@ type ( Diff string Closed bool Merged bool + Merge string Base Reference Head Reference Author User From c7c7db684a217ff0514650a9d3562c6e64f3cfd4 Mon Sep 17 00:00:00 2001 From: raghavharness Date: Wed, 14 Sep 2022 18:39:13 +0530 Subject: [PATCH 137/282] use new merge field instead of exisiting sha field --- scm/driver/bitbucket/pr.go | 8 ++------ .../bitbucket/testdata/webhooks/pr_fulfilled.json.golden | 3 ++- scm/driver/bitbucket/webhook.go | 8 ++------ scm/driver/stash/pr.go | 9 ++------- scm/driver/stash/testdata/webhooks/pr_merged.json.golden | 3 ++- 5 files changed, 10 insertions(+), 21 deletions(-) diff --git a/scm/driver/bitbucket/pr.go b/scm/driver/bitbucket/pr.go index 033860f85..5cc3e5ba9 100644 --- a/scm/driver/bitbucket/pr.go +++ b/scm/driver/bitbucket/pr.go @@ -148,16 +148,12 @@ func convertPullRequests(from *prs) []*scm.PullRequest { } func convertPullRequest(from *pr) *scm.PullRequest { - sha := from.Source.Commit.Hash - // if pr is merged, use the merge commit - if from.MergeCommit.Hash != "" { - sha = from.MergeCommit.Hash - } return &scm.PullRequest{ Number: from.ID, Title: from.Title, Body: from.Description, - Sha: sha, + Sha: from.Source.Commit.Hash, + Merge: from.MergeCommit.Hash, Source: from.Source.Branch.Name, Target: from.Destination.Branch.Name, Fork: from.Source.Repository.FullName, diff --git a/scm/driver/bitbucket/testdata/webhooks/pr_fulfilled.json.golden b/scm/driver/bitbucket/testdata/webhooks/pr_fulfilled.json.golden index 6b03b80fd..b76c354af 100644 --- a/scm/driver/bitbucket/testdata/webhooks/pr_fulfilled.json.golden +++ b/scm/driver/bitbucket/testdata/webhooks/pr_fulfilled.json.golden @@ -17,7 +17,8 @@ "Number": 1, "Title": "Awesome new feature", "Body": "made some changes", - "Sha": "4f8f6de9d0ff", + "Sha": "0704fc5beccc", + "Merge": "4f8f6de9d0ff", "Ref": "refs/pull-requests/1/from", "Source": "develop", "Target": "master", diff --git a/scm/driver/bitbucket/webhook.go b/scm/driver/bitbucket/webhook.go index 51f2c3f48..b47675e6d 100644 --- a/scm/driver/bitbucket/webhook.go +++ b/scm/driver/bitbucket/webhook.go @@ -782,11 +782,6 @@ func convertTagDeleteHook(src *pushHook) *scm.TagHook { // func convertPullRequestHook(src *webhook) *scm.PullRequestHook { - sha := src.PullRequest.Source.Commit.Hash - // if pr is merged, use the merge commit - if src.PullRequest.MergeCommit.Hash != "" { - sha = src.PullRequest.MergeCommit.Hash - } namespace, name := scm.Split(src.Repository.FullName) return &scm.PullRequestHook{ Action: scm.ActionOpen, @@ -794,7 +789,8 @@ func convertPullRequestHook(src *webhook) *scm.PullRequestHook { Number: src.PullRequest.ID, Title: src.PullRequest.Title, Body: src.PullRequest.Description, - Sha: sha, + Sha: src.PullRequest.Source.Commit.Hash, + Merge: src.PullRequest.MergeCommit.Hash, Ref: fmt.Sprintf("refs/pull-requests/%d/from", src.PullRequest.ID), Source: src.PullRequest.Source.Branch.Name, Target: src.PullRequest.Destination.Branch.Name, diff --git a/scm/driver/stash/pr.go b/scm/driver/stash/pr.go index e7607b859..87cdb8fda 100644 --- a/scm/driver/stash/pr.go +++ b/scm/driver/stash/pr.go @@ -218,12 +218,6 @@ func convertPullRequests(from *prs) []*scm.PullRequest { } func convertPullRequest(from *pr) *scm.PullRequest { - sha := from.FromRef.LatestCommit - // if pr is merged, use the merge commit - if from.Properties.MergeCommit.ID != "" { - sha = from.Properties.MergeCommit.ID - } - fork := scm.Join( from.FromRef.Repository.Project.Key, from.FromRef.Repository.Slug, @@ -232,7 +226,8 @@ func convertPullRequest(from *pr) *scm.PullRequest { Number: from.ID, Title: from.Title, Body: from.Description, - Sha: sha, + Sha: from.FromRef.LatestCommit, + Merge: from.Properties.MergeCommit.ID, Ref: fmt.Sprintf("refs/pull-requests/%d/from", from.ID), Source: from.FromRef.DisplayID, Target: from.ToRef.DisplayID, diff --git a/scm/driver/stash/testdata/webhooks/pr_merged.json.golden b/scm/driver/stash/testdata/webhooks/pr_merged.json.golden index f4ab41c57..2b3367535 100644 --- a/scm/driver/stash/testdata/webhooks/pr_merged.json.golden +++ b/scm/driver/stash/testdata/webhooks/pr_merged.json.golden @@ -17,7 +17,8 @@ "Number": 3, "Title": "Develop", "Body": "* added LICENSE\r\n* add COPYING file", - "Sha": "83f836ca538dc4f43d29fda46a5b85ea49f1b8e7", + "Sha": "b9eaed50a03c073b20dfa82e5e753d295e7f0e56", + "Merge": "83f836ca538dc4f43d29fda46a5b85ea49f1b8e7", "Ref": "refs/pull-requests/3/from", "Source": "develop", "Target": "master", From a6796f5d93e6c43ac7879bb4d2515514b8c01a1b Mon Sep 17 00:00:00 2001 From: Rutvij Mehta Date: Fri, 23 Sep 2022 14:43:02 -0700 Subject: [PATCH 138/282] Add Actor UUID to Sender for all webhooks responses for Bitbucket --- scm/driver/bitbucket/testdata/webhooks/pr_created.json.golden | 1 + .../bitbucket/testdata/webhooks/pr_declined.json.golden | 1 + .../bitbucket/testdata/webhooks/pr_fulfilled.json.golden | 1 + scm/driver/bitbucket/testdata/webhooks/pr_updated.json.golden | 1 + .../testdata/webhooks/push_branch_delete.json.golden | 1 + .../bitbucket/testdata/webhooks/push_tag_delete.json.golden | 1 + scm/driver/bitbucket/webhook.go | 4 ++++ 7 files changed, 10 insertions(+) diff --git a/scm/driver/bitbucket/testdata/webhooks/pr_created.json.golden b/scm/driver/bitbucket/testdata/webhooks/pr_created.json.golden index 00825c69a..f1901d6d9 100644 --- a/scm/driver/bitbucket/testdata/webhooks/pr_created.json.golden +++ b/scm/driver/bitbucket/testdata/webhooks/pr_created.json.golden @@ -35,6 +35,7 @@ "Updated": "2018-07-02T21:51:39.532546Z" }, "Sender": { + "ID": "{87bb15eb-47c1-49b3-9f16-ca824a2979a4}", "Login": "brydzewski", "Name": "Brad Rydzewski", "Email": "", diff --git a/scm/driver/bitbucket/testdata/webhooks/pr_declined.json.golden b/scm/driver/bitbucket/testdata/webhooks/pr_declined.json.golden index 395a0bc80..081cf4aff 100644 --- a/scm/driver/bitbucket/testdata/webhooks/pr_declined.json.golden +++ b/scm/driver/bitbucket/testdata/webhooks/pr_declined.json.golden @@ -35,6 +35,7 @@ "Updated": "2018-07-03T01:44:00.030575Z" }, "Sender": { + "ID": "{87bb15eb-47c1-49b3-9f16-ca824a2979a4}", "Login": "brydzewski", "Name": "Brad Rydzewski", "Email": "", diff --git a/scm/driver/bitbucket/testdata/webhooks/pr_fulfilled.json.golden b/scm/driver/bitbucket/testdata/webhooks/pr_fulfilled.json.golden index b76c354af..642fe2a9f 100644 --- a/scm/driver/bitbucket/testdata/webhooks/pr_fulfilled.json.golden +++ b/scm/driver/bitbucket/testdata/webhooks/pr_fulfilled.json.golden @@ -36,6 +36,7 @@ "Updated": "2018-07-03T01:28:05.903251Z" }, "Sender": { + "ID": "{87bb15eb-47c1-49b3-9f16-ca824a2979a4}", "Login": "brydzewski", "Name": "Brad Rydzewski", "Email": "", diff --git a/scm/driver/bitbucket/testdata/webhooks/pr_updated.json.golden b/scm/driver/bitbucket/testdata/webhooks/pr_updated.json.golden index b5a933fbb..3c4a45ea4 100644 --- a/scm/driver/bitbucket/testdata/webhooks/pr_updated.json.golden +++ b/scm/driver/bitbucket/testdata/webhooks/pr_updated.json.golden @@ -35,6 +35,7 @@ "Updated": "2018-07-02T21:54:34.210775Z" }, "Sender": { + "ID": "{87bb15eb-47c1-49b3-9f16-ca824a2979a4}", "Login": "brydzewski", "Name": "Brad Rydzewski", "Email": "", diff --git a/scm/driver/bitbucket/testdata/webhooks/push_branch_delete.json.golden b/scm/driver/bitbucket/testdata/webhooks/push_branch_delete.json.golden index 34a12d028..9c5ed6dce 100644 --- a/scm/driver/bitbucket/testdata/webhooks/push_branch_delete.json.golden +++ b/scm/driver/bitbucket/testdata/webhooks/push_branch_delete.json.golden @@ -18,6 +18,7 @@ }, "Action": "deleted", "Sender": { + "ID": "{87bb15eb-47c1-49b3-9f16-ca824a2979a4}", "Login": "brydzewski", "Name": "Brad Rydzewski", "Email": "", diff --git a/scm/driver/bitbucket/testdata/webhooks/push_tag_delete.json.golden b/scm/driver/bitbucket/testdata/webhooks/push_tag_delete.json.golden index 5fe074bcb..479ffec02 100644 --- a/scm/driver/bitbucket/testdata/webhooks/push_tag_delete.json.golden +++ b/scm/driver/bitbucket/testdata/webhooks/push_tag_delete.json.golden @@ -18,6 +18,7 @@ }, "Action": "deleted", "Sender": { + "ID": "{87bb15eb-47c1-49b3-9f16-ca824a2979a4}", "Login": "brydzewski", "Name": "Brad Rydzewski", "Email": "", diff --git a/scm/driver/bitbucket/webhook.go b/scm/driver/bitbucket/webhook.go index b47675e6d..7ba3783a1 100644 --- a/scm/driver/bitbucket/webhook.go +++ b/scm/driver/bitbucket/webhook.go @@ -716,6 +716,7 @@ func convertBranchDeleteHook(src *pushHook) *scm.BranchHook { Link: src.Repository.Links.HTML.Href, }, Sender: scm.User{ + ID: src.Actor.UUID, Login: src.Actor.Username, Name: src.Actor.DisplayName, Avatar: src.Actor.Links.Avatar.Href, @@ -743,6 +744,7 @@ func convertTagCreateHook(src *pushHook) *scm.TagHook { Link: src.Repository.Links.HTML.Href, }, Sender: scm.User{ + ID: src.Actor.UUID, Login: src.Actor.Username, Name: src.Actor.DisplayName, Avatar: src.Actor.Links.Avatar.Href, @@ -770,6 +772,7 @@ func convertTagDeleteHook(src *pushHook) *scm.TagHook { Link: src.Repository.Links.HTML.Href, }, Sender: scm.User{ + ID: src.Actor.UUID, Login: src.Actor.Username, Name: src.Actor.DisplayName, Avatar: src.Actor.Links.Avatar.Href, @@ -816,6 +819,7 @@ func convertPullRequestHook(src *webhook) *scm.PullRequestHook { Link: src.Repository.Links.HTML.Href, }, Sender: scm.User{ + ID: src.Actor.UUID, Login: src.Actor.Username, Name: src.Actor.DisplayName, Avatar: src.Actor.Links.Avatar.Href, From 81afb0fa48d4d083518f98f6eeaf95107e44cf48 Mon Sep 17 00:00:00 2001 From: kit101 Date: Tue, 27 Sep 2022 17:11:35 +0800 Subject: [PATCH 139/282] fixbug: gitee convert repository (#226) --- scm/driver/gitee/repo.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/driver/gitee/repo.go b/scm/driver/gitee/repo.go index 2628c5df7..fa14ab8ea 100644 --- a/scm/driver/gitee/repo.go +++ b/scm/driver/gitee/repo.go @@ -159,7 +159,7 @@ func convertRepositoryList(from []*repository) []*scm.Repository { func convertRepository(from *repository) *scm.Repository { return &scm.Repository{ ID: strconv.Itoa(from.ID), - Name: from.Name, + Name: from.Path, Namespace: from.Namespace.Path, Perm: &scm.Perm{ Push: from.Permission.Push, From 692aa9a8d2888daa7237e5cdee1037f42e317af6 Mon Sep 17 00:00:00 2001 From: Rutvij Mehta Date: Thu, 10 Nov 2022 09:50:32 +0530 Subject: [PATCH 140/282] Add Actor UUID to push and branch create events for Bitbucket --- scm/driver/bitbucket/testdata/webhooks/push.json.golden | 1 + .../bitbucket/testdata/webhooks/push_branch_create.json.golden | 1 + .../bitbucket/testdata/webhooks/push_tag_create.json.golden | 1 + scm/driver/bitbucket/webhook.go | 2 ++ 4 files changed, 5 insertions(+) diff --git a/scm/driver/bitbucket/testdata/webhooks/push.json.golden b/scm/driver/bitbucket/testdata/webhooks/push.json.golden index 5c76ff577..7d6e576b5 100644 --- a/scm/driver/bitbucket/testdata/webhooks/push.json.golden +++ b/scm/driver/bitbucket/testdata/webhooks/push.json.golden @@ -56,6 +56,7 @@ } ], "Sender": { + "ID": "{87bb15eb-47c1-49b3-9f16-ca824a2979a4}", "Login": "brydzewski", "Name": "Brad Rydzewski", "Email": "", diff --git a/scm/driver/bitbucket/testdata/webhooks/push_branch_create.json.golden b/scm/driver/bitbucket/testdata/webhooks/push_branch_create.json.golden index 0797aae42..d8986b55a 100644 --- a/scm/driver/bitbucket/testdata/webhooks/push_branch_create.json.golden +++ b/scm/driver/bitbucket/testdata/webhooks/push_branch_create.json.golden @@ -74,6 +74,7 @@ } ], "Sender": { + "ID": "{87bb15eb-47c1-49b3-9f16-ca824a2979a4}", "Login": "brydzewski", "Name": "Brad Rydzewski", "Email": "", diff --git a/scm/driver/bitbucket/testdata/webhooks/push_tag_create.json.golden b/scm/driver/bitbucket/testdata/webhooks/push_tag_create.json.golden index 322223a56..688fff348 100644 --- a/scm/driver/bitbucket/testdata/webhooks/push_tag_create.json.golden +++ b/scm/driver/bitbucket/testdata/webhooks/push_tag_create.json.golden @@ -34,6 +34,7 @@ "Link": "https://bitbucket.org/brydzewski/foo/commits/141977fedf5cf35aa290ac87d4b5177ac4cd9de1" }, "Sender": { + "ID": "{87bb15eb-47c1-49b3-9f16-ca824a2979a4}", "Login": "brydzewski", "Name": "Brad Rydzewski", "Email": "", diff --git a/scm/driver/bitbucket/webhook.go b/scm/driver/bitbucket/webhook.go index 7ba3783a1..6d88690ec 100644 --- a/scm/driver/bitbucket/webhook.go +++ b/scm/driver/bitbucket/webhook.go @@ -657,6 +657,7 @@ func convertPushHook(src *pushHook) *scm.PushHook { Link: src.Repository.Links.HTML.Href, }, Sender: scm.User{ + ID: src.Actor.UUID, Login: src.Actor.Username, Name: src.Actor.DisplayName, Avatar: src.Actor.Links.Avatar.Href, @@ -689,6 +690,7 @@ func convertBranchCreateHook(src *pushHook) *scm.BranchHook { Link: src.Repository.Links.HTML.Href, }, Sender: scm.User{ + ID: src.Actor.UUID, Login: src.Actor.Username, Name: src.Actor.DisplayName, Avatar: src.Actor.Links.Avatar.Href, From 1949a8eb740777e552841264c9913ab9af11e99e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Calasans?= Date: Wed, 16 Nov 2022 10:20:08 -0300 Subject: [PATCH 141/282] Add support for Github release webhook (#229) * Add support for Github release webhook --- scm/const.go | 23 ++- .../testdata/webhooks/release_created.json | 164 ++++++++++++++++++ .../webhooks/release_created.json.golden | 34 ++++ .../testdata/webhooks/release_deleted.json | 164 ++++++++++++++++++ .../webhooks/release_deleted.json.golden | 34 ++++ .../testdata/webhooks/release_edited.json | 164 ++++++++++++++++++ .../webhooks/release_edited.json.golden | 34 ++++ .../webhooks/release_prereleased.json | 164 ++++++++++++++++++ .../webhooks/release_prereleased.json.golden | 34 ++++ .../testdata/webhooks/release_published.json | 164 ++++++++++++++++++ .../webhooks/release_published.json.golden | 34 ++++ .../testdata/webhooks/release_released.json | 164 ++++++++++++++++++ .../webhooks/release_released.json.golden | 34 ++++ .../webhooks/release_unpublished.json | 164 ++++++++++++++++++ .../webhooks/release_unpublished.json.golden | 34 ++++ scm/driver/github/webhook.go | 79 +++++++++ scm/driver/github/webhook_test.go | 45 +++++ scm/webhook.go | 10 ++ 18 files changed, 1541 insertions(+), 2 deletions(-) create mode 100644 scm/driver/github/testdata/webhooks/release_created.json create mode 100644 scm/driver/github/testdata/webhooks/release_created.json.golden create mode 100644 scm/driver/github/testdata/webhooks/release_deleted.json create mode 100644 scm/driver/github/testdata/webhooks/release_deleted.json.golden create mode 100644 scm/driver/github/testdata/webhooks/release_edited.json create mode 100644 scm/driver/github/testdata/webhooks/release_edited.json.golden create mode 100644 scm/driver/github/testdata/webhooks/release_prereleased.json create mode 100644 scm/driver/github/testdata/webhooks/release_prereleased.json.golden create mode 100644 scm/driver/github/testdata/webhooks/release_published.json create mode 100644 scm/driver/github/testdata/webhooks/release_published.json.golden create mode 100644 scm/driver/github/testdata/webhooks/release_released.json create mode 100644 scm/driver/github/testdata/webhooks/release_released.json.golden create mode 100644 scm/driver/github/testdata/webhooks/release_unpublished.json create mode 100644 scm/driver/github/testdata/webhooks/release_unpublished.json.golden diff --git a/scm/const.go b/scm/const.go index 690202cb5..84fb47151 100644 --- a/scm/const.go +++ b/scm/const.go @@ -42,6 +42,11 @@ const ( ActionMerge // issue comment ActionEdit + // release + ActionPublish + ActionUnpublish + ActionPrerelease + ActionRelease ) // String returns the string representation of Action. @@ -67,8 +72,14 @@ func (a Action) String() (s string) { return "synchronized" case ActionMerge: return "merged" - case ActionEdit: - return "edited" + case ActionPublish: + return "published" + case ActionUnpublish: + return "unpublished" + case ActionPrerelease: + return "prereleased" + case ActionRelease: + return "released" default: return } @@ -108,6 +119,14 @@ func (a *Action) UnmarshalJSON(data []byte) error { *a = ActionMerge case "edited": *a = ActionEdit + case "published": + *a = ActionPublish + case "unpublished": + *a = ActionUnpublish + case "prereleased": + *a = ActionPrerelease + case "released": + *a = ActionRelease } return nil } diff --git a/scm/driver/github/testdata/webhooks/release_created.json b/scm/driver/github/testdata/webhooks/release_created.json new file mode 100644 index 000000000..39a6d8d78 --- /dev/null +++ b/scm/driver/github/testdata/webhooks/release_created.json @@ -0,0 +1,164 @@ +{ + "action": "created", + "release": { + "url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309", + "assets_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309/assets", + "upload_url": "https://uploads.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309/assets{?name,label}", + "html_url": "https://github.com/vcalasansh/harness-ngtriggers-test/releases/tag/v1.0.0", + "id": 81372309, + "author": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + }, + "node_id": "RE_kwDOH5utuc4E2aSV", + "tag_name": "v1.0.0", + "target_commitish": "test-branch", + "name": "New release!", + "draft": false, + "prerelease": false, + "created_at": "2022-10-28T13:03:11Z", + "published_at": "2022-10-28T16:36:52Z", + "assets": [ + + ], + "tarball_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/tarball/v1.0.0", + "zipball_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/zipball/v1.0.0", + "body": "New release!" + }, + "repository": { + "id": 530296249, + "node_id": "R_kgDOH5utuQ", + "name": "harness-ngtriggers-test", + "full_name": "vcalasansh/harness-ngtriggers-test", + "private": true, + "owner": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/vcalasansh/harness-ngtriggers-test", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test", + "forks_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/forks", + "keys_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/teams", + "hooks_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/hooks", + "issue_events_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues/events{/number}", + "events_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/events", + "assignees_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/assignees{/user}", + "branches_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/branches{/branch}", + "tags_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/tags", + "blobs_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/statuses/{sha}", + "languages_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/languages", + "stargazers_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/stargazers", + "contributors_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/contributors", + "subscribers_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/subscribers", + "subscription_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/subscription", + "commits_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/contents/{+path}", + "compare_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/merges", + "archive_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/downloads", + "issues_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues{/number}", + "pulls_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/pulls{/number}", + "milestones_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/milestones{/number}", + "notifications_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/labels{/name}", + "releases_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases{/id}", + "deployments_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/deployments", + "created_at": "2022-08-29T16:12:07Z", + "updated_at": "2022-08-29T16:12:07Z", + "pushed_at": "2022-10-28T16:36:27Z", + "git_url": "git://github.com/vcalasansh/harness-ngtriggers-test.git", + "ssh_url": "git@github.com:vcalasansh/harness-ngtriggers-test.git", + "clone_url": "https://github.com/vcalasansh/harness-ngtriggers-test.git", + "svn_url": "https://github.com/vcalasansh/harness-ngtriggers-test", + "homepage": null, + "size": 11, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 0, + "license": null, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [ + + ], + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "test-branch" + }, + "sender": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/scm/driver/github/testdata/webhooks/release_created.json.golden b/scm/driver/github/testdata/webhooks/release_created.json.golden new file mode 100644 index 000000000..b7935c46d --- /dev/null +++ b/scm/driver/github/testdata/webhooks/release_created.json.golden @@ -0,0 +1,34 @@ +{ + "Action": "created", + "Release": { + "ID": 81372309, + "Title": "New release!", + "Description": "New release!", + "Link": "https://github.com/vcalasansh/harness-ngtriggers-test/releases/tag/v1.0.0", + "Tag": "v1.0.0", + "Commitish": "test-branch", + "Draft": false, + "Prerelease": false, + "Created": "2022-10-28T13:03:11Z", + "Published": "2022-10-28T16:36:52Z" + }, + "Repo": { + "ID": "530296249", + "Namespace": "vcalasansh", + "Name": "harness-ngtriggers-test", + "Perm": null, + "Branch": "test-branch", + "Private": true, + "Clone": "https://github.com/vcalasansh/harness-ngtriggers-test.git", + "CloneSSH": "git@github.com:vcalasansh/harness-ngtriggers-test.git", + "Link": "https://github.com/vcalasansh/harness-ngtriggers-test", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Sender": { + "Login": "vcalasansh", + "Name": "", + "Email": "", + "Avatar": "https://avatars.githubusercontent.com/u/109106581?v=4" + } +} diff --git a/scm/driver/github/testdata/webhooks/release_deleted.json b/scm/driver/github/testdata/webhooks/release_deleted.json new file mode 100644 index 000000000..a5ba0fef2 --- /dev/null +++ b/scm/driver/github/testdata/webhooks/release_deleted.json @@ -0,0 +1,164 @@ +{ + "action": "deleted", + "release": { + "url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309", + "assets_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309/assets", + "upload_url": "https://uploads.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309/assets{?name,label}", + "html_url": "https://github.com/vcalasansh/harness-ngtriggers-test/releases/tag/v1.0.0", + "id": 81372309, + "author": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + }, + "node_id": "RE_kwDOH5utuc4E2aSV", + "tag_name": "v1.0.0", + "target_commitish": "test-branch", + "name": "New release!", + "draft": false, + "prerelease": false, + "created_at": "2022-10-28T13:03:11Z", + "published_at": "2022-10-28T16:36:52Z", + "assets": [ + + ], + "tarball_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/tarball/v1.0.0", + "zipball_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/zipball/v1.0.0", + "body": "New release!" + }, + "repository": { + "id": 530296249, + "node_id": "R_kgDOH5utuQ", + "name": "harness-ngtriggers-test", + "full_name": "vcalasansh/harness-ngtriggers-test", + "private": true, + "owner": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/vcalasansh/harness-ngtriggers-test", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test", + "forks_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/forks", + "keys_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/teams", + "hooks_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/hooks", + "issue_events_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues/events{/number}", + "events_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/events", + "assignees_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/assignees{/user}", + "branches_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/branches{/branch}", + "tags_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/tags", + "blobs_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/statuses/{sha}", + "languages_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/languages", + "stargazers_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/stargazers", + "contributors_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/contributors", + "subscribers_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/subscribers", + "subscription_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/subscription", + "commits_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/contents/{+path}", + "compare_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/merges", + "archive_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/downloads", + "issues_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues{/number}", + "pulls_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/pulls{/number}", + "milestones_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/milestones{/number}", + "notifications_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/labels{/name}", + "releases_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases{/id}", + "deployments_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/deployments", + "created_at": "2022-08-29T16:12:07Z", + "updated_at": "2022-08-29T16:12:07Z", + "pushed_at": "2022-10-28T16:36:27Z", + "git_url": "git://github.com/vcalasansh/harness-ngtriggers-test.git", + "ssh_url": "git@github.com:vcalasansh/harness-ngtriggers-test.git", + "clone_url": "https://github.com/vcalasansh/harness-ngtriggers-test.git", + "svn_url": "https://github.com/vcalasansh/harness-ngtriggers-test", + "homepage": null, + "size": 11, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 0, + "license": null, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [ + + ], + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "test-branch" + }, + "sender": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/scm/driver/github/testdata/webhooks/release_deleted.json.golden b/scm/driver/github/testdata/webhooks/release_deleted.json.golden new file mode 100644 index 000000000..30dee53c1 --- /dev/null +++ b/scm/driver/github/testdata/webhooks/release_deleted.json.golden @@ -0,0 +1,34 @@ +{ + "Action": "deleted", + "Release": { + "ID": 81372309, + "Title": "New release!", + "Description": "New release!", + "Link": "https://github.com/vcalasansh/harness-ngtriggers-test/releases/tag/v1.0.0", + "Tag": "v1.0.0", + "Commitish": "test-branch", + "Draft": false, + "Prerelease": false, + "Created": "2022-10-28T13:03:11Z", + "Published": "2022-10-28T16:36:52Z" + }, + "Repo": { + "ID": "530296249", + "Namespace": "vcalasansh", + "Name": "harness-ngtriggers-test", + "Perm": null, + "Branch": "test-branch", + "Private": true, + "Clone": "https://github.com/vcalasansh/harness-ngtriggers-test.git", + "CloneSSH": "git@github.com:vcalasansh/harness-ngtriggers-test.git", + "Link": "https://github.com/vcalasansh/harness-ngtriggers-test", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Sender": { + "Login": "vcalasansh", + "Name": "", + "Email": "", + "Avatar": "https://avatars.githubusercontent.com/u/109106581?v=4" + } +} diff --git a/scm/driver/github/testdata/webhooks/release_edited.json b/scm/driver/github/testdata/webhooks/release_edited.json new file mode 100644 index 000000000..45f7511b4 --- /dev/null +++ b/scm/driver/github/testdata/webhooks/release_edited.json @@ -0,0 +1,164 @@ +{ + "action": "edited", + "release": { + "url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309", + "assets_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309/assets", + "upload_url": "https://uploads.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309/assets{?name,label}", + "html_url": "https://github.com/vcalasansh/harness-ngtriggers-test/releases/tag/v1.0.0", + "id": 81372309, + "author": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + }, + "node_id": "RE_kwDOH5utuc4E2aSV", + "tag_name": "v1.0.0", + "target_commitish": "test-branch", + "name": "New release!", + "draft": false, + "prerelease": false, + "created_at": "2022-10-28T13:03:11Z", + "published_at": "2022-10-28T16:36:52Z", + "assets": [ + + ], + "tarball_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/tarball/v1.0.0", + "zipball_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/zipball/v1.0.0", + "body": "New release!" + }, + "repository": { + "id": 530296249, + "node_id": "R_kgDOH5utuQ", + "name": "harness-ngtriggers-test", + "full_name": "vcalasansh/harness-ngtriggers-test", + "private": true, + "owner": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/vcalasansh/harness-ngtriggers-test", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test", + "forks_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/forks", + "keys_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/teams", + "hooks_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/hooks", + "issue_events_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues/events{/number}", + "events_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/events", + "assignees_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/assignees{/user}", + "branches_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/branches{/branch}", + "tags_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/tags", + "blobs_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/statuses/{sha}", + "languages_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/languages", + "stargazers_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/stargazers", + "contributors_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/contributors", + "subscribers_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/subscribers", + "subscription_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/subscription", + "commits_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/contents/{+path}", + "compare_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/merges", + "archive_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/downloads", + "issues_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues{/number}", + "pulls_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/pulls{/number}", + "milestones_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/milestones{/number}", + "notifications_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/labels{/name}", + "releases_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases{/id}", + "deployments_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/deployments", + "created_at": "2022-08-29T16:12:07Z", + "updated_at": "2022-08-29T16:12:07Z", + "pushed_at": "2022-10-28T16:36:27Z", + "git_url": "git://github.com/vcalasansh/harness-ngtriggers-test.git", + "ssh_url": "git@github.com:vcalasansh/harness-ngtriggers-test.git", + "clone_url": "https://github.com/vcalasansh/harness-ngtriggers-test.git", + "svn_url": "https://github.com/vcalasansh/harness-ngtriggers-test", + "homepage": null, + "size": 11, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 0, + "license": null, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [ + + ], + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "test-branch" + }, + "sender": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/scm/driver/github/testdata/webhooks/release_edited.json.golden b/scm/driver/github/testdata/webhooks/release_edited.json.golden new file mode 100644 index 000000000..0b1e387ad --- /dev/null +++ b/scm/driver/github/testdata/webhooks/release_edited.json.golden @@ -0,0 +1,34 @@ +{ + "Action": "edited", + "Release": { + "ID": 81372309, + "Title": "New release!", + "Description": "New release!", + "Link": "https://github.com/vcalasansh/harness-ngtriggers-test/releases/tag/v1.0.0", + "Tag": "v1.0.0", + "Commitish": "test-branch", + "Draft": false, + "Prerelease": false, + "Created": "2022-10-28T13:03:11Z", + "Published": "2022-10-28T16:36:52Z" + }, + "Repo": { + "ID": "530296249", + "Namespace": "vcalasansh", + "Name": "harness-ngtriggers-test", + "Perm": null, + "Branch": "test-branch", + "Private": true, + "Clone": "https://github.com/vcalasansh/harness-ngtriggers-test.git", + "CloneSSH": "git@github.com:vcalasansh/harness-ngtriggers-test.git", + "Link": "https://github.com/vcalasansh/harness-ngtriggers-test", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Sender": { + "Login": "vcalasansh", + "Name": "", + "Email": "", + "Avatar": "https://avatars.githubusercontent.com/u/109106581?v=4" + } +} diff --git a/scm/driver/github/testdata/webhooks/release_prereleased.json b/scm/driver/github/testdata/webhooks/release_prereleased.json new file mode 100644 index 000000000..94ab938c8 --- /dev/null +++ b/scm/driver/github/testdata/webhooks/release_prereleased.json @@ -0,0 +1,164 @@ +{ + "action": "prereleased", + "release": { + "url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309", + "assets_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309/assets", + "upload_url": "https://uploads.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309/assets{?name,label}", + "html_url": "https://github.com/vcalasansh/harness-ngtriggers-test/releases/tag/v1.0.0", + "id": 81372309, + "author": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + }, + "node_id": "RE_kwDOH5utuc4E2aSV", + "tag_name": "v1.0.0", + "target_commitish": "test-branch", + "name": "New release!", + "draft": false, + "prerelease": false, + "created_at": "2022-10-28T13:03:11Z", + "published_at": "2022-10-28T16:36:52Z", + "assets": [ + + ], + "tarball_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/tarball/v1.0.0", + "zipball_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/zipball/v1.0.0", + "body": "New release!" + }, + "repository": { + "id": 530296249, + "node_id": "R_kgDOH5utuQ", + "name": "harness-ngtriggers-test", + "full_name": "vcalasansh/harness-ngtriggers-test", + "private": true, + "owner": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/vcalasansh/harness-ngtriggers-test", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test", + "forks_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/forks", + "keys_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/teams", + "hooks_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/hooks", + "issue_events_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues/events{/number}", + "events_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/events", + "assignees_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/assignees{/user}", + "branches_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/branches{/branch}", + "tags_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/tags", + "blobs_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/statuses/{sha}", + "languages_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/languages", + "stargazers_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/stargazers", + "contributors_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/contributors", + "subscribers_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/subscribers", + "subscription_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/subscription", + "commits_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/contents/{+path}", + "compare_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/merges", + "archive_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/downloads", + "issues_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues{/number}", + "pulls_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/pulls{/number}", + "milestones_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/milestones{/number}", + "notifications_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/labels{/name}", + "releases_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases{/id}", + "deployments_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/deployments", + "created_at": "2022-08-29T16:12:07Z", + "updated_at": "2022-08-29T16:12:07Z", + "pushed_at": "2022-10-28T16:36:27Z", + "git_url": "git://github.com/vcalasansh/harness-ngtriggers-test.git", + "ssh_url": "git@github.com:vcalasansh/harness-ngtriggers-test.git", + "clone_url": "https://github.com/vcalasansh/harness-ngtriggers-test.git", + "svn_url": "https://github.com/vcalasansh/harness-ngtriggers-test", + "homepage": null, + "size": 11, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 0, + "license": null, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [ + + ], + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "test-branch" + }, + "sender": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/scm/driver/github/testdata/webhooks/release_prereleased.json.golden b/scm/driver/github/testdata/webhooks/release_prereleased.json.golden new file mode 100644 index 000000000..996beb3a6 --- /dev/null +++ b/scm/driver/github/testdata/webhooks/release_prereleased.json.golden @@ -0,0 +1,34 @@ +{ + "Action": "prereleased", + "Release": { + "ID": 81372309, + "Title": "New release!", + "Description": "New release!", + "Link": "https://github.com/vcalasansh/harness-ngtriggers-test/releases/tag/v1.0.0", + "Tag": "v1.0.0", + "Commitish": "test-branch", + "Draft": false, + "Prerelease": false, + "Created": "2022-10-28T13:03:11Z", + "Published": "2022-10-28T16:36:52Z" + }, + "Repo": { + "ID": "530296249", + "Namespace": "vcalasansh", + "Name": "harness-ngtriggers-test", + "Perm": null, + "Branch": "test-branch", + "Private": true, + "Clone": "https://github.com/vcalasansh/harness-ngtriggers-test.git", + "CloneSSH": "git@github.com:vcalasansh/harness-ngtriggers-test.git", + "Link": "https://github.com/vcalasansh/harness-ngtriggers-test", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Sender": { + "Login": "vcalasansh", + "Name": "", + "Email": "", + "Avatar": "https://avatars.githubusercontent.com/u/109106581?v=4" + } +} diff --git a/scm/driver/github/testdata/webhooks/release_published.json b/scm/driver/github/testdata/webhooks/release_published.json new file mode 100644 index 000000000..23b9bad66 --- /dev/null +++ b/scm/driver/github/testdata/webhooks/release_published.json @@ -0,0 +1,164 @@ +{ + "action": "published", + "release": { + "url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309", + "assets_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309/assets", + "upload_url": "https://uploads.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309/assets{?name,label}", + "html_url": "https://github.com/vcalasansh/harness-ngtriggers-test/releases/tag/v1.0.0", + "id": 81372309, + "author": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + }, + "node_id": "RE_kwDOH5utuc4E2aSV", + "tag_name": "v1.0.0", + "target_commitish": "test-branch", + "name": "New release!", + "draft": false, + "prerelease": false, + "created_at": "2022-10-28T13:03:11Z", + "published_at": "2022-10-28T16:36:52Z", + "assets": [ + + ], + "tarball_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/tarball/v1.0.0", + "zipball_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/zipball/v1.0.0", + "body": "New release!" + }, + "repository": { + "id": 530296249, + "node_id": "R_kgDOH5utuQ", + "name": "harness-ngtriggers-test", + "full_name": "vcalasansh/harness-ngtriggers-test", + "private": true, + "owner": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/vcalasansh/harness-ngtriggers-test", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test", + "forks_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/forks", + "keys_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/teams", + "hooks_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/hooks", + "issue_events_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues/events{/number}", + "events_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/events", + "assignees_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/assignees{/user}", + "branches_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/branches{/branch}", + "tags_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/tags", + "blobs_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/statuses/{sha}", + "languages_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/languages", + "stargazers_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/stargazers", + "contributors_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/contributors", + "subscribers_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/subscribers", + "subscription_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/subscription", + "commits_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/contents/{+path}", + "compare_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/merges", + "archive_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/downloads", + "issues_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues{/number}", + "pulls_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/pulls{/number}", + "milestones_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/milestones{/number}", + "notifications_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/labels{/name}", + "releases_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases{/id}", + "deployments_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/deployments", + "created_at": "2022-08-29T16:12:07Z", + "updated_at": "2022-08-29T16:12:07Z", + "pushed_at": "2022-10-28T16:36:27Z", + "git_url": "git://github.com/vcalasansh/harness-ngtriggers-test.git", + "ssh_url": "git@github.com:vcalasansh/harness-ngtriggers-test.git", + "clone_url": "https://github.com/vcalasansh/harness-ngtriggers-test.git", + "svn_url": "https://github.com/vcalasansh/harness-ngtriggers-test", + "homepage": null, + "size": 11, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 0, + "license": null, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [ + + ], + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "test-branch" + }, + "sender": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/scm/driver/github/testdata/webhooks/release_published.json.golden b/scm/driver/github/testdata/webhooks/release_published.json.golden new file mode 100644 index 000000000..a1f070b04 --- /dev/null +++ b/scm/driver/github/testdata/webhooks/release_published.json.golden @@ -0,0 +1,34 @@ +{ + "Action": "published", + "Release": { + "ID": 81372309, + "Title": "New release!", + "Description": "New release!", + "Link": "https://github.com/vcalasansh/harness-ngtriggers-test/releases/tag/v1.0.0", + "Tag": "v1.0.0", + "Commitish": "test-branch", + "Draft": false, + "Prerelease": false, + "Created": "2022-10-28T13:03:11Z", + "Published": "2022-10-28T16:36:52Z" + }, + "Repo": { + "ID": "530296249", + "Namespace": "vcalasansh", + "Name": "harness-ngtriggers-test", + "Perm": null, + "Branch": "test-branch", + "Private": true, + "Clone": "https://github.com/vcalasansh/harness-ngtriggers-test.git", + "CloneSSH": "git@github.com:vcalasansh/harness-ngtriggers-test.git", + "Link": "https://github.com/vcalasansh/harness-ngtriggers-test", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Sender": { + "Login": "vcalasansh", + "Name": "", + "Email": "", + "Avatar": "https://avatars.githubusercontent.com/u/109106581?v=4" + } +} diff --git a/scm/driver/github/testdata/webhooks/release_released.json b/scm/driver/github/testdata/webhooks/release_released.json new file mode 100644 index 000000000..b4af3b457 --- /dev/null +++ b/scm/driver/github/testdata/webhooks/release_released.json @@ -0,0 +1,164 @@ +{ + "action": "released", + "release": { + "url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309", + "assets_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309/assets", + "upload_url": "https://uploads.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309/assets{?name,label}", + "html_url": "https://github.com/vcalasansh/harness-ngtriggers-test/releases/tag/v1.0.0", + "id": 81372309, + "author": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + }, + "node_id": "RE_kwDOH5utuc4E2aSV", + "tag_name": "v1.0.0", + "target_commitish": "test-branch", + "name": "New release!", + "draft": false, + "prerelease": false, + "created_at": "2022-10-28T13:03:11Z", + "published_at": "2022-10-28T16:36:52Z", + "assets": [ + + ], + "tarball_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/tarball/v1.0.0", + "zipball_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/zipball/v1.0.0", + "body": "New release!" + }, + "repository": { + "id": 530296249, + "node_id": "R_kgDOH5utuQ", + "name": "harness-ngtriggers-test", + "full_name": "vcalasansh/harness-ngtriggers-test", + "private": true, + "owner": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/vcalasansh/harness-ngtriggers-test", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test", + "forks_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/forks", + "keys_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/teams", + "hooks_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/hooks", + "issue_events_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues/events{/number}", + "events_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/events", + "assignees_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/assignees{/user}", + "branches_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/branches{/branch}", + "tags_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/tags", + "blobs_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/statuses/{sha}", + "languages_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/languages", + "stargazers_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/stargazers", + "contributors_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/contributors", + "subscribers_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/subscribers", + "subscription_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/subscription", + "commits_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/contents/{+path}", + "compare_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/merges", + "archive_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/downloads", + "issues_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues{/number}", + "pulls_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/pulls{/number}", + "milestones_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/milestones{/number}", + "notifications_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/labels{/name}", + "releases_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases{/id}", + "deployments_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/deployments", + "created_at": "2022-08-29T16:12:07Z", + "updated_at": "2022-08-29T16:12:07Z", + "pushed_at": "2022-10-28T16:36:27Z", + "git_url": "git://github.com/vcalasansh/harness-ngtriggers-test.git", + "ssh_url": "git@github.com:vcalasansh/harness-ngtriggers-test.git", + "clone_url": "https://github.com/vcalasansh/harness-ngtriggers-test.git", + "svn_url": "https://github.com/vcalasansh/harness-ngtriggers-test", + "homepage": null, + "size": 11, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 0, + "license": null, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [ + + ], + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "test-branch" + }, + "sender": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/scm/driver/github/testdata/webhooks/release_released.json.golden b/scm/driver/github/testdata/webhooks/release_released.json.golden new file mode 100644 index 000000000..3e93aa08e --- /dev/null +++ b/scm/driver/github/testdata/webhooks/release_released.json.golden @@ -0,0 +1,34 @@ +{ + "Action": "released", + "Release": { + "ID": 81372309, + "Title": "New release!", + "Description": "New release!", + "Link": "https://github.com/vcalasansh/harness-ngtriggers-test/releases/tag/v1.0.0", + "Tag": "v1.0.0", + "Commitish": "test-branch", + "Draft": false, + "Prerelease": false, + "Created": "2022-10-28T13:03:11Z", + "Published": "2022-10-28T16:36:52Z" + }, + "Repo": { + "ID": "530296249", + "Namespace": "vcalasansh", + "Name": "harness-ngtriggers-test", + "Perm": null, + "Branch": "test-branch", + "Private": true, + "Clone": "https://github.com/vcalasansh/harness-ngtriggers-test.git", + "CloneSSH": "git@github.com:vcalasansh/harness-ngtriggers-test.git", + "Link": "https://github.com/vcalasansh/harness-ngtriggers-test", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Sender": { + "Login": "vcalasansh", + "Name": "", + "Email": "", + "Avatar": "https://avatars.githubusercontent.com/u/109106581?v=4" + } +} diff --git a/scm/driver/github/testdata/webhooks/release_unpublished.json b/scm/driver/github/testdata/webhooks/release_unpublished.json new file mode 100644 index 000000000..6ee38d4e2 --- /dev/null +++ b/scm/driver/github/testdata/webhooks/release_unpublished.json @@ -0,0 +1,164 @@ +{ + "action": "unpublished", + "release": { + "url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309", + "assets_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309/assets", + "upload_url": "https://uploads.github.com/repos/vcalasansh/harness-ngtriggers-test/releases/81372309/assets{?name,label}", + "html_url": "https://github.com/vcalasansh/harness-ngtriggers-test/releases/tag/v1.0.0", + "id": 81372309, + "author": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + }, + "node_id": "RE_kwDOH5utuc4E2aSV", + "tag_name": "v1.0.0", + "target_commitish": "test-branch", + "name": "New release!", + "draft": false, + "prerelease": false, + "created_at": "2022-10-28T13:03:11Z", + "published_at": "2022-10-28T16:36:52Z", + "assets": [ + + ], + "tarball_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/tarball/v1.0.0", + "zipball_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/zipball/v1.0.0", + "body": "New release!" + }, + "repository": { + "id": 530296249, + "node_id": "R_kgDOH5utuQ", + "name": "harness-ngtriggers-test", + "full_name": "vcalasansh/harness-ngtriggers-test", + "private": true, + "owner": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/vcalasansh/harness-ngtriggers-test", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test", + "forks_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/forks", + "keys_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/teams", + "hooks_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/hooks", + "issue_events_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues/events{/number}", + "events_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/events", + "assignees_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/assignees{/user}", + "branches_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/branches{/branch}", + "tags_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/tags", + "blobs_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/statuses/{sha}", + "languages_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/languages", + "stargazers_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/stargazers", + "contributors_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/contributors", + "subscribers_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/subscribers", + "subscription_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/subscription", + "commits_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/contents/{+path}", + "compare_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/merges", + "archive_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/downloads", + "issues_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/issues{/number}", + "pulls_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/pulls{/number}", + "milestones_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/milestones{/number}", + "notifications_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/labels{/name}", + "releases_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/releases{/id}", + "deployments_url": "https://api.github.com/repos/vcalasansh/harness-ngtriggers-test/deployments", + "created_at": "2022-08-29T16:12:07Z", + "updated_at": "2022-08-29T16:12:07Z", + "pushed_at": "2022-10-28T16:36:27Z", + "git_url": "git://github.com/vcalasansh/harness-ngtriggers-test.git", + "ssh_url": "git@github.com:vcalasansh/harness-ngtriggers-test.git", + "clone_url": "https://github.com/vcalasansh/harness-ngtriggers-test.git", + "svn_url": "https://github.com/vcalasansh/harness-ngtriggers-test", + "homepage": null, + "size": 11, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 0, + "license": null, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [ + + ], + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "test-branch" + }, + "sender": { + "login": "vcalasansh", + "id": 109106581, + "node_id": "U_kgDOBoDVlQ", + "avatar_url": "https://avatars.githubusercontent.com/u/109106581?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/vcalasansh", + "html_url": "https://github.com/vcalasansh", + "followers_url": "https://api.github.com/users/vcalasansh/followers", + "following_url": "https://api.github.com/users/vcalasansh/following{/other_user}", + "gists_url": "https://api.github.com/users/vcalasansh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/vcalasansh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/vcalasansh/subscriptions", + "organizations_url": "https://api.github.com/users/vcalasansh/orgs", + "repos_url": "https://api.github.com/users/vcalasansh/repos", + "events_url": "https://api.github.com/users/vcalasansh/events{/privacy}", + "received_events_url": "https://api.github.com/users/vcalasansh/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/scm/driver/github/testdata/webhooks/release_unpublished.json.golden b/scm/driver/github/testdata/webhooks/release_unpublished.json.golden new file mode 100644 index 000000000..21ea08eea --- /dev/null +++ b/scm/driver/github/testdata/webhooks/release_unpublished.json.golden @@ -0,0 +1,34 @@ +{ + "Action": "unpublished", + "Release": { + "ID": 81372309, + "Title": "New release!", + "Description": "New release!", + "Link": "https://github.com/vcalasansh/harness-ngtriggers-test/releases/tag/v1.0.0", + "Tag": "v1.0.0", + "Commitish": "test-branch", + "Draft": false, + "Prerelease": false, + "Created": "2022-10-28T13:03:11Z", + "Published": "2022-10-28T16:36:52Z" + }, + "Repo": { + "ID": "530296249", + "Namespace": "vcalasansh", + "Name": "harness-ngtriggers-test", + "Perm": null, + "Branch": "test-branch", + "Private": true, + "Clone": "https://github.com/vcalasansh/harness-ngtriggers-test.git", + "CloneSSH": "git@github.com:vcalasansh/harness-ngtriggers-test.git", + "Link": "https://github.com/vcalasansh/harness-ngtriggers-test", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Sender": { + "Login": "vcalasansh", + "Name": "", + "Email": "", + "Avatar": "https://avatars.githubusercontent.com/u/109106581?v=4" + } +} diff --git a/scm/driver/github/webhook.go b/scm/driver/github/webhook.go index e0f6ae77a..57d3ed9ed 100644 --- a/scm/driver/github/webhook.go +++ b/scm/driver/github/webhook.go @@ -46,6 +46,8 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo // case "issues": case "issue_comment": hook, err = s.parseIssueCommentHook(data) + case "release": + hook, err = s.parseReleaseHook(data) default: return nil, scm.ErrUnknownEvent } @@ -178,6 +180,34 @@ func (s *webhookService) parsePullRequestHook(data []byte) (scm.Webhook, error) return dst, nil } +func (s *webhookService) parseReleaseHook(data []byte) (scm.Webhook, error) { + src := new(releaseHook) + err := json.Unmarshal(data, src) + if err != nil { + return nil, err + } + dst := convertReleaseHook(src) + switch src.Action { + case "created": + dst.Action = scm.ActionCreate + case "edited": + dst.Action = scm.ActionEdit + case "deleted": + dst.Action = scm.ActionDelete + case "published": + dst.Action = scm.ActionPublish + case "unpublished": + dst.Action = scm.ActionUnpublish + case "prereleased": + dst.Action = scm.ActionPrerelease + case "released": + dst.Action = scm.ActionRelease + default: + dst.Action = scm.ActionUnknown + } + return dst, nil +} + // // native data structures // @@ -301,6 +331,25 @@ type ( Updated time.Time `json:"updated_at"` } `json:"comment"` } + + // github release webhook payload + releaseHook struct { + Action string `json:"action"` + Release struct { + ID int `json:"id"` + Title string `json:"name"` + Description string `json:"body"` + Link string `json:"html_url,omitempty"` + Tag string `json:"tag_name,omitempty"` + Commitish string `json:"target_commitish,omitempty"` + Draft bool `json:"draft"` + Prerelease bool `json:"prerelease"` + Created time.Time `json:"created_at"` + Published time.Time `json:"published_at"` + } `json:"release"` + Repository repository `json:"repository"` + Sender user `json:"sender"` + } ) // @@ -500,6 +549,36 @@ func convertIssueCommentHook(src *issueCommentHook) *scm.IssueCommentHook { return dst } +func convertReleaseHook(src *releaseHook) *scm.ReleaseHook { + dst := &scm.ReleaseHook{ + Release: scm.Release{ + ID: src.Release.ID, + Title: src.Release.Title, + Description: src.Release.Description, + Link: src.Release.Link, + Tag: src.Release.Tag, + Commitish: src.Release.Commitish, + Draft: src.Release.Draft, + Prerelease: src.Release.Prerelease, + Created: src.Release.Created, + Published: src.Release.Published, + }, + Repo: scm.Repository{ + ID: fmt.Sprint(src.Repository.ID), + Namespace: src.Repository.Owner.Login, + Name: src.Repository.Name, + Branch: src.Repository.DefaultBranch, + Private: src.Repository.Private, + Visibility: convertVisibility(src.Repository.Visibility), + Clone: src.Repository.CloneURL, + CloneSSH: src.Repository.SSHURL, + Link: src.Repository.HTMLURL, + }, + Sender: *convertUser(&src.Sender), + } + return dst +} + // regexp help determine if the named git object is a tag. // this is not meant to be 100% accurate. var tagRE = regexp.MustCompile("^v?(\\d+).(.+)") diff --git a/scm/driver/github/webhook_test.go b/scm/driver/github/webhook_test.go index e54970f0d..7d3621c94 100644 --- a/scm/driver/github/webhook_test.go +++ b/scm/driver/github/webhook_test.go @@ -185,6 +185,51 @@ func TestWebhooks(t *testing.T) { after: "testdata/webhooks/deployment_commit.json.golden", obj: new(scm.DeployHook), }, + // + // release + // + { + event: "release", + before: "testdata/webhooks/release_published.json", + after: "testdata/webhooks/release_published.json.golden", + obj: new(scm.ReleaseHook), + }, + { + event: "release", + before: "testdata/webhooks/release_unpublished.json", + after: "testdata/webhooks/release_unpublished.json.golden", + obj: new(scm.ReleaseHook), + }, + { + event: "release", + before: "testdata/webhooks/release_created.json", + after: "testdata/webhooks/release_created.json.golden", + obj: new(scm.ReleaseHook), + }, + { + event: "release", + before: "testdata/webhooks/release_edited.json", + after: "testdata/webhooks/release_edited.json.golden", + obj: new(scm.ReleaseHook), + }, + { + event: "release", + before: "testdata/webhooks/release_deleted.json", + after: "testdata/webhooks/release_deleted.json.golden", + obj: new(scm.ReleaseHook), + }, + { + event: "release", + before: "testdata/webhooks/release_prereleased.json", + after: "testdata/webhooks/release_prereleased.json.golden", + obj: new(scm.ReleaseHook), + }, + { + event: "release", + before: "testdata/webhooks/release_released.json", + after: "testdata/webhooks/release_released.json.golden", + obj: new(scm.ReleaseHook), + }, } for _, test := range tests { diff --git a/scm/webhook.go b/scm/webhook.go index b36c25feb..f6875f6f2 100644 --- a/scm/webhook.go +++ b/scm/webhook.go @@ -115,6 +115,15 @@ type ( Task string } + // ReleaseHook represents a release event. This is + // currently a GitHub-specific event type. + ReleaseHook struct { + Action Action + Release Release + Repo Repository + Sender User + } + // SecretFunc provides the Webhook parser with the // secret key used to validate webhook authenticity. SecretFunc func(webhook Webhook) (string, error) @@ -140,3 +149,4 @@ func (h *IssueCommentHook) Repository() Repository { return h.Repo } func (h *PullRequestHook) Repository() Repository { return h.Repo } func (h *PullRequestCommentHook) Repository() Repository { return h.Repo } func (h *ReviewCommentHook) Repository() Repository { return h.Repo } +func (h *ReleaseHook) Repository() Repository { return h.Repo } From 5f3c26274ccaf748b36ee9a29bf1363f37b7ee87 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Tue, 22 Nov 2022 15:57:05 +0000 Subject: [PATCH 142/282] (maint) release prep for 1.28.0 (#232) --- CHANGELOG.md | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ccb06957..0d74e8c58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,44 @@ # Changelog -## [v1.27.0](https://github.com/drone/go-scm/tree/v1.27.0) (2022-07-18) +## [1.28.0](https://github.com/drone/go-scm/tree/1.28.0) (2022-11-22) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.27.0...1.28.0) + +**Implemented enhancements:** + +- Add Actor UUID to push and branch create events for Bitbucket [\#230](https://github.com/drone/go-scm/pull/230) ([rutvijmehta-harness](https://github.com/rutvijmehta-harness)) +- Add support for Github release webhook [\#229](https://github.com/drone/go-scm/pull/229) ([vcalasansh](https://github.com/vcalasansh)) +- Add Actor UUID to Sender for all webhooks responses for Bitbucket [\#227](https://github.com/drone/go-scm/pull/227) ([rutvijmehta-harness](https://github.com/rutvijmehta-harness)) +- added date info for commits in push hook [\#223](https://github.com/drone/go-scm/pull/223) ([raghavharness](https://github.com/raghavharness)) +- Added support for branch in list commits bb onprem API [\#215](https://github.com/drone/go-scm/pull/215) ([mohitg0795](https://github.com/mohitg0795)) +- \[PL-26239\]: added api to list installation for github app [\#213](https://github.com/drone/go-scm/pull/213) ([bhavya181](https://github.com/bhavya181)) + +**Fixed bugs:** + +- fixbug: gitee convert repository [\#226](https://github.com/drone/go-scm/pull/226) ([kit101](https://github.com/kit101)) +- Bitbucket sha fix for merged pr [\#225](https://github.com/drone/go-scm/pull/225) ([raghavharness](https://github.com/raghavharness)) +- decoding projectName for azure repo [\#224](https://github.com/drone/go-scm/pull/224) ([raghavharness](https://github.com/raghavharness)) +- added omitempty annotation for secret [\#221](https://github.com/drone/go-scm/pull/221) ([raghavharness](https://github.com/raghavharness)) +- \[PL-26239\]: fix for list response [\#218](https://github.com/drone/go-scm/pull/218) ([bhavya181](https://github.com/bhavya181)) + +**Closed issues:** + +- gitlab: force\_remove\_source\_branch type is inconsistent [\#228](https://github.com/drone/go-scm/issues/228) +- gitee: When the name and path are inconsistent, got 404 error [\#217](https://github.com/drone/go-scm/issues/217) +- file naming conventions [\#208](https://github.com/drone/go-scm/issues/208) +- Support for Azure Devops git repos? [\#53](https://github.com/drone/go-scm/issues/53) + +**Merged pull requests:** + +- \(maint\) fixing naming and add more go best practice [\#211](https://github.com/drone/go-scm/pull/211) ([tphoney](https://github.com/tphoney)) + +## [v1.27.0](https://github.com/drone/go-scm/tree/v1.27.0) (2022-07-19) [Full Changelog](https://github.com/drone/go-scm/compare/v1.26.0...v1.27.0) **Merged pull requests:** +- Update scm version 1.27.0 [\#206](https://github.com/drone/go-scm/pull/206) ([raghavharness](https://github.com/raghavharness)) - Using resource version 2.0 for Azure [\#205](https://github.com/drone/go-scm/pull/205) ([raghavharness](https://github.com/raghavharness)) ## [v1.26.0](https://github.com/drone/go-scm/tree/v1.26.0) (2022-07-01) From ef3c3cc4886311ff6617e78f9e8537633a53b241 Mon Sep 17 00:00:00 2001 From: Mohit Garg Date: Fri, 27 Jan 2023 15:39:44 +0530 Subject: [PATCH 143/282] feat: [PIE-7927]: added header to avoid/bypass csrf check (#234) --- scm/driver/stash/stash.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scm/driver/stash/stash.go b/scm/driver/stash/stash.go index 440cf3844..60511ed7d 100644 --- a/scm/driver/stash/stash.go +++ b/scm/driver/stash/stash.go @@ -69,7 +69,8 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface Method: method, Path: path, Header: map[string][]string{ - "Accept": {"application/json"}, + "Accept": {"application/json"}, + "x-atlassian-token": {"no-token"}, }, } // if we are posting or putting data, we need to From 4121e2cc0f3d9a2f8c39aa5886ae8768e181c0b5 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Fri, 27 Jan 2023 10:25:10 +0000 Subject: [PATCH 144/282] (maint) prep 1.28.1 release (#235) --- CHANGELOG.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d74e8c58..5f8653ef1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,20 @@ # Changelog -## [1.28.0](https://github.com/drone/go-scm/tree/1.28.0) (2022-11-22) +## [1.28.1](https://github.com/drone/go-scm/tree/1.28.1) (2023-01-27) -[Full Changelog](https://github.com/drone/go-scm/compare/v1.27.0...1.28.0) +[Full Changelog](https://github.com/drone/go-scm/compare/v1.28.0...1.28.1) + +**Fixed bugs:** + +- feat: \[PIE-7927\]: added header to avoid/bypass csrf check [\#234](https://github.com/drone/go-scm/pull/234) ([mohitg0795](https://github.com/mohitg0795)) + +**Closed issues:** + +- Gogs commit fails to deserialize commitDetails in some cases [\#231](https://github.com/drone/go-scm/issues/231) + +## [v1.28.0](https://github.com/drone/go-scm/tree/v1.28.0) (2022-11-22) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.27.0...v1.28.0) **Implemented enhancements:** @@ -30,6 +42,7 @@ **Merged pull requests:** +- \(maint\) release prep for 1.28.0 [\#232](https://github.com/drone/go-scm/pull/232) ([tphoney](https://github.com/tphoney)) - \(maint\) fixing naming and add more go best practice [\#211](https://github.com/drone/go-scm/pull/211) ([tphoney](https://github.com/tphoney)) ## [v1.27.0](https://github.com/drone/go-scm/tree/v1.27.0) (2022-07-19) From 4428a9bf64df846195cf80ba133a5be2f3f5091a Mon Sep 17 00:00:00 2001 From: Mohit Garg Date: Mon, 30 Jan 2023 16:52:42 +0530 Subject: [PATCH 145/282] fix: [PIE-7927]: Fix header value typo issue for BB OnPrem CSRF header (#236) --- scm/driver/stash/stash.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/driver/stash/stash.go b/scm/driver/stash/stash.go index 60511ed7d..33f3d5711 100644 --- a/scm/driver/stash/stash.go +++ b/scm/driver/stash/stash.go @@ -70,7 +70,7 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface Path: path, Header: map[string][]string{ "Accept": {"application/json"}, - "x-atlassian-token": {"no-token"}, + "x-atlassian-token": {"no-check"}, }, } // if we are posting or putting data, we need to From ca3776c0f0b280b28bd7a8d0298fb207a4d8072b Mon Sep 17 00:00:00 2001 From: TP Honey Date: Mon, 6 Feb 2023 16:36:56 +0000 Subject: [PATCH 146/282] Harness move (#237) * (feat) initial commit for harness code * (feat) harness, add update delete create file --- scm/const.go | 3 + scm/driver/harness/content.go | 234 ++++++++++++ scm/driver/harness/content_test.go | 208 ++++++++++ scm/driver/harness/git.go | 187 +++++++++ scm/driver/harness/git_test.go | 5 + scm/driver/harness/harness.go | 108 ++++++ scm/driver/harness/harness_test.go | 47 +++ scm/driver/harness/issue.go | 147 +++++++ scm/driver/harness/issue_test.go | 5 + scm/driver/harness/linker.go | 27 ++ scm/driver/harness/linker_test.go | 5 + scm/driver/harness/milestone.go | 90 +++++ scm/driver/harness/milestone_test.go | 1 + scm/driver/harness/org.go | 57 +++ scm/driver/harness/org_test.go | 5 + scm/driver/harness/pr.go | 157 ++++++++ scm/driver/harness/pr_test.go | 5 + scm/driver/harness/release.go | 112 ++++++ scm/driver/harness/release_test.go | 1 + scm/driver/harness/repo.go | 273 +++++++++++++ scm/driver/harness/repo_test.go | 9 + scm/driver/harness/review.go | 31 ++ scm/driver/harness/review_test.go | 5 + scm/driver/harness/testdata/content.json | 30 ++ scm/driver/harness/testdata/content_list.json | 79 ++++ .../harness/testdata/content_list.json.golden | 14 + .../webhooks/pull_request_opened.json | 172 +++++++++ .../webhooks/pull_request_opened.json.golden | 47 +++ scm/driver/harness/user.go | 66 ++++ scm/driver/harness/user_test.go | 5 + scm/driver/harness/util.go | 103 +++++ scm/driver/harness/util_test.go | 81 ++++ scm/driver/harness/webhook.go | 361 ++++++++++++++++++ scm/driver/harness/webhook_test.go | 5 + 34 files changed, 2685 insertions(+) create mode 100644 scm/driver/harness/content.go create mode 100644 scm/driver/harness/content_test.go create mode 100644 scm/driver/harness/git.go create mode 100644 scm/driver/harness/git_test.go create mode 100644 scm/driver/harness/harness.go create mode 100644 scm/driver/harness/harness_test.go create mode 100644 scm/driver/harness/issue.go create mode 100644 scm/driver/harness/issue_test.go create mode 100644 scm/driver/harness/linker.go create mode 100644 scm/driver/harness/linker_test.go create mode 100644 scm/driver/harness/milestone.go create mode 100644 scm/driver/harness/milestone_test.go create mode 100644 scm/driver/harness/org.go create mode 100644 scm/driver/harness/org_test.go create mode 100644 scm/driver/harness/pr.go create mode 100644 scm/driver/harness/pr_test.go create mode 100644 scm/driver/harness/release.go create mode 100644 scm/driver/harness/release_test.go create mode 100644 scm/driver/harness/repo.go create mode 100644 scm/driver/harness/repo_test.go create mode 100644 scm/driver/harness/review.go create mode 100644 scm/driver/harness/review_test.go create mode 100644 scm/driver/harness/testdata/content.json create mode 100644 scm/driver/harness/testdata/content_list.json create mode 100644 scm/driver/harness/testdata/content_list.json.golden create mode 100644 scm/driver/harness/testdata/webhooks/pull_request_opened.json create mode 100644 scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden create mode 100644 scm/driver/harness/user.go create mode 100644 scm/driver/harness/user_test.go create mode 100644 scm/driver/harness/util.go create mode 100644 scm/driver/harness/util_test.go create mode 100644 scm/driver/harness/webhook.go create mode 100644 scm/driver/harness/webhook_test.go diff --git a/scm/const.go b/scm/const.go index 84fb47151..dca74b699 100644 --- a/scm/const.go +++ b/scm/const.go @@ -146,6 +146,7 @@ const ( DriverCoding DriverGitee DriverAzure + DriverHarness ) // String returns the string representation of Driver. @@ -169,6 +170,8 @@ func (d Driver) String() (s string) { return "gitee" case DriverAzure: return "azure" + case DriverHarness: + return "harness" default: return "unknown" } diff --git a/scm/driver/harness/content.go b/scm/driver/harness/content.go new file mode 100644 index 000000000..e5e7724b3 --- /dev/null +++ b/scm/driver/harness/content.go @@ -0,0 +1,234 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness + +import ( + "context" + "encoding/base64" + "fmt" + "time" + + "github.com/drone/go-scm/scm" +) + +type contentService struct { + client *wrapper +} + +func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm.Content, *scm.Response, error) { + repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + endpoint := fmt.Sprintf("api/v1/repos/%s/content/%s?%s&include_commit=true", repo, path, ref) + out := new(fileContent) + res, err := s.client.do(ctx, "GET", endpoint, nil, out) + // decode raw output content + raw, _ := base64.StdEncoding.DecodeString(out.Content.Data) + return &scm.Content{ + Path: path, + Sha: out.LatestCommit.Sha, + BlobID: out.Sha, + Data: raw, + }, res, err +} + +func (s *contentService) Create(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { + repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + endpoint := fmt.Sprintf("api/v1/repos/%s/commits", repo) + a := action{ + Action: "CREATE", + Path: path, + Payload: string(params.Data), + Encoding: "string", + } + in := editFile{ + Branch: params.Branch, + Message: params.Message, + Title: params.Message, + Actions: []action{a}, + } + + res, err := s.client.do(ctx, "POST", endpoint, in, nil) + return res, err +} + +func (s *contentService) Update(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { + repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + endpoint := fmt.Sprintf("api/v1/repos/%s/commits", repo) + a := action{ + Action: "UPDATE", + Path: path, + Payload: string(params.Data), + Encoding: "string", + } + in := editFile{ + Branch: params.Branch, + Message: params.Message, + Title: params.Message, + Actions: []action{a}, + } + + res, err := s.client.do(ctx, "POST", endpoint, in, nil) + return res, err +} + +func (s *contentService) Delete(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { + repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + endpoint := fmt.Sprintf("api/v1/repos/%s/commits", repo) + a := action{ + Action: "DELETE", + Path: path, + Encoding: "string", + } + in := editFile{ + Branch: params.Branch, + Message: params.Message, + Title: params.Message, + Actions: []action{a}, + } + + res, err := s.client.do(ctx, "POST", endpoint, in, nil) + return res, err +} + +func buildHarnessURI(account, organization, project, repo string) (uri string) { + if account != "" { + return fmt.Sprintf("%s/%s/%s/%s/+", account, organization, project, repo) + } + return repo +} + +func (s *contentService) List(ctx context.Context, repo, path, ref string, _ scm.ListOptions) ([]*scm.ContentInfo, *scm.Response, error) { + repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + endpoint := fmt.Sprintf("api/v1/repos/%s/content/%s?%s&include_commit=true", repo, path, ref) + out := new(contentList) + res, err := s.client.do(ctx, "GET", endpoint, nil, &out) + return convertContentInfoList(out.Content.Entries), res, err +} + +type editFile struct { + Actions []action `json:"actions"` + Branch string `json:"branch"` + Message string `json:"message"` + NewBranch string `json:"new_branch"` + Title string `json:"title"` +} + +type action struct { + Action string `json:"action"` + Encoding string `json:"encoding"` + Path string `json:"path"` + Payload string `json:"payload"` + Sha string `json:"sha"` +} + +type fileContent struct { + Type string `json:"type"` + Sha string `json:"sha"` + Name string `json:"name"` + Path string `json:"path"` + LatestCommit struct { + Sha string `json:"sha"` + Title string `json:"title"` + Message string `json:"message"` + Author struct { + Identity struct { + Name string `json:"name"` + Email string `json:"email"` + } `json:"identity"` + When time.Time `json:"when"` + } `json:"author"` + Committer struct { + Identity struct { + Name string `json:"name"` + Email string `json:"email"` + } `json:"identity"` + When time.Time `json:"when"` + } `json:"committer"` + } `json:"latest_commit"` + Content struct { + Encoding string `json:"encoding"` + Data string `json:"data"` + Size int `json:"size"` + } `json:"content"` +} + +type contentList struct { + Type string `json:"type"` + Sha string `json:"sha"` + Name string `json:"name"` + Path string `json:"path"` + LatestCommit struct { + Sha string `json:"sha"` + Title string `json:"title"` + Message string `json:"message"` + Author struct { + Identity struct { + Name string `json:"name"` + Email string `json:"email"` + } `json:"identity"` + When time.Time `json:"when"` + } `json:"author"` + Committer struct { + Identity struct { + Name string `json:"name"` + Email string `json:"email"` + } `json:"identity"` + When time.Time `json:"when"` + } `json:"committer"` + } `json:"latest_commit"` + Content struct { + Entries []fileEntry `json:"entries"` + } `json:"content"` +} + +type fileEntry struct { + Type string `json:"type"` + Sha string `json:"sha"` + Name string `json:"name"` + Path string `json:"path"` + LatestCommit struct { + Sha string `json:"sha"` + Title string `json:"title"` + Message string `json:"message"` + Author struct { + Identity struct { + Name string `json:"name"` + Email string `json:"email"` + } `json:"identity"` + When time.Time `json:"when"` + } `json:"author"` + Committer struct { + Identity struct { + Name string `json:"name"` + Email string `json:"email"` + } `json:"identity"` + When time.Time `json:"when"` + } `json:"committer"` + } `json:"latest_commit"` +} + +func convertContentInfoList(from []fileEntry) []*scm.ContentInfo { + to := []*scm.ContentInfo{} + for _, v := range from { + to = append(to, convertContentInfo(v)) + } + return to +} + +func convertContentInfo(from fileEntry) *scm.ContentInfo { + to := &scm.ContentInfo{ + Path: from.Path, + Sha: from.LatestCommit.Sha, + BlobID: from.Sha, + } + switch from.Type { + case "file": + to.Kind = scm.ContentKindFile + case "dir": + to.Kind = scm.ContentKindDirectory + default: + to.Kind = scm.ContentKindUnsupported + } + return to +} diff --git a/scm/driver/harness/content_test.go b/scm/driver/harness/content_test.go new file mode 100644 index 000000000..feba75672 --- /dev/null +++ b/scm/driver/harness/content_test.go @@ -0,0 +1,208 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness + +import ( + "context" + "encoding/json" + "io/ioutil" + "net/http" + "strings" + "testing" + + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/transport" + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" +) + +const ( + gockOrigin = "https://qa.harness.io/gateway/code" + harnessOrg = "px7xd_BFRCi-pfWPYXVjvw" + harnessAccount = "default" + harnessProject = "codeciintegration" + harnessRepo = "demo" + harnessPAT = "" +) + +func TestContentFind(t *testing.T) { + defer gock.Off() + + gock.New(gockOrigin). + Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo/+/content/README.md"). + Reply(200). + Type("plain/text"). + File("testdata/content.json") + + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + result, _, err := client.Contents.Find( + context.Background(), + harnessRepo, + "README.md", + "98189d5cf2a751a6246c24a72945ba70839f1b20", + ) + if err != nil { + t.Error(err) + } + + if got, want := result.Path, "README.md"; got != want { + t.Errorf("Want file Path %q, got %q", want, got) + } + if !strings.Contains(string(result.Data), "demo") { + t.Errorf("Want file Data %q, must contain 'demo'", result.Data) + } +} + +func TestContentCreate(t *testing.T) { + defer gock.Off() + + gock.New(gockOrigin). + Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo/+/commits"). + Reply(200). + Type("plain/text"). + BodyString("{\"commit_id\":\"20ecde1f8c277da0e91750bef9f3b88f228d86db\"}") + + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + result, err := client.Contents.Create( + context.Background(), + harnessRepo, + "README.2", + &scm.ContentParams{ + Data: []byte("hello world"), + Message: "create README.2", + Branch: "main", + }, + ) + if err != nil { + t.Error(err) + } + + if result.Status != 200 { + t.Errorf("Unexpected Results") + } +} + +func TestContentUpdate(t *testing.T) { + defer gock.Off() + + gock.New(gockOrigin). + Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo/+/commits"). + Reply(200). + Type("plain/text"). + BodyString("{\"commit_id\":\"20ecde1f8c277da0e91750bef9f3b88f228d86db\"}") + + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + result, err := client.Contents.Update( + context.Background(), + harnessRepo, + "README.2", + &scm.ContentParams{ + Data: []byte("hello world 2"), + Message: "update README.2", + Branch: "main", + }, + ) + if err != nil { + t.Error(err) + } + + if result.Status != 200 { + t.Errorf("Unexpected Results") + } +} + +func TestContentDelete(t *testing.T) { + defer gock.Off() + + gock.New(gockOrigin). + Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo/+/commits"). + Reply(200). + Type("plain/text"). + BodyString("{\"commit_id\":\"20ecde1f8c277da0e91750bef9f3b88f228d86db\"}") + + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + result, err := client.Contents.Delete( + context.Background(), + harnessRepo, + "README.2", + &scm.ContentParams{ + Message: "delete README.2", + Branch: "main", + }, + ) + if err != nil { + t.Error(err) + } + + if result.Status != 200 { + t.Errorf("Unexpected Results") + } +} + +func TestContentList(t *testing.T) { + defer gock.Off() + + gock.New(gockOrigin). + Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo/+/content/docker"). + Reply(200). + Type("application/json"). + File("testdata/content_list.json") + + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + got, _, err := client.Contents.List( + context.Background(), + harnessRepo, + "docker", + "", + scm.ListOptions{}, + ) + if err != nil { + t.Error(err) + } + + want := []*scm.ContentInfo{} + raw, _ := ioutil.ReadFile("testdata/content_list.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} diff --git a/scm/driver/harness/git.go b/scm/driver/harness/git.go new file mode 100644 index 000000000..47b228021 --- /dev/null +++ b/scm/driver/harness/git.go @@ -0,0 +1,187 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness + +import ( + "context" + "fmt" + "net/url" + "time" + + "github.com/drone/go-scm/scm" +) + +type gitService struct { + client *wrapper +} + +func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.ReferenceInput) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { + path := fmt.Sprintf("api/v1/repos/%s/branches/%s", repo, name) + out := new(branch) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertBranch(out), res, err +} + +func (s *gitService) FindCommit(ctx context.Context, repo, ref string) (*scm.Commit, *scm.Response, error) { + ref = scm.TrimRef(ref) + path := fmt.Sprintf("api/v1/repos/%s/git/commits/%s", repo, url.PathEscape(ref)) + out := new(commitInfo) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertCommitInfo(out), res, err +} + +func (s *gitService) FindTag(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *gitService) ListBranches(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { + path := fmt.Sprintf("api/v1/repos/%s/branches?%s", repo, encodeListOptions(opts)) + out := []*branch{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertBranchList(out), res, err +} + +func (s *gitService) ListCommits(ctx context.Context, repo string, _ scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { + path := fmt.Sprintf("api/v1/repos/%s/commits", repo) + out := []*commitInfo{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertCommitList(out), res, err +} + +func (s *gitService) ListTags(ctx context.Context, repo string, _ scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *gitService) ListChanges(ctx context.Context, repo, ref string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +// +// native data structures +// + +type ( + // gitea branch object. + branch struct { + Name string `json:"name"` + Commit commit `json:"commit"` + } + + // gitea commit object. + commit struct { + ID string `json:"id"` + Sha string `json:"sha"` + Message string `json:"message"` + URL string `json:"url"` + Author signature `json:"author"` + Committer signature `json:"committer"` + Timestamp time.Time `json:"timestamp"` + } + + // gitea commit info object. + commitInfo struct { + Sha string `json:"sha"` + Commit commit `json:"commit"` + Author user `json:"author"` + Committer user `json:"committer"` + } + + // gitea signature object. + signature struct { + Name string `json:"name"` + Email string `json:"email"` + Username string `json:"username"` + } + + // gitea tag object + tag struct { + Ref string `json:"ref"` + URL string `json:"url"` + Object struct { + Type string `json:"type"` + Sha string `json:"sha"` + URL string `json:"url"` + } `json:"object"` + } +) + +// +// native data structure conversion +// + +func convertBranchList(src []*branch) []*scm.Reference { + dst := []*scm.Reference{} + for _, v := range src { + dst = append(dst, convertBranch(v)) + } + return dst +} + +func convertBranch(src *branch) *scm.Reference { + return &scm.Reference{ + Name: scm.TrimRef(src.Name), + Path: scm.ExpandRef(src.Name, "refs/heads/"), + Sha: src.Commit.ID, + } +} + +func convertCommitList(src []*commitInfo) []*scm.Commit { + dst := []*scm.Commit{} + for _, v := range src { + dst = append(dst, convertCommitInfo(v)) + } + return dst +} + +func convertCommitInfo(src *commitInfo) *scm.Commit { + return &scm.Commit{ + Sha: src.Sha, + Link: src.Commit.URL, + Message: src.Commit.Message, + Author: convertUserSignature(src.Author), + Committer: convertUserSignature(src.Committer), + } +} + +func convertSignature(src signature) scm.Signature { + return scm.Signature{ + Login: src.Username, + Email: src.Email, + Name: src.Name, + } +} + +func convertUserSignature(src user) scm.Signature { + return scm.Signature{ + Login: userLogin(&src), + Email: src.Email, + Name: src.Fullname, + Avatar: src.Avatar, + } +} + +func convertTagList(src []*tag) []*scm.Reference { + var dst []*scm.Reference + for _, v := range src { + dst = append(dst, convertTag(v)) + } + return dst +} + +func convertTag(src *tag) *scm.Reference { + return &scm.Reference{ + Name: scm.TrimRef(src.Ref), + Path: src.Ref, + Sha: src.Object.Sha, + } +} diff --git a/scm/driver/harness/git_test.go b/scm/driver/harness/git_test.go new file mode 100644 index 000000000..5d232e2ff --- /dev/null +++ b/scm/driver/harness/git_test.go @@ -0,0 +1,5 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness diff --git a/scm/driver/harness/harness.go b/scm/driver/harness/harness.go new file mode 100644 index 000000000..d26835374 --- /dev/null +++ b/scm/driver/harness/harness.go @@ -0,0 +1,108 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "net/url" + "strings" + + "github.com/drone/go-scm/scm" +) + +// New returns a new gitness API client. +func New(uri, account, organization, project string) (*scm.Client, error) { + if !((organization == "" && account == "" && project == "") || (organization != "" && account != "" && project != "")) { + return nil, fmt.Errorf("harness account, organization and project are required") + } + base, err := url.Parse(uri) + if err != nil { + return nil, err + } + if !strings.HasSuffix(base.Path, "/") { + base.Path = base.Path + "/" + } + client := &wrapper{new(scm.Client), account, organization, project} + client.BaseURL = base + // initialize services + client.Driver = scm.DriverGitea + client.Linker = &linker{base.String()} + client.Contents = &contentService{client} + client.Git = &gitService{client} + client.Issues = &issueService{client} + client.Milestones = &milestoneService{client} + client.Organizations = &organizationService{client} + client.PullRequests = &pullService{client} + client.Repositories = &repositoryService{client} + client.Releases = &releaseService{client} + client.Reviews = &reviewService{client} + client.Users = &userService{client} + client.Webhooks = &webhookService{client} + return client.Client, nil +} + +// wraper wraps the Client to provide high level helper functions +// for making http requests and unmarshaling the response. +type wrapper struct { + *scm.Client + account string + organization string + project string +} + +// do wraps the Client.Do function by creating the Request and +// unmarshalling the response. +func (c *wrapper) do(ctx context.Context, method, path string, in, out interface{}) (*scm.Response, error) { + req := &scm.Request{ + Method: method, + Path: path, + } + // if we are posting or putting data, we need to + // write it to the body of the request. + if in != nil { + buf := new(bytes.Buffer) + json.NewEncoder(buf).Encode(in) + req.Header = map[string][]string{ + "Content-Type": {"application/json"}, + } + req.Body = buf + } + + // execute the http request + res, err := c.Client.Do(ctx, req) + if err != nil { + return nil, err + } + defer res.Body.Close() + + // if an error is encountered, unmarshal and return the + // error response. + if res.Status > 300 { + return res, errors.New( + http.StatusText(res.Status), + ) + } + + if out == nil { + return res, nil + } + + // if raw output is expected, copy to the provided + // buffer and exit. + if w, ok := out.(io.Writer); ok { + io.Copy(w, res.Body) + return res, nil + } + + // if a json response is expected, parse and return + // the json response. + return res, json.NewDecoder(res.Body).Decode(out) +} diff --git a/scm/driver/harness/harness_test.go b/scm/driver/harness/harness_test.go new file mode 100644 index 000000000..a1ccc6f90 --- /dev/null +++ b/scm/driver/harness/harness_test.go @@ -0,0 +1,47 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// package gitea implements a Gogs client. +package harness + +import ( + "fmt" + "testing" + + "github.com/drone/go-scm/scm" +) + +func TestClient(t *testing.T) { + client, err := New(gockOrigin, "", "", "") + if err != nil { + t.Error(err) + } + if got, want := client.BaseURL.String(), fmt.Sprintf("%s/", gockOrigin); got != want { + t.Errorf("Want Client URL %q, got %q", want, got) + } +} + +func TestClient_Error(t *testing.T) { + _, err := New("http://a b.com/", "", "", "") + if err == nil { + t.Errorf("Expect error when invalid URL") + } +} + +func testPage(res *scm.Response) func(t *testing.T) { + return func(t *testing.T) { + if got, want := res.Page.Next, 2; got != want { + t.Errorf("Want next page %d, got %d", want, got) + } + if got, want := res.Page.Prev, 1; got != want { + t.Errorf("Want prev page %d, got %d", want, got) + } + if got, want := res.Page.First, 1; got != want { + t.Errorf("Want first page %d, got %d", want, got) + } + if got, want := res.Page.Last, 5; got != want { + t.Errorf("Want last page %d, got %d", want, got) + } + } +} diff --git a/scm/driver/harness/issue.go b/scm/driver/harness/issue.go new file mode 100644 index 000000000..6eab881c5 --- /dev/null +++ b/scm/driver/harness/issue.go @@ -0,0 +1,147 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness + +import ( + "context" + "time" + + "github.com/drone/go-scm/scm" +) + +type issueService struct { + client *wrapper +} + +func (s *issueService) Find(ctx context.Context, repo string, number int) (*scm.Issue, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *issueService) FindComment(ctx context.Context, repo string, index, id int) (*scm.Comment, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *issueService) List(ctx context.Context, repo string, opts scm.IssueListOptions) ([]*scm.Issue, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported + +} + +func (s *issueService) ListComments(ctx context.Context, repo string, index int, opts scm.ListOptions) ([]*scm.Comment, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported + +} + +func (s *issueService) Create(ctx context.Context, repo string, input *scm.IssueInput) (*scm.Issue, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported + +} + +func (s *issueService) CreateComment(ctx context.Context, repo string, index int, input *scm.CommentInput) (*scm.Comment, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *issueService) DeleteComment(ctx context.Context, repo string, index, id int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *issueService) Close(ctx context.Context, repo string, number int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *issueService) Lock(ctx context.Context, repo string, number int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *issueService) Unlock(ctx context.Context, repo string, number int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +// +// native data structures +// + +type ( + // gitea issue response object. + issue struct { + ID int `json:"id"` + Number int `json:"number"` + User user `json:"user"` + Title string `json:"title"` + Body string `json:"body"` + State string `json:"state"` + Labels []string `json:"labels"` + Comments int `json:"comments"` + Created time.Time `json:"created_at"` + Updated time.Time `json:"updated_at"` + PullRequest *struct { + Merged bool `json:"merged"` + MergedAt interface{} `json:"merged_at"` + } `json:"pull_request"` + } + + // gitea issue request object. + issueInput struct { + Title string `json:"title"` + Body string `json:"body"` + } + + // gitea issue comment response object. + issueComment struct { + ID int `json:"id"` + HTMLURL string `json:"html_url"` + User user `json:"user"` + Body string `json:"body"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + } + + // gitea issue comment request object. + issueCommentInput struct { + Body string `json:"body"` + } +) + +// +// native data structure conversion +// + +func convertIssueList(from []*issue) []*scm.Issue { + to := []*scm.Issue{} + for _, v := range from { + to = append(to, convertIssue(v)) + } + return to +} + +func convertIssue(from *issue) *scm.Issue { + return &scm.Issue{ + Number: from.Number, + Title: from.Title, + Body: from.Body, + Link: "", // TODO construct the link to the issue. + Closed: from.State == "closed", + Author: *convertUser(&from.User), + Created: from.Created, + Updated: from.Updated, + } +} + +func convertIssueCommentList(from []*issueComment) []*scm.Comment { + to := []*scm.Comment{} + for _, v := range from { + to = append(to, convertIssueComment(v)) + } + return to +} + +func convertIssueComment(from *issueComment) *scm.Comment { + return &scm.Comment{ + ID: from.ID, + Body: from.Body, + Author: *convertUser(&from.User), + Created: from.CreatedAt, + Updated: from.UpdatedAt, + } +} diff --git a/scm/driver/harness/issue_test.go b/scm/driver/harness/issue_test.go new file mode 100644 index 000000000..5d232e2ff --- /dev/null +++ b/scm/driver/harness/issue_test.go @@ -0,0 +1,5 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness diff --git a/scm/driver/harness/linker.go b/scm/driver/harness/linker.go new file mode 100644 index 000000000..e0c01d820 --- /dev/null +++ b/scm/driver/harness/linker.go @@ -0,0 +1,27 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type linker struct { + base string +} + +// Resource returns a link to the resource. +func (l *linker) Resource(ctx context.Context, repo string, ref scm.Reference) (string, error) { + return "", scm.ErrNotSupported + +} + +// Diff returns a link to the diff. +func (l *linker) Diff(ctx context.Context, repo string, source, target scm.Reference) (string, error) { + return "", scm.ErrNotSupported + +} diff --git a/scm/driver/harness/linker_test.go b/scm/driver/harness/linker_test.go new file mode 100644 index 000000000..5d232e2ff --- /dev/null +++ b/scm/driver/harness/linker_test.go @@ -0,0 +1,5 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness diff --git a/scm/driver/harness/milestone.go b/scm/driver/harness/milestone.go new file mode 100644 index 000000000..34784287a --- /dev/null +++ b/scm/driver/harness/milestone.go @@ -0,0 +1,90 @@ +package harness + +import ( + "context" + + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/internal/null" +) + +type milestoneService struct { + client *wrapper +} + +func (s *milestoneService) Find(ctx context.Context, repo string, id int) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported + +} + +func (s *milestoneService) List(ctx context.Context, repo string, opts scm.MilestoneListOptions) ([]*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported + +} + +func (s *milestoneService) Create(ctx context.Context, repo string, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported + +} + +func (s *milestoneService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + return nil, scm.ErrNotSupported + +} + +func (s *milestoneService) Update(ctx context.Context, repo string, id int, input *scm.MilestoneInput) (*scm.Milestone, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +// stateType issue state type +type stateType string + +const ( + // stateOpen pr/issue is open + stateOpen stateType = "open" + // stateClosed pr/issue is closed + stateClosed stateType = "closed" + // stateAll is all + stateAll stateType = "all" +) + +type milestone struct { + ID int64 `json:"id"` + Title string `json:"title"` + Description string `json:"description"` + State stateType `json:"state"` + OpenIssues int `json:"open_issues"` + ClosedIssues int `json:"closed_issues"` + Created null.Time `json:"created_at"` + Updated null.Time `json:"updated_at"` + Closed null.Time `json:"closed_at"` + Deadline null.Time `json:"due_on"` +} + +type milestoneInput struct { + Title string `json:"title"` + Description string `json:"description"` + State stateType `json:"state"` + Deadline null.Time `json:"due_on"` +} + +func convertMilestoneList(src []*milestone) []*scm.Milestone { + var dst []*scm.Milestone + for _, v := range src { + dst = append(dst, convertMilestone(v)) + } + return dst +} + +func convertMilestone(src *milestone) *scm.Milestone { + if src == nil || src.Deadline.IsZero() { + return nil + } + return &scm.Milestone{ + Number: int(src.ID), + ID: int(src.ID), + Title: src.Title, + Description: src.Description, + State: string(src.State), + DueDate: src.Deadline.ValueOrZero(), + } +} diff --git a/scm/driver/harness/milestone_test.go b/scm/driver/harness/milestone_test.go new file mode 100644 index 000000000..1815bffed --- /dev/null +++ b/scm/driver/harness/milestone_test.go @@ -0,0 +1 @@ +package harness diff --git a/scm/driver/harness/org.go b/scm/driver/harness/org.go new file mode 100644 index 000000000..28239d8d6 --- /dev/null +++ b/scm/driver/harness/org.go @@ -0,0 +1,57 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type organizationService struct { + client *wrapper +} + +func (s *organizationService) Find(ctx context.Context, name string) (*scm.Organization, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported + +} + +func (s *organizationService) FindMembership(ctx context.Context, name, username string) (*scm.Membership, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *organizationService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Organization, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported + +} + +// +// native data structures +// + +type org struct { + Name string `json:"username"` + Avatar string `json:"avatar_url"` +} + +// +// native data structure conversion +// + +func convertOrgList(from []*org) []*scm.Organization { + to := []*scm.Organization{} + for _, v := range from { + to = append(to, convertOrg(v)) + } + return to +} + +func convertOrg(from *org) *scm.Organization { + return &scm.Organization{ + Name: from.Name, + Avatar: from.Avatar, + } +} diff --git a/scm/driver/harness/org_test.go b/scm/driver/harness/org_test.go new file mode 100644 index 000000000..5d232e2ff --- /dev/null +++ b/scm/driver/harness/org_test.go @@ -0,0 +1,5 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness diff --git a/scm/driver/harness/pr.go b/scm/driver/harness/pr.go new file mode 100644 index 000000000..46f64367b --- /dev/null +++ b/scm/driver/harness/pr.go @@ -0,0 +1,157 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness + +import ( + "context" + "fmt" + "time" + + "github.com/drone/go-scm/scm" +) + +type pullService struct { + client *wrapper +} + +func (s *pullService) Find(ctx context.Context, repo string, index int) (*scm.PullRequest, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported + +} + +func (s *pullService) FindComment(context.Context, string, int, int) (*scm.Comment, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *pullService) List(ctx context.Context, repo string, opts scm.PullRequestListOptions) ([]*scm.PullRequest, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *pullService) ListComments(context.Context, string, int, scm.ListOptions) ([]*scm.Comment, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *pullService) ListCommits(context.Context, string, int, scm.ListOptions) ([]*scm.Commit, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *pullService) ListChanges(context.Context, string, int, scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *pullService) Create(ctx context.Context, repo string, input *scm.PullRequestInput) (*scm.PullRequest, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *pullService) CreateComment(context.Context, string, int, *scm.CommentInput) (*scm.Comment, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *pullService) DeleteComment(context.Context, string, int, int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *pullService) Merge(ctx context.Context, repo string, index int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *pullService) Close(context.Context, string, int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +// +// native data structures +// + +type pr struct { + ID int `json:"id"` + Number int `json:"number"` + User user `json:"user"` + Title string `json:"title"` + Body string `json:"body"` + State string `json:"state"` + HeadBranch string `json:"head_branch"` + HeadRepo repository `json:"head_repo"` + Head reference `json:"head"` + BaseBranch string `json:"base_branch"` + BaseRepo repository `json:"base_repo"` + Base reference `json:"base"` + HTMLURL string `json:"html_url"` + DiffURL string `json:"diff_url"` + Mergeable bool `json:"mergeable"` + Merged bool `json:"merged"` + Created time.Time `json:"created_at"` + Updated time.Time `json:"updated_at"` + Labels []struct { + Name string `json:"name"` + Color string `json:"color"` + } `json:"labels"` +} + +type reference struct { + Repo repository `json:"repo"` + Name string `json:"ref"` + Sha string `json:"sha"` +} + +type prInput struct { + Title string `json:"title"` + Body string `json:"body"` + Head string `json:"head"` + Base string `json:"base"` +} + +// +// native data structure conversion +// + +func convertPullRequests(src []*pr) []*scm.PullRequest { + dst := []*scm.PullRequest{} + for _, v := range src { + dst = append(dst, convertPullRequest(v)) + } + return dst +} + +func convertPullRequest(src *pr) *scm.PullRequest { + var labels []scm.Label + for _, label := range src.Labels { + labels = append(labels, scm.Label{ + Name: label.Name, + Color: label.Color, + }) + } + return &scm.PullRequest{ + Number: src.Number, + Title: src.Title, + Body: src.Body, + Sha: src.Head.Sha, + Source: src.Head.Name, + Target: src.Base.Name, + Link: src.HTMLURL, + Diff: src.DiffURL, + Fork: src.Base.Repo.FullName, + Ref: fmt.Sprintf("refs/pull/%d/head", src.Number), + Closed: src.State == "closed", + Author: *convertUser(&src.User), + Merged: src.Merged, + Created: src.Created, + Updated: src.Updated, + Labels: labels, + } +} + +func convertPullRequestFromIssue(src *issue) *scm.PullRequest { + return &scm.PullRequest{ + Number: src.Number, + Title: src.Title, + Body: src.Body, + Closed: src.State == "closed", + Author: *convertUser(&src.User), + Merged: src.PullRequest.Merged, + Created: src.Created, + Updated: src.Updated, + } +} diff --git a/scm/driver/harness/pr_test.go b/scm/driver/harness/pr_test.go new file mode 100644 index 000000000..5d232e2ff --- /dev/null +++ b/scm/driver/harness/pr_test.go @@ -0,0 +1,5 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness diff --git a/scm/driver/harness/release.go b/scm/driver/harness/release.go new file mode 100644 index 000000000..45e10704a --- /dev/null +++ b/scm/driver/harness/release.go @@ -0,0 +1,112 @@ +package harness + +import ( + "context" + + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/internal/null" +) + +type releaseService struct { + client *wrapper +} + +func (s *releaseService) Find(ctx context.Context, repo string, id int) (*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *releaseService) FindByTag(ctx context.Context, repo string, tag string) (*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *releaseService) List(ctx context.Context, repo string, opts scm.ReleaseListOptions) ([]*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *releaseService) Create(ctx context.Context, repo string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *releaseService) Delete(ctx context.Context, repo string, id int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *releaseService) DeleteByTag(ctx context.Context, repo string, tag string) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + +func (s *releaseService) Update(ctx context.Context, repo string, id int, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *releaseService) UpdateByTag(ctx context.Context, repo string, tag string, input *scm.ReleaseInput) (*scm.Release, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +type ReleaseInput struct { + TagName string `json:"tag_name"` + Target string `json:"target_commitish"` + Title string `json:"name"` + Note string `json:"body"` + IsDraft bool `json:"draft"` + IsPrerelease bool `json:"prerelease"` +} + +// release represents a repository release +type release struct { + ID int64 `json:"id"` + TagName string `json:"tag_name"` + Target string `json:"target_commitish"` + Title string `json:"name"` + Note string `json:"body"` + URL string `json:"url"` + HTMLURL string `json:"html_url"` + TarURL string `json:"tarball_url"` + ZipURL string `json:"zipball_url"` + IsDraft bool `json:"draft"` + IsPrerelease bool `json:"prerelease"` + CreatedAt null.Time `json:"created_at"` + PublishedAt null.Time `json:"published_at"` + Publisher *user `json:"author"` + Attachments []*Attachment `json:"assets"` +} + +type Attachment struct { + ID int64 `json:"id"` + Name string `json:"name"` + Size int64 `json:"size"` + DownloadCount int64 `json:"download_count"` + Created null.Time `json:"created_at"` + UUID string `json:"uuid"` + DownloadURL string `json:"browser_download_url"` +} + +func convertRelease(src *release) *scm.Release { + return &scm.Release{ + ID: int(src.ID), + Title: src.Title, + Description: src.Note, + Link: convertAPIURLToHTMLURL(src.URL, src.TagName), + Tag: src.TagName, + Commitish: src.Target, + Draft: src.IsDraft, + Prerelease: src.IsPrerelease, + Created: src.CreatedAt.ValueOrZero(), + Published: src.PublishedAt.ValueOrZero(), + } +} + +func convertReleaseList(src []*release) []*scm.Release { + var dst []*scm.Release + for _, v := range src { + dst = append(dst, convertRelease(v)) + } + return dst +} + +func releaseListOptionsToGiteaListOptions(in scm.ReleaseListOptions) ListOptions { + return ListOptions{ + Page: in.Page, + PageSize: in.Size, + } +} diff --git a/scm/driver/harness/release_test.go b/scm/driver/harness/release_test.go new file mode 100644 index 000000000..1815bffed --- /dev/null +++ b/scm/driver/harness/release_test.go @@ -0,0 +1 @@ +package harness diff --git a/scm/driver/harness/repo.go b/scm/driver/harness/repo.go new file mode 100644 index 000000000..d21017154 --- /dev/null +++ b/scm/driver/harness/repo.go @@ -0,0 +1,273 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness + +import ( + "context" + "fmt" + "net/url" + "strconv" + "time" + + "github.com/drone/go-scm/scm" +) + +type repositoryService struct { + client *wrapper +} + +func (s *repositoryService) Find(ctx context.Context, repo string) (*scm.Repository, *scm.Response, error) { + path := fmt.Sprintf("api/v1/repos/%s", repo) + out := new(repository) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertRepository(out), res, err +} + +func (s *repositoryService) FindHook(ctx context.Context, repo string, id string) (*scm.Hook, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *repositoryService) FindPerms(ctx context.Context, repo string) (*scm.Perm, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { + path := fmt.Sprintf("api/v1/user/repos?%s", encodeListOptions(opts)) + out := []*repository{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertRepositoryList(out), res, err +} + +func (s *repositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { + path := fmt.Sprintf("api/v1/repos/%s/hooks?%s", repo, encodeListOptions(opts)) + out := []*hook{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertHookList(out), res, err +} + +func (s *repositoryService) ListStatus(ctx context.Context, repo string, ref string, opts scm.ListOptions) ([]*scm.Status, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *repositoryService) CreateHook(ctx context.Context, repo string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) { + target, err := url.Parse(input.Target) + if err != nil { + return nil, nil, err + } + params := target.Query() + params.Set("secret", input.Secret) + target.RawQuery = params.Encode() + + path := fmt.Sprintf("api/v1/repos/%s/hooks", repo) + in := new(hook) + in.Type = "gitea" + in.Active = true + in.Config.Secret = input.Secret + in.Config.ContentType = "json" + in.Config.URL = target.String() + in.Events = append( + input.NativeEvents, + convertHookEvent(input.Events)..., + ) + out := new(hook) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertHook(out), res, err +} + +func (s *repositoryService) CreateStatus(ctx context.Context, repo string, ref string, input *scm.StatusInput) (*scm.Status, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *repositoryService) UpdateHook(ctx context.Context, repo, id string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *repositoryService) DeleteHook(ctx context.Context, repo string, id string) (*scm.Response, error) { + path := fmt.Sprintf("api/v1/repos/%s/hooks/%s", repo, id) + return s.client.do(ctx, "DELETE", path, nil, nil) +} + +// +// native data structures +// + +type ( + // gitea repository resource. + repository struct { + ID int `json:"id"` + Owner user `json:"owner"` + Name string `json:"name"` + FullName string `json:"full_name"` + Private bool `json:"private"` + Fork bool `json:"fork"` + HTMLURL string `json:"html_url"` + SSHURL string `json:"ssh_url"` + CloneURL string `json:"clone_url"` + DefaultBranch string `json:"default_branch"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + Permissions perm `json:"permissions"` + Archived bool `json:"archived"` + } + + // gitea permissions details. + perm struct { + Admin bool `json:"admin"` + Push bool `json:"push"` + Pull bool `json:"pull"` + } + + // gitea hook resource. + hook struct { + ID int `json:"id"` + Type string `json:"type"` + Events []string `json:"events"` + Active bool `json:"active"` + Config hookConfig `json:"config"` + } + + // gitea hook configuration details. + hookConfig struct { + URL string `json:"url"` + ContentType string `json:"content_type"` + Secret string `json:"secret"` + } + + // gitea status resource. + status struct { + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + State string `json:"status"` + TargetURL string `json:"target_url"` + Description string `json:"description"` + Context string `json:"context"` + } + + // gitea status creation request. + statusInput struct { + State string `json:"state"` + TargetURL string `json:"target_url"` + Description string `json:"description"` + Context string `json:"context"` + } +) + +// +// native data structure conversion +// + +func convertRepositoryList(src []*repository) []*scm.Repository { + var dst []*scm.Repository + for _, v := range src { + dst = append(dst, convertRepository(v)) + } + return dst +} + +func convertRepository(src *repository) *scm.Repository { + return &scm.Repository{ + ID: strconv.Itoa(src.ID), + Namespace: userLogin(&src.Owner), + Name: src.Name, + Perm: convertPerm(src.Permissions), + Branch: src.DefaultBranch, + Private: src.Private, + Clone: src.CloneURL, + CloneSSH: src.SSHURL, + Link: src.HTMLURL, + Archived: src.Archived, + } +} + +func convertPerm(src perm) *scm.Perm { + return &scm.Perm{ + Push: src.Push, + Pull: src.Pull, + Admin: src.Admin, + } +} + +func convertHookList(src []*hook) []*scm.Hook { + var dst []*scm.Hook + for _, v := range src { + dst = append(dst, convertHook(v)) + } + return dst +} + +func convertHook(from *hook) *scm.Hook { + return &scm.Hook{ + ID: strconv.Itoa(from.ID), + Active: from.Active, + Target: from.Config.URL, + Events: from.Events, + } +} + +func convertHookEvent(from scm.HookEvents) []string { + var events []string + if from.PullRequest { + events = append(events, "pull_request") + } + if from.Issue { + events = append(events, "issues") + } + if from.IssueComment || from.PullRequestComment { + events = append(events, "issue_comment") + } + if from.Branch || from.Tag { + events = append(events, "create") + events = append(events, "delete") + } + if from.Push { + events = append(events, "push") + } + return events +} + +func convertStatusList(src []*status) []*scm.Status { + var dst []*scm.Status + for _, v := range src { + dst = append(dst, convertStatus(v)) + } + return dst +} + +func convertStatus(from *status) *scm.Status { + return &scm.Status{ + State: convertState(from.State), + Label: from.Context, + Desc: from.Description, + Target: from.TargetURL, + } +} + +func convertState(from string) scm.State { + switch from { + case "error": + return scm.StateError + case "failure": + return scm.StateFailure + case "pending": + return scm.StatePending + case "success": + return scm.StateSuccess + default: + return scm.StateUnknown + } +} + +func convertFromState(from scm.State) string { + switch from { + case scm.StatePending, scm.StateRunning: + return "pending" + case scm.StateSuccess: + return "success" + case scm.StateFailure: + return "failure" + default: + return "error" + } +} diff --git a/scm/driver/harness/repo_test.go b/scm/driver/harness/repo_test.go new file mode 100644 index 000000000..8bb7df63a --- /dev/null +++ b/scm/driver/harness/repo_test.go @@ -0,0 +1,9 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness + +// +// repository sub-tests +// diff --git a/scm/driver/harness/review.go b/scm/driver/harness/review.go new file mode 100644 index 000000000..898595bd4 --- /dev/null +++ b/scm/driver/harness/review.go @@ -0,0 +1,31 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type reviewService struct { + client *wrapper +} + +func (s *reviewService) Find(ctx context.Context, repo string, number, id int) (*scm.Review, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *reviewService) List(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Review, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *reviewService) Create(ctx context.Context, repo string, number int, input *scm.ReviewInput) (*scm.Review, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *reviewService) Delete(ctx context.Context, repo string, number, id int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} diff --git a/scm/driver/harness/review_test.go b/scm/driver/harness/review_test.go new file mode 100644 index 000000000..5d232e2ff --- /dev/null +++ b/scm/driver/harness/review_test.go @@ -0,0 +1,5 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness diff --git a/scm/driver/harness/testdata/content.json b/scm/driver/harness/testdata/content.json new file mode 100644 index 000000000..b7408335a --- /dev/null +++ b/scm/driver/harness/testdata/content.json @@ -0,0 +1,30 @@ +{ + "type": "file", + "sha": "7839122fc2ec4af9d5a6c14c779a82a05c5769b5", + "name": "README.md", + "path": "README.md", + "latest_commit": { + "sha": "98189d5cf2a751a6246c24a72945ba70839f1b20", + "title": "initial commit", + "message": "initial commit", + "author": { + "identity": { + "name": "gitness", + "email": "system@gitness" + }, + "when": "2023-02-02T14:12:13Z" + }, + "committer": { + "identity": { + "name": "gitness", + "email": "system@gitness" + }, + "when": "2023-02-02T14:12:13Z" + } + }, + "content": { + "encoding": "base64", + "data": "ZGVtbw0KdGVzdCBzdHJpbmc=", + "size": 23 + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/content_list.json b/scm/driver/harness/testdata/content_list.json new file mode 100644 index 000000000..33575adee --- /dev/null +++ b/scm/driver/harness/testdata/content_list.json @@ -0,0 +1,79 @@ +{ + "type": "dir", + "sha": "4fdc5acb2f9074a6d6ec826f01518fb27fe20a06", + "name": "", + "path": "", + "latest_commit": { + "sha": "4381eecb9dd29c34972087c4185f392c20d9f7c0", + "title": "move to version 1.1.2", + "message": "move to version 1.1.2", + "author": { + "identity": { + "name": "Johannes Batzill", + "email": "johannes.batzill@harness.io" + }, + "when": "2023-02-01T02:27:42Z" + }, + "committer": { + "identity": { + "name": "Johannes Batzill", + "email": "johannes.batzill@harness.io" + }, + "when": "2023-02-01T02:27:42Z" + } + }, + "content": { + "entries": [ + { + "type": "file", + "sha": "41fdf994e79e42bd4136c7e3004367f6d21d800d", + "name": ".gitignore", + "path": ".gitignore", + "latest_commit": { + "sha": "f8de11b6f3e4499889e16b989977c66c84ad02c9", + "title": "add initial version of demo application", + "message": "add initial version of demo application", + "author": { + "identity": { + "name": "Johannes Batzill", + "email": "johannes.batzill@harness.io" + }, + "when": "2023-02-01T00:08:20Z" + }, + "committer": { + "identity": { + "name": "Johannes Batzill", + "email": "johannes.batzill@harness.io" + }, + "when": "2023-02-01T00:08:20Z" + } + } + }, + { + "type": "file", + "sha": "261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64", + "name": "LICENSE", + "path": "LICENSE", + "latest_commit": { + "sha": "a2a1bb3664f096e69f4b15b80f4650cc9f8ae913", + "title": "Initial commit", + "message": "Initial commit", + "author": { + "identity": { + "name": "Johannes Batzill", + "email": "johannes.batzill@harness.io" + }, + "when": "2023-01-31T23:54:24Z" + }, + "committer": { + "identity": { + "name": "GitHub", + "email": "noreply@github.com" + }, + "when": "2023-01-31T23:54:24Z" + } + } + } + ] + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/content_list.json.golden b/scm/driver/harness/testdata/content_list.json.golden new file mode 100644 index 000000000..c23fd5007 --- /dev/null +++ b/scm/driver/harness/testdata/content_list.json.golden @@ -0,0 +1,14 @@ +[ + { + "Path": ".gitignore", + "Sha": "f8de11b6f3e4499889e16b989977c66c84ad02c9", + "BlobID": "41fdf994e79e42bd4136c7e3004367f6d21d800d", + "kind": "file" + }, + { + "Path": "LICENSE", + "Sha": "a2a1bb3664f096e69f4b15b80f4650cc9f8ae913", + "BlobID": "261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64", + "kind": "file" + } +] diff --git a/scm/driver/harness/testdata/webhooks/pull_request_opened.json b/scm/driver/harness/testdata/webhooks/pull_request_opened.json new file mode 100644 index 000000000..9244c2035 --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/pull_request_opened.json @@ -0,0 +1,172 @@ +{ + "secret": "12345", + "action": "opened", + "number": 1, + "pull_request": { + "id": 473, + "url": "", + "number": 1, + "user": { + "id": 6641, + "login": "jcitizen", + "full_name": "", + "email": "jane@example.com", + "avatar_url": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon", + "language": "en-US", + "username": "jcitizen" + }, + "title": "Add License File", + "body": "Using a BSD License", + "labels": [], + "milestone": null, + "assignee": null, + "assignees": null, + "state": "open", + "comments": 0, + "html_url": "https://try.gitea.io/jcitizen/my-repo/pulls/1", + "diff_url": "https://try.gitea.io/jcitizen/my-repo/pulls/1.diff", + "patch_url": "https://try.gitea.io/jcitizen/my-repo/pulls/1.patch", + "mergeable": true, + "merged": false, + "merged_at": null, + "merge_commit_sha": null, + "merged_by": null, + "base": { + "label": "master", + "ref": "master", + "sha": "39af58f1eff02aa308e16913e887c8d50362b474", + "repo_id": 6589, + "repo": { + "id": 6589, + "owner": { + "id": 6641, + "login": "jcitizen", + "full_name": "", + "email": "jane@example.com", + "avatar_url": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon", + "language": "en-US", + "username": "jcitizen" + }, + "name": "my-repo", + "full_name": "jcitizen/my-repo", + "description": "", + "empty": false, + "private": false, + "fork": false, + "parent": null, + "mirror": false, + "size": 64, + "html_url": "https://try.gitea.io/jcitizen/my-repo", + "ssh_url": "git@try.gitea.io:jcitizen/my-repo.git", + "clone_url": "https://try.gitea.io/jcitizen/my-repo.git", + "website": "", + "stars_count": 0, + "forks_count": 0, + "watchers_count": 1, + "open_issues_count": 0, + "default_branch": "master", + "created_at": "2018-07-06T00:08:02Z", + "updated_at": "2018-07-06T01:06:56Z", + "permissions": { + "admin": false, + "push": false, + "pull": false + } + } + }, + "head": { + "label": "feature", + "ref": "feature", + "sha": "2eba238e33607c1fa49253182e9fff42baafa1eb", + "repo_id": 6589, + "repo": { + "id": 6589, + "owner": { + "id": 6641, + "login": "jcitizen", + "full_name": "", + "email": "jane@example.com", + "avatar_url": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon", + "language": "en-US", + "username": "jcitizen" + }, + "name": "my-repo", + "full_name": "jcitizen/my-repo", + "description": "", + "empty": false, + "private": false, + "fork": false, + "parent": null, + "mirror": false, + "size": 64, + "html_url": "https://try.gitea.io/jcitizen/my-repo", + "ssh_url": "git@try.gitea.io:jcitizen/my-repo.git", + "clone_url": "https://try.gitea.io/jcitizen/my-repo.git", + "website": "", + "stars_count": 0, + "forks_count": 0, + "watchers_count": 1, + "open_issues_count": 0, + "default_branch": "master", + "created_at": "2018-07-06T00:08:02Z", + "updated_at": "2018-07-06T01:06:56Z", + "permissions": { + "admin": false, + "push": false, + "pull": false + } + } + }, + "merge_base": "39af58f1eff02aa308e16913e887c8d50362b474", + "due_date": null, + "created_at": "2018-07-06T00:37:47Z", + "updated_at": "2018-07-06T00:37:47Z", + "closed_at": null + }, + "repository": { + "id": 6589, + "owner": { + "id": 6641, + "login": "jcitizen", + "full_name": "", + "email": "jane@example.com", + "avatar_url": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon", + "language": "en-US", + "username": "jcitizen" + }, + "name": "my-repo", + "full_name": "jcitizen/my-repo", + "description": "", + "empty": false, + "private": false, + "fork": false, + "parent": null, + "mirror": false, + "size": 64, + "html_url": "https://try.gitea.io/jcitizen/my-repo", + "ssh_url": "git@try.gitea.io:jcitizen/my-repo.git", + "clone_url": "https://try.gitea.io/jcitizen/my-repo.git", + "website": "", + "stars_count": 0, + "forks_count": 0, + "watchers_count": 1, + "open_issues_count": 0, + "default_branch": "master", + "created_at": "2018-07-06T00:08:02Z", + "updated_at": "2018-07-06T01:06:56Z", + "permissions": { + "admin": false, + "push": false, + "pull": false + } + }, + "sender": { + "id": 6641, + "login": "jcitizen", + "full_name": "", + "email": "jane@example.com", + "avatar_url": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon", + "language": "en-US", + "username": "jcitizen" + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden new file mode 100644 index 000000000..b44944b2d --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden @@ -0,0 +1,47 @@ +{ + "Action": "opened", + "Repo": { + "ID": "6589", + "Namespace": "jcitizen", + "Name": "my-repo", + "Perm": { + "Pull": false, + "Push": false, + "Admin": false + }, + "Branch": "master", + "Private": false, + "Clone": "https://try.gitea.io/jcitizen/my-repo.git", + "CloneSSH": "git@try.gitea.io:jcitizen/my-repo.git", + "Link": "https://try.gitea.io/jcitizen/my-repo", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 1, + "Title": "Add License File", + "Body": "Using a BSD License", + "Sha": "2eba238e33607c1fa49253182e9fff42baafa1eb", + "Ref": "refs/pull/1/head", + "Source": "feature", + "Target": "master", + "Fork": "jcitizen/my-repo", + "Link": "https://try.gitea.io/jcitizen/my-repo/pulls/1", + "Closed": false, + "Merged": false, + "Author": { + "Login": "jcitizen", + "Name": "", + "Email": "jane@example.com", + "Avatar": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon" + }, + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Sender": { + "Login": "jcitizen", + "Name": "", + "Email": "jane@example.com", + "Avatar": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon" + } +} \ No newline at end of file diff --git a/scm/driver/harness/user.go b/scm/driver/harness/user.go new file mode 100644 index 000000000..18cba27b4 --- /dev/null +++ b/scm/driver/harness/user.go @@ -0,0 +1,66 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness + +import ( + "context" + + "github.com/drone/go-scm/scm" +) + +type userService struct { + client *wrapper +} + +func (s *userService) Find(ctx context.Context) (*scm.User, *scm.Response, error) { + out := new(user) + res, err := s.client.do(ctx, "GET", "api/v1/user", nil, out) + return convertUser(out), res, err +} + +func (s *userService) FindLogin(ctx context.Context, login string) (*scm.User, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, error) { + return "", nil, scm.ErrNotSupported +} + +func (s *userService) ListEmail(context.Context, scm.ListOptions) ([]*scm.Email, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +// +// native data structures +// + +type user struct { + ID int `json:"id"` + Login string `json:"login"` + Username string `json:"username"` + Fullname string `json:"full_name"` + Email string `json:"email"` + Avatar string `json:"avatar_url"` +} + +// +// native data structure conversion +// + +func convertUser(src *user) *scm.User { + return &scm.User{ + Login: userLogin(src), + Avatar: src.Avatar, + Email: src.Email, + Name: src.Fullname, + } +} + +func userLogin(src *user) string { + if src.Username != "" { + return src.Username + } + return src.Login +} diff --git a/scm/driver/harness/user_test.go b/scm/driver/harness/user_test.go new file mode 100644 index 000000000..5d232e2ff --- /dev/null +++ b/scm/driver/harness/user_test.go @@ -0,0 +1,5 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness diff --git a/scm/driver/harness/util.go b/scm/driver/harness/util.go new file mode 100644 index 000000000..5a9cfab18 --- /dev/null +++ b/scm/driver/harness/util.go @@ -0,0 +1,103 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness + +import ( + "fmt" + "net/url" + "strconv" + "strings" + + "github.com/drone/go-scm/scm" +) + +func encodeListOptions(opts scm.ListOptions) string { + params := url.Values{} + if opts.Page != 0 { + params.Set("page", strconv.Itoa(opts.Page)) + } + if opts.Size != 0 { + params.Set("limit", strconv.Itoa(opts.Size)) + } + return params.Encode() +} + +func encodeIssueListOptions(opts scm.IssueListOptions) string { + params := url.Values{} + if opts.Page != 0 { + params.Set("page", strconv.Itoa(opts.Page)) + } + if opts.Size != 0 { + params.Set("limit", strconv.Itoa(opts.Size)) + } + if opts.Open && opts.Closed { + params.Set("state", "all") + } else if opts.Closed { + params.Set("state", "closed") + } + return params.Encode() +} + +func encodePullRequestListOptions(opts scm.PullRequestListOptions) string { + params := url.Values{} + if opts.Page != 0 { + params.Set("page", strconv.Itoa(opts.Page)) + } + if opts.Size != 0 { + params.Set("limit", strconv.Itoa(opts.Size)) + } + if opts.Open && opts.Closed { + params.Set("state", "all") + } else if opts.Closed { + params.Set("state", "closed") + } + return params.Encode() +} + +// convertAPIURLToHTMLURL converts an release API endpoint into a html endpoint +func convertAPIURLToHTMLURL(apiURL string, tagName string) string { + // "url": "https://try.gitea.com/api/v1/repos/octocat/Hello-World/123", + // "html_url": "https://try.gitea.com/octocat/Hello-World/releases/tag/v1.0.0", + // the url field is the API url, not the html url, so until go-sdk v0.13.3, build it ourselves + link, err := url.Parse(apiURL) + if err != nil { + return "" + } + + pathParts := strings.Split(link.Path, "/") + if len(pathParts) != 7 { + return "" + } + link.Path = fmt.Sprintf("/%s/%s/releases/tag/%s", pathParts[4], pathParts[5], tagName) + return link.String() +} + +func encodeMilestoneListOptions(opts scm.MilestoneListOptions) string { + params := url.Values{} + if opts.Page != 0 { + params.Set("page", strconv.Itoa(opts.Page)) + } + if opts.Size != 0 { + params.Set("per_page", strconv.Itoa(opts.Size)) + } + if opts.Open && opts.Closed { + params.Set("state", "all") + } else if opts.Closed { + params.Set("state", "closed") + } + return params.Encode() +} + +type ListOptions struct { + Page int + PageSize int +} + +func encodeReleaseListOptions(o ListOptions) string { + query := make(url.Values) + query.Add("page", fmt.Sprintf("%d", o.Page)) + query.Add("limit", fmt.Sprintf("%d", o.PageSize)) + return query.Encode() +} diff --git a/scm/driver/harness/util_test.go b/scm/driver/harness/util_test.go new file mode 100644 index 000000000..2264536e0 --- /dev/null +++ b/scm/driver/harness/util_test.go @@ -0,0 +1,81 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness + +import ( + "testing" + + "github.com/drone/go-scm/scm" +) + +func Test_encodeListOptions(t *testing.T) { + opts := scm.ListOptions{ + Page: 10, + Size: 30, + } + want := "limit=30&page=10" + got := encodeListOptions(opts) + if got != want { + t.Errorf("Want encoded list options %q, got %q", want, got) + } +} + +func Test_encodeIssueListOptions(t *testing.T) { + opts := scm.IssueListOptions{ + Page: 10, + Size: 30, + Open: true, + Closed: true, + } + want := "limit=30&page=10&state=all" + got := encodeIssueListOptions(opts) + if got != want { + t.Errorf("Want encoded issue list options %q, got %q", want, got) + } +} + +func Test_encodeIssueListOptions_Closed(t *testing.T) { + opts := scm.IssueListOptions{ + Page: 10, + Size: 30, + Open: false, + Closed: true, + } + want := "limit=30&page=10&state=closed" + got := encodeIssueListOptions(opts) + if got != want { + t.Errorf("Want encoded issue list options %q, got %q", want, got) + } +} + +func Test_encodePullRequestListOptions(t *testing.T) { + t.Parallel() + opts := scm.PullRequestListOptions{ + Page: 10, + Size: 30, + Open: true, + Closed: true, + } + want := "limit=30&page=10&state=all" + got := encodePullRequestListOptions(opts) + if got != want { + t.Errorf("Want encoded pr list options %q, got %q", want, got) + } +} + +func Test_encodePullRequestListOptions_Closed(t *testing.T) { + t.Parallel() + opts := scm.PullRequestListOptions{ + Page: 10, + Size: 30, + Open: false, + Closed: true, + } + want := "limit=30&page=10&state=closed" + got := encodePullRequestListOptions(opts) + if got != want { + t.Errorf("Want encoded pr list options %q, got %q", want, got) + } +} diff --git a/scm/driver/harness/webhook.go b/scm/driver/harness/webhook.go new file mode 100644 index 000000000..7465668ff --- /dev/null +++ b/scm/driver/harness/webhook.go @@ -0,0 +1,361 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness + +import ( + "crypto/sha256" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net/http" + + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/driver/internal/hmac" +) + +type webhookService struct { + client *wrapper +} + +func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhook, error) { + data, err := ioutil.ReadAll( + io.LimitReader(req.Body, 10000000), + ) + if err != nil { + return nil, err + } + + var hook scm.Webhook + switch req.Header.Get("X-Gitea-Event") { + case "push": + hook, err = s.parsePushHook(data) + case "create": + hook, err = s.parseCreateHook(data) + case "delete": + hook, err = s.parseDeleteHook(data) + case "issues": + hook, err = s.parseIssueHook(data) + case "issue_comment": + hook, err = s.parseIssueCommentHook(data) + case "pull_request": + hook, err = s.parsePullRequestHook(data) + default: + return nil, scm.ErrUnknownEvent + } + if err != nil { + return nil, err + } + + // get the gitea signature key to verify the payload + // signature. If no key is provided, no validation + // is performed. + key, err := fn(hook) + if err != nil { + return hook, err + } else if key == "" { + return hook, nil + } + + secret := req.FormValue("secret") + signature := req.Header.Get("X-Gitea-Signature") + + // fail if no signature passed + if signature == "" && secret == "" { + return hook, scm.ErrSignatureInvalid + } + + // test signature if header not set and secret is in payload + if signature == "" && secret != "" && secret != key { + return hook, scm.ErrSignatureInvalid + } + + // test signature using header + if signature != "" && !hmac.Validate(sha256.New, data, []byte(key), signature) { + return hook, scm.ErrSignatureInvalid + } + + return hook, nil +} + +func (s *webhookService) parsePushHook(data []byte) (scm.Webhook, error) { + dst := new(pushHook) + err := json.Unmarshal(data, dst) + return convertPushHook(dst), err +} + +func (s *webhookService) parseCreateHook(data []byte) (scm.Webhook, error) { + dst := new(createHook) + err := json.Unmarshal(data, dst) + switch dst.RefType { + case "tag": + return convertTagHook(dst, scm.ActionCreate), err + case "branch": + return convertBranchHook(dst, scm.ActionCreate), err + default: + return nil, scm.ErrUnknownEvent + } +} + +func (s *webhookService) parseDeleteHook(data []byte) (scm.Webhook, error) { + dst := new(createHook) + err := json.Unmarshal(data, dst) + switch dst.RefType { + case "tag": + return convertTagHook(dst, scm.ActionDelete), err + case "branch": + return convertBranchHook(dst, scm.ActionDelete), err + default: + return nil, scm.ErrUnknownEvent + } +} + +func (s *webhookService) parseIssueHook(data []byte) (scm.Webhook, error) { + dst := new(issueHook) + err := json.Unmarshal(data, dst) + return convertIssueHook(dst), err +} + +func (s *webhookService) parseIssueCommentHook(data []byte) (scm.Webhook, error) { + dst := new(issueHook) + err := json.Unmarshal(data, dst) + if dst.Issue.PullRequest != nil { + return convertPullRequestCommentHook(dst), err + } + return convertIssueCommentHook(dst), err +} + +func (s *webhookService) parsePullRequestHook(data []byte) (scm.Webhook, error) { + dst := new(pullRequestHook) + err := json.Unmarshal(data, dst) + return convertPullRequestHook(dst), err +} + +// +// native data structures +// + +type ( + // gitea push webhook payload + pushHook struct { + Ref string `json:"ref"` + Before string `json:"before"` + After string `json:"after"` + Compare string `json:"compare_url"` + Commits []commit `json:"commits"` + Repository repository `json:"repository"` + Pusher user `json:"pusher"` + Sender user `json:"sender"` + } + + // gitea create webhook payload + createHook struct { + Ref string `json:"ref"` + RefType string `json:"ref_type"` + Sha string `json:"sha"` + DefaultBranch string `json:"default_branch"` + Repository repository `json:"repository"` + Sender user `json:"sender"` + } + + // gitea issue webhook payload + issueHook struct { + Action string `json:"action"` + Issue issue `json:"issue"` + Comment issueComment `json:"comment"` + Repository repository `json:"repository"` + Sender user `json:"sender"` + } + + // gitea pull request webhook payload + pullRequestHook struct { + Action string `json:"action"` + Number int `json:"number"` + PullRequest pr `json:"pull_request"` + Repository repository `json:"repository"` + Sender user `json:"sender"` + } +) + +// +// native data structure conversion +// + +func convertTagHook(dst *createHook, action scm.Action) *scm.TagHook { + return &scm.TagHook{ + Action: action, + Ref: scm.Reference{ + Name: dst.Ref, + Sha: dst.Sha, + }, + Repo: *convertRepository(&dst.Repository), + Sender: *convertUser(&dst.Sender), + } +} + +func convertBranchHook(dst *createHook, action scm.Action) *scm.BranchHook { + return &scm.BranchHook{ + Action: action, + Ref: scm.Reference{ + Name: dst.Ref, + }, + Repo: *convertRepository(&dst.Repository), + Sender: *convertUser(&dst.Sender), + } +} + +func convertPushHook(dst *pushHook) *scm.PushHook { + if len(dst.Commits) > 0 { + var commits []scm.Commit + for _, c := range dst.Commits { + commits = append(commits, + scm.Commit{ + Sha: c.ID, + Message: c.Message, + Link: c.URL, + Author: scm.Signature{ + Login: c.Author.Username, + Email: c.Author.Email, + Name: c.Author.Name, + Date: c.Timestamp, + }, + Committer: scm.Signature{ + Login: c.Committer.Username, + Email: c.Committer.Email, + Name: c.Committer.Name, + Date: c.Timestamp, + }, + }) + } + + return &scm.PushHook{ + Ref: dst.Ref, + Before: dst.Before, + Commit: scm.Commit{ + Sha: dst.After, + Message: dst.Commits[0].Message, + Link: dst.Compare, + Author: scm.Signature{ + Login: dst.Commits[0].Author.Username, + Email: dst.Commits[0].Author.Email, + Name: dst.Commits[0].Author.Name, + Date: dst.Commits[0].Timestamp, + }, + Committer: scm.Signature{ + Login: dst.Commits[0].Committer.Username, + Email: dst.Commits[0].Committer.Email, + Name: dst.Commits[0].Committer.Name, + Date: dst.Commits[0].Timestamp, + }, + }, + Commits: commits, + Repo: *convertRepository(&dst.Repository), + Sender: *convertUser(&dst.Sender), + } + } + return &scm.PushHook{ + Ref: dst.Ref, + Commit: scm.Commit{ + Sha: dst.After, + Link: dst.Compare, + Author: scm.Signature{ + Login: dst.Pusher.Login, + Email: dst.Pusher.Email, + Name: dst.Pusher.Fullname, + }, + Committer: scm.Signature{ + Login: dst.Pusher.Login, + Email: dst.Pusher.Email, + Name: dst.Pusher.Fullname, + }, + }, + Repo: *convertRepository(&dst.Repository), + Sender: *convertUser(&dst.Sender), + } +} + +func convertPullRequestHook(dst *pullRequestHook) *scm.PullRequestHook { + return &scm.PullRequestHook{ + Action: convertAction(dst.Action), + PullRequest: scm.PullRequest{ + Number: dst.PullRequest.Number, + Title: dst.PullRequest.Title, + Body: dst.PullRequest.Body, + Closed: dst.PullRequest.State == "closed", + Author: scm.User{ + Login: dst.PullRequest.User.Login, + Email: dst.PullRequest.User.Email, + Avatar: dst.PullRequest.User.Avatar, + }, + Merged: dst.PullRequest.Merged, + // Created: nil, + // Updated: nil, + Source: dst.PullRequest.Head.Name, + Target: dst.PullRequest.Base.Name, + Fork: dst.PullRequest.Head.Repo.FullName, + Link: dst.PullRequest.HTMLURL, + Ref: fmt.Sprintf("refs/pull/%d/head", dst.PullRequest.Number), + Sha: dst.PullRequest.Head.Sha, + }, + Repo: *convertRepository(&dst.Repository), + Sender: *convertUser(&dst.Sender), + } +} + +func convertPullRequestCommentHook(dst *issueHook) *scm.PullRequestCommentHook { + return &scm.PullRequestCommentHook{ + Action: convertAction(dst.Action), + PullRequest: *convertPullRequestFromIssue(&dst.Issue), + Comment: *convertIssueComment(&dst.Comment), + Repo: *convertRepository(&dst.Repository), + Sender: *convertUser(&dst.Sender), + } +} + +func convertIssueHook(dst *issueHook) *scm.IssueHook { + return &scm.IssueHook{ + Action: convertAction(dst.Action), + Issue: *convertIssue(&dst.Issue), + Repo: *convertRepository(&dst.Repository), + Sender: *convertUser(&dst.Sender), + } +} + +func convertIssueCommentHook(dst *issueHook) *scm.IssueCommentHook { + return &scm.IssueCommentHook{ + Action: convertAction(dst.Action), + Issue: *convertIssue(&dst.Issue), + Comment: *convertIssueComment(&dst.Comment), + Repo: *convertRepository(&dst.Repository), + Sender: *convertUser(&dst.Sender), + } +} + +func convertAction(src string) (action scm.Action) { + switch src { + case "create", "created": + return scm.ActionCreate + case "delete", "deleted": + return scm.ActionDelete + case "update", "updated", "edit", "edited": + return scm.ActionUpdate + case "open", "opened": + return scm.ActionOpen + case "reopen", "reopened": + return scm.ActionReopen + case "close", "closed": + return scm.ActionClose + case "label", "labeled": + return scm.ActionLabel + case "unlabel", "unlabeled": + return scm.ActionUnlabel + case "merge", "merged": + return scm.ActionMerge + case "synchronize", "synchronized": + return scm.ActionSync + default: + return + } +} diff --git a/scm/driver/harness/webhook_test.go b/scm/driver/harness/webhook_test.go new file mode 100644 index 000000000..5d232e2ff --- /dev/null +++ b/scm/driver/harness/webhook_test.go @@ -0,0 +1,5 @@ +// Copyright 2017 Drone.IO Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package harness From 7df18e165adf4e8cd83cdaab9e8ad573d0998097 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Tue, 7 Feb 2023 11:16:06 +0000 Subject: [PATCH 147/282] (feat) harness, add repo list --- scm/driver/harness/content.go | 7 -- scm/driver/harness/pr.go | 2 +- scm/driver/harness/repo.go | 98 ++++++------------- scm/driver/harness/repo_test.go | 52 +++++++++- scm/driver/harness/testdata/repos.json | 40 ++++++++ scm/driver/harness/testdata/repos.json.golden | 22 +++++ scm/driver/harness/util.go | 13 +++ scm/driver/harness/webhook.go | 2 +- 8 files changed, 158 insertions(+), 78 deletions(-) create mode 100644 scm/driver/harness/testdata/repos.json create mode 100644 scm/driver/harness/testdata/repos.json.golden diff --git a/scm/driver/harness/content.go b/scm/driver/harness/content.go index e5e7724b3..310c0e06c 100644 --- a/scm/driver/harness/content.go +++ b/scm/driver/harness/content.go @@ -91,13 +91,6 @@ func (s *contentService) Delete(ctx context.Context, repo, path string, params * return res, err } -func buildHarnessURI(account, organization, project, repo string) (uri string) { - if account != "" { - return fmt.Sprintf("%s/%s/%s/%s/+", account, organization, project, repo) - } - return repo -} - func (s *contentService) List(ctx context.Context, repo, path, ref string, _ scm.ListOptions) ([]*scm.ContentInfo, *scm.Response, error) { repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) endpoint := fmt.Sprintf("api/v1/repos/%s/content/%s?%s&include_commit=true", repo, path, ref) diff --git a/scm/driver/harness/pr.go b/scm/driver/harness/pr.go index 46f64367b..631d994b7 100644 --- a/scm/driver/harness/pr.go +++ b/scm/driver/harness/pr.go @@ -132,7 +132,7 @@ func convertPullRequest(src *pr) *scm.PullRequest { Target: src.Base.Name, Link: src.HTMLURL, Diff: src.DiffURL, - Fork: src.Base.Repo.FullName, + Fork: "fork", Ref: fmt.Sprintf("refs/pull/%d/head", src.Number), Closed: src.State == "closed", Author: *convertUser(&src.User), diff --git a/scm/driver/harness/repo.go b/scm/driver/harness/repo.go index d21017154..eed9ab711 100644 --- a/scm/driver/harness/repo.go +++ b/scm/driver/harness/repo.go @@ -7,7 +7,6 @@ package harness import ( "context" "fmt" - "net/url" "strconv" "time" @@ -19,10 +18,7 @@ type repositoryService struct { } func (s *repositoryService) Find(ctx context.Context, repo string) (*scm.Repository, *scm.Response, error) { - path := fmt.Sprintf("api/v1/repos/%s", repo) - out := new(repository) - res, err := s.client.do(ctx, "GET", path, nil, out) - return convertRepository(out), res, err + return nil, nil, scm.ErrNotSupported } func (s *repositoryService) FindHook(ctx context.Context, repo string, id string) (*scm.Hook, *scm.Response, error) { @@ -34,17 +30,15 @@ func (s *repositoryService) FindPerms(ctx context.Context, repo string) (*scm.Pe } func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { - path := fmt.Sprintf("api/v1/user/repos?%s", encodeListOptions(opts)) + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, "") + path := fmt.Sprintf("api/v1/spaces/%s/repos?sort=path&order=asc&%s", harnessURI, encodeListOptions(opts)) out := []*repository{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertRepositoryList(out), res, err } func (s *repositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { - path := fmt.Sprintf("api/v1/repos/%s/hooks?%s", repo, encodeListOptions(opts)) - out := []*hook{} - res, err := s.client.do(ctx, "GET", path, nil, &out) - return convertHookList(out), res, err + return nil, nil, scm.ErrNotSupported } func (s *repositoryService) ListStatus(ctx context.Context, repo string, ref string, opts scm.ListOptions) ([]*scm.Status, *scm.Response, error) { @@ -52,28 +46,7 @@ func (s *repositoryService) ListStatus(ctx context.Context, repo string, ref str } func (s *repositoryService) CreateHook(ctx context.Context, repo string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) { - target, err := url.Parse(input.Target) - if err != nil { - return nil, nil, err - } - params := target.Query() - params.Set("secret", input.Secret) - target.RawQuery = params.Encode() - - path := fmt.Sprintf("api/v1/repos/%s/hooks", repo) - in := new(hook) - in.Type = "gitea" - in.Active = true - in.Config.Secret = input.Secret - in.Config.ContentType = "json" - in.Config.URL = target.String() - in.Events = append( - input.NativeEvents, - convertHookEvent(input.Events)..., - ) - out := new(hook) - res, err := s.client.do(ctx, "POST", path, in, out) - return convertHook(out), res, err + return nil, nil, scm.ErrNotSupported } func (s *repositoryService) CreateStatus(ctx context.Context, repo string, ref string, input *scm.StatusInput) (*scm.Status, *scm.Response, error) { @@ -85,8 +58,7 @@ func (s *repositoryService) UpdateHook(ctx context.Context, repo, id string, inp } func (s *repositoryService) DeleteHook(ctx context.Context, repo string, id string) (*scm.Response, error) { - path := fmt.Sprintf("api/v1/repos/%s/hooks/%s", repo, id) - return s.client.do(ctx, "DELETE", path, nil, nil) + return nil, scm.ErrNotSupported } // @@ -94,22 +66,25 @@ func (s *repositoryService) DeleteHook(ctx context.Context, repo string, id stri // type ( - // gitea repository resource. + // harness repository resource. repository struct { - ID int `json:"id"` - Owner user `json:"owner"` - Name string `json:"name"` - FullName string `json:"full_name"` - Private bool `json:"private"` - Fork bool `json:"fork"` - HTMLURL string `json:"html_url"` - SSHURL string `json:"ssh_url"` - CloneURL string `json:"clone_url"` - DefaultBranch string `json:"default_branch"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - Permissions perm `json:"permissions"` - Archived bool `json:"archived"` + ID int `json:"id"` + ParentID int `json:"parent_id"` + UID string `json:"uid"` + Path string `json:"path"` + Description string `json:"description"` + IsPublic bool `json:"is_public"` + CreatedBy int `json:"created_by"` + Created int64 `json:"created"` + Updated int64 `json:"updated"` + DefaultBranch string `json:"default_branch"` + ForkID int `json:"fork_id"` + NumForks int `json:"num_forks"` + NumPulls int `json:"num_pulls"` + NumClosedPulls int `json:"num_closed_pulls"` + NumOpenPulls int `json:"num_open_pulls"` + NumMergedPulls int `json:"num_merged_pulls"` + GitURL string `json:"git_url"` } // gitea permissions details. @@ -169,26 +144,17 @@ func convertRepositoryList(src []*repository) []*scm.Repository { func convertRepository(src *repository) *scm.Repository { return &scm.Repository{ ID: strconv.Itoa(src.ID), - Namespace: userLogin(&src.Owner), - Name: src.Name, - Perm: convertPerm(src.Permissions), + Namespace: src.Path, + Name: src.UID, Branch: src.DefaultBranch, - Private: src.Private, - Clone: src.CloneURL, - CloneSSH: src.SSHURL, - Link: src.HTMLURL, - Archived: src.Archived, + Private: !src.IsPublic, + Clone: src.GitURL, + CloneSSH: src.GitURL, + Link: src.GitURL, + // Created: time.Unix(src.Created, 0), + // Updated: time.Unix(src.Updated, 0), } } - -func convertPerm(src perm) *scm.Perm { - return &scm.Perm{ - Push: src.Push, - Pull: src.Pull, - Admin: src.Admin, - } -} - func convertHookList(src []*hook) []*scm.Hook { var dst []*scm.Hook for _, v := range src { diff --git a/scm/driver/harness/repo_test.go b/scm/driver/harness/repo_test.go index 8bb7df63a..aa689214f 100644 --- a/scm/driver/harness/repo_test.go +++ b/scm/driver/harness/repo_test.go @@ -4,6 +4,52 @@ package harness -// -// repository sub-tests -// +import ( + "context" + "encoding/json" + "io/ioutil" + "net/http" + "testing" + + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/transport" + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" +) + +func TestRepositoryList(t *testing.T) { + defer gock.Off() + + gock.New(gockOrigin). + Get("/gateway/code/api/v1/spaces/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/+/repos"). + MatchParam("page", "1"). + MatchParam("limit", "20"). + MatchParam("sort", "path"). + MatchParam("order", "asc"). + Reply(200). + Type("application/json"). + File("testdata/repos.json") + + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + got, _, err := client.Repositories.List(context.Background(), scm.ListOptions{Page: 1, Size: 20}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Repository{} + raw, _ := ioutil.ReadFile("testdata/repos.json.golden") + _ = json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} diff --git a/scm/driver/harness/testdata/repos.json b/scm/driver/harness/testdata/repos.json new file mode 100644 index 000000000..77fb6f96e --- /dev/null +++ b/scm/driver/harness/testdata/repos.json @@ -0,0 +1,40 @@ +[ + { + "id": 9, + "parent_id": 16, + "uid": "demo", + "path": "px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo", + "description": "", + "is_public": false, + "created_by": 10, + "created": 1675210116158, + "updated": 1675389801066, + "default_branch": "main", + "fork_id": 0, + "num_forks": 0, + "num_pulls": 4, + "num_closed_pulls": 0, + "num_open_pulls": 1, + "num_merged_pulls": 3, + "git_url": "https://qa.harness.io/code/git/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo.git" + }, + { + "id": 11, + "parent_id": 16, + "uid": "thomas", + "path": "px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas", + "description": "Playground project for Thomas", + "is_public": true, + "created_by": 10, + "created": 1675458112548, + "updated": 1675458112548, + "default_branch": "main", + "fork_id": 0, + "num_forks": 0, + "num_pulls": 0, + "num_closed_pulls": 0, + "num_open_pulls": 0, + "num_merged_pulls": 0, + "git_url": "https://qa.harness.io/code/git/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas.git" + } +] \ No newline at end of file diff --git a/scm/driver/harness/testdata/repos.json.golden b/scm/driver/harness/testdata/repos.json.golden new file mode 100644 index 000000000..d58eb804b --- /dev/null +++ b/scm/driver/harness/testdata/repos.json.golden @@ -0,0 +1,22 @@ +[ + { + "ID": "9", + "Namespace": "px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo", + "Name": "demo", + "Branch": "main", + "Private": true, + "Clone": "https://qa.harness.io/code/git/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo.git", + "CloneSSH": "https://qa.harness.io/code/git/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo.git", + "Link": "https://qa.harness.io/code/git/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo.git" + }, + { + "ID": "11", + "Namespace": "px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas", + "Name": "thomas", + "Branch": "main", + "Private": false, + "Clone": "https://qa.harness.io/code/git/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas.git", + "CloneSSH": "https://qa.harness.io/code/git/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas.git", + "Link": "https://qa.harness.io/code/git/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas.git" + } +] \ No newline at end of file diff --git a/scm/driver/harness/util.go b/scm/driver/harness/util.go index 5a9cfab18..fe7778d9e 100644 --- a/scm/driver/harness/util.go +++ b/scm/driver/harness/util.go @@ -13,6 +13,19 @@ import ( "github.com/drone/go-scm/scm" ) +func buildHarnessURI(account, organization, project, repo string) (uri string) { + if account != "" { + uri = fmt.Sprintf("%s/%s/%s/", account, organization, project) + if repo != "" { + uri += fmt.Sprintf("%s/+", repo) + } else { + uri += "+" + } + return uri + } + return repo +} + func encodeListOptions(opts scm.ListOptions) string { params := url.Values{} if opts.Page != 0 { diff --git a/scm/driver/harness/webhook.go b/scm/driver/harness/webhook.go index 7465668ff..4f7bc187c 100644 --- a/scm/driver/harness/webhook.go +++ b/scm/driver/harness/webhook.go @@ -294,7 +294,7 @@ func convertPullRequestHook(dst *pullRequestHook) *scm.PullRequestHook { // Updated: nil, Source: dst.PullRequest.Head.Name, Target: dst.PullRequest.Base.Name, - Fork: dst.PullRequest.Head.Repo.FullName, + Fork: "fork", Link: dst.PullRequest.HTMLURL, Ref: fmt.Sprintf("refs/pull/%d/head", dst.PullRequest.Number), Sha: dst.PullRequest.Head.Sha, From e62b23f48a7f7909326988e484cc5fa476940459 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Tue, 7 Feb 2023 11:47:07 +0000 Subject: [PATCH 148/282] (feat) harness, add find repo --- scm/driver/harness/repo.go | 138 ++----------------- scm/driver/harness/repo_test.go | 34 +++++ scm/driver/harness/testdata/repo.json | 19 +++ scm/driver/harness/testdata/repo.json.golden | 10 ++ 4 files changed, 76 insertions(+), 125 deletions(-) create mode 100644 scm/driver/harness/testdata/repo.json create mode 100644 scm/driver/harness/testdata/repo.json.golden diff --git a/scm/driver/harness/repo.go b/scm/driver/harness/repo.go index eed9ab711..33fbc832c 100644 --- a/scm/driver/harness/repo.go +++ b/scm/driver/harness/repo.go @@ -6,9 +6,9 @@ package harness import ( "context" + "errors" "fmt" "strconv" - "time" "github.com/drone/go-scm/scm" ) @@ -18,7 +18,18 @@ type repositoryService struct { } func (s *repositoryService) Find(ctx context.Context, repo string) (*scm.Repository, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s", repo) + out := new(repository) + res, err := s.client.do(ctx, "GET", path, nil, out) + if err != nil { + return nil, res, err + } + convertedRepo := convertRepository(out) + if convertedRepo == nil { + return nil, res, errors.New("Harness returned an unexpected null repository") + } + return convertedRepo, res, err } func (s *repositoryService) FindHook(ctx context.Context, repo string, id string) (*scm.Hook, *scm.Response, error) { @@ -86,47 +97,6 @@ type ( NumMergedPulls int `json:"num_merged_pulls"` GitURL string `json:"git_url"` } - - // gitea permissions details. - perm struct { - Admin bool `json:"admin"` - Push bool `json:"push"` - Pull bool `json:"pull"` - } - - // gitea hook resource. - hook struct { - ID int `json:"id"` - Type string `json:"type"` - Events []string `json:"events"` - Active bool `json:"active"` - Config hookConfig `json:"config"` - } - - // gitea hook configuration details. - hookConfig struct { - URL string `json:"url"` - ContentType string `json:"content_type"` - Secret string `json:"secret"` - } - - // gitea status resource. - status struct { - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - State string `json:"status"` - TargetURL string `json:"target_url"` - Description string `json:"description"` - Context string `json:"context"` - } - - // gitea status creation request. - statusInput struct { - State string `json:"state"` - TargetURL string `json:"target_url"` - Description string `json:"description"` - Context string `json:"context"` - } ) // @@ -155,85 +125,3 @@ func convertRepository(src *repository) *scm.Repository { // Updated: time.Unix(src.Updated, 0), } } -func convertHookList(src []*hook) []*scm.Hook { - var dst []*scm.Hook - for _, v := range src { - dst = append(dst, convertHook(v)) - } - return dst -} - -func convertHook(from *hook) *scm.Hook { - return &scm.Hook{ - ID: strconv.Itoa(from.ID), - Active: from.Active, - Target: from.Config.URL, - Events: from.Events, - } -} - -func convertHookEvent(from scm.HookEvents) []string { - var events []string - if from.PullRequest { - events = append(events, "pull_request") - } - if from.Issue { - events = append(events, "issues") - } - if from.IssueComment || from.PullRequestComment { - events = append(events, "issue_comment") - } - if from.Branch || from.Tag { - events = append(events, "create") - events = append(events, "delete") - } - if from.Push { - events = append(events, "push") - } - return events -} - -func convertStatusList(src []*status) []*scm.Status { - var dst []*scm.Status - for _, v := range src { - dst = append(dst, convertStatus(v)) - } - return dst -} - -func convertStatus(from *status) *scm.Status { - return &scm.Status{ - State: convertState(from.State), - Label: from.Context, - Desc: from.Description, - Target: from.TargetURL, - } -} - -func convertState(from string) scm.State { - switch from { - case "error": - return scm.StateError - case "failure": - return scm.StateFailure - case "pending": - return scm.StatePending - case "success": - return scm.StateSuccess - default: - return scm.StateUnknown - } -} - -func convertFromState(from scm.State) string { - switch from { - case scm.StatePending, scm.StateRunning: - return "pending" - case scm.StateSuccess: - return "success" - case scm.StateFailure: - return "failure" - default: - return "error" - } -} diff --git a/scm/driver/harness/repo_test.go b/scm/driver/harness/repo_test.go index aa689214f..3136e28cf 100644 --- a/scm/driver/harness/repo_test.go +++ b/scm/driver/harness/repo_test.go @@ -17,6 +17,40 @@ import ( "github.com/h2non/gock" ) +func TestRepositoryFind(t *testing.T) { + defer gock.Off() + + gock.New(gockOrigin). + Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo/+"). + Reply(200). + Type("application/json"). + File("testdata/repo.json") + + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + got, _, err := client.Repositories.Find(context.Background(), "demo") + if err != nil { + t.Error(err) + return + } + + want := new(scm.Repository) + raw, _ := ioutil.ReadFile("testdata/repo.json.golden") + _ = json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + +} + func TestRepositoryList(t *testing.T) { defer gock.Off() diff --git a/scm/driver/harness/testdata/repo.json b/scm/driver/harness/testdata/repo.json new file mode 100644 index 000000000..7e246e625 --- /dev/null +++ b/scm/driver/harness/testdata/repo.json @@ -0,0 +1,19 @@ +{ + "id": 9, + "parent_id": 16, + "uid": "demo", + "path": "px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo", + "description": "", + "is_public": false, + "created_by": 10, + "created": 1675210116158, + "updated": 1675389801066, + "default_branch": "main", + "fork_id": 0, + "num_forks": 0, + "num_pulls": 4, + "num_closed_pulls": 0, + "num_open_pulls": 1, + "num_merged_pulls": 3, + "git_url": "https://qa.harness.io/code/git/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo.git" +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/repo.json.golden b/scm/driver/harness/testdata/repo.json.golden new file mode 100644 index 000000000..4e187a6d4 --- /dev/null +++ b/scm/driver/harness/testdata/repo.json.golden @@ -0,0 +1,10 @@ +{ + "ID": "9", + "Namespace": "px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo", + "Name": "demo", + "Branch": "main", + "Private": true, + "Clone": "https://qa.harness.io/code/git/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo.git", + "CloneSSH": "https://qa.harness.io/code/git/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo.git", + "Link": "https://qa.harness.io/code/git/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo.git" +} \ No newline at end of file From 2066d100540ea807097ca693a68331b8bfe5f52e Mon Sep 17 00:00:00 2001 From: TP Honey Date: Tue, 7 Feb 2023 15:20:04 +0000 Subject: [PATCH 149/282] fix, harness add blobid for update --- scm/driver/harness/content.go | 1 + scm/driver/harness/content_test.go | 69 +++++++++++++----------- scm/driver/harness/repo_test.go | 38 ++++++------- scm/driver/harness/testdata/content.json | 4 +- 4 files changed, 60 insertions(+), 52 deletions(-) diff --git a/scm/driver/harness/content.go b/scm/driver/harness/content.go index 310c0e06c..7eac5b990 100644 --- a/scm/driver/harness/content.go +++ b/scm/driver/harness/content.go @@ -60,6 +60,7 @@ func (s *contentService) Update(ctx context.Context, repo, path string, params * Path: path, Payload: string(params.Data), Encoding: "string", + Sha: params.BlobID, } in := editFile{ Branch: params.Branch, diff --git a/scm/driver/harness/content_test.go b/scm/driver/harness/content_test.go index feba75672..6a84ec797 100644 --- a/scm/driver/harness/content_test.go +++ b/scm/driver/harness/content_test.go @@ -23,19 +23,20 @@ const ( harnessOrg = "px7xd_BFRCi-pfWPYXVjvw" harnessAccount = "default" harnessProject = "codeciintegration" - harnessRepo = "demo" + harnessRepo = "thomas" harnessPAT = "" ) func TestContentFind(t *testing.T) { - defer gock.Off() - - gock.New(gockOrigin). - Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo/+/content/README.md"). - Reply(200). - Type("plain/text"). - File("testdata/content.json") + if harnessPAT == "" { + defer gock.Off() + gock.New(gockOrigin). + Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/content/README.md"). + Reply(200). + Type("plain/text"). + File("testdata/content.json") + } client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) client.Client = &http.Client{ Transport: &transport.Custom{ @@ -57,20 +58,21 @@ func TestContentFind(t *testing.T) { if got, want := result.Path, "README.md"; got != want { t.Errorf("Want file Path %q, got %q", want, got) } - if !strings.Contains(string(result.Data), "demo") { - t.Errorf("Want file Data %q, must contain 'demo'", result.Data) + if !strings.Contains(string(result.Data), "project") { + t.Errorf("Want file Data %q, must contain 'project'", result.Data) } } func TestContentCreate(t *testing.T) { - defer gock.Off() - - gock.New(gockOrigin). - Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo/+/commits"). - Reply(200). - Type("plain/text"). - BodyString("{\"commit_id\":\"20ecde1f8c277da0e91750bef9f3b88f228d86db\"}") + if harnessPAT == "" { + defer gock.Off() + gock.New(gockOrigin). + Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/commits"). + Reply(200). + Type("plain/text"). + BodyString("{\"commit_id\":\"20ecde1f8c277da0e91750bef9f3b88f228d86db\"}") + } client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) client.Client = &http.Client{ Transport: &transport.Custom{ @@ -99,14 +101,15 @@ func TestContentCreate(t *testing.T) { } func TestContentUpdate(t *testing.T) { - defer gock.Off() - - gock.New(gockOrigin). - Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo/+/commits"). - Reply(200). - Type("plain/text"). - BodyString("{\"commit_id\":\"20ecde1f8c277da0e91750bef9f3b88f228d86db\"}") + if harnessPAT == "" { + defer gock.Off() + gock.New(gockOrigin). + Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/commits"). + Reply(200). + Type("plain/text"). + BodyString("{\"commit_id\":\"20ecde1f8c277da0e91750bef9f3b88f228d86db\"}") + } client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) client.Client = &http.Client{ Transport: &transport.Custom{ @@ -123,6 +126,7 @@ func TestContentUpdate(t *testing.T) { Data: []byte("hello world 2"), Message: "update README.2", Branch: "main", + BlobID: "95d09f2b10159347eece71399a7e2e907ea3df4f", }, ) if err != nil { @@ -135,14 +139,15 @@ func TestContentUpdate(t *testing.T) { } func TestContentDelete(t *testing.T) { - defer gock.Off() - - gock.New(gockOrigin). - Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo/+/commits"). - Reply(200). - Type("plain/text"). - BodyString("{\"commit_id\":\"20ecde1f8c277da0e91750bef9f3b88f228d86db\"}") + if harnessPAT == "" { + defer gock.Off() + gock.New(gockOrigin). + Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/commits"). + Reply(200). + Type("plain/text"). + BodyString("{\"commit_id\":\"20ecde1f8c277da0e91750bef9f3b88f228d86db\"}") + } client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) client.Client = &http.Client{ Transport: &transport.Custom{ @@ -173,7 +178,7 @@ func TestContentList(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo/+/content/docker"). + Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/content/docker"). Reply(200). Type("application/json"). File("testdata/content_list.json") diff --git a/scm/driver/harness/repo_test.go b/scm/driver/harness/repo_test.go index 3136e28cf..812866cba 100644 --- a/scm/driver/harness/repo_test.go +++ b/scm/driver/harness/repo_test.go @@ -18,14 +18,15 @@ import ( ) func TestRepositoryFind(t *testing.T) { - defer gock.Off() - - gock.New(gockOrigin). - Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo/+"). - Reply(200). - Type("application/json"). - File("testdata/repo.json") + if harnessPAT == "" { + defer gock.Off() + gock.New(gockOrigin). + Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo/+"). + Reply(200). + Type("application/json"). + File("testdata/repo.json") + } client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) client.Client = &http.Client{ Transport: &transport.Custom{ @@ -52,18 +53,19 @@ func TestRepositoryFind(t *testing.T) { } func TestRepositoryList(t *testing.T) { - defer gock.Off() - - gock.New(gockOrigin). - Get("/gateway/code/api/v1/spaces/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/+/repos"). - MatchParam("page", "1"). - MatchParam("limit", "20"). - MatchParam("sort", "path"). - MatchParam("order", "asc"). - Reply(200). - Type("application/json"). - File("testdata/repos.json") + if harnessPAT == "" { + defer gock.Off() + gock.New(gockOrigin). + Get("/gateway/code/api/v1/spaces/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/+/repos"). + MatchParam("page", "1"). + MatchParam("limit", "20"). + MatchParam("sort", "path"). + MatchParam("order", "asc"). + Reply(200). + Type("application/json"). + File("testdata/repos.json") + } client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) client.Client = &http.Client{ Transport: &transport.Custom{ diff --git a/scm/driver/harness/testdata/content.json b/scm/driver/harness/testdata/content.json index b7408335a..fbcda4f5f 100644 --- a/scm/driver/harness/testdata/content.json +++ b/scm/driver/harness/testdata/content.json @@ -24,7 +24,7 @@ }, "content": { "encoding": "base64", - "data": "ZGVtbw0KdGVzdCBzdHJpbmc=", - "size": 23 + "data": "IyB0aG9tYXMKUGxheWdyb3VuZCBwcm9qZWN0IGZvciBUaG9tYXM=", + "size": 38 } } \ No newline at end of file From 16252ffc2540299ba3c8706e1d401d27d2c5b1cf Mon Sep 17 00:00:00 2001 From: TP Honey Date: Wed, 8 Feb 2023 13:08:46 +0000 Subject: [PATCH 150/282] (feat) harness, add webhook parsing --- .../testdata/webhooks/branch_create.json | 50 +++ .../webhooks/branch_create.json.golden | 43 ++ .../webhooks/pull_request_branch_updated.json | 71 ++++ .../pull_request_branch_updated.json.golden | 42 ++ .../webhooks/pull_request_opened.json | 225 +++------- .../webhooks/pull_request_opened.json.golden | 51 ++- .../webhooks/pull_request_reopened.json | 69 ++++ .../pull_request_reopened.json.golden | 42 ++ scm/driver/harness/webhook.go | 384 ++++++------------ scm/driver/harness/webhook_test.go | 113 ++++++ 10 files changed, 648 insertions(+), 442 deletions(-) create mode 100644 scm/driver/harness/testdata/webhooks/branch_create.json create mode 100644 scm/driver/harness/testdata/webhooks/branch_create.json.golden create mode 100644 scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json create mode 100644 scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden create mode 100644 scm/driver/harness/testdata/webhooks/pull_request_reopened.json create mode 100644 scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden diff --git a/scm/driver/harness/testdata/webhooks/branch_create.json b/scm/driver/harness/testdata/webhooks/branch_create.json new file mode 100644 index 000000000..51ff0b383 --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/branch_create.json @@ -0,0 +1,50 @@ +{ + "trigger": "branch_created", + "repo": { + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" + }, + "principal": { + "id": 8, + "uid": "0osgWsTZRsSZ8RWfjLRkEg", + "display_name": "default", + "email": "default@harness.io", + "type": "user", + "created": 1675390885380, + "updated": 1675390885380 + }, + "ref": { + "name": "refs/heads/new2", + "repo": { + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" + } + }, + "sha": "aeafa0e2e4ec6909ad75cb8fad57c0b1eb5986e6", + "commit": { + "sha": "aeafa0e2e4ec6909ad75cb8fad57c0b1eb5986e6", + "message": "version 4", + "author": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-02-01T13:21:15-08:00" + }, + "committer": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-02-01T13:21:15-08:00" + } + }, + "old_sha": "0000000000000000000000000000000000000000", + "forced": false +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/branch_create.json.golden b/scm/driver/harness/testdata/webhooks/branch_create.json.golden new file mode 100644 index 000000000..00e4ce11b --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/branch_create.json.golden @@ -0,0 +1,43 @@ +{ + "Ref": "aeafa0e2e4ec6909ad75cb8fad57c0b1eb5986e6", + "Before": "0000000000000000000000000000000000000000", + "After": "aeafa0e2e4ec6909ad75cb8fad57c0b1eb5986e6", + "Repo": { + "ID": "", + "Namespace": "", + "Name": "aba", + "Perm": null, + "Branch": "", + "Private": false, + "Clone": "", + "CloneSSH": "", + "Link": "", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Commit": { + "Sha": "aeafa0e2e4ec6909ad75cb8fad57c0b1eb5986e6", + "Message": "version 4", + "Author": { + "Name": "Admin", + "Email": "admin@harness.io", + "Date": "0001-01-01T00:00:00Z", + "Login": "", + "Avatar": "" + }, + "Committer": { + "Name": "", + "Email": "", + "Date": "0001-01-01T00:00:00Z", + "Login": "", + "Avatar": "" + }, + "Link": "" + }, + "Sender": { + "Login": "", + "Name": "default", + "Email": "", + "Avatar": "" + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json new file mode 100644 index 000000000..7509798e9 --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json @@ -0,0 +1,71 @@ +{ + "trigger": "pullreq_branch_updated", + "repo": { + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" + }, + "principal": { + "id": 8, + "uid": "0osgWsTZRsSZ8RWfjLRkEg", + "display_name": "default", + "email": "default@harness.io", + "type": "user", + "created": 1675390885380, + "updated": 1675390885380 + }, + "pull_req": { + "number": 4, + "state": "open", + "is_draft": false, + "title": "aw", + "source_repo_id": 13, + "source_branch": "b", + "target_repo_id": 13, + "target_branch": "main", + "merge_strategy": null + }, + "target_ref": { + "name": "refs/heads/main", + "repo": { + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" + } + }, + "ref": { + "name": "refs/heads/b", + "repo": { + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" + } + }, + "sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef", + "commit": { + "sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef", + "message": "updated b2", + "author": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-02-01T13:28:55-08:00" + }, + "committer": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-02-01T13:28:55-08:00" + } + }, + "old_sha": "d74b1ebfe520ac01b209dd9085f005884cc9f4cd", + "forced": false +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden new file mode 100644 index 000000000..d978a3b13 --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden @@ -0,0 +1,42 @@ +{ + "Action": "updated", + "Repo": { + "ID": "aba", + "Namespace": "", + "Name": "", + "Branch": "main", + "Private": false, + "Clone": "", + "CloneSSH": "", + "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 4, + "Title": "aw", + "Body": "", + "Sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef", + "Ref": "", + "Source": "13", + "Target": "13", + "Fork": "fork", + "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", + "Closed": false, + "Merged": false, + "Author": { + "Login": "", + "Name": "", + "Email": "", + "Avatar": "" + }, + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Sender": { + "Login": "", + "Name": "", + "Email": "default@harness.io", + "Avatar": "" + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_opened.json b/scm/driver/harness/testdata/webhooks/pull_request_opened.json index 9244c2035..a7fd7666b 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_opened.json +++ b/scm/driver/harness/testdata/webhooks/pull_request_opened.json @@ -1,172 +1,69 @@ { - "secret": "12345", - "action": "opened", - "number": 1, - "pull_request": { - "id": 473, - "url": "", - "number": 1, - "user": { - "id": 6641, - "login": "jcitizen", - "full_name": "", - "email": "jane@example.com", - "avatar_url": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon", - "language": "en-US", - "username": "jcitizen" - }, - "title": "Add License File", - "body": "Using a BSD License", - "labels": [], - "milestone": null, - "assignee": null, - "assignees": null, - "state": "open", - "comments": 0, - "html_url": "https://try.gitea.io/jcitizen/my-repo/pulls/1", - "diff_url": "https://try.gitea.io/jcitizen/my-repo/pulls/1.diff", - "patch_url": "https://try.gitea.io/jcitizen/my-repo/pulls/1.patch", - "mergeable": true, - "merged": false, - "merged_at": null, - "merge_commit_sha": null, - "merged_by": null, - "base": { - "label": "master", - "ref": "master", - "sha": "39af58f1eff02aa308e16913e887c8d50362b474", - "repo_id": 6589, + "trigger": "pullreq_created", + "repo": { + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" + }, + "principal": { + "id": 8, + "uid": "0osgWsTZRsSZ8RWfjLRkEg", + "display_name": "default", + "email": "default@harness.io", + "type": "user", + "created": 1675390885380, + "updated": 1675390885380 + }, + "pull_req": { + "number": 4, + "state": "open", + "is_draft": false, + "title": "aw", + "source_repo_id": 13, + "source_branch": "b", + "target_repo_id": 13, + "target_branch": "main", + "merge_strategy": null + }, + "target_ref": { + "name": "refs/heads/main", "repo": { - "id": 6589, - "owner": { - "id": 6641, - "login": "jcitizen", - "full_name": "", - "email": "jane@example.com", - "avatar_url": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon", - "language": "en-US", - "username": "jcitizen" - }, - "name": "my-repo", - "full_name": "jcitizen/my-repo", - "description": "", - "empty": false, - "private": false, - "fork": false, - "parent": null, - "mirror": false, - "size": 64, - "html_url": "https://try.gitea.io/jcitizen/my-repo", - "ssh_url": "git@try.gitea.io:jcitizen/my-repo.git", - "clone_url": "https://try.gitea.io/jcitizen/my-repo.git", - "website": "", - "stars_count": 0, - "forks_count": 0, - "watchers_count": 1, - "open_issues_count": 0, - "default_branch": "master", - "created_at": "2018-07-06T00:08:02Z", - "updated_at": "2018-07-06T01:06:56Z", - "permissions": { - "admin": false, - "push": false, - "pull": false - } + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" } - }, - "head": { - "label": "feature", - "ref": "feature", - "sha": "2eba238e33607c1fa49253182e9fff42baafa1eb", - "repo_id": 6589, + }, + "ref": { + "name": "refs/heads/b", "repo": { - "id": 6589, - "owner": { - "id": 6641, - "login": "jcitizen", - "full_name": "", - "email": "jane@example.com", - "avatar_url": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon", - "language": "en-US", - "username": "jcitizen" - }, - "name": "my-repo", - "full_name": "jcitizen/my-repo", - "description": "", - "empty": false, - "private": false, - "fork": false, - "parent": null, - "mirror": false, - "size": 64, - "html_url": "https://try.gitea.io/jcitizen/my-repo", - "ssh_url": "git@try.gitea.io:jcitizen/my-repo.git", - "clone_url": "https://try.gitea.io/jcitizen/my-repo.git", - "website": "", - "stars_count": 0, - "forks_count": 0, - "watchers_count": 1, - "open_issues_count": 0, - "default_branch": "master", - "created_at": "2018-07-06T00:08:02Z", - "updated_at": "2018-07-06T01:06:56Z", - "permissions": { - "admin": false, - "push": false, - "pull": false - } + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" } - }, - "merge_base": "39af58f1eff02aa308e16913e887c8d50362b474", - "due_date": null, - "created_at": "2018-07-06T00:37:47Z", - "updated_at": "2018-07-06T00:37:47Z", - "closed_at": null - }, - "repository": { - "id": 6589, - "owner": { - "id": 6641, - "login": "jcitizen", - "full_name": "", - "email": "jane@example.com", - "avatar_url": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon", - "language": "en-US", - "username": "jcitizen" - }, - "name": "my-repo", - "full_name": "jcitizen/my-repo", - "description": "", - "empty": false, - "private": false, - "fork": false, - "parent": null, - "mirror": false, - "size": 64, - "html_url": "https://try.gitea.io/jcitizen/my-repo", - "ssh_url": "git@try.gitea.io:jcitizen/my-repo.git", - "clone_url": "https://try.gitea.io/jcitizen/my-repo.git", - "website": "", - "stars_count": 0, - "forks_count": 0, - "watchers_count": 1, - "open_issues_count": 0, - "default_branch": "master", - "created_at": "2018-07-06T00:08:02Z", - "updated_at": "2018-07-06T01:06:56Z", - "permissions": { - "admin": false, - "push": false, - "pull": false - } }, - "sender": { - "id": 6641, - "login": "jcitizen", - "full_name": "", - "email": "jane@example.com", - "avatar_url": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon", - "language": "en-US", - "username": "jcitizen" + "sha": "d74b1ebfe520ac01b209dd9085f005884cc9f4cd", + "commit": { + "sha": "d74b1ebfe520ac01b209dd9085f005884cc9f4cd", + "message": "Update b.txt", + "author": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-01-31T22:01:55-08:00" + }, + "committer": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-01-31T22:01:55-08:00" + } } } \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden index b44944b2d..936a53c7a 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden +++ b/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden @@ -1,47 +1,42 @@ { - "Action": "opened", + "Action": "created", "Repo": { - "ID": "6589", - "Namespace": "jcitizen", - "Name": "my-repo", - "Perm": { - "Pull": false, - "Push": false, - "Admin": false - }, - "Branch": "master", + "ID": "aba", + "Namespace": "", + "Name": "", + "Branch": "main", "Private": false, - "Clone": "https://try.gitea.io/jcitizen/my-repo.git", - "CloneSSH": "git@try.gitea.io:jcitizen/my-repo.git", - "Link": "https://try.gitea.io/jcitizen/my-repo", + "Clone": "", + "CloneSSH": "", + "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", "Created": "0001-01-01T00:00:00Z", "Updated": "0001-01-01T00:00:00Z" }, "PullRequest": { - "Number": 1, - "Title": "Add License File", - "Body": "Using a BSD License", - "Sha": "2eba238e33607c1fa49253182e9fff42baafa1eb", - "Ref": "refs/pull/1/head", - "Source": "feature", - "Target": "master", - "Fork": "jcitizen/my-repo", - "Link": "https://try.gitea.io/jcitizen/my-repo/pulls/1", + "Number": 4, + "Title": "aw", + "Body": "", + "Sha": "d74b1ebfe520ac01b209dd9085f005884cc9f4cd", + "Ref": "", + "Source": "13", + "Target": "13", + "Fork": "fork", + "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", "Closed": false, "Merged": false, "Author": { - "Login": "jcitizen", + "Login": "", "Name": "", - "Email": "jane@example.com", - "Avatar": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon" + "Email": "", + "Avatar": "" }, "Created": "0001-01-01T00:00:00Z", "Updated": "0001-01-01T00:00:00Z" }, "Sender": { - "Login": "jcitizen", + "Login": "", "Name": "", - "Email": "jane@example.com", - "Avatar": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon" + "Email": "default@harness.io", + "Avatar": "" } } \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_reopened.json b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json new file mode 100644 index 000000000..c6549d374 --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json @@ -0,0 +1,69 @@ +{ + "trigger": "pullreq_reopened", + "repo": { + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" + }, + "principal": { + "id": 8, + "uid": "0osgWsTZRsSZ8RWfjLRkEg", + "display_name": "default", + "email": "default@harness.io", + "type": "user", + "created": 1675390885380, + "updated": 1675390885380 + }, + "pull_req": { + "number": 4, + "state": "open", + "is_draft": false, + "title": "aw", + "source_repo_id": 13, + "source_branch": "b", + "target_repo_id": 13, + "target_branch": "main", + "merge_strategy": null + }, + "target_ref": { + "name": "refs/heads/main", + "repo": { + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" + } + }, + "ref": { + "name": "refs/heads/b", + "repo": { + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" + } + }, + "sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef", + "commit": { + "sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef", + "message": "updated b2", + "author": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-02-01T13:28:55-08:00" + }, + "committer": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-02-01T13:28:55-08:00" + } + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden new file mode 100644 index 000000000..17b0f8657 --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden @@ -0,0 +1,42 @@ +{ + "Action": "reopened", + "Repo": { + "ID": "aba", + "Namespace": "", + "Name": "", + "Branch": "main", + "Private": false, + "Clone": "", + "CloneSSH": "", + "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 4, + "Title": "aw", + "Body": "", + "Sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef", + "Ref": "", + "Source": "13", + "Target": "13", + "Fork": "fork", + "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", + "Closed": false, + "Merged": false, + "Author": { + "Login": "", + "Name": "", + "Email": "", + "Avatar": "" + }, + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Sender": { + "Login": "", + "Name": "", + "Email": "default@harness.io", + "Avatar": "" + } +} \ No newline at end of file diff --git a/scm/driver/harness/webhook.go b/scm/driver/harness/webhook.go index 4f7bc187c..6b8c2777e 100644 --- a/scm/driver/harness/webhook.go +++ b/scm/driver/harness/webhook.go @@ -29,18 +29,16 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo } var hook scm.Webhook - switch req.Header.Get("X-Gitea-Event") { - case "push": + switch req.Header.Get("X-Harness-Trigger") { + // case "create": + // hook, err = s.parseCreateHook(data) + // case "delete": + // hook, err = s.parseDeleteHook(data) + // case "issues": + // hook, err = s.parseIssueHook(data) + case "branch_created": hook, err = s.parsePushHook(data) - case "create": - hook, err = s.parseCreateHook(data) - case "delete": - hook, err = s.parseDeleteHook(data) - case "issues": - hook, err = s.parseIssueHook(data) - case "issue_comment": - hook, err = s.parseIssueCommentHook(data) - case "pull_request": + case "pullreq_created", "pullreq_reopened", "pullreq_branch_updated": hook, err = s.parsePullRequestHook(data) default: return nil, scm.ErrUnknownEvent @@ -80,102 +78,106 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo return hook, nil } -func (s *webhookService) parsePushHook(data []byte) (scm.Webhook, error) { - dst := new(pushHook) - err := json.Unmarshal(data, dst) - return convertPushHook(dst), err -} - -func (s *webhookService) parseCreateHook(data []byte) (scm.Webhook, error) { - dst := new(createHook) - err := json.Unmarshal(data, dst) - switch dst.RefType { - case "tag": - return convertTagHook(dst, scm.ActionCreate), err - case "branch": - return convertBranchHook(dst, scm.ActionCreate), err - default: - return nil, scm.ErrUnknownEvent - } -} - -func (s *webhookService) parseDeleteHook(data []byte) (scm.Webhook, error) { - dst := new(createHook) - err := json.Unmarshal(data, dst) - switch dst.RefType { - case "tag": - return convertTagHook(dst, scm.ActionDelete), err - case "branch": - return convertBranchHook(dst, scm.ActionDelete), err - default: - return nil, scm.ErrUnknownEvent - } -} - -func (s *webhookService) parseIssueHook(data []byte) (scm.Webhook, error) { - dst := new(issueHook) - err := json.Unmarshal(data, dst) - return convertIssueHook(dst), err -} - -func (s *webhookService) parseIssueCommentHook(data []byte) (scm.Webhook, error) { - dst := new(issueHook) - err := json.Unmarshal(data, dst) - if dst.Issue.PullRequest != nil { - return convertPullRequestCommentHook(dst), err - } - return convertIssueCommentHook(dst), err -} - func (s *webhookService) parsePullRequestHook(data []byte) (scm.Webhook, error) { dst := new(pullRequestHook) err := json.Unmarshal(data, dst) return convertPullRequestHook(dst), err } -// -// native data structures -// +func (s *webhookService) parsePushHook(data []byte) (scm.Webhook, error) { + dst := new(pushHook) + err := json.Unmarshal(data, dst) + return convertPushHook(dst), err +} +// native data structures type ( - // gitea push webhook payload - pushHook struct { - Ref string `json:"ref"` - Before string `json:"before"` - After string `json:"after"` - Compare string `json:"compare_url"` - Commits []commit `json:"commits"` - Repository repository `json:"repository"` - Pusher user `json:"pusher"` - Sender user `json:"sender"` - } - - // gitea create webhook payload - createHook struct { - Ref string `json:"ref"` - RefType string `json:"ref_type"` - Sha string `json:"sha"` - DefaultBranch string `json:"default_branch"` - Repository repository `json:"repository"` - Sender user `json:"sender"` - } - - // gitea issue webhook payload - issueHook struct { - Action string `json:"action"` - Issue issue `json:"issue"` - Comment issueComment `json:"comment"` - Repository repository `json:"repository"` - Sender user `json:"sender"` - } - - // gitea pull request webhook payload + repo struct { + ID int `json:"id"` + Path string `json:"path"` + UID string `json:"uid"` + DefaultBranch string `json:"default_branch"` + GitURL string `json:"git_url"` + } + principal struct { + ID int `json:"id"` + UID string `json:"uid"` + DisplayName string `json:"display_name"` + Email string `json:"email"` + Type string `json:"type"` + Created int64 `json:"created"` + Updated int64 `json:"updated"` + } + pullReq struct { + Number int `json:"number"` + State string `json:"state"` + IsDraft bool `json:"is_draft"` + Title string `json:"title"` + SourceRepoID int `json:"source_repo_id"` + SourceBranch string `json:"source_branch"` + TargetRepoID int `json:"target_repo_id"` + TargetBranch string `json:"target_branch"` + MergeStrategy interface{} `json:"merge_strategy"` + } + targetRef struct { + Name string `json:"name"` + Repo struct { + ID int `json:"id"` + Path string `json:"path"` + UID string `json:"uid"` + DefaultBranch string `json:"default_branch"` + GitURL string `json:"git_url"` + } `json:"repo"` + } + ref struct { + Name string `json:"name"` + Repo struct { + ID int `json:"id"` + Path string `json:"path"` + UID string `json:"uid"` + DefaultBranch string `json:"default_branch"` + GitURL string `json:"git_url"` + } `json:"repo"` + } + hookCommit struct { + Sha string `json:"sha"` + Message string `json:"message"` + Author struct { + Identity struct { + Name string `json:"name"` + Email string `json:"email"` + } `json:"identity"` + When string `json:"when"` + } `json:"author"` + Committer struct { + Identity struct { + Name string `json:"name"` + Email string `json:"email"` + } `json:"identity"` + When string `json:"when"` + } `json:"committer"` + } + // harness pull request webhook payload pullRequestHook struct { - Action string `json:"action"` - Number int `json:"number"` - PullRequest pr `json:"pull_request"` - Repository repository `json:"repository"` - Sender user `json:"sender"` + Trigger string `json:"trigger"` + Repo repo `json:"repo"` + Principal principal `json:"principal"` + PullReq pullReq `json:"pull_req"` + TargetRef targetRef `json:"target_ref"` + Ref ref `json:"ref"` + Sha string `json:"sha"` + Commit hookCommit `json:"commit"` + } + // harness push webhook payload + pushHook struct { + Trigger string `json:"trigger"` + Repo repo `json:"repo"` + Principal principal `json:"principal"` + Ref ref `json:"ref"` + Commit hookCommit `json:"commit"` + Sha string `json:"sha"` + OldSha string `json:"old_sha"` + Forced bool `json:"forced"` } ) @@ -183,178 +185,60 @@ type ( // native data structure conversion // -func convertTagHook(dst *createHook, action scm.Action) *scm.TagHook { - return &scm.TagHook{ - Action: action, - Ref: scm.Reference{ - Name: dst.Ref, - Sha: dst.Sha, +func convertPullRequestHook(dst *pullRequestHook) *scm.PullRequestHook { + return &scm.PullRequestHook{ + Action: convertAction(dst.Trigger), + PullRequest: scm.PullRequest{ + Number: dst.PullReq.Number, + Title: dst.PullReq.Title, + Closed: dst.PullReq.State != "open", + Source: fmt.Sprintf("%d", dst.PullReq.SourceRepoID), + Target: fmt.Sprintf("%d", dst.PullReq.TargetRepoID), + Fork: "fork", + Link: dst.Ref.Repo.GitURL, + Sha: dst.Commit.Sha, }, - Repo: *convertRepository(&dst.Repository), - Sender: *convertUser(&dst.Sender), - } -} - -func convertBranchHook(dst *createHook, action scm.Action) *scm.BranchHook { - return &scm.BranchHook{ - Action: action, - Ref: scm.Reference{ - Name: dst.Ref, + Repo: scm.Repository{ + ID: dst.Repo.UID, + Branch: dst.Repo.DefaultBranch, + Link: dst.Repo.GitURL, + }, + Sender: scm.User{ + Email: dst.Principal.Email, }, - Repo: *convertRepository(&dst.Repository), - Sender: *convertUser(&dst.Sender), } } func convertPushHook(dst *pushHook) *scm.PushHook { - if len(dst.Commits) > 0 { - var commits []scm.Commit - for _, c := range dst.Commits { - commits = append(commits, - scm.Commit{ - Sha: c.ID, - Message: c.Message, - Link: c.URL, - Author: scm.Signature{ - Login: c.Author.Username, - Email: c.Author.Email, - Name: c.Author.Name, - Date: c.Timestamp, - }, - Committer: scm.Signature{ - Login: c.Committer.Username, - Email: c.Committer.Email, - Name: c.Committer.Name, - Date: c.Timestamp, - }, - }) - } - - return &scm.PushHook{ - Ref: dst.Ref, - Before: dst.Before, - Commit: scm.Commit{ - Sha: dst.After, - Message: dst.Commits[0].Message, - Link: dst.Compare, - Author: scm.Signature{ - Login: dst.Commits[0].Author.Username, - Email: dst.Commits[0].Author.Email, - Name: dst.Commits[0].Author.Name, - Date: dst.Commits[0].Timestamp, - }, - Committer: scm.Signature{ - Login: dst.Commits[0].Committer.Username, - Email: dst.Commits[0].Committer.Email, - Name: dst.Commits[0].Committer.Name, - Date: dst.Commits[0].Timestamp, - }, - }, - Commits: commits, - Repo: *convertRepository(&dst.Repository), - Sender: *convertUser(&dst.Sender), - } - } return &scm.PushHook{ - Ref: dst.Ref, + Ref: dst.Sha, + Before: dst.OldSha, + After: dst.Sha, + Repo: scm.Repository{ + Name: dst.Repo.UID, + }, Commit: scm.Commit{ - Sha: dst.After, - Link: dst.Compare, + Sha: dst.Commit.Sha, + Message: dst.Commit.Message, Author: scm.Signature{ - Login: dst.Pusher.Login, - Email: dst.Pusher.Email, - Name: dst.Pusher.Fullname, - }, - Committer: scm.Signature{ - Login: dst.Pusher.Login, - Email: dst.Pusher.Email, - Name: dst.Pusher.Fullname, + Name: dst.Commit.Author.Identity.Name, + Email: dst.Commit.Author.Identity.Email, }, }, - Repo: *convertRepository(&dst.Repository), - Sender: *convertUser(&dst.Sender), - } -} - -func convertPullRequestHook(dst *pullRequestHook) *scm.PullRequestHook { - return &scm.PullRequestHook{ - Action: convertAction(dst.Action), - PullRequest: scm.PullRequest{ - Number: dst.PullRequest.Number, - Title: dst.PullRequest.Title, - Body: dst.PullRequest.Body, - Closed: dst.PullRequest.State == "closed", - Author: scm.User{ - Login: dst.PullRequest.User.Login, - Email: dst.PullRequest.User.Email, - Avatar: dst.PullRequest.User.Avatar, - }, - Merged: dst.PullRequest.Merged, - // Created: nil, - // Updated: nil, - Source: dst.PullRequest.Head.Name, - Target: dst.PullRequest.Base.Name, - Fork: "fork", - Link: dst.PullRequest.HTMLURL, - Ref: fmt.Sprintf("refs/pull/%d/head", dst.PullRequest.Number), - Sha: dst.PullRequest.Head.Sha, + Sender: scm.User{ + Name: dst.Principal.DisplayName, }, - Repo: *convertRepository(&dst.Repository), - Sender: *convertUser(&dst.Sender), - } -} - -func convertPullRequestCommentHook(dst *issueHook) *scm.PullRequestCommentHook { - return &scm.PullRequestCommentHook{ - Action: convertAction(dst.Action), - PullRequest: *convertPullRequestFromIssue(&dst.Issue), - Comment: *convertIssueComment(&dst.Comment), - Repo: *convertRepository(&dst.Repository), - Sender: *convertUser(&dst.Sender), - } -} - -func convertIssueHook(dst *issueHook) *scm.IssueHook { - return &scm.IssueHook{ - Action: convertAction(dst.Action), - Issue: *convertIssue(&dst.Issue), - Repo: *convertRepository(&dst.Repository), - Sender: *convertUser(&dst.Sender), - } -} - -func convertIssueCommentHook(dst *issueHook) *scm.IssueCommentHook { - return &scm.IssueCommentHook{ - Action: convertAction(dst.Action), - Issue: *convertIssue(&dst.Issue), - Comment: *convertIssueComment(&dst.Comment), - Repo: *convertRepository(&dst.Repository), - Sender: *convertUser(&dst.Sender), } } func convertAction(src string) (action scm.Action) { switch src { - case "create", "created": + case "pullreq_created": return scm.ActionCreate - case "delete", "deleted": - return scm.ActionDelete - case "update", "updated", "edit", "edited": + case "pullreq_branch_updated": return scm.ActionUpdate - case "open", "opened": - return scm.ActionOpen - case "reopen", "reopened": + case "pullreq_reopened": return scm.ActionReopen - case "close", "closed": - return scm.ActionClose - case "label", "labeled": - return scm.ActionLabel - case "unlabel", "unlabeled": - return scm.ActionUnlabel - case "merge", "merged": - return scm.ActionMerge - case "synchronize", "synchronized": - return scm.ActionSync default: return } diff --git a/scm/driver/harness/webhook_test.go b/scm/driver/harness/webhook_test.go index 5d232e2ff..4e38687be 100644 --- a/scm/driver/harness/webhook_test.go +++ b/scm/driver/harness/webhook_test.go @@ -3,3 +3,116 @@ // license that can be found in the LICENSE file. package harness + +import ( + "bytes" + "encoding/json" + "io/ioutil" + "net/http" + "os" + "testing" + + "github.com/drone/go-scm/scm" + "github.com/google/go-cmp/cmp" +) + +func TestWebhooks(t *testing.T) { + tests := []struct { + event string + before string + after string + obj interface{} + }{ + // + // branch events + // + // push branch create + { + event: "branch_created", + before: "testdata/webhooks/branch_create.json", + after: "testdata/webhooks/branch_create.json.golden", + obj: new(scm.PushHook), + }, + // + // pull request events + // + // pull request opened + { + event: "pullreq_created", + before: "testdata/webhooks/pull_request_opened.json", + after: "testdata/webhooks/pull_request_opened.json.golden", + obj: new(scm.PullRequestHook), + }, + // pull request reopened + { + event: "pullreq_reopened", + before: "testdata/webhooks/pull_request_reopened.json", + after: "testdata/webhooks/pull_request_reopened.json.golden", + obj: new(scm.PullRequestHook), + }, + // pull request branch updated + { + event: "pullreq_branch_updated", + before: "testdata/webhooks/pull_request_branch_updated.json", + after: "testdata/webhooks/pull_request_branch_updated.json.golden", + obj: new(scm.PullRequestHook), + }, + } + + for _, test := range tests { + before, err := ioutil.ReadFile(test.before) + if err != nil { + t.Error(err) + continue + } + after, err := ioutil.ReadFile(test.after) + if err != nil { + t.Error(err) + continue + } + + buf := bytes.NewBuffer(before) + r, _ := http.NewRequest("GET", "/", buf) + r.Header.Set("X-Harness-Trigger", test.event) + + s := new(webhookService) + o, err := s.Parse(r, secretFunc) + if err != nil && err != scm.ErrSignatureInvalid { + t.Error(err) + continue + } + + err = json.Unmarshal(after, test.obj) + if err != nil { + t.Error(err) + continue + } + + if diff := cmp.Diff(test.obj, o); diff != "" { + t.Errorf("Error unmarshaling %s", test.before) + t.Log(diff) + + // debug only. remove once implemented + _ = json.NewEncoder(os.Stdout).Encode(o) + + } + + // switch event := o.(type) { + // case *scm.PushHook: + // if !strings.HasPrefix(event.Ref, "refs/") { + // t.Errorf("Push hook reference must start with refs/") + // } + // case *scm.BranchHook: + // if strings.HasPrefix(event.Ref.Name, "refs/") { + // t.Errorf("Branch hook reference must not start with refs/") + // } + // case *scm.TagHook: + // if strings.HasPrefix(event.Ref.Name, "refs/") { + // t.Errorf("Branch hook reference must not start with refs/") + // } + // } + } +} +func secretFunc(scm.Webhook) (string, error) { + return "topsecret", nil +} From ff7deab27e87e4fede0a76c9443163e164f4322c Mon Sep 17 00:00:00 2001 From: TP Honey Date: Wed, 8 Feb 2023 14:51:40 +0000 Subject: [PATCH 151/282] (feat) harness, add list webhooks --- scm/driver/harness/repo.go | 42 ++++++++++++++++++- scm/driver/harness/repo_test.go | 38 +++++++++++++++++ scm/driver/harness/testdata/hooks.json | 19 +++++++++ scm/driver/harness/testdata/hooks.json.golden | 10 +++++ 4 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 scm/driver/harness/testdata/hooks.json create mode 100644 scm/driver/harness/testdata/hooks.json.golden diff --git a/scm/driver/harness/repo.go b/scm/driver/harness/repo.go index 33fbc832c..5046d56c2 100644 --- a/scm/driver/harness/repo.go +++ b/scm/driver/harness/repo.go @@ -49,7 +49,11 @@ func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* } func (s *repositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s/webhooks?sort=display_name&order=asc&%s", harnessURI, encodeListOptions(opts)) + out := []*hook{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertHookList(out), res, err } func (s *repositoryService) ListStatus(ctx context.Context, repo string, ref string, opts scm.ListOptions) ([]*scm.Status, *scm.Response, error) { @@ -97,6 +101,23 @@ type ( NumMergedPulls int `json:"num_merged_pulls"` GitURL string `json:"git_url"` } + hook struct { + Created int `json:"created"` + CreatedBy int `json:"created_by"` + Description string `json:"description"` + DisplayName string `json:"display_name"` + Enabled bool `json:"enabled"` + HasSecret bool `json:"has_secret"` + ID int `json:"id"` + Insecure bool `json:"insecure"` + LatestExecutionResult string `json:"latest_execution_result"` + ParentID int `json:"parent_id"` + ParentType string `json:"parent_type"` + Triggers []string `json:"triggers"` + Updated int `json:"updated"` + URL string `json:"url"` + Version int `json:"version"` + } ) // @@ -125,3 +146,22 @@ func convertRepository(src *repository) *scm.Repository { // Updated: time.Unix(src.Updated, 0), } } + +func convertHookList(from []*hook) []*scm.Hook { + to := []*scm.Hook{} + for _, v := range from { + to = append(to, convertHook(v)) + } + return to +} + +func convertHook(from *hook) *scm.Hook { + return &scm.Hook{ + ID: strconv.Itoa(from.ID), + Name: from.DisplayName, + Active: from.Enabled, + Target: from.URL, + Events: from.Triggers, + SkipVerify: from.Insecure, + } +} diff --git a/scm/driver/harness/repo_test.go b/scm/driver/harness/repo_test.go index 812866cba..777aadbc2 100644 --- a/scm/driver/harness/repo_test.go +++ b/scm/driver/harness/repo_test.go @@ -89,3 +89,41 @@ func TestRepositoryList(t *testing.T) { t.Log(diff) } } + +func TestRepositoryHookList(t *testing.T) { + if harnessPAT == "" { + defer gock.Off() + + gock.New(gockOrigin). + Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/webhooks"). + MatchParam("page", "1"). + MatchParam("limit", "30"). + MatchParam("sort", "display_name"). + MatchParam("order", "asc"). + Reply(200). + Type("application/json"). + File("testdata/hooks.json") + } + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + got, _, err := client.Repositories.ListHooks(context.Background(), harnessRepo, scm.ListOptions{Page: 1, Size: 30}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Hook{} + raw, _ := ioutil.ReadFile("testdata/hooks.json.golden") + _ = json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} diff --git a/scm/driver/harness/testdata/hooks.json b/scm/driver/harness/testdata/hooks.json new file mode 100644 index 000000000..372ad34a7 --- /dev/null +++ b/scm/driver/harness/testdata/hooks.json @@ -0,0 +1,19 @@ +[ + { + "id": 6, + "version": 1, + "parent_id": 11, + "parent_type": "repo", + "created_by": 14, + "created": 1675867490853, + "updated": 1675867531549, + "display_name": "webhookname", + "description": "webhookdescription", + "url": "http://1.1.1.1", + "enabled": true, + "insecure": true, + "triggers": [], + "latest_execution_result": "success", + "has_secret": true + } +] \ No newline at end of file diff --git a/scm/driver/harness/testdata/hooks.json.golden b/scm/driver/harness/testdata/hooks.json.golden new file mode 100644 index 000000000..f21533cbe --- /dev/null +++ b/scm/driver/harness/testdata/hooks.json.golden @@ -0,0 +1,10 @@ +[ + { + "ID": "6", + "Name": "webhookname", + "Target": "http://1.1.1.1", + "Events": [], + "Active": true, + "SkipVerify": true + } +] \ No newline at end of file From b8eea16f4bb0ef6038e0b6747511fbf12d2ec41f Mon Sep 17 00:00:00 2001 From: TP Honey Date: Wed, 8 Feb 2023 15:34:10 +0000 Subject: [PATCH 152/282] (feat) harness, add find hook --- scm/driver/harness/repo.go | 6 +++- scm/driver/harness/repo_test.go | 34 ++++++++++++++++++++ scm/driver/harness/testdata/hook.json | 17 ++++++++++ scm/driver/harness/testdata/hook.json.golden | 8 +++++ 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 scm/driver/harness/testdata/hook.json create mode 100644 scm/driver/harness/testdata/hook.json.golden diff --git a/scm/driver/harness/repo.go b/scm/driver/harness/repo.go index 5046d56c2..289d85e23 100644 --- a/scm/driver/harness/repo.go +++ b/scm/driver/harness/repo.go @@ -33,7 +33,11 @@ func (s *repositoryService) Find(ctx context.Context, repo string) (*scm.Reposit } func (s *repositoryService) FindHook(ctx context.Context, repo string, id string) (*scm.Hook, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s/webhooks/%s", harnessURI, id) + out := new(hook) + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertHook(out), res, err } func (s *repositoryService) FindPerms(ctx context.Context, repo string) (*scm.Perm, *scm.Response, error) { diff --git a/scm/driver/harness/repo_test.go b/scm/driver/harness/repo_test.go index 777aadbc2..082dbb4f1 100644 --- a/scm/driver/harness/repo_test.go +++ b/scm/driver/harness/repo_test.go @@ -127,3 +127,37 @@ func TestRepositoryHookList(t *testing.T) { t.Log(diff) } } + +func TestRepositoryFindHook(t *testing.T) { + if harnessPAT == "" { + defer gock.Off() + + gock.New(gockOrigin). + Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/webhooks/6"). + Reply(200). + Type("application/json"). + File("testdata/hook.json") + } + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + got, _, err := client.Repositories.FindHook(context.Background(), harnessRepo, "6") + if err != nil { + t.Error(err) + return + } + + want := new(scm.Hook) + raw, _ := ioutil.ReadFile("testdata/hook.json.golden") + _ = json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} diff --git a/scm/driver/harness/testdata/hook.json b/scm/driver/harness/testdata/hook.json new file mode 100644 index 000000000..994de6ed8 --- /dev/null +++ b/scm/driver/harness/testdata/hook.json @@ -0,0 +1,17 @@ +{ + "id": 6, + "version": 1, + "parent_id": 11, + "parent_type": "repo", + "created_by": 14, + "created": 1675867490853, + "updated": 1675867531549, + "display_name": "webhookname", + "description": "webhookdescription", + "url": "http://1.1.1.1", + "enabled": true, + "insecure": true, + "triggers": [], + "latest_execution_result": "success", + "has_secret": true +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/hook.json.golden b/scm/driver/harness/testdata/hook.json.golden new file mode 100644 index 000000000..53463fce4 --- /dev/null +++ b/scm/driver/harness/testdata/hook.json.golden @@ -0,0 +1,8 @@ +{ + "ID": "6", + "Name": "webhookname", + "Target": "http://1.1.1.1", + "Events": [], + "Active": true, + "SkipVerify": true +} \ No newline at end of file From d6e3618f2eb2e2762cbbda158c7ce9aa67e20bf8 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Wed, 8 Feb 2023 16:18:32 +0000 Subject: [PATCH 153/282] (feat) harness, add create / delete webhook --- scm/driver/harness/repo.go | 20 +++++- scm/driver/harness/repo_test.go | 64 +++++++++++++++++++ scm/driver/harness/testdata/hook_create.json | 17 +++++ .../harness/testdata/hook_create.json.golden | 8 +++ 4 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 scm/driver/harness/testdata/hook_create.json create mode 100644 scm/driver/harness/testdata/hook_create.json.golden diff --git a/scm/driver/harness/repo.go b/scm/driver/harness/repo.go index 289d85e23..a55089516 100644 --- a/scm/driver/harness/repo.go +++ b/scm/driver/harness/repo.go @@ -65,7 +65,20 @@ func (s *repositoryService) ListStatus(ctx context.Context, repo string, ref str } func (s *repositoryService) CreateHook(ctx context.Context, repo string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s/webhooks", harnessURI) + in := new(hook) + in.Enabled = true + in.DisplayName = input.Name + in.Secret = input.Secret + in.Insecure = input.SkipVerify + in.URL = input.Target + in.Triggers = append( + input.NativeEvents, + ) + out := new(hook) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertHook(out), res, err } func (s *repositoryService) CreateStatus(ctx context.Context, repo string, ref string, input *scm.StatusInput) (*scm.Status, *scm.Response, error) { @@ -77,7 +90,9 @@ func (s *repositoryService) UpdateHook(ctx context.Context, repo, id string, inp } func (s *repositoryService) DeleteHook(ctx context.Context, repo string, id string) (*scm.Response, error) { - return nil, scm.ErrNotSupported + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s/webhooks/%s", harnessURI, id) + return s.client.do(ctx, "DELETE", path, nil, nil) } // @@ -112,6 +127,7 @@ type ( DisplayName string `json:"display_name"` Enabled bool `json:"enabled"` HasSecret bool `json:"has_secret"` + Secret string `json:"secret"` ID int `json:"id"` Insecure bool `json:"insecure"` LatestExecutionResult string `json:"latest_execution_result"` diff --git a/scm/driver/harness/repo_test.go b/scm/driver/harness/repo_test.go index 082dbb4f1..8cd9a3a22 100644 --- a/scm/driver/harness/repo_test.go +++ b/scm/driver/harness/repo_test.go @@ -7,6 +7,7 @@ package harness import ( "context" "encoding/json" + "fmt" "io/ioutil" "net/http" "testing" @@ -14,6 +15,7 @@ import ( "github.com/drone/go-scm/scm" "github.com/drone/go-scm/scm/transport" "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" "github.com/h2non/gock" ) @@ -161,3 +163,65 @@ func TestRepositoryFindHook(t *testing.T) { t.Log(diff) } } + +func TestRepositoryHookCreateDelete(t *testing.T) { + if harnessPAT == "" { + defer gock.Off() + + gock.New(gockOrigin). + Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/webhooks"). + Reply(200). + Type("application/json"). + File("testdata/hook_create.json") + } + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + in := &scm.HookInput{ + Name: "drone", + Target: "https://example.com", + Secret: "topsecret", + SkipVerify: true, + } + got, _, err := client.Repositories.CreateHook(context.Background(), harnessRepo, in) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Hook) + raw, _ := ioutil.ReadFile("testdata/hook_create.json.golden") + _ = json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want, cmpopts.IgnoreFields(scm.Hook{}, "ID")); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + // delete webhook + if harnessPAT == "" { + defer gock.Off() + + gock.New(gockOrigin). + Delete(fmt.Sprintf("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/webhooks/%s", got.ID)). + Reply(204) + } + client, _ = New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + + _, deleteErr := client.Repositories.DeleteHook(context.Background(), harnessRepo, got.ID) + if deleteErr != nil { + t.Error(deleteErr) + return + } +} diff --git a/scm/driver/harness/testdata/hook_create.json b/scm/driver/harness/testdata/hook_create.json new file mode 100644 index 000000000..131b6d7cb --- /dev/null +++ b/scm/driver/harness/testdata/hook_create.json @@ -0,0 +1,17 @@ +{ + "id": 9, + "version": 1, + "parent_id": 11, + "parent_type": "repo", + "created_by": 14, + "created": 1675872629243, + "updated": 1675872777592, + "display_name": "drone", + "description": "", + "url": "https://example.com", + "enabled": true, + "insecure": true, + "triggers": [], + "latest_execution_result": "success", + "has_secret": true +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/hook_create.json.golden b/scm/driver/harness/testdata/hook_create.json.golden new file mode 100644 index 000000000..06e9a45dc --- /dev/null +++ b/scm/driver/harness/testdata/hook_create.json.golden @@ -0,0 +1,8 @@ +{ + "ID": "9", + "Name": "drone", + "Target": "https://example.com", + "Events": [], + "Active": true, + "SkipVerify": true +} \ No newline at end of file From df6c516a40d3f1b1902049487d9caadaadd6f2ee Mon Sep 17 00:00:00 2001 From: Dev Mittal Date: Tue, 7 Feb 2023 15:00:05 +0530 Subject: [PATCH 154/282] fetch branch for bitbucket onprem --- scm/driver/stash/repo.go | 14 ++++++++- scm/driver/stash/repo_test.go | 30 +++++++++++++++++++ scm/driver/stash/testdata/content_list.json | 3 +- .../stash/testdata/content_list.json.golden | 4 +++ scm/driver/stash/testdata/default_branch.json | 8 +++++ scm/driver/stash/testdata/repo.json.golden | 2 +- 6 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 scm/driver/stash/testdata/default_branch.json diff --git a/scm/driver/stash/repo.go b/scm/driver/stash/repo.go index 70f4c01de..070bfd373 100644 --- a/scm/driver/stash/repo.go +++ b/scm/driver/stash/repo.go @@ -103,7 +103,19 @@ func (s *repositoryService) Find(ctx context.Context, repo string) (*scm.Reposit path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s", namespace, name) out := new(repository) res, err := s.client.do(ctx, "GET", path, nil, out) - return convertRepository(out), res, err + outputRepo := convertRepository(out) + + branch := new(branch) + pathBranch := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/branches/default", namespace, name) + _, errBranch := s.client.do(ctx, "GET", pathBranch, nil, branch) + if errBranch == nil { + outputRepo.Branch = branch.DisplayID + } + if err == nil { + err = errBranch + } + + return outputRepo, res, err } // FindHook returns a repository hook. diff --git a/scm/driver/stash/repo_test.go b/scm/driver/stash/repo_test.go index 83924a8ba..ee337dc24 100644 --- a/scm/driver/stash/repo_test.go +++ b/scm/driver/stash/repo_test.go @@ -25,6 +25,12 @@ func TestRepositoryFind(t *testing.T) { Type("application/json"). File("testdata/repo.json") + gock.New("http://example.com:7990"). + Get("/rest/api/1.0/projects/PRJ/repos/my-repo/branches/default"). + Reply(200). + Type("application/json"). + File("testdata/default_branch.json") + client, _ := New("http://example.com:7990") got, _, err := client.Repositories.Find(context.Background(), "PRJ/my-repo") if err != nil { @@ -76,6 +82,12 @@ func TestRepositoryPerms(t *testing.T) { Type("application/json"). File("testdata/webhooks.json") + gock.New("http://example.com:7990"). + Get("/rest/api/1.0/projects/PRJ/repos/my-repo/branches/default"). + Reply(200). + Type("application/json"). + File("testdata/default_branch.json") + client, _ := New("http://example.com:7990") got, _, err := client.Repositories.FindPerms(context.Background(), "PRJ/my-repo") if err != nil { @@ -117,6 +129,12 @@ func TestRepositoryPerms_ReadOnly(t *testing.T) { Type("application/json"). File("testdata/repo.json") + gock.New("http://example.com:7990"). + Get("/rest/api/1.0/projects/PRJ/repos/my-repo/branches/default"). + Reply(200). + Type("application/json"). + File("testdata/default_branch.json") + client, _ := New("http://example.com:7990") got, _, err := client.Repositories.FindPerms(context.Background(), "PRJ/my-repo") if err != nil { @@ -162,6 +180,12 @@ func TestRepositoryPerms_Write(t *testing.T) { Type("application/json"). File("testdata/repos.json") + gock.New("http://example.com:7990"). + Get("/rest/api/1.0/projects/PRJ/repos/my-repo/branches/default"). + Reply(200). + Type("application/json"). + File("testdata/default_branch.json") + client, _ := New("http://example.com:7990") got, _, err := client.Repositories.FindPerms(context.Background(), "PRJ/my-repo") if err != nil { @@ -207,6 +231,12 @@ func TestRepositoryPermsDifferentProjectName_Write(t *testing.T) { Type("application/json"). File("testdata/repos.json") + gock.New("http://example.com:7990"). + Get("/rest/api/1.0/projects/PRJ/repos/quux/branches/default"). + Reply(200). + Type("application/json"). + File("testdata/default_branch.json") + client, _ := New("http://example.com:7990") got, _, err := client.Repositories.FindPerms(context.Background(), "PRJ/quux") if err != nil { diff --git a/scm/driver/stash/testdata/content_list.json b/scm/driver/stash/testdata/content_list.json index ec0447795..4d5f72873 100644 --- a/scm/driver/stash/testdata/content_list.json +++ b/scm/driver/stash/testdata/content_list.json @@ -27,7 +27,8 @@ "testdata/branches.json.golden", "testdata/changes.json", "testdata/changes.json.golden", - "testdata/commit.json" + "testdata/commit.json", + "testdata/default_branch.json" ], "start": 0, "nextPageStart": 25 diff --git a/scm/driver/stash/testdata/content_list.json.golden b/scm/driver/stash/testdata/content_list.json.golden index 72d6fcf30..f02920ac4 100644 --- a/scm/driver/stash/testdata/content_list.json.golden +++ b/scm/driver/stash/testdata/content_list.json.golden @@ -98,5 +98,9 @@ { "path": "testdata/commit.json", "kind": "file" + }, + { + "path": "testdata/default_branch.json", + "kind": "file" } ] diff --git a/scm/driver/stash/testdata/default_branch.json b/scm/driver/stash/testdata/default_branch.json new file mode 100644 index 000000000..ceeec302e --- /dev/null +++ b/scm/driver/stash/testdata/default_branch.json @@ -0,0 +1,8 @@ +{ + "id": "refs/heads/feature_branch", + "displayId": "feature_branch", + "type": "BRANCH", + "latestCommit": "c567b3f4a2980299e2a1148360f23ffb0f4c9764", + "latestChangeset": "c567b3f4a2980299e2a1148360f23ffb0f4c9764", + "isDefault": true +} \ No newline at end of file diff --git a/scm/driver/stash/testdata/repo.json.golden b/scm/driver/stash/testdata/repo.json.golden index e7257362f..66414388a 100644 --- a/scm/driver/stash/testdata/repo.json.golden +++ b/scm/driver/stash/testdata/repo.json.golden @@ -3,7 +3,7 @@ "Namespace": "PRJ", "Name": "my-repo", "Perm": null, - "Branch": "master", + "Branch": "feature_branch", "Private": true, "Clone": "http://example.com:7990/scm/prj/my-repo.git", "CloneSSH": "ssh://git@example.com:7999/prj/my-repo.git", From 85d76f0df54862b7eddee0513dc57c160136a0e8 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Wed, 8 Feb 2023 17:22:31 +0000 Subject: [PATCH 155/282] (feat) harness, add list commits / branches --- scm/driver/harness/git.go | 153 +++++++--------- scm/driver/harness/git_test.go | 170 ++++++++++++++++++ scm/driver/harness/repo_test.go | 5 +- scm/driver/harness/testdata/branch.json | 23 +++ .../harness/testdata/branch.json.golden | 5 + scm/driver/harness/testdata/branches.json | 25 +++ .../harness/testdata/branches.json.golden | 7 + scm/driver/harness/testdata/commit.json | 19 ++ .../harness/testdata/commit.json.golden | 19 ++ scm/driver/harness/testdata/commits.json | 21 +++ .../harness/testdata/commits.json.golden | 21 +++ 11 files changed, 379 insertions(+), 89 deletions(-) create mode 100644 scm/driver/harness/testdata/branch.json create mode 100644 scm/driver/harness/testdata/branch.json.golden create mode 100644 scm/driver/harness/testdata/branches.json create mode 100644 scm/driver/harness/testdata/branches.json.golden create mode 100644 scm/driver/harness/testdata/commit.json create mode 100644 scm/driver/harness/testdata/commit.json.golden create mode 100644 scm/driver/harness/testdata/commits.json create mode 100644 scm/driver/harness/testdata/commits.json.golden diff --git a/scm/driver/harness/git.go b/scm/driver/harness/git.go index 47b228021..3cbee37ee 100644 --- a/scm/driver/harness/git.go +++ b/scm/driver/harness/git.go @@ -7,7 +7,6 @@ package harness import ( "context" "fmt" - "net/url" "time" "github.com/drone/go-scm/scm" @@ -18,19 +17,23 @@ type gitService struct { } func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.ReferenceInput) (*scm.Response, error) { - return nil, scm.ErrNotSupported + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s/branches", harnessURI) + out := new(branch) + return s.client.do(ctx, "GET", path, nil, out) } func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { - path := fmt.Sprintf("api/v1/repos/%s/branches/%s", repo, name) + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s/branches/%s", harnessURI, name) out := new(branch) res, err := s.client.do(ctx, "GET", path, nil, out) return convertBranch(out), res, err } func (s *gitService) FindCommit(ctx context.Context, repo, ref string) (*scm.Commit, *scm.Response, error) { - ref = scm.TrimRef(ref) - path := fmt.Sprintf("api/v1/repos/%s/git/commits/%s", repo, url.PathEscape(ref)) + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s/commits/%s", harnessURI, ref) out := new(commitInfo) res, err := s.client.do(ctx, "GET", path, nil, out) return convertCommitInfo(out), res, err @@ -41,14 +44,16 @@ func (s *gitService) FindTag(ctx context.Context, repo, name string) (*scm.Refer } func (s *gitService) ListBranches(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { - path := fmt.Sprintf("api/v1/repos/%s/branches?%s", repo, encodeListOptions(opts)) + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s/branches?%s", harnessURI, encodeListOptions(opts)) out := []*branch{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertBranchList(out), res, err } func (s *gitService) ListCommits(ctx context.Context, repo string, _ scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { - path := fmt.Sprintf("api/v1/repos/%s/commits", repo) + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s/commits", harnessURI) out := []*commitInfo{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertCommitList(out), res, err @@ -66,52 +71,50 @@ func (s *gitService) CompareChanges(ctx context.Context, repo, source, target st return nil, nil, scm.ErrNotSupported } -// // native data structures -// - type ( - // gitea branch object. - branch struct { - Name string `json:"name"` - Commit commit `json:"commit"` - } - - // gitea commit object. - commit struct { - ID string `json:"id"` - Sha string `json:"sha"` - Message string `json:"message"` - URL string `json:"url"` - Author signature `json:"author"` - Committer signature `json:"committer"` - Timestamp time.Time `json:"timestamp"` - } - - // gitea commit info object. commitInfo struct { - Sha string `json:"sha"` - Commit commit `json:"commit"` - Author user `json:"author"` - Committer user `json:"committer"` - } - - // gitea signature object. - signature struct { - Name string `json:"name"` - Email string `json:"email"` - Username string `json:"username"` + Author struct { + Identity struct { + Email string `json:"email"` + Name string `json:"name"` + } `json:"identity"` + When time.Time `json:"when"` + } `json:"author"` + Committer struct { + Identity struct { + Email string `json:"email"` + Name string `json:"name"` + } `json:"identity"` + When time.Time `json:"when"` + } `json:"committer"` + Message string `json:"message"` + Sha string `json:"sha"` + Title string `json:"title"` } - // gitea tag object - tag struct { - Ref string `json:"ref"` - URL string `json:"url"` - Object struct { - Type string `json:"type"` - Sha string `json:"sha"` - URL string `json:"url"` - } `json:"object"` + branch struct { + Commit struct { + Author struct { + Identity struct { + Email string `json:"email"` + Name string `json:"name"` + } `json:"identity"` + When time.Time `json:"when"` + } `json:"author"` + Committer struct { + Identity struct { + Email string `json:"email"` + Name string `json:"name"` + } `json:"identity"` + When time.Time `json:"when"` + } `json:"committer"` + Message string `json:"message"` + Sha string `json:"sha"` + Title string `json:"title"` + } `json:"commit"` + Name string `json:"name"` + Sha string `json:"sha"` } ) @@ -129,9 +132,9 @@ func convertBranchList(src []*branch) []*scm.Reference { func convertBranch(src *branch) *scm.Reference { return &scm.Reference{ - Name: scm.TrimRef(src.Name), + Name: src.Name, Path: scm.ExpandRef(src.Name, "refs/heads/"), - Sha: src.Commit.ID, + Sha: src.Sha, } } @@ -145,43 +148,17 @@ func convertCommitList(src []*commitInfo) []*scm.Commit { func convertCommitInfo(src *commitInfo) *scm.Commit { return &scm.Commit{ - Sha: src.Sha, - Link: src.Commit.URL, - Message: src.Commit.Message, - Author: convertUserSignature(src.Author), - Committer: convertUserSignature(src.Committer), - } -} - -func convertSignature(src signature) scm.Signature { - return scm.Signature{ - Login: src.Username, - Email: src.Email, - Name: src.Name, - } -} - -func convertUserSignature(src user) scm.Signature { - return scm.Signature{ - Login: userLogin(&src), - Email: src.Email, - Name: src.Fullname, - Avatar: src.Avatar, - } -} - -func convertTagList(src []*tag) []*scm.Reference { - var dst []*scm.Reference - for _, v := range src { - dst = append(dst, convertTag(v)) - } - return dst -} - -func convertTag(src *tag) *scm.Reference { - return &scm.Reference{ - Name: scm.TrimRef(src.Ref), - Path: src.Ref, - Sha: src.Object.Sha, + Sha: src.Sha, + Message: src.Message, + Author: scm.Signature{ + Name: src.Author.Identity.Name, + Email: src.Author.Identity.Email, + Date: src.Author.When, + }, + Committer: scm.Signature{ + Name: src.Committer.Identity.Name, + Email: src.Committer.Identity.Email, + Date: src.Committer.When, + }, } } diff --git a/scm/driver/harness/git_test.go b/scm/driver/harness/git_test.go index 5d232e2ff..133905253 100644 --- a/scm/driver/harness/git_test.go +++ b/scm/driver/harness/git_test.go @@ -3,3 +3,173 @@ // license that can be found in the LICENSE file. package harness + +import ( + "context" + "encoding/json" + "io/ioutil" + "net/http" + "testing" + + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/transport" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/h2non/gock" +) + +func TestListCommits(t *testing.T) { + if harnessPAT == "" { + defer gock.Off() + + gock.New(gockOrigin). + Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/commits"). + Reply(200). + Type("application/json"). + File("testdata/commits.json") + } + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + got, _, err := client.Git.ListCommits(context.Background(), harnessRepo, scm.CommitListOptions{}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Commit{} + raw, _ := ioutil.ReadFile("testdata/commits.json.golden") + wantErr := json.Unmarshal(raw, &want) + if wantErr != nil { + t.Error(wantErr) + return + } + if harnessPAT != "" && len(got) > 0 { + // if testing against a real system and we get commits + return + } + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + +func TestFindCommit(t *testing.T) { + if harnessPAT == "" { + defer gock.Off() + + gock.New(gockOrigin). + Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/commits/1d640265d8bdd818175fa736f0fcbad2c9b716c9"). + Reply(200). + Type("application/json"). + File("testdata/commit.json") + } + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + got, _, err := client.Git.FindCommit(context.Background(), harnessRepo, "1d640265d8bdd818175fa736f0fcbad2c9b716c9") + if err != nil { + t.Error(err) + return + } + + want := new(scm.Commit) + raw, _ := ioutil.ReadFile("testdata/commit.json.golden") + wantErr := json.Unmarshal(raw, &want) + if wantErr != nil { + t.Error(wantErr) + return + } + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + +func TestFindBranch(t *testing.T) { + if harnessPAT == "" { + defer gock.Off() + + gock.New(gockOrigin). + Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/branches/main"). + Reply(200). + Type("application/json"). + File("testdata/branch.json") + } + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + got, _, err := client.Git.FindBranch(context.Background(), harnessRepo, "main") + if err != nil { + t.Error(err) + return + } + + want := new(scm.Reference) + raw, _ := ioutil.ReadFile("testdata/branch.json.golden") + wantErr := json.Unmarshal(raw, &want) + if wantErr != nil { + t.Error(wantErr) + return + } + + if diff := cmp.Diff(got, want, cmpopts.IgnoreFields(scm.Reference{}, "Sha")); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + +func TestListBranches(t *testing.T) { + if harnessPAT == "" { + defer gock.Off() + + gock.New(gockOrigin). + Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/branches"). + Reply(200). + Type("application/json"). + File("testdata/branches.json") + } + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + got, _, err := client.Git.ListBranches(context.Background(), harnessRepo, scm.ListOptions{}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Reference{} + raw, _ := ioutil.ReadFile("testdata/branches.json.golden") + wantErr := json.Unmarshal(raw, &want) + if wantErr != nil { + t.Error(wantErr) + return + } + + if diff := cmp.Diff(got, want, cmpopts.IgnoreFields(scm.Reference{}, "Sha")); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} diff --git a/scm/driver/harness/repo_test.go b/scm/driver/harness/repo_test.go index 8cd9a3a22..d482d4bcb 100644 --- a/scm/driver/harness/repo_test.go +++ b/scm/driver/harness/repo_test.go @@ -51,7 +51,6 @@ func TestRepositoryFind(t *testing.T) { t.Errorf("Unexpected Results") t.Log(diff) } - } func TestRepositoryList(t *testing.T) { @@ -86,6 +85,10 @@ func TestRepositoryList(t *testing.T) { raw, _ := ioutil.ReadFile("testdata/repos.json.golden") _ = json.Unmarshal(raw, &want) + if harnessPAT != "" && len(got) > 0 { + // pass when running against a live harness instance and we get more than one repo + return + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") t.Log(diff) diff --git a/scm/driver/harness/testdata/branch.json b/scm/driver/harness/testdata/branch.json new file mode 100644 index 000000000..79159c0fc --- /dev/null +++ b/scm/driver/harness/testdata/branch.json @@ -0,0 +1,23 @@ +{ + "name": "main", + "sha": "1d640265d8bdd818175fa736f0fcbad2c9b716c9", + "commit": { + "sha": "1d640265d8bdd818175fa736f0fcbad2c9b716c9", + "title": "delete README.2", + "message": "delete README.2\n\ndelete README.2", + "author": { + "identity": { + "name": "thomas.honey", + "email": "thomas.honey@harness.io" + }, + "when": "2023-02-08T16:17:50Z" + }, + "committer": { + "identity": { + "name": "Harness", + "email": "noreply@harness.io" + }, + "when": "2023-02-08T16:17:50Z" + } + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/branch.json.golden b/scm/driver/harness/testdata/branch.json.golden new file mode 100644 index 000000000..0b5426713 --- /dev/null +++ b/scm/driver/harness/testdata/branch.json.golden @@ -0,0 +1,5 @@ +{ + "Name": "main", + "Path": "refs/heads/main", + "Sha": "1d640265d8bdd818175fa736f0fcbad2c9b716c9" +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/branches.json b/scm/driver/harness/testdata/branches.json new file mode 100644 index 000000000..7f87681a1 --- /dev/null +++ b/scm/driver/harness/testdata/branches.json @@ -0,0 +1,25 @@ +[ + { + "name": "main", + "sha": "1d640265d8bdd818175fa736f0fcbad2c9b716c9", + "commit": { + "sha": "1d640265d8bdd818175fa736f0fcbad2c9b716c9", + "title": "delete README.2", + "message": "delete README.2\n\ndelete README.2", + "author": { + "identity": { + "name": "thomas.honey", + "email": "thomas.honey@harness.io" + }, + "when": "2023-02-08T16:17:50Z" + }, + "committer": { + "identity": { + "name": "Harness", + "email": "noreply@harness.io" + }, + "when": "2023-02-08T16:17:50Z" + } + } + } +] \ No newline at end of file diff --git a/scm/driver/harness/testdata/branches.json.golden b/scm/driver/harness/testdata/branches.json.golden new file mode 100644 index 000000000..8946da89e --- /dev/null +++ b/scm/driver/harness/testdata/branches.json.golden @@ -0,0 +1,7 @@ +[ + { + "Name": "main", + "Path": "refs/heads/main", + "Sha": "1d640265d8bdd818175fa736f0fcbad2c9b716c9" + } +] \ No newline at end of file diff --git a/scm/driver/harness/testdata/commit.json b/scm/driver/harness/testdata/commit.json new file mode 100644 index 000000000..38a6066ad --- /dev/null +++ b/scm/driver/harness/testdata/commit.json @@ -0,0 +1,19 @@ +{ + "sha": "1d640265d8bdd818175fa736f0fcbad2c9b716c9", + "title": "delete README.2", + "message": "delete README.2\n\ndelete README.2", + "author": { + "identity": { + "name": "thomas.honey", + "email": "thomas.honey@harness.io" + }, + "when": "2023-02-08T16:17:50Z" + }, + "committer": { + "identity": { + "name": "Harness", + "email": "noreply@harness.io" + }, + "when": "2023-02-08T16:17:50Z" + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/commit.json.golden b/scm/driver/harness/testdata/commit.json.golden new file mode 100644 index 000000000..01d7f0f40 --- /dev/null +++ b/scm/driver/harness/testdata/commit.json.golden @@ -0,0 +1,19 @@ +{ + "Sha": "1d640265d8bdd818175fa736f0fcbad2c9b716c9", + "Message": "delete README.2\n\ndelete README.2", + "Author": { + "Name": "thomas.honey", + "Email": "thomas.honey@harness.io", + "Date": "2023-02-08T16:17:50Z", + "Login": "", + "Avatar": "" + }, + "Committer": { + "Name": "Harness", + "Email": "noreply@harness.io", + "Date": "2023-02-08T16:17:50Z", + "Login": "", + "Avatar": "" + }, + "Link": "" +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/commits.json b/scm/driver/harness/testdata/commits.json new file mode 100644 index 000000000..96576e18f --- /dev/null +++ b/scm/driver/harness/testdata/commits.json @@ -0,0 +1,21 @@ +[ + { + "sha": "1d640265d8bdd818175fa736f0fcbad2c9b716c9", + "title": "delete README.2", + "message": "delete README.2\n\ndelete README.2", + "author": { + "identity": { + "name": "thomas.honey", + "email": "thomas.honey@harness.io" + }, + "when": "2023-02-08T16:17:50Z" + }, + "committer": { + "identity": { + "name": "Harness", + "email": "noreply@harness.io" + }, + "when": "2023-02-08T16:17:50Z" + } + } +] \ No newline at end of file diff --git a/scm/driver/harness/testdata/commits.json.golden b/scm/driver/harness/testdata/commits.json.golden new file mode 100644 index 000000000..83570e704 --- /dev/null +++ b/scm/driver/harness/testdata/commits.json.golden @@ -0,0 +1,21 @@ +[ + { + "Sha": "1d640265d8bdd818175fa736f0fcbad2c9b716c9", + "Message": "delete README.2\n\ndelete README.2", + "Author": { + "Name": "thomas.honey", + "Email": "thomas.honey@harness.io", + "Date": "2023-02-08T16:17:50Z", + "Login": "", + "Avatar": "" + }, + "Committer": { + "Name": "Harness", + "Email": "noreply@harness.io", + "Date": "2023-02-08T16:17:50Z", + "Login": "", + "Avatar": "" + }, + "Link": "" + } +] \ No newline at end of file From 2fd14107827389c5ce21e0d03b7afd83a694e503 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Thu, 9 Feb 2023 12:51:06 +0000 Subject: [PATCH 156/282] (feat) harness, add user and compare branches --- scm/driver/harness/git.go | 17 ++++++- scm/driver/harness/testdata/branches.json | 31 +++++++++-- .../harness/testdata/branches.json.golden | 5 ++ scm/driver/harness/testdata/user.json | 9 ++++ scm/driver/harness/testdata/user.json.golden | 7 +++ scm/driver/harness/user.go | 28 ++++------ scm/driver/harness/user_test.go | 51 +++++++++++++++++++ 7 files changed, 125 insertions(+), 23 deletions(-) create mode 100644 scm/driver/harness/testdata/user.json create mode 100644 scm/driver/harness/testdata/user.json.golden diff --git a/scm/driver/harness/git.go b/scm/driver/harness/git.go index 3cbee37ee..b66562797 100644 --- a/scm/driver/harness/git.go +++ b/scm/driver/harness/git.go @@ -7,6 +7,8 @@ package harness import ( "context" "fmt" + "io" + "strings" "time" "github.com/drone/go-scm/scm" @@ -68,7 +70,19 @@ func (s *gitService) ListChanges(ctx context.Context, repo, ref string, _ scm.Li } func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s/compare/%s...%s", harnessURI, source, target) + res, err := s.client.do(ctx, "GET", path, nil, nil) + // convert response to a string + buf := new(strings.Builder) + _, _ = io.Copy(buf, res.Body) + changes := []*scm.Change{ + { + Path: "not implemented", + Sha: buf.String(), + }, + } + return changes, res, err } // native data structures @@ -92,7 +106,6 @@ type ( Sha string `json:"sha"` Title string `json:"title"` } - branch struct { Commit struct { Author struct { diff --git a/scm/driver/harness/testdata/branches.json b/scm/driver/harness/testdata/branches.json index 7f87681a1..e35f84b4e 100644 --- a/scm/driver/harness/testdata/branches.json +++ b/scm/driver/harness/testdata/branches.json @@ -1,9 +1,32 @@ [ + { + "name": "bla", + "sha": "0c221fd126b9457d0ad2037641416083549f59c5", + "commit": { + "sha": "0c221fd126b9457d0ad2037641416083549f59c5", + "title": "Create bla_file", + "message": "Create bla_file", + "author": { + "identity": { + "name": "thomas.honey", + "email": "thomas.honey@harness.io" + }, + "when": "2023-02-09T11:20:14Z" + }, + "committer": { + "identity": { + "name": "Harness", + "email": "noreply@harness.io" + }, + "when": "2023-02-09T11:20:14Z" + } + } + }, { "name": "main", - "sha": "1d640265d8bdd818175fa736f0fcbad2c9b716c9", + "sha": "de2837f8911710cfb7bbb323d0de285fd2ef9155", "commit": { - "sha": "1d640265d8bdd818175fa736f0fcbad2c9b716c9", + "sha": "de2837f8911710cfb7bbb323d0de285fd2ef9155", "title": "delete README.2", "message": "delete README.2\n\ndelete README.2", "author": { @@ -11,14 +34,14 @@ "name": "thomas.honey", "email": "thomas.honey@harness.io" }, - "when": "2023-02-08T16:17:50Z" + "when": "2023-02-09T12:39:37Z" }, "committer": { "identity": { "name": "Harness", "email": "noreply@harness.io" }, - "when": "2023-02-08T16:17:50Z" + "when": "2023-02-09T12:39:37Z" } } } diff --git a/scm/driver/harness/testdata/branches.json.golden b/scm/driver/harness/testdata/branches.json.golden index 8946da89e..66ad737e5 100644 --- a/scm/driver/harness/testdata/branches.json.golden +++ b/scm/driver/harness/testdata/branches.json.golden @@ -1,4 +1,9 @@ [ + { + "Name": "bla", + "Path": "refs/heads/bla", + "Sha": "0c221fd126b9457d0ad2037641416083549f59c5" + }, { "Name": "main", "Path": "refs/heads/main", diff --git a/scm/driver/harness/testdata/user.json b/scm/driver/harness/testdata/user.json new file mode 100644 index 000000000..459c42c39 --- /dev/null +++ b/scm/driver/harness/testdata/user.json @@ -0,0 +1,9 @@ +{ + "admin": true, + "blocked": true, + "created": 0, + "display_name": "1", + "email": "2", + "uid": "3", + "updated": 0 +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/user.json.golden b/scm/driver/harness/testdata/user.json.golden new file mode 100644 index 000000000..1c38875a7 --- /dev/null +++ b/scm/driver/harness/testdata/user.json.golden @@ -0,0 +1,7 @@ +{ + "ID": "3", + "Login": "2", + "Name": "1", + "Email": "2", + "Avatar": "" +} \ No newline at end of file diff --git a/scm/driver/harness/user.go b/scm/driver/harness/user.go index 18cba27b4..3bdd3514d 100644 --- a/scm/driver/harness/user.go +++ b/scm/driver/harness/user.go @@ -37,12 +37,13 @@ func (s *userService) ListEmail(context.Context, scm.ListOptions) ([]*scm.Email, // type user struct { - ID int `json:"id"` - Login string `json:"login"` - Username string `json:"username"` - Fullname string `json:"full_name"` - Email string `json:"email"` - Avatar string `json:"avatar_url"` + Admin bool `json:"admin"` + Blocked bool `json:"blocked"` + Created int `json:"created"` + DisplayName string `json:"display_name"` + Email string `json:"email"` + UID string `json:"uid"` + Updated int `json:"updated"` } // @@ -51,16 +52,9 @@ type user struct { func convertUser(src *user) *scm.User { return &scm.User{ - Login: userLogin(src), - Avatar: src.Avatar, - Email: src.Email, - Name: src.Fullname, + Login: src.Email, + Email: src.Email, + Name: src.DisplayName, + ID: src.UID, } } - -func userLogin(src *user) string { - if src.Username != "" { - return src.Username - } - return src.Login -} diff --git a/scm/driver/harness/user_test.go b/scm/driver/harness/user_test.go index 5d232e2ff..755294de3 100644 --- a/scm/driver/harness/user_test.go +++ b/scm/driver/harness/user_test.go @@ -3,3 +3,54 @@ // license that can be found in the LICENSE file. package harness + +import ( + "context" + "encoding/json" + "io/ioutil" + "net/http" + "testing" + + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/transport" + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" +) + +func TestUsersFind(t *testing.T) { + + defer gock.Off() + + gock.New(gockOrigin). + Get("/gateway/code/api/v1/user"). + Reply(200). + Type("application/json"). + File("testdata/user.json") + + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + got, _, err := client.Users.Find(context.Background()) + if err != nil { + t.Error(err) + return + } + + want := new(scm.User) + raw, _ := ioutil.ReadFile("testdata/user.json.golden") + wantErr := json.Unmarshal(raw, &want) + if wantErr != nil { + t.Error(wantErr) + return + } + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} From f8d9958ec380bb15a84c4a10a3aef02ef94e98e5 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Thu, 9 Feb 2023 16:14:19 +0000 Subject: [PATCH 157/282] (feat) harness, fix create branch, PR calls --- scm/driver/harness/git.go | 11 +- scm/driver/harness/git_test.go | 34 +++++ scm/driver/harness/issue.go | 92 ------------- scm/driver/harness/pr.go | 152 ++++++++++----------- scm/driver/harness/pr_test.go | 49 +++++++ scm/driver/harness/release.go | 2 +- scm/driver/harness/testdata/pr.json | 32 +++++ scm/driver/harness/testdata/pr.json.golden | 20 +++ 8 files changed, 218 insertions(+), 174 deletions(-) create mode 100644 scm/driver/harness/testdata/pr.json create mode 100644 scm/driver/harness/testdata/pr.json.golden diff --git a/scm/driver/harness/git.go b/scm/driver/harness/git.go index b66562797..9186112e6 100644 --- a/scm/driver/harness/git.go +++ b/scm/driver/harness/git.go @@ -21,8 +21,11 @@ type gitService struct { func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.ReferenceInput) (*scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) path := fmt.Sprintf("api/v1/repos/%s/branches", harnessURI) - out := new(branch) - return s.client.do(ctx, "GET", path, nil, out) + in := &branchInput{ + Name: params.Name, + Target: params.Sha, + } + return s.client.do(ctx, "POST", path, in, nil) } func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { @@ -106,6 +109,10 @@ type ( Sha string `json:"sha"` Title string `json:"title"` } + branchInput struct { + Name string `json:"name"` + Target string `json:"target"` + } branch struct { Commit struct { Author struct { diff --git a/scm/driver/harness/git_test.go b/scm/driver/harness/git_test.go index 133905253..016d65e49 100644 --- a/scm/driver/harness/git_test.go +++ b/scm/driver/harness/git_test.go @@ -173,3 +173,37 @@ func TestListBranches(t *testing.T) { t.Log(diff) } } + +func TestCreateBranch(t *testing.T) { + + defer gock.Off() + + gock.New(gockOrigin). + Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/branches"). + Reply(200). + Type("application/json"). + File("testdata/branch.json") + + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + input := &scm.ReferenceInput{ + Name: "test", + Sha: "e8ef0374ca0cee8048e94b28eaf0d9e2e2515a14", + } + result, err := client.Git.CreateBranch(context.Background(), harnessRepo, input) + if err != nil { + t.Error(err) + return + } + + if result.Status != 200 { + t.Errorf("Unexpected Results") + } + +} diff --git a/scm/driver/harness/issue.go b/scm/driver/harness/issue.go index 6eab881c5..99d904791 100644 --- a/scm/driver/harness/issue.go +++ b/scm/driver/harness/issue.go @@ -6,7 +6,6 @@ package harness import ( "context" - "time" "github.com/drone/go-scm/scm" ) @@ -25,17 +24,14 @@ func (s *issueService) FindComment(ctx context.Context, repo string, index, id i func (s *issueService) List(ctx context.Context, repo string, opts scm.IssueListOptions) ([]*scm.Issue, *scm.Response, error) { return nil, nil, scm.ErrNotSupported - } func (s *issueService) ListComments(ctx context.Context, repo string, index int, opts scm.ListOptions) ([]*scm.Comment, *scm.Response, error) { return nil, nil, scm.ErrNotSupported - } func (s *issueService) Create(ctx context.Context, repo string, input *scm.IssueInput) (*scm.Issue, *scm.Response, error) { return nil, nil, scm.ErrNotSupported - } func (s *issueService) CreateComment(ctx context.Context, repo string, index int, input *scm.CommentInput) (*scm.Comment, *scm.Response, error) { @@ -57,91 +53,3 @@ func (s *issueService) Lock(ctx context.Context, repo string, number int) (*scm. func (s *issueService) Unlock(ctx context.Context, repo string, number int) (*scm.Response, error) { return nil, scm.ErrNotSupported } - -// -// native data structures -// - -type ( - // gitea issue response object. - issue struct { - ID int `json:"id"` - Number int `json:"number"` - User user `json:"user"` - Title string `json:"title"` - Body string `json:"body"` - State string `json:"state"` - Labels []string `json:"labels"` - Comments int `json:"comments"` - Created time.Time `json:"created_at"` - Updated time.Time `json:"updated_at"` - PullRequest *struct { - Merged bool `json:"merged"` - MergedAt interface{} `json:"merged_at"` - } `json:"pull_request"` - } - - // gitea issue request object. - issueInput struct { - Title string `json:"title"` - Body string `json:"body"` - } - - // gitea issue comment response object. - issueComment struct { - ID int `json:"id"` - HTMLURL string `json:"html_url"` - User user `json:"user"` - Body string `json:"body"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - } - - // gitea issue comment request object. - issueCommentInput struct { - Body string `json:"body"` - } -) - -// -// native data structure conversion -// - -func convertIssueList(from []*issue) []*scm.Issue { - to := []*scm.Issue{} - for _, v := range from { - to = append(to, convertIssue(v)) - } - return to -} - -func convertIssue(from *issue) *scm.Issue { - return &scm.Issue{ - Number: from.Number, - Title: from.Title, - Body: from.Body, - Link: "", // TODO construct the link to the issue. - Closed: from.State == "closed", - Author: *convertUser(&from.User), - Created: from.Created, - Updated: from.Updated, - } -} - -func convertIssueCommentList(from []*issueComment) []*scm.Comment { - to := []*scm.Comment{} - for _, v := range from { - to = append(to, convertIssueComment(v)) - } - return to -} - -func convertIssueComment(from *issueComment) *scm.Comment { - return &scm.Comment{ - ID: from.ID, - Body: from.Body, - Author: *convertUser(&from.User), - Created: from.CreatedAt, - Updated: from.UpdatedAt, - } -} diff --git a/scm/driver/harness/pr.go b/scm/driver/harness/pr.go index 631d994b7..61f802972 100644 --- a/scm/driver/harness/pr.go +++ b/scm/driver/harness/pr.go @@ -7,7 +7,6 @@ package harness import ( "context" "fmt" - "time" "github.com/drone/go-scm/scm" ) @@ -17,7 +16,11 @@ type pullService struct { } func (s *pullService) Find(ctx context.Context, repo string, index int) (*scm.PullRequest, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s/pullreq/%d", harnessURI, index) + out := new(pr) + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertPullRequest(out), res, err } @@ -61,52 +64,64 @@ func (s *pullService) Close(context.Context, string, int) (*scm.Response, error) return nil, scm.ErrNotSupported } -// // native data structures -// - -type pr struct { - ID int `json:"id"` - Number int `json:"number"` - User user `json:"user"` - Title string `json:"title"` - Body string `json:"body"` - State string `json:"state"` - HeadBranch string `json:"head_branch"` - HeadRepo repository `json:"head_repo"` - Head reference `json:"head"` - BaseBranch string `json:"base_branch"` - BaseRepo repository `json:"base_repo"` - Base reference `json:"base"` - HTMLURL string `json:"html_url"` - DiffURL string `json:"diff_url"` - Mergeable bool `json:"mergeable"` - Merged bool `json:"merged"` - Created time.Time `json:"created_at"` - Updated time.Time `json:"updated_at"` - Labels []struct { - Name string `json:"name"` - Color string `json:"color"` - } `json:"labels"` -} +type ( + pr struct { + Author struct { + Created int `json:"created"` + DisplayName string `json:"display_name"` + Email string `json:"email"` + ID int `json:"id"` + Type string `json:"type"` + UID string `json:"uid"` + Updated int `json:"updated"` + } `json:"author"` + Created int `json:"created"` + Description string `json:"description"` + Edited int `json:"edited"` + IsDraft bool `json:"is_draft"` + MergeBaseSha string `json:"merge_base_sha"` + MergeHeadSha string `json:"merge_head_sha"` + MergeStrategy string `json:"merge_strategy"` + Merged int `json:"merged"` + Merger struct { + Created int `json:"created"` + DisplayName string `json:"display_name"` + Email string `json:"email"` + ID int `json:"id"` + Type string `json:"type"` + UID string `json:"uid"` + Updated int `json:"updated"` + } `json:"merger"` + Number int `json:"number"` + SourceBranch string `json:"source_branch"` + SourceRepoID int `json:"source_repo_id"` + State string `json:"state"` + Stats struct { + Commits int `json:"commits"` + Conversations int `json:"conversations"` + FilesChanged int `json:"files_changed"` + } `json:"stats"` + TargetBranch string `json:"target_branch"` + TargetRepoID int `json:"target_repo_id"` + Title string `json:"title"` + } -type reference struct { - Repo repository `json:"repo"` - Name string `json:"ref"` - Sha string `json:"sha"` -} + reference struct { + Repo repository `json:"repo"` + Name string `json:"ref"` + Sha string `json:"sha"` + } -type prInput struct { - Title string `json:"title"` - Body string `json:"body"` - Head string `json:"head"` - Base string `json:"base"` -} + prInput struct { + Title string `json:"title"` + Body string `json:"body"` + Head string `json:"head"` + Base string `json:"base"` + } +) -// // native data structure conversion -// - func convertPullRequests(src []*pr) []*scm.PullRequest { dst := []*scm.PullRequest{} for _, v := range src { @@ -116,42 +131,21 @@ func convertPullRequests(src []*pr) []*scm.PullRequest { } func convertPullRequest(src *pr) *scm.PullRequest { - var labels []scm.Label - for _, label := range src.Labels { - labels = append(labels, scm.Label{ - Name: label.Name, - Color: label.Color, - }) - } - return &scm.PullRequest{ - Number: src.Number, - Title: src.Title, - Body: src.Body, - Sha: src.Head.Sha, - Source: src.Head.Name, - Target: src.Base.Name, - Link: src.HTMLURL, - Diff: src.DiffURL, - Fork: "fork", - Ref: fmt.Sprintf("refs/pull/%d/head", src.Number), - Closed: src.State == "closed", - Author: *convertUser(&src.User), - Merged: src.Merged, - Created: src.Created, - Updated: src.Updated, - Labels: labels, - } -} - -func convertPullRequestFromIssue(src *issue) *scm.PullRequest { return &scm.PullRequest{ - Number: src.Number, - Title: src.Title, - Body: src.Body, - Closed: src.State == "closed", - Author: *convertUser(&src.User), - Merged: src.PullRequest.Merged, - Created: src.Created, - Updated: src.Updated, + Number: src.Number, + Title: src.Title, + Body: src.Description, + Source: src.SourceBranch, + Target: src.TargetBranch, + Merged: src.Merged != 0, + Author: scm.User{ + Login: src.Author.Email, + Name: src.Author.DisplayName, + ID: src.Author.UID, + Email: src.Author.Email, + }, + Fork: "fork", + Ref: fmt.Sprintf("refs/pull/%d/head", src.Number), + Closed: src.State == "closed", } } diff --git a/scm/driver/harness/pr_test.go b/scm/driver/harness/pr_test.go index 5d232e2ff..51ab690b9 100644 --- a/scm/driver/harness/pr_test.go +++ b/scm/driver/harness/pr_test.go @@ -3,3 +3,52 @@ // license that can be found in the LICENSE file. package harness + +import ( + "context" + "encoding/json" + "io/ioutil" + "net/http" + "testing" + + "github.com/drone/go-scm/scm" + "github.com/drone/go-scm/scm/transport" + "github.com/google/go-cmp/cmp" + "github.com/h2non/gock" +) + +func TestPRFind(t *testing.T) { + if harnessPAT == "" { + defer gock.Off() + + gock.New(gockOrigin). + Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/pullreq/1"). + Reply(200). + Type("plain/text"). + File("testdata/pr.json") + } + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + got, _, err := client.PullRequests.Find(context.Background(), harnessRepo, 1) + if err != nil { + t.Error(err) + } + + want := new(scm.PullRequest) + raw, err := ioutil.ReadFile("testdata/pr.json.golden") + if err != nil { + t.Error(err) + } + json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} diff --git a/scm/driver/harness/release.go b/scm/driver/harness/release.go index 45e10704a..66d62cdb3 100644 --- a/scm/driver/harness/release.go +++ b/scm/driver/harness/release.go @@ -67,7 +67,7 @@ type release struct { IsPrerelease bool `json:"prerelease"` CreatedAt null.Time `json:"created_at"` PublishedAt null.Time `json:"published_at"` - Publisher *user `json:"author"` + Publisher *string `json:"author"` Attachments []*Attachment `json:"assets"` } diff --git a/scm/driver/harness/testdata/pr.json b/scm/driver/harness/testdata/pr.json new file mode 100644 index 000000000..89e773b96 --- /dev/null +++ b/scm/driver/harness/testdata/pr.json @@ -0,0 +1,32 @@ +{ + "number": 1, + "created": 1675960384081, + "edited": 1675960384081, + "state": "open", + "is_draft": false, + "title": "pull title", + "description": "pull description", + "source_repo_id": 11, + "source_branch": "bla", + "target_repo_id": 11, + "target_branch": "main", + "merged": null, + "merge_strategy": null, + "merge_head_sha": null, + "merge_base_sha": null, + "author": { + "id": 14, + "uid": "0Nnoezs6RGa_fOWvG_Ta4w", + "display_name": "thomas.honey", + "email": "thomas.honey@harness.io", + "type": "user", + "created": 1675248918372, + "updated": 1675248918372 + }, + "merger": null, + "stats": { + "conversations": 0, + "commits": 1, + "files_changed": 1 + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/pr.json.golden b/scm/driver/harness/testdata/pr.json.golden new file mode 100644 index 000000000..224b66050 --- /dev/null +++ b/scm/driver/harness/testdata/pr.json.golden @@ -0,0 +1,20 @@ +{ + "Number": 1, + "Title": "pull title", + "Body": "pull description", + "Sha": "", + "Ref": "refs/pull/1/head", + "Source": "bla", + "Target": "main", + "Fork": "fork", + "Link": "", + "Diff": "", + "Closed": false, + "Merged": false, + "Author": { + "ID": "0Nnoezs6RGa_fOWvG_Ta4w", + "Login": "thomas.honey@harness.io", + "Name": "thomas.honey", + "Email": "thomas.honey@harness.io" + } +} \ No newline at end of file From cc7b846c96081a87a3d2518b0b65cdc9441f87b2 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Fri, 10 Feb 2023 10:48:32 +0000 Subject: [PATCH 158/282] (feat) harness, add get pr commits --- scm/driver/harness/pr.go | 51 ++++++++++++++++++- scm/driver/harness/pr_test.go | 44 +++++++++++++++- scm/driver/harness/testdata/pr_commits.json | 21 ++++++++ .../harness/testdata/pr_commits.json.golden | 19 +++++++ 4 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 scm/driver/harness/testdata/pr_commits.json create mode 100644 scm/driver/harness/testdata/pr_commits.json.golden diff --git a/scm/driver/harness/pr.go b/scm/driver/harness/pr.go index 61f802972..a223b8d41 100644 --- a/scm/driver/harness/pr.go +++ b/scm/driver/harness/pr.go @@ -7,6 +7,7 @@ package harness import ( "context" "fmt" + "time" "github.com/drone/go-scm/scm" ) @@ -36,8 +37,12 @@ func (s *pullService) ListComments(context.Context, string, int, scm.ListOptions return nil, nil, scm.ErrNotSupported } -func (s *pullService) ListCommits(context.Context, string, int, scm.ListOptions) ([]*scm.Commit, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported +func (s *pullService) ListCommits(ctx context.Context, repo string, index int, opts scm.ListOptions) ([]*scm.Commit, *scm.Response, error) { + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s/pullreq/%d/commits?%s", harnessURI, index, encodeListOptions(opts)) + out := []*commit{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertCommits(out), res, err } func (s *pullService) ListChanges(context.Context, string, int, scm.ListOptions) ([]*scm.Change, *scm.Response, error) { @@ -119,6 +124,25 @@ type ( Head string `json:"head"` Base string `json:"base"` } + commit struct { + Author struct { + Identity struct { + Email string `json:"email"` + Name string `json:"name"` + } `json:"identity"` + When time.Time `json:"when"` + } `json:"author"` + Committer struct { + Identity struct { + Email string `json:"email"` + Name string `json:"name"` + } `json:"identity"` + When time.Time `json:"when"` + } `json:"committer"` + Message string `json:"message"` + Sha string `json:"sha"` + Title string `json:"title"` + } ) // native data structure conversion @@ -149,3 +173,26 @@ func convertPullRequest(src *pr) *scm.PullRequest { Closed: src.State == "closed", } } + +func convertCommits(src []*commit) []*scm.Commit { + dst := []*scm.Commit{} + for _, v := range src { + dst = append(dst, convertCommit(v)) + } + return dst +} + +func convertCommit(src *commit) *scm.Commit { + return &scm.Commit{ + Message: src.Message, + Sha: src.Sha, + Author: scm.Signature{ + Name: src.Author.Identity.Name, + Email: src.Author.Identity.Email, + }, + Committer: scm.Signature{ + Name: src.Committer.Identity.Name, + Email: src.Committer.Identity.Email, + }, + } +} diff --git a/scm/driver/harness/pr_test.go b/scm/driver/harness/pr_test.go index 51ab690b9..28f43e40f 100644 --- a/scm/driver/harness/pr_test.go +++ b/scm/driver/harness/pr_test.go @@ -45,7 +45,49 @@ func TestPRFind(t *testing.T) { if err != nil { t.Error(err) } - json.Unmarshal(raw, want) + err = json.Unmarshal(raw, want) + if err != nil { + t.Error(err) + } + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + +func TestPRCommits(t *testing.T) { + if harnessPAT == "" { + defer gock.Off() + + gock.New(gockOrigin). + Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/pullreq/1/commits"). + Reply(200). + Type("plain/text"). + File("testdata/pr_commits.json") + } + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + got, _, err := client.PullRequests.ListCommits(context.Background(), harnessRepo, 1, scm.ListOptions{}) + if err != nil { + t.Error(err) + } + + want := []*scm.Commit{} + raw, err := ioutil.ReadFile("testdata/pr_commits.json.golden") + if err != nil { + t.Error(err) + } + err = json.Unmarshal(raw, &want) + if err != nil { + t.Error(err) + } if diff := cmp.Diff(got, want); diff != "" { t.Errorf("Unexpected Results") diff --git a/scm/driver/harness/testdata/pr_commits.json b/scm/driver/harness/testdata/pr_commits.json new file mode 100644 index 000000000..286654d14 --- /dev/null +++ b/scm/driver/harness/testdata/pr_commits.json @@ -0,0 +1,21 @@ +[ + { + "author": { + "identity": { + "email": "thomas.honey@harness.io", + "name": "thomas.honey" + }, + "when": "2023-02-09T17:12:10.976Z" + }, + "committer": { + "identity": { + "email": "noreply@harness.io", + "name": "Harness" + }, + "when": "2023-02-09T17:12:10.976Z" + }, + "message": "Create bla_file", + "sha": "0c221fd126b9457d0ad2037641416083549f59c5", + "title": "string" + } +] \ No newline at end of file diff --git a/scm/driver/harness/testdata/pr_commits.json.golden b/scm/driver/harness/testdata/pr_commits.json.golden new file mode 100644 index 000000000..aeceed89f --- /dev/null +++ b/scm/driver/harness/testdata/pr_commits.json.golden @@ -0,0 +1,19 @@ +[ + { + "Sha": "0c221fd126b9457d0ad2037641416083549f59c5", + "Message": "Create bla_file", + "Author": { + "Name": "thomas.honey", + "Email": "thomas.honey@harness.io", + "Login": "", + "Avatar": "" + }, + "Committer": { + "Name": "Harness", + "Email": "noreply@harness.io", + "Login": "", + "Avatar": "" + }, + "Link": "" + } +] \ No newline at end of file From 3d6625f3f2f927fd71496c10be05105a7977e446 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Fri, 10 Feb 2023 11:18:52 +0000 Subject: [PATCH 159/282] (feat) harness, add create PR --- scm/driver/harness/pr.go | 23 ++++++++--- scm/driver/harness/pr_test.go | 40 +++++++++++++++++++ scm/driver/harness/testdata/branches.json | 23 +++++++++++ .../harness/testdata/branches.json.golden | 7 +++- 4 files changed, 87 insertions(+), 6 deletions(-) diff --git a/scm/driver/harness/pr.go b/scm/driver/harness/pr.go index a223b8d41..6e0266a0d 100644 --- a/scm/driver/harness/pr.go +++ b/scm/driver/harness/pr.go @@ -50,7 +50,17 @@ func (s *pullService) ListChanges(context.Context, string, int, scm.ListOptions) } func (s *pullService) Create(ctx context.Context, repo string, input *scm.PullRequestInput) (*scm.PullRequest, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s/pullreq", harnessURI) + in := &prInput{ + Title: input.Title, + Description: input.Body, + SourceBranch: input.Source, + TargetBranch: input.Target, + } + out := new(pr) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertPullRequest(out), res, err } func (s *pullService) CreateComment(context.Context, string, int, *scm.CommentInput) (*scm.Comment, *scm.Response, error) { @@ -119,11 +129,14 @@ type ( } prInput struct { - Title string `json:"title"` - Body string `json:"body"` - Head string `json:"head"` - Base string `json:"base"` + Description string `json:"description"` + IsDraft bool `json:"is_draft"` + SourceBranch string `json:"source_branch"` + SourceRepoRef string `json:"source_repo_ref"` + TargetBranch string `json:"target_branch"` + Title string `json:"title"` } + commit struct { Author struct { Identity struct { diff --git a/scm/driver/harness/pr_test.go b/scm/driver/harness/pr_test.go index 28f43e40f..b9bc5a631 100644 --- a/scm/driver/harness/pr_test.go +++ b/scm/driver/harness/pr_test.go @@ -94,3 +94,43 @@ func TestPRCommits(t *testing.T) { t.Log(diff) } } + +func TestPullCreate(t *testing.T) { + defer gock.Off() + gock.New(gockOrigin). + Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/pullreq"). + Reply(200). + Type("plain/text"). + File("testdata/pr.json") + + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + + input := scm.PullRequestInput{ + Title: "pull title", + Body: "pull description", + Source: "bla", + Target: "main", + } + + got, _, err := client.PullRequests.Create(context.Background(), harnessRepo, &input) + if err != nil { + t.Error(err) + return + } + + want := new(scm.PullRequest) + raw, _ := ioutil.ReadFile("testdata/pr.json.golden") + _ = json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} diff --git a/scm/driver/harness/testdata/branches.json b/scm/driver/harness/testdata/branches.json index e35f84b4e..2490e4ae3 100644 --- a/scm/driver/harness/testdata/branches.json +++ b/scm/driver/harness/testdata/branches.json @@ -22,6 +22,29 @@ } } }, + { + "name": "branch3", + "sha": "59e1cdf0e421fd14b106f4861fb02dfd56b4dc34", + "commit": { + "sha": "59e1cdf0e421fd14b106f4861fb02dfd56b4dc34", + "title": "delete README.2", + "message": "delete README.2\n\ndelete README.2", + "author": { + "identity": { + "name": "thomas.honey", + "email": "thomas.honey@harness.io" + }, + "when": "2023-02-09T12:39:37Z" + }, + "committer": { + "identity": { + "name": "Harness", + "email": "noreply@harness.io" + }, + "when": "2023-02-09T12:39:37Z" + } + } + }, { "name": "main", "sha": "de2837f8911710cfb7bbb323d0de285fd2ef9155", diff --git a/scm/driver/harness/testdata/branches.json.golden b/scm/driver/harness/testdata/branches.json.golden index 66ad737e5..3f2458b08 100644 --- a/scm/driver/harness/testdata/branches.json.golden +++ b/scm/driver/harness/testdata/branches.json.golden @@ -1,9 +1,14 @@ [ - { + { "Name": "bla", "Path": "refs/heads/bla", "Sha": "0c221fd126b9457d0ad2037641416083549f59c5" }, + { + "Name": "branch3", + "Path": "refs/heads/branch3", + "Sha": "59e1cdf0e421fd14b106f4861fb02dfd56b4dc34" + }, { "Name": "main", "Path": "refs/heads/main", From 643af2e8f3a4295313b75b951a4fa19d1a4a1586 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Fri, 10 Feb 2023 13:54:49 +0000 Subject: [PATCH 160/282] (fix) harness, webhook fixes --- scm/driver/harness/harness.go | 2 +- scm/driver/harness/webhook.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scm/driver/harness/harness.go b/scm/driver/harness/harness.go index d26835374..9b36f87f3 100644 --- a/scm/driver/harness/harness.go +++ b/scm/driver/harness/harness.go @@ -33,7 +33,7 @@ func New(uri, account, organization, project string) (*scm.Client, error) { client := &wrapper{new(scm.Client), account, organization, project} client.BaseURL = base // initialize services - client.Driver = scm.DriverGitea + client.Driver = scm.DriverHarness client.Linker = &linker{base.String()} client.Contents = &contentService{client} client.Git = &gitService{client} diff --git a/scm/driver/harness/webhook.go b/scm/driver/harness/webhook.go index 6b8c2777e..fc89148e5 100644 --- a/scm/driver/harness/webhook.go +++ b/scm/driver/harness/webhook.go @@ -58,7 +58,7 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo } secret := req.FormValue("secret") - signature := req.Header.Get("X-Gitea-Signature") + signature := req.Header.Get("X-Harness-Signature") // fail if no signature passed if signature == "" && secret == "" { From f8f38dff4e0e8cd7f7d847b35b96de21ea28d426 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Mon, 13 Feb 2023 12:01:02 +0000 Subject: [PATCH 161/282] (feat) harness, add finduser --- scm/driver/harness/testdata/user.json | 52 ++++++++++++-- scm/driver/harness/testdata/user.json.golden | 8 +-- scm/driver/harness/user.go | 72 +++++++++++++++----- scm/driver/harness/user_test.go | 17 +++-- 4 files changed, 115 insertions(+), 34 deletions(-) diff --git a/scm/driver/harness/testdata/user.json b/scm/driver/harness/testdata/user.json index 459c42c39..21ea693f2 100644 --- a/scm/driver/harness/testdata/user.json +++ b/scm/driver/harness/testdata/user.json @@ -1,9 +1,47 @@ { - "admin": true, - "blocked": true, - "created": 0, - "display_name": "1", - "email": "2", - "uid": "3", - "updated": 0 + "status": "SUCCESS", + "data": { + "uuid": "0Nnoezs6RGa_fOWvG_Ta4w", + "name": "thomas.honey", + "email": "thomas.honey@harness.io", + "token": null, + "defaultAccountId": "px7xd_BFRCi-pfWPYXVjvw", + "intent": null, + "accounts": [ + { + "uuid": "px7xd_BFRCi-pfWPYXVjvw", + "accountName": "harness-dev", + "companyName": "harness-dev", + "defaultExperience": "NG", + "createdFromNG": false, + "nextGenEnabled": true + }, + { + "uuid": "Ws0xvw71Sm2YmpSC7A8z4g", + "accountName": "OPA-Governance", + "companyName": "Feature-Flag", + "defaultExperience": "NG", + "createdFromNG": false, + "nextGenEnabled": true + } + ], + "admin": false, + "twoFactorAuthenticationEnabled": false, + "emailVerified": true, + "locked": false, + "disabled": false, + "signupAction": null, + "edition": null, + "billingFrequency": null, + "utmInfo": { + "utmSource": null, + "utmContent": null, + "utmMedium": null, + "utmTerm": null, + "utmCampaign": null + }, + "externallyManaged": false + }, + "metaData": null, + "correlationId": "c4014fdb-10a1-4dc4-ace0-6fad93544993" } \ No newline at end of file diff --git a/scm/driver/harness/testdata/user.json.golden b/scm/driver/harness/testdata/user.json.golden index 1c38875a7..5f81bfeba 100644 --- a/scm/driver/harness/testdata/user.json.golden +++ b/scm/driver/harness/testdata/user.json.golden @@ -1,7 +1,7 @@ { - "ID": "3", - "Login": "2", - "Name": "1", - "Email": "2", + "ID": "0Nnoezs6RGa_fOWvG_Ta4w", + "Login": "thomas.honey@harness.io", + "Name": "thomas.honey", + "Email": "thomas.honey@harness.io", "Avatar": "" } \ No newline at end of file diff --git a/scm/driver/harness/user.go b/scm/driver/harness/user.go index 3bdd3514d..500cad249 100644 --- a/scm/driver/harness/user.go +++ b/scm/driver/harness/user.go @@ -6,6 +6,8 @@ package harness import ( "context" + "fmt" + "strings" "github.com/drone/go-scm/scm" ) @@ -15,9 +17,19 @@ type userService struct { } func (s *userService) Find(ctx context.Context) (*scm.User, *scm.Response, error) { - out := new(user) - res, err := s.client.do(ctx, "GET", "api/v1/user", nil, out) - return convertUser(out), res, err + out := new(harnessUser) + // the following is for the corporate version of Harness code + tempUserService := *s + // get the basepath + basePath := tempUserService.client.BaseURL.Path + // use the NG user endpoint + basePath = strings.Replace(basePath, "code", "ng", 1) + // set the new basepath + tempUserService.client.BaseURL.Path = basePath + // set the path + path := fmt.Sprintf("api/user/currentUser") + res, err := s.client.do(ctx, "GET", path, nil, out) + return convertHarnessUser(out), res, err } func (s *userService) FindLogin(ctx context.Context, login string) (*scm.User, *scm.Response, error) { @@ -36,25 +48,53 @@ func (s *userService) ListEmail(context.Context, scm.ListOptions) ([]*scm.Email, // native data structures // -type user struct { - Admin bool `json:"admin"` - Blocked bool `json:"blocked"` - Created int `json:"created"` - DisplayName string `json:"display_name"` - Email string `json:"email"` - UID string `json:"uid"` - Updated int `json:"updated"` +type harnessUser struct { + Status string `json:"status"` + Data struct { + UUID string `json:"uuid"` + Name string `json:"name"` + Email string `json:"email"` + Token interface{} `json:"token"` + Defaultaccountid string `json:"defaultAccountId"` + Intent interface{} `json:"intent"` + Accounts []struct { + UUID string `json:"uuid"` + Accountname string `json:"accountName"` + Companyname string `json:"companyName"` + Defaultexperience string `json:"defaultExperience"` + Createdfromng bool `json:"createdFromNG"` + Nextgenenabled bool `json:"nextGenEnabled"` + } `json:"accounts"` + Admin bool `json:"admin"` + Twofactorauthenticationenabled bool `json:"twoFactorAuthenticationEnabled"` + Emailverified bool `json:"emailVerified"` + Locked bool `json:"locked"` + Disabled bool `json:"disabled"` + Signupaction interface{} `json:"signupAction"` + Edition interface{} `json:"edition"` + Billingfrequency interface{} `json:"billingFrequency"` + Utminfo struct { + Utmsource interface{} `json:"utmSource"` + Utmcontent interface{} `json:"utmContent"` + Utmmedium interface{} `json:"utmMedium"` + Utmterm interface{} `json:"utmTerm"` + Utmcampaign interface{} `json:"utmCampaign"` + } `json:"utmInfo"` + Externallymanaged bool `json:"externallyManaged"` + } `json:"data"` + Metadata interface{} `json:"metaData"` + Correlationid string `json:"correlationId"` } // // native data structure conversion // -func convertUser(src *user) *scm.User { +func convertHarnessUser(src *harnessUser) *scm.User { return &scm.User{ - Login: src.Email, - Email: src.Email, - Name: src.DisplayName, - ID: src.UID, + Login: src.Data.Email, + Email: src.Data.Email, + Name: src.Data.Name, + ID: src.Data.UUID, } } diff --git a/scm/driver/harness/user_test.go b/scm/driver/harness/user_test.go index 755294de3..886494c13 100644 --- a/scm/driver/harness/user_test.go +++ b/scm/driver/harness/user_test.go @@ -9,6 +9,7 @@ import ( "encoding/json" "io/ioutil" "net/http" + "strings" "testing" "github.com/drone/go-scm/scm" @@ -18,15 +19,17 @@ import ( ) func TestUsersFind(t *testing.T) { + if harnessPAT == "" { + defer gock.Off() - defer gock.Off() - - gock.New(gockOrigin). - Get("/gateway/code/api/v1/user"). - Reply(200). - Type("application/json"). - File("testdata/user.json") + harnessUserOrigin := strings.Replace(gockOrigin, "code", "ng", 1) + gock.New(harnessUserOrigin). + Get("/gateway/ng/api/user/currentUser"). + Reply(200). + Type("application/json"). + File("testdata/user.json") + } client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) client.Client = &http.Client{ Transport: &transport.Custom{ From a9651b1e4b178182ffe8dabe12d984326050d31e Mon Sep 17 00:00:00 2001 From: TP Honey Date: Wed, 15 Feb 2023 10:23:58 +0000 Subject: [PATCH 162/282] (maint) prep for 1.29.0 --- CHANGELOG.md | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f8653ef1..0eb4ae3a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,28 @@ # Changelog -## [1.28.1](https://github.com/drone/go-scm/tree/1.28.1) (2023-01-27) +## [1.29.0](https://github.com/drone/go-scm/tree/1.29.0) (2023-02-15) -[Full Changelog](https://github.com/drone/go-scm/compare/v1.28.0...1.28.1) +[Full Changelog](https://github.com/drone/go-scm/compare/v1.28.1...1.29.0) + +**Implemented enhancements:** + +- \(feat\) harness, add finduser [\#250](https://github.com/drone/go-scm/pull/250) ([tphoney](https://github.com/tphoney)) +- \(feat\) harness, fix create branch, PR calls [\#247](https://github.com/drone/go-scm/pull/247) ([tphoney](https://github.com/tphoney)) +- \(feat\) harness, add user and compare branches [\#246](https://github.com/drone/go-scm/pull/246) ([tphoney](https://github.com/tphoney)) +- \(feat\) harness, add list commits / branches [\#245](https://github.com/drone/go-scm/pull/245) ([tphoney](https://github.com/tphoney)) +- \(feat\) harness, add webhook parsing [\#244](https://github.com/drone/go-scm/pull/244) ([tphoney](https://github.com/tphoney)) +- fetch branch for bitbucket onprem [\#242](https://github.com/drone/go-scm/pull/242) ([devkimittal](https://github.com/devkimittal)) +- \(feat\) harness, add repo list [\#241](https://github.com/drone/go-scm/pull/241) ([tphoney](https://github.com/tphoney)) +- Harness move [\#237](https://github.com/drone/go-scm/pull/237) ([tphoney](https://github.com/tphoney)) + +**Fixed bugs:** + +- \(fix\) harness, webhook fixes [\#248](https://github.com/drone/go-scm/pull/248) ([tphoney](https://github.com/tphoney)) +- fix: \[PIE-7927\]: Fix header value typo issue for BB OnPrem CSRF header [\#236](https://github.com/drone/go-scm/pull/236) ([mohitg0795](https://github.com/mohitg0795)) + +## [v1.28.1](https://github.com/drone/go-scm/tree/v1.28.1) (2023-01-27) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.28.0...v1.28.1) **Fixed bugs:** @@ -12,6 +32,10 @@ - Gogs commit fails to deserialize commitDetails in some cases [\#231](https://github.com/drone/go-scm/issues/231) +**Merged pull requests:** + +- \(maint\) prep 1.28.1 release [\#235](https://github.com/drone/go-scm/pull/235) ([tphoney](https://github.com/tphoney)) + ## [v1.28.0](https://github.com/drone/go-scm/tree/v1.28.0) (2022-11-22) [Full Changelog](https://github.com/drone/go-scm/compare/v1.27.0...v1.28.0) From 971da4d64ddd33589eeae533a7c0afb5388c49f5 Mon Sep 17 00:00:00 2001 From: Eoin McAfee <83226740+eoinmcafee00@users.noreply.github.com> Date: Wed, 15 Feb 2023 15:24:46 +0000 Subject: [PATCH 163/282] update list url to scopepath instead of path (#249) --- scm/driver/azure/content.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/scm/driver/azure/content.go b/scm/driver/azure/content.go index 18cd0402a..689f6718f 100644 --- a/scm/driver/azure/content.go +++ b/scm/driver/azure/content.go @@ -19,8 +19,8 @@ type contentService struct { func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm.Content, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/items/get?view=azure-devops-rest-6.0 if s.client.project == "" { - return nil, nil, ProjectRequiredError() - } + return nil, nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/items?path=%s&includeContent=true&$format=json", s.client.owner, s.client.project, repo, path) endpoint += generateURIFromRef(ref) endpoint += "&api-version=6.0" @@ -37,8 +37,8 @@ func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm func (s *contentService) Create(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { if s.client.project == "" { - return nil, ProjectRequiredError() - } + return nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/pushes?api-version=6.0", s.client.owner, s.client.project, repo) ref := refUpdate{ Name: SanitizeBranchName(params.Branch), @@ -66,8 +66,8 @@ func (s *contentService) Create(ctx context.Context, repo, path string, params * func (s *contentService) Update(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { if s.client.project == "" { - return nil, ProjectRequiredError() - } + return nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/pushes?api-version=6.0", s.client.owner, s.client.project, repo) ref := refUpdate{ Name: SanitizeBranchName(params.Branch), @@ -95,8 +95,8 @@ func (s *contentService) Update(ctx context.Context, repo, path string, params * func (s *contentService) Delete(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { if s.client.project == "" { - return nil, ProjectRequiredError() - } + return nil, ProjectRequiredError() + } endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/pushes?api-version=6.0", s.client.owner, s.client.project, repo) ref := refUpdate{ Name: SanitizeBranchName(params.Branch), @@ -122,9 +122,9 @@ func (s *contentService) Delete(ctx context.Context, repo, path string, params * func (s *contentService) List(ctx context.Context, repo, path, ref string, _ scm.ListOptions) ([]*scm.ContentInfo, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/items/list?view=azure-devops-rest-6.0 if s.client.project == "" { - return nil, nil, ProjectRequiredError() - } - endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/items?path=%s&recursionLevel=Full&$format=json", s.client.owner, s.client.project, repo, path) + return nil, nil, ProjectRequiredError() + } + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/items?scopePath=%s&recursionLevel=Full&$format=json", s.client.owner, s.client.project, repo, path) endpoint += generateURIFromRef(ref) out := new(contentList) res, err := s.client.do(ctx, "GET", endpoint, nil, &out) From 430a0a7800c74adb95ea72e684349649bf4fea92 Mon Sep 17 00:00:00 2001 From: Mohit Garg Date: Thu, 16 Feb 2023 02:04:36 +0530 Subject: [PATCH 164/282] add required header for bitbucket server in commit API use-case to handle csrf failures --- scm/driver/stash/stash.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scm/driver/stash/stash.go b/scm/driver/stash/stash.go index 33f3d5711..62db1c7fd 100644 --- a/scm/driver/stash/stash.go +++ b/scm/driver/stash/stash.go @@ -95,7 +95,8 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface req.Body = &b // write the content type that contains the length of the multipart req.Header = map[string][]string{ - "Content-Type": {mw.FormDataContentType()}, + "Content-Type": {mw.FormDataContentType()}, + "x-atlassian-token": {"no-check"}, } default: buf := new(bytes.Buffer) From 2957cd32fe5dbb0880f2590219937984d1071ed9 Mon Sep 17 00:00:00 2001 From: Eoin McAfee Date: Thu, 16 Feb 2023 10:50:11 +0000 Subject: [PATCH 165/282] release prep v1.29.1 --- CHANGELOG.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0eb4ae3a1..872d6396c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,16 @@ # Changelog -## [1.29.0](https://github.com/drone/go-scm/tree/1.29.0) (2023-02-15) +## [v1.29.1](https://github.com/drone/go-scm/tree/v1.29.1) (2023-02-16) -[Full Changelog](https://github.com/drone/go-scm/compare/v1.28.1...1.29.0) +[Full Changelog](https://github.com/drone/go-scm/compare/v1.29.0...v1.29.1) + +**Fixed bugs:** + +- \(fix\) - azure content list queryparam incorrect [\#249](https://github.com/drone/go-scm/pull/249) ([eoinmcafee00](https://github.com/eoinmcafee00)) + +## [v1.29.0](https://github.com/drone/go-scm/tree/v1.29.0) (2023-02-15) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.28.1...v1.29.0) **Implemented enhancements:** @@ -20,6 +28,10 @@ - \(fix\) harness, webhook fixes [\#248](https://github.com/drone/go-scm/pull/248) ([tphoney](https://github.com/tphoney)) - fix: \[PIE-7927\]: Fix header value typo issue for BB OnPrem CSRF header [\#236](https://github.com/drone/go-scm/pull/236) ([mohitg0795](https://github.com/mohitg0795)) +**Merged pull requests:** + +- \(maint\) prep for 1.29.0 [\#251](https://github.com/drone/go-scm/pull/251) ([tphoney](https://github.com/tphoney)) + ## [v1.28.1](https://github.com/drone/go-scm/tree/v1.28.1) (2023-01-27) [Full Changelog](https://github.com/drone/go-scm/compare/v1.28.0...v1.28.1) From bdac4837fcef86672478d5923044962eaae6dc1d Mon Sep 17 00:00:00 2001 From: Dev Mittal Date: Wed, 1 Mar 2023 17:54:53 +0530 Subject: [PATCH 166/282] fix: [CI-6978] fixed gitlab webhook parse --- .../testdata/webhooks/merge_request_comment_create.json.golden | 2 +- scm/driver/gitlab/webhook.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scm/driver/gitlab/testdata/webhooks/merge_request_comment_create.json.golden b/scm/driver/gitlab/testdata/webhooks/merge_request_comment_create.json.golden index 3b84d1116..dcc3e2448 100644 --- a/scm/driver/gitlab/testdata/webhooks/merge_request_comment_create.json.golden +++ b/scm/driver/gitlab/testdata/webhooks/merge_request_comment_create.json.golden @@ -40,7 +40,7 @@ "Source": "feature", "Target": "master", "Fork": "", - "Link": "https://gitlab.com/gitlab-org/hello-world", + "Link": "https://gitlab.com/gitlab-org/hello-world/merge_requests/1", "Diff": "", "Closed": false, "Merged": false, diff --git a/scm/driver/gitlab/webhook.go b/scm/driver/gitlab/webhook.go index b0a519739..56da8f195 100644 --- a/scm/driver/gitlab/webhook.go +++ b/scm/driver/gitlab/webhook.go @@ -237,7 +237,7 @@ func convertCommentHook(src *commentHook) (*scm.IssueCommentHook, error) { Ref: fmt.Sprintf("refs/merge-requests/%d/head", src.MergeRequest.Iid), Source: src.MergeRequest.SourceBranch, Target: src.MergeRequest.TargetBranch, - Link: src.Project.WebURL, + Link: src.MergeRequest.URL, Closed: src.MergeRequest.State != "opened", Merged: src.MergeRequest.State == "merged", Author: *convertUser(&src.User), From 194f53fb37164b85170a71b0040456191797a0fe Mon Sep 17 00:00:00 2001 From: Shalini Agrawal Date: Fri, 28 Apr 2023 15:12:29 +0530 Subject: [PATCH 167/282] fix: [CDS-67745]: fix find user email api for bitbucket in go-scm (#255) Co-authored-by: Mohit Garg --- scm/driver/bitbucket/testdata/userEmail.json | 8 +++++++ scm/driver/bitbucket/user.go | 22 +++++++++++++++++++- scm/driver/bitbucket/user_test.go | 21 ++++++++++++++++--- 3 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 scm/driver/bitbucket/testdata/userEmail.json diff --git a/scm/driver/bitbucket/testdata/userEmail.json b/scm/driver/bitbucket/testdata/userEmail.json new file mode 100644 index 000000000..80e1c227a --- /dev/null +++ b/scm/driver/bitbucket/testdata/userEmail.json @@ -0,0 +1,8 @@ +{ + "Values": [ + { + "email": "test@harness.io", + "is_primary": true + } + ] +} \ No newline at end of file diff --git a/scm/driver/bitbucket/user.go b/scm/driver/bitbucket/user.go index b349cb5c1..eba34f022 100644 --- a/scm/driver/bitbucket/user.go +++ b/scm/driver/bitbucket/user.go @@ -29,13 +29,24 @@ func (s *userService) FindLogin(ctx context.Context, login string) (*scm.User, * } func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, error) { - return "", nil, scm.ErrNotSupported + out := new(emails) + res, err := s.client.do(ctx, "GET", "2.0/user/emails", nil, &out) + return convertEmailList(out), res, err } func (s *userService) ListEmail(context.Context, scm.ListOptions) ([]*scm.Email, *scm.Response, error) { return nil, nil, scm.ErrNotSupported } +func convertEmailList(from *emails) string { + for _, v := range from.Values { + if v.IsPrimary == true { + return v.Email + } + } + return "" +} + type user struct { // The `username` field is no longer available after 29 April 2019 in // accordance with GDPR regulations. See: @@ -53,6 +64,15 @@ type user struct { UUID string `json:"uuid"` } +type email struct { + Email string `json:"email"` + IsPrimary bool `json:"is_primary"` +} + +type emails struct { + Values []*email `json:"values"` +} + func convertUser(from *user) *scm.User { return &scm.User{ Avatar: fmt.Sprintf("https://bitbucket.org/account/%s/avatar/32/", from.Username), diff --git a/scm/driver/bitbucket/user_test.go b/scm/driver/bitbucket/user_test.go index aa3b4e947..4e6b3c9f4 100644 --- a/scm/driver/bitbucket/user_test.go +++ b/scm/driver/bitbucket/user_test.go @@ -67,9 +67,24 @@ func TestUserLoginFind(t *testing.T) { } func TestUserFindEmail(t *testing.T) { + defer gock.Off() + + gock.New("https://api.bitbucket.org"). + Get("/2.0/user/emails"). + Reply(200). + Type("application/json"). + File("testdata/userEmail.json") + client, _ := New("https://api.bitbucket.org") - _, _, err := client.Users.FindEmail(context.Background()) - if err != scm.ErrNotSupported { - t.Errorf("Expect Not Supported error") + got, _, err := client.Users.FindEmail(context.Background()) + if err != nil { + t.Error(err) + } + + want := "test@harness.io" + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) } } From 5877f3846131efb292e01d717d1a5c69c851dbd9 Mon Sep 17 00:00:00 2001 From: Shalini Agrawal Date: Mon, 15 May 2023 14:58:09 +0530 Subject: [PATCH 168/282] feat: [CDS-69341]: add find user email api for github in go-scm (#256) * feat: [CDS-69341]: add find user email api for github in go-scm --- scm/driver/github/user.go | 13 +++++++++++-- scm/driver/github/user_test.go | 4 ++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/scm/driver/github/user.go b/scm/driver/github/user.go index fd6243e13..6da295679 100644 --- a/scm/driver/github/user.go +++ b/scm/driver/github/user.go @@ -31,8 +31,8 @@ func (s *userService) FindLogin(ctx context.Context, login string) (*scm.User, * } func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, error) { - user, res, err := s.Find(ctx) - return user.Email, res, err + out, res, err := s.ListEmail(ctx, scm.ListOptions{}) + return returnPrimaryEmail(out), res, err } func (s *userService) ListEmail(ctx context.Context, opts scm.ListOptions) ([]*scm.Email, *scm.Response, error) { @@ -69,6 +69,15 @@ func convertUser(from *user) *scm.User { } } +func returnPrimaryEmail(from []*scm.Email) string { + for _, v := range from { + if v.Primary == true { + return v.Value + } + } + return "" +} + // helper function to convert from the github email list to // the common email structure. func convertEmailList(from []*email) []*scm.Email { diff --git a/scm/driver/github/user_test.go b/scm/driver/github/user_test.go index e2fd64bad..8888d18a5 100644 --- a/scm/driver/github/user_test.go +++ b/scm/driver/github/user_test.go @@ -87,14 +87,14 @@ func TestUserEmailFind(t *testing.T) { defer gock.Off() gock.New("https://api.github.com"). - Get("/user"). + Get("/user/emails"). Reply(200). Type("application/json"). SetHeader("X-GitHub-Request-Id", "DD0E:6011:12F21A8:1926790:5A2064E2"). SetHeader("X-RateLimit-Limit", "60"). SetHeader("X-RateLimit-Remaining", "59"). SetHeader("X-RateLimit-Reset", "1512076018"). - File("testdata/user.json") + File("testdata/emails.json") client := NewDefault() result, res, err := client.Users.FindEmail(context.Background()) From ad21d44b0fe3a9649a24dfb4d954da7c6c5178aa Mon Sep 17 00:00:00 2001 From: TP Honey Date: Thu, 22 Jun 2023 14:00:18 +0100 Subject: [PATCH 169/282] (maint) stash/bitbucket on prem v5 add push webhook test (#257) Co-authored-by: dependabot-ci --- .../stash/testdata/webhooks/push_v5.json | 44 ++++++++++++++++ .../testdata/webhooks/push_v5.json.golden | 50 +++++++++++++++++++ scm/driver/stash/webhook_test.go | 9 +++- 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 scm/driver/stash/testdata/webhooks/push_v5.json create mode 100644 scm/driver/stash/testdata/webhooks/push_v5.json.golden diff --git a/scm/driver/stash/testdata/webhooks/push_v5.json b/scm/driver/stash/testdata/webhooks/push_v5.json new file mode 100644 index 000000000..444d2ff44 --- /dev/null +++ b/scm/driver/stash/testdata/webhooks/push_v5.json @@ -0,0 +1,44 @@ +{ + "eventKey": "repo:refs_changed", + "date": "2023-05-30T15:40:47-0400", + "actor": { + "name": "trangineni", + "emailAddress": "tanuja.rangineni@transamerica.com", + "id": 39725, + "displayName": "Rangineni, Tanuja", + "active": true, + "slug": "trangineni", + "type": "NORMAL" + }, + "repository": { + "slug": "transamerica.cloud.individual.tftest", + "id": 13027, + "name": "transamerica.cloud.individual.tftest", + "scmId": "git", + "state": "AVAILABLE", + "statusMessage": "Available", + "forkable": true, + "project": { + "key": "ISCLOUD", + "id": 1453, + "name": "Individual Cloud", + "description": "Project for Individual Solutions application terraform.", + "public": false, + "type": "NORMAL" + }, + "public": false + }, + "changes": [ + { + "ref": { + "id": "refs/heads/trangineni/devtfvars-1685475548410", + "displayId": "trangineni/devtfvars-1685475548410", + "type": "BRANCH" + }, + "refId": "refs/heads/trangineni/devtfvars-1685475548410", + "fromHash": "b2b710209761a3fab9fc867aad7b7725fd0fd028", + "toHash": "51a33664b6d7fb5aa15063064eb230362cd02e9e", + "type": "UPDATE" + } + ] +} \ No newline at end of file diff --git a/scm/driver/stash/testdata/webhooks/push_v5.json.golden b/scm/driver/stash/testdata/webhooks/push_v5.json.golden new file mode 100644 index 000000000..ffe8c4c87 --- /dev/null +++ b/scm/driver/stash/testdata/webhooks/push_v5.json.golden @@ -0,0 +1,50 @@ +{ + "Ref": "refs/heads/trangineni/devtfvars-1685475548410", + "After": "51a33664b6d7fb5aa15063064eb230362cd02e9e", + "Before": "b2b710209761a3fab9fc867aad7b7725fd0fd028", + "Repo": { + "ID": "13027", + "Namespace": "ISCLOUD", + "Name": "transamerica.cloud.individual.tftest", + "Perm": null, + "Branch": "master", + "Private": true, + "Clone": "", + "CloneSSH": "", + "Link": "", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Commit": { + "Sha": "51a33664b6d7fb5aa15063064eb230362cd02e9e", + "Message": "", + "Author": { + "Name": "Rangineni, Tanuja", + "Email": "tanuja.rangineni@transamerica.com", + "Date": "0001-01-01T00:00:00Z", + "Login": "trangineni", + "Avatar": "https://www.gravatar.com/avatar/1c0ba1559ee8ed291204dad48479149b.jpg" + }, + "Committer": { + "Name": "Rangineni, Tanuja", + "Email": "tanuja.rangineni@transamerica.com", + "Date": "0001-01-01T00:00:00Z", + "Login": "trangineni", + "Avatar": "https://www.gravatar.com/avatar/1c0ba1559ee8ed291204dad48479149b.jpg" + }, + "Link": "" + }, + "Commits": [ + { + "Sha": "51a33664b6d7fb5aa15063064eb230362cd02e9e", + "Message": "", + "Link": "" + } + ], + "Sender": { + "Login": "trangineni", + "Name": "Rangineni, Tanuja", + "Email": "tanuja.rangineni@transamerica.com", + "Avatar": "https://www.gravatar.com/avatar/1c0ba1559ee8ed291204dad48479149b.jpg" + } +} \ No newline at end of file diff --git a/scm/driver/stash/webhook_test.go b/scm/driver/stash/webhook_test.go index 711adc694..28e72a0ad 100644 --- a/scm/driver/stash/webhook_test.go +++ b/scm/driver/stash/webhook_test.go @@ -37,7 +37,14 @@ func TestWebhooks(t *testing.T) { after: "testdata/webhooks/push.json.golden", obj: new(scm.PushHook), }, - + // v5 test + { + sig: "71295b197fa25f4356d2fb9965df3f2379d903d7", + event: "repo:refs_changed", + before: "testdata/webhooks/push_v5.json", + after: "testdata/webhooks/push_v5.json.golden", + obj: new(scm.PushHook), + }, // // tag events // From 64a614ce5db57d436f93c9204417728578742d14 Mon Sep 17 00:00:00 2001 From: Adithya Viswanathan Date: Wed, 5 Jul 2023 16:21:06 +0530 Subject: [PATCH 170/282] [feat]: [CDS-73030]: Support for text based branch filtration --- scm/client.go | 7 + scm/driver/azure/git.go | 11 + scm/driver/azure/git_test.go | 26 +++ scm/driver/azure/testdata/branchesFilter.json | 41 ++++ .../azure/testdata/branchesFilter.json.golden | 12 ++ scm/driver/bitbucket/git.go | 7 + scm/driver/bitbucket/git_test.go | 34 +++ .../bitbucket/testdata/branchesFilter.json | 201 ++++++++++++++++++ .../testdata/branchesFilter.json.golden | 12 ++ scm/driver/bitbucket/util.go | 19 ++ scm/driver/gitea/git.go | 4 + scm/driver/gitee/git.go | 4 + scm/driver/github/git.go | 4 + scm/driver/gitlab/git.go | 7 + scm/driver/gitlab/git_test.go | 32 +++ .../gitlab/testdata/branchesFilter.json | 46 ++++ .../testdata/branchesFilter.json.golden | 12 ++ scm/driver/gitlab/util.go | 14 ++ scm/driver/gogs/git.go | 4 + scm/driver/harness/git.go | 4 + scm/driver/stash/git.go | 9 + scm/driver/stash/git_test.go | 28 +++ scm/driver/stash/testdata/branchesFilter.json | 24 +++ .../stash/testdata/branchesFilter.json.golden | 12 ++ scm/driver/stash/util.go | 16 ++ scm/git.go | 1 + 26 files changed, 591 insertions(+) create mode 100644 scm/driver/azure/testdata/branchesFilter.json create mode 100644 scm/driver/azure/testdata/branchesFilter.json.golden create mode 100644 scm/driver/bitbucket/testdata/branchesFilter.json create mode 100644 scm/driver/bitbucket/testdata/branchesFilter.json.golden create mode 100644 scm/driver/gitlab/testdata/branchesFilter.json create mode 100644 scm/driver/gitlab/testdata/branchesFilter.json.golden create mode 100644 scm/driver/stash/testdata/branchesFilter.json create mode 100644 scm/driver/stash/testdata/branchesFilter.json.golden diff --git a/scm/client.go b/scm/client.go index d3d8a7d21..ca3d1cafc 100644 --- a/scm/client.go +++ b/scm/client.go @@ -68,6 +68,13 @@ type ( Reset int64 } + // BranchListOptions specifies optional branch search term and pagination + // parameters. + BranchListOptions struct { + SearchTerm string + PageListOptions ListOptions + } + // ListOptions specifies optional pagination // parameters. ListOptions struct { diff --git a/scm/driver/azure/git.go b/scm/driver/azure/git.go index b23a0f7d7..af6656c13 100644 --- a/scm/driver/azure/git.go +++ b/scm/driver/azure/git.go @@ -63,6 +63,17 @@ func (s *gitService) ListBranches(ctx context.Context, repo string, _ scm.ListOp return convertBranchList(out.Value), res, err } +func (s *gitService) ListBranchesV2(ctx context.Context, repo string, opts scm.BranchListOptions) ([]*scm.Reference, *scm.Response, error) { + // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/refs/list?view=azure-devops-rest-6.0 + if s.client.project == "" { + return nil, nil, ProjectRequiredError() + } + endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/refs?api-version=6.0&filterContains=%s", s.client.owner, s.client.project, repo, opts.SearchTerm) + out := new(branchList) + res, err := s.client.do(ctx, "GET", endpoint, nil, &out) + return convertBranchList(out.Value), res, err +} + func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/git/commits/get-commits?view=azure-devops-rest-6.0 if s.client.project == "" { diff --git a/scm/driver/azure/git_test.go b/scm/driver/azure/git_test.go index d5faf0ef7..846e2b97b 100644 --- a/scm/driver/azure/git_test.go +++ b/scm/driver/azure/git_test.go @@ -123,6 +123,32 @@ func TestGitListBranches(t *testing.T) { } } +func TestGitListBranchesV2(t *testing.T) { + defer gock.Off() + + gock.New("https:/dev.azure.com/"). + Get("/ORG/PROJ/_apis/git/repositories/REPOID/"). + Reply(200). + Type("application/json"). + File("testdata/branchesFilter.json") + + client := NewDefault("ORG", "PROJ") + got, _, err := client.Git.ListBranchesV2(context.Background(), "REPOID", scm.BranchListOptions{SearchTerm: "main"}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Reference{} + raw, _ := ioutil.ReadFile("testdata/branchesFilter.json.golden") + _ = json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + func TestGitCompareChanges(t *testing.T) { defer gock.Off() diff --git a/scm/driver/azure/testdata/branchesFilter.json b/scm/driver/azure/testdata/branchesFilter.json new file mode 100644 index 000000000..b9043edb5 --- /dev/null +++ b/scm/driver/azure/testdata/branchesFilter.json @@ -0,0 +1,41 @@ +{ + "value": [ + { + "name": "refs/heads/main", + "objectId": "e0aee6aa543294d62520fb906689da6710af149c", + "creator": { + "displayName": "tp", + "url": "https://spsproduks1.vssps.visualstudio.com/A93f74f38-2b8d-42d4-a5cb-74646f46666e/_apis/Identities/3ff4a20f-306e-677e-8a01-57f35e71f109", + "_links": { + "avatar": { + "href": "https://dev.azure.com/tphoney/_apis/GraphProfile/MemberAvatars/msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + } + }, + "id": "3ff4a20f-306e-677e-8a01-57f35e71f109", + "uniqueName": "tp@harness.io", + "imageUrl": "https://dev.azure.com/tphoney/_api/_common/identityImage?id=3ff4a20f-306e-677e-8a01-57f35e71f109", + "descriptor": "msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + }, + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/refs?filter=heads%2Fmain" + }, + { + "name": "refs/heads/main-patch", + "objectId": "01768d964c03e97260af0bd8cd9e5cd1f9ac6356", + "creator": { + "displayName": "tp", + "url": "https://spsproduks1.vssps.visualstudio.com/A93f74f38-2b8d-42d4-a5cb-74646f46666e/_apis/Identities/3ff4a20f-306e-677e-8a01-57f35e71f109", + "_links": { + "avatar": { + "href": "https://dev.azure.com/tphoney/_apis/GraphProfile/MemberAvatars/msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + } + }, + "id": "3ff4a20f-306e-677e-8a01-57f35e71f109", + "uniqueName": "tp@harness.io", + "imageUrl": "https://dev.azure.com/tphoney/_api/_common/identityImage?id=3ff4a20f-306e-677e-8a01-57f35e71f109", + "descriptor": "msa.M2ZmNGEyMGYtMzA2ZS03NzdlLThhMDEtNTdmMzVlNzFmMTA5" + }, + "url": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/refs?filter=heads%2Fpr_branch" + } + ], + "count": 2 +} \ No newline at end of file diff --git a/scm/driver/azure/testdata/branchesFilter.json.golden b/scm/driver/azure/testdata/branchesFilter.json.golden new file mode 100644 index 000000000..df3589ce6 --- /dev/null +++ b/scm/driver/azure/testdata/branchesFilter.json.golden @@ -0,0 +1,12 @@ +[ + { + "Name": "main", + "Path": "refs/heads/main", + "Sha": "e0aee6aa543294d62520fb906689da6710af149c" + }, + { + "Name": "main-patch", + "Path": "refs/heads/main-patch", + "Sha": "01768d964c03e97260af0bd8cd9e5cd1f9ac6356" + } +] \ No newline at end of file diff --git a/scm/driver/bitbucket/git.go b/scm/driver/bitbucket/git.go index 4a2298d59..8efbe341e 100644 --- a/scm/driver/bitbucket/git.go +++ b/scm/driver/bitbucket/git.go @@ -64,6 +64,13 @@ func (s *gitService) ListBranches(ctx context.Context, repo string, opts scm.Lis copyPagination(out.pagination, res) return convertBranchList(out), res, err } +func (s *gitService) ListBranchesV2(ctx context.Context, repo string, opts scm.BranchListOptions) ([]*scm.Reference, *scm.Response, error) { + path := fmt.Sprintf("2.0/repositories/%s/refs/branches?%s", repo, encodeBranchListOptions(opts)) + out := new(branches) + res, err := s.client.do(ctx, "GET", path, nil, out) + copyPagination(out.pagination, res) + return convertBranchList(out), res, err +} func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { path := fmt.Sprintf("2.0/repositories/%s/commits/%s?%s", repo, opts.Ref, encodeCommitListOptions(opts)) diff --git a/scm/driver/bitbucket/git_test.go b/scm/driver/bitbucket/git_test.go index ec3b49f43..275707a0b 100644 --- a/scm/driver/bitbucket/git_test.go +++ b/scm/driver/bitbucket/git_test.go @@ -206,6 +206,40 @@ func TestGitListBranches(t *testing.T) { t.Run("Page", testPage(res)) } +func TestGitListBranchesV2(t *testing.T) { + defer gock.Off() + + gock.New("https://api.bitbucket.org"). + Get("/2.0/repositories/atlassian/stash-example-plugin/refs"). + MatchParam("q", "name~\\\"mast\\\""). + MatchParam("page", "1"). + MatchParam("pagelen", "30"). + Reply(200). + Type("application/json"). + File("testdata/branchesFilter.json") + + client, _ := New("https://api.bitbucket.org") + got, res, err := client.Git.ListBranchesV2(context.Background(), "atlassian/stash-example-plugin", scm.BranchListOptions{SearchTerm: "mast", PageListOptions: struct { + URL string + Page int + Size int + }{Page: 1, Size: 30}}) + if err != nil { + t.Error(err) + } + + want := []*scm.Reference{} + raw, _ := ioutil.ReadFile("testdata/branchesFilter.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Page", testPage(res)) +} + func TestGitListTags(t *testing.T) { defer gock.Off() diff --git a/scm/driver/bitbucket/testdata/branchesFilter.json b/scm/driver/bitbucket/testdata/branchesFilter.json new file mode 100644 index 000000000..122655ec4 --- /dev/null +++ b/scm/driver/bitbucket/testdata/branchesFilter.json @@ -0,0 +1,201 @@ +{ + "pagelen": 30, + "values": [ + { + "type": "branch", + "name": "master", + "links": { + "commits": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin\/commits\/master" + }, + "self": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin\/refs\/branches\/master" + }, + "html": { + "href": "https:\/\/bitbucket.org\/atlassian\/stash-example-plugin\/branch\/master" + } + }, + "target": { + "hash": "a6e5e7d797edf751cbd839d6bd4aef86c941eec9", + "repository": { + "links": { + "self": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin" + }, + "html": { + "href": "https:\/\/bitbucket.org\/atlassian\/stash-example-plugin" + }, + "avatar": { + "href": "https:\/\/bytebucket.org\/ravatar\/%7B7dd600e6-0d9c-4801-b967-cb4cc17359ff%7D?ts=default" + } + }, + "type": "repository", + "name": "stash-example-plugin", + "full_name": "atlassian\/stash-example-plugin", + "uuid": "{7dd600e6-0d9c-4801-b967-cb4cc17359ff}" + }, + "links": { + "self": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin\/commit\/a6e5e7d797edf751cbd839d6bd4aef86c941eec9" + }, + "comments": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin\/commit\/a6e5e7d797edf751cbd839d6bd4aef86c941eec9\/comments" + }, + "patch": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin\/patch\/a6e5e7d797edf751cbd839d6bd4aef86c941eec9" + }, + "html": { + "href": "https:\/\/bitbucket.org\/atlassian\/stash-example-plugin\/commits\/a6e5e7d797edf751cbd839d6bd4aef86c941eec9" + }, + "diff": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin\/diff\/a6e5e7d797edf751cbd839d6bd4aef86c941eec9" + }, + "approve": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin\/commit\/a6e5e7d797edf751cbd839d6bd4aef86c941eec9\/approve" + }, + "statuses": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin\/commit\/a6e5e7d797edf751cbd839d6bd4aef86c941eec9\/statuses" + } + }, + "author": { + "raw": "Adam Ahmed ", + "type": "author", + "user": { + "username": "aahmed", + "display_name": "Adam Ahmed", + "account_id": "557057:74dc5efb-ffe7-49af-b427-6abc299bb3b9", + "links": { + "self": { + "href": "https:\/\/api.bitbucket.org\/2.0\/users\/aahmed" + }, + "html": { + "href": "https:\/\/bitbucket.org\/aahmed\/" + }, + "avatar": { + "href": "https:\/\/bitbucket.org\/account\/aahmed\/avatar\/32\/" + } + }, + "type": "user", + "uuid": "{3d5de233-98d4-4138-b4af-8678fbb009ad}" + } + }, + "parents": [ + { + "hash": "5be6855032e171280a1acb860d7265c29f40487c", + "type": "commit", + "links": { + "self": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin\/commit\/5be6855032e171280a1acb860d7265c29f40487c" + }, + "html": { + "href": "https:\/\/bitbucket.org\/atlassian\/stash-example-plugin\/commits\/5be6855032e171280a1acb860d7265c29f40487c" + } + } + } + ], + "date": "2015-08-27T03:25:04+00:00", + "message": "Add Apache 2.0 License\n", + "type": "commit" + } + }, + { + "type": "branch", + "name": "master-patch", + "links": { + "commits": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin\/commits\/master" + }, + "self": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin\/refs\/branches\/master" + }, + "html": { + "href": "https:\/\/bitbucket.org\/atlassian\/stash-example-plugin\/branch\/master" + } + }, + "target": { + "hash": "a6e5e7d797edf751cbd839d6bd4aef86c941eec8", + "repository": { + "links": { + "self": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin" + }, + "html": { + "href": "https:\/\/bitbucket.org\/atlassian\/stash-example-plugin" + }, + "avatar": { + "href": "https:\/\/bytebucket.org\/ravatar\/%7B7dd600e6-0d9c-4801-b967-cb4cc17359ff%7D?ts=default" + } + }, + "type": "repository", + "name": "stash-example-plugin", + "full_name": "atlassian\/stash-example-plugin", + "uuid": "{7dd600e6-0d9c-4801-b967-cb4cc17359ff}" + }, + "links": { + "self": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin\/commit\/a6e5e7d797edf751cbd839d6bd4aef86c941eec9" + }, + "comments": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin\/commit\/a6e5e7d797edf751cbd839d6bd4aef86c941eec9\/comments" + }, + "patch": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin\/patch\/a6e5e7d797edf751cbd839d6bd4aef86c941eec9" + }, + "html": { + "href": "https:\/\/bitbucket.org\/atlassian\/stash-example-plugin\/commits\/a6e5e7d797edf751cbd839d6bd4aef86c941eec9" + }, + "diff": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin\/diff\/a6e5e7d797edf751cbd839d6bd4aef86c941eec9" + }, + "approve": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin\/commit\/a6e5e7d797edf751cbd839d6bd4aef86c941eec9\/approve" + }, + "statuses": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin\/commit\/a6e5e7d797edf751cbd839d6bd4aef86c941eec9\/statuses" + } + }, + "author": { + "raw": "Adam Ahmed ", + "type": "author", + "user": { + "username": "aahmed", + "display_name": "Adam Ahmed", + "account_id": "557057:74dc5efb-ffe7-49af-b427-6abc299bb3b9", + "links": { + "self": { + "href": "https:\/\/api.bitbucket.org\/2.0\/users\/aahmed" + }, + "html": { + "href": "https:\/\/bitbucket.org\/aahmed\/" + }, + "avatar": { + "href": "https:\/\/bitbucket.org\/account\/aahmed\/avatar\/32\/" + } + }, + "type": "user", + "uuid": "{3d5de233-98d4-4138-b4af-8678fbb009ad}" + } + }, + "parents": [ + { + "hash": "5be6855032e171280a1acb860d7265c29f40487c", + "type": "commit", + "links": { + "self": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin\/commit\/5be6855032e171280a1acb860d7265c29f40487c" + }, + "html": { + "href": "https:\/\/bitbucket.org\/atlassian\/stash-example-plugin\/commits\/5be6855032e171280a1acb860d7265c29f40487c" + } + } + } + ], + "date": "2015-08-27T03:25:04+00:00", + "message": "Add Apache 2.0 License\n", + "type": "commit" + } + } + ], + "page": 1, + "next": "https:\/\/bitbucket.org\/atlassian\/stash-example-plugin\/refs\/branches?pagelen=30&page=2" +} \ No newline at end of file diff --git a/scm/driver/bitbucket/testdata/branchesFilter.json.golden b/scm/driver/bitbucket/testdata/branchesFilter.json.golden new file mode 100644 index 000000000..79754a78f --- /dev/null +++ b/scm/driver/bitbucket/testdata/branchesFilter.json.golden @@ -0,0 +1,12 @@ +[ + { + "Name": "master", + "Path": "refs/heads/master", + "Sha": "a6e5e7d797edf751cbd839d6bd4aef86c941eec9" + }, + { + "Name": "master-patch", + "Path": "refs/heads/master-patch", + "Sha": "a6e5e7d797edf751cbd839d6bd4aef86c941eec8" + } +] \ No newline at end of file diff --git a/scm/driver/bitbucket/util.go b/scm/driver/bitbucket/util.go index 03c5eaae4..b53ba777c 100644 --- a/scm/driver/bitbucket/util.go +++ b/scm/driver/bitbucket/util.go @@ -8,6 +8,7 @@ import ( "net/url" "regexp" "strconv" + "strings" "github.com/drone/go-scm/scm" ) @@ -24,6 +25,24 @@ func extractEmail(gitauthor string) (author string) { return } +func encodeBranchListOptions(opts scm.BranchListOptions) string { + params := url.Values{} + if opts.SearchTerm != "" { + var sb strings.Builder + sb.WriteString("name~\"") + sb.WriteString(opts.SearchTerm) + sb.WriteString("\"") + params.Set("q", sb.String()) + } + if opts.PageListOptions.Page != 0 { + params.Set("page", strconv.Itoa(opts.PageListOptions.Page)) + } + if opts.PageListOptions.Size != 0 { + params.Set("pagelen", strconv.Itoa(opts.PageListOptions.Size)) + } + return params.Encode() +} + func encodeListOptions(opts scm.ListOptions) string { params := url.Values{} if opts.Page != 0 { diff --git a/scm/driver/gitea/git.go b/scm/driver/gitea/git.go index 60de87bec..3fab00f7c 100644 --- a/scm/driver/gitea/git.go +++ b/scm/driver/gitea/git.go @@ -59,6 +59,10 @@ func (s *gitService) ListBranches(ctx context.Context, repo string, opts scm.Lis return convertBranchList(out), res, err } +func (s *gitService) ListBranchesV2(ctx context.Context, repo string, opts scm.BranchListOptions) ([]*scm.Reference, *scm.Response, error) { + return s.ListBranches(ctx, repo, opts.PageListOptions) +} + func (s *gitService) ListCommits(ctx context.Context, repo string, _ scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { path := fmt.Sprintf("api/v1/repos/%s/commits", repo) out := []*commitInfo{} diff --git a/scm/driver/gitee/git.go b/scm/driver/gitee/git.go index ffbd5c0e2..2f8f93d57 100644 --- a/scm/driver/gitee/git.go +++ b/scm/driver/gitee/git.go @@ -60,6 +60,10 @@ func (s *gitService) ListBranches(ctx context.Context, repo string, _ scm.ListOp return convertBranchList(out), res, err } +func (s *gitService) ListBranchesV2(ctx context.Context, repo string, opts scm.BranchListOptions) ([]*scm.Reference, *scm.Response, error) { + return s.ListBranches(ctx, repo, opts.PageListOptions) +} + func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { path := fmt.Sprintf("repos/%s/commits?%s", repo, encodeCommitListOptions(opts)) out := []*commit{} diff --git a/scm/driver/github/git.go b/scm/driver/github/git.go index 5a5829f4d..d6ce73d69 100644 --- a/scm/driver/github/git.go +++ b/scm/driver/github/git.go @@ -53,6 +53,10 @@ func (s *gitService) ListBranches(ctx context.Context, repo string, opts scm.Lis return convertBranchList(out), res, err } +func (s *gitService) ListBranchesV2(ctx context.Context, repo string, opts scm.BranchListOptions) ([]*scm.Reference, *scm.Response, error) { + return s.ListBranches(ctx, repo, opts.PageListOptions) +} + func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { path := fmt.Sprintf("repos/%s/commits?%s", repo, encodeCommitListOptions(opts)) out := []*commit{} diff --git a/scm/driver/gitlab/git.go b/scm/driver/gitlab/git.go index ebada6c99..3bc37ef7d 100644 --- a/scm/driver/gitlab/git.go +++ b/scm/driver/gitlab/git.go @@ -60,6 +60,13 @@ func (s *gitService) ListBranches(ctx context.Context, repo string, opts scm.Lis return convertBranchList(out), res, err } +func (s *gitService) ListBranchesV2(ctx context.Context, repo string, opts scm.BranchListOptions) ([]*scm.Reference, *scm.Response, error) { + path := fmt.Sprintf("api/v4/projects/%s/repository/branches?%s", encode(repo), encodeBranchListOptions(opts)) + out := []*branch{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertBranchList(out), res, err +} + func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { path := fmt.Sprintf("api/v4/projects/%s/repository/commits?%s", encode(repo), encodeCommitListOptions(opts)) out := []*commit{} diff --git a/scm/driver/gitlab/git_test.go b/scm/driver/gitlab/git_test.go index 32d58f6f2..ee4595398 100644 --- a/scm/driver/gitlab/git_test.go +++ b/scm/driver/gitlab/git_test.go @@ -206,6 +206,38 @@ func TestGitListBranches(t *testing.T) { t.Run("Page", testPage(res)) } +func TestGitListBranchesWithBranchFilter(t *testing.T) { + defer gock.Off() + + gock.New("https://gitlab.com"). + Get("/api/v4/projects/diaspora/diaspora/repository/branches"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + SetHeaders(mockPageHeaders). + File("testdata/branchesFilter.json") + + client := NewDefault() + got, res, err := client.Git.ListBranchesV2(context.Background(), "diaspora/diaspora", scm.BranchListOptions{SearchTerm: "mast"}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Reference{} + raw, _ := ioutil.ReadFile("testdata/branchesFilter.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) + t.Run("Page", testPage(res)) +} + func TestGitListTags(t *testing.T) { defer gock.Off() diff --git a/scm/driver/gitlab/testdata/branchesFilter.json b/scm/driver/gitlab/testdata/branchesFilter.json new file mode 100644 index 000000000..c5072e736 --- /dev/null +++ b/scm/driver/gitlab/testdata/branchesFilter.json @@ -0,0 +1,46 @@ +[ + { + "name": "master", + "merged": false, + "protected": true, + "developers_can_push": false, + "developers_can_merge": false, + "commit": { + "author_email": "john@example.com", + "author_name": "John Smith", + "authored_date": "2012-06-27T05:51:39-07:00", + "committed_date": "2012-06-28T03:44:20-07:00", + "committer_email": "john@example.com", + "committer_name": "John Smith", + "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c", + "short_id": "7b5c3cc", + "title": "add projects API", + "message": "add projects API", + "parent_ids": [ + "4ad91d3c1144c406e50c7b33bae684bd6837faf8" + ] + } + }, + { + "name": "master-patch", + "merged": false, + "protected": true, + "developers_can_push": false, + "developers_can_merge": false, + "commit": { + "author_email": "john@example.com", + "author_name": "John Smith", + "authored_date": "2012-06-27T05:51:39-07:00", + "committed_date": "2012-06-28T03:44:20-07:00", + "committer_email": "john@example.com", + "committer_name": "John Smith", + "id": "7b5c3cc8be40ee161ae89a06bba6229da1032a0d", + "short_id": "7b5c3cc", + "title": "add projects API", + "message": "add projects API", + "parent_ids": [ + "4ad91d3c1144c406e50c7b33bae684bd6837faf9" + ] + } + } +] \ No newline at end of file diff --git a/scm/driver/gitlab/testdata/branchesFilter.json.golden b/scm/driver/gitlab/testdata/branchesFilter.json.golden new file mode 100644 index 000000000..d6f1a9210 --- /dev/null +++ b/scm/driver/gitlab/testdata/branchesFilter.json.golden @@ -0,0 +1,12 @@ +[ + { + "Name": "master", + "Path": "refs/heads/master", + "Sha": "7b5c3cc8be40ee161ae89a06bba6229da1032a0c" + }, + { + "Name": "master-patch", + "Path": "refs/heads/master-patch", + "Sha": "7b5c3cc8be40ee161ae89a06bba6229da1032a0d" + } +] \ No newline at end of file diff --git a/scm/driver/gitlab/util.go b/scm/driver/gitlab/util.go index 05670bcd2..55f106f71 100644 --- a/scm/driver/gitlab/util.go +++ b/scm/driver/gitlab/util.go @@ -24,6 +24,20 @@ func encodePath(s string) string { return strings.Replace(url.PathEscape(s), ".", "%2E", -1) } +func encodeBranchListOptions(opts scm.BranchListOptions) string { + params := url.Values{} + if opts.SearchTerm != "" { + params.Set("search", opts.SearchTerm) + } + if opts.PageListOptions.Page != 0 { + params.Set("page", strconv.Itoa(opts.PageListOptions.Page)) + } + if opts.PageListOptions.Size != 0 { + params.Set("per_page", strconv.Itoa(opts.PageListOptions.Size)) + } + return params.Encode() +} + func encodeListOptions(opts scm.ListOptions) string { params := url.Values{} if opts.Page != 0 { diff --git a/scm/driver/gogs/git.go b/scm/driver/gogs/git.go index aaf6a0616..15b9e7429 100644 --- a/scm/driver/gogs/git.go +++ b/scm/driver/gogs/git.go @@ -54,6 +54,10 @@ func (s *gitService) ListBranches(ctx context.Context, repo string, _ scm.ListOp return convertBranchList(out), res, err } +func (s *gitService) ListBranchesV2(ctx context.Context, repo string, opts scm.BranchListOptions) ([]*scm.Reference, *scm.Response, error) { + return s.ListBranches(ctx, repo, opts.PageListOptions) +} + func (s *gitService) ListCommits(ctx context.Context, repo string, _ scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { return nil, nil, scm.ErrNotSupported } diff --git a/scm/driver/harness/git.go b/scm/driver/harness/git.go index 9186112e6..59c9691cf 100644 --- a/scm/driver/harness/git.go +++ b/scm/driver/harness/git.go @@ -56,6 +56,10 @@ func (s *gitService) ListBranches(ctx context.Context, repo string, opts scm.Lis return convertBranchList(out), res, err } +func (s *gitService) ListBranchesV2(ctx context.Context, repo string, opts scm.BranchListOptions) ([]*scm.Reference, *scm.Response, error) { + return s.ListBranches(ctx, repo, opts.PageListOptions) +} + func (s *gitService) ListCommits(ctx context.Context, repo string, _ scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) path := fmt.Sprintf("api/v1/repos/%s/commits", harnessURI) diff --git a/scm/driver/stash/git.go b/scm/driver/stash/git.go index dece5d940..221b59911 100644 --- a/scm/driver/stash/git.go +++ b/scm/driver/stash/git.go @@ -79,6 +79,15 @@ func (s *gitService) ListBranches(ctx context.Context, repo string, opts scm.Lis return convertBranchList(out), res, err } +func (s *gitService) ListBranchesV2(ctx context.Context, repo string, opts scm.BranchListOptions) ([]*scm.Reference, *scm.Response, error) { + namespace, name := scm.Split(repo) + path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/branches?%s", namespace, name, encodeBranchListOptions(opts)) + out := new(branches) + res, err := s.client.do(ctx, "GET", path, nil, out) + copyPagination(out.pagination, res) + return convertBranchList(out), res, err +} + func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { namespace, name := scm.Split(repo) var requestPath string diff --git a/scm/driver/stash/git_test.go b/scm/driver/stash/git_test.go index 4d92fec4e..720e8fa6f 100644 --- a/scm/driver/stash/git_test.go +++ b/scm/driver/stash/git_test.go @@ -147,6 +147,34 @@ func TestGitListBranches(t *testing.T) { // t.Run("Page", testPage(res)) } +func TestGitListBranchesWithBranchFilter(t *testing.T) { + defer gock.Off() + + gock.New("http://example.com:7990"). + Get("/rest/api/1.0/projects/PRJ/repos/my-repo/branches"). + MatchParam("filterText", "mast"). + Reply(200). + Type("application/json"). + File("testdata/branchesFilter.json") + + client, _ := New("http://example.com:7990") + got, _, err := client.Git.ListBranchesV2(context.Background(), "PRJ/my-repo", scm.BranchListOptions{SearchTerm: "mast"}) + if err != nil { + t.Error(err) + } + + want := []*scm.Reference{} + raw, _ := ioutil.ReadFile("testdata/branchesFilter.json.golden") + _ = json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + // + // t.Run("Page", testPage(res)) +} + func TestGitListTags(t *testing.T) { defer gock.Off() diff --git a/scm/driver/stash/testdata/branchesFilter.json b/scm/driver/stash/testdata/branchesFilter.json new file mode 100644 index 000000000..f6b88ab8f --- /dev/null +++ b/scm/driver/stash/testdata/branchesFilter.json @@ -0,0 +1,24 @@ +{ + "size": 1, + "limit": 25, + "isLastPage": true, + "values": [ + { + "id": "refs/heads/master", + "displayId": "master", + "type": "BRANCH", + "latestCommit": "11ce869211917dd65610e70fcee454943b35ac6e", + "latestChangeset": "11ce869211917dd65610e70fcee454943b35ac6e", + "isDefault": true + }, + { + "id": "refs/heads/master-patch", + "displayId": "master-patch", + "type": "BRANCH", + "latestCommit": "11ce869211917dd65610e70fcee454943b35ac6f", + "latestChangeset": "11ce869211917dd65610e70fcee454943b35ac6f", + "isDefault": true + } + ], + "start": 0 +} \ No newline at end of file diff --git a/scm/driver/stash/testdata/branchesFilter.json.golden b/scm/driver/stash/testdata/branchesFilter.json.golden new file mode 100644 index 000000000..a158fbac2 --- /dev/null +++ b/scm/driver/stash/testdata/branchesFilter.json.golden @@ -0,0 +1,12 @@ +[ + { + "Name": "master", + "Path": "refs/heads/master", + "Sha": "11ce869211917dd65610e70fcee454943b35ac6e" + }, + { + "Name": "master-patch", + "Path": "refs/heads/master-patch", + "Sha": "11ce869211917dd65610e70fcee454943b35ac6f" + } +] \ No newline at end of file diff --git a/scm/driver/stash/util.go b/scm/driver/stash/util.go index 64e982ba2..0de82e3fa 100644 --- a/scm/driver/stash/util.go +++ b/scm/driver/stash/util.go @@ -25,6 +25,22 @@ func encodeListOptions(opts scm.ListOptions) string { return params.Encode() } +func encodeBranchListOptions(opts scm.BranchListOptions) string { + params := url.Values{} + if opts.SearchTerm != "" { + params.Set("filterText", opts.SearchTerm) + } + if opts.PageListOptions.Page > 1 { + params.Set("start", strconv.Itoa( + (opts.PageListOptions.Page-1)*opts.PageListOptions.Size), + ) + } + if opts.PageListOptions.Size != 0 { + params.Set("limit", strconv.Itoa(opts.PageListOptions.Size)) + } + return params.Encode() +} + func encodeListRoleOptions(opts scm.ListOptions) string { params := url.Values{} if opts.Page > 1 { diff --git a/scm/git.go b/scm/git.go index eff476038..847020932 100644 --- a/scm/git.go +++ b/scm/git.go @@ -72,6 +72,7 @@ type ( // ListBranches returns a list of git branches. ListBranches(ctx context.Context, repo string, opts ListOptions) ([]*Reference, *Response, error) + ListBranchesV2(ctx context.Context, repo string, opts BranchListOptions) ([]*Reference, *Response, error) // ListCommits returns a list of git commits. ListCommits(ctx context.Context, repo string, opts CommitListOptions) ([]*Commit, *Response, error) From aefd6d1f0af9d80ac2b1a9201ac98ed8d46d7f21 Mon Sep 17 00:00:00 2001 From: Adithya Viswanathan Date: Wed, 5 Jul 2023 16:29:04 +0530 Subject: [PATCH 171/282] [feat]: [CDS-73030]: added comments --- scm/driver/gitea/git.go | 2 ++ scm/driver/gitee/git.go | 2 ++ scm/driver/github/git.go | 2 ++ scm/driver/gogs/git.go | 2 ++ scm/driver/harness/git.go | 2 ++ scm/git.go | 2 ++ 6 files changed, 12 insertions(+) diff --git a/scm/driver/gitea/git.go b/scm/driver/gitea/git.go index 3fab00f7c..aaa58134f 100644 --- a/scm/driver/gitea/git.go +++ b/scm/driver/gitea/git.go @@ -60,6 +60,8 @@ func (s *gitService) ListBranches(ctx context.Context, repo string, opts scm.Lis } func (s *gitService) ListBranchesV2(ctx context.Context, repo string, opts scm.BranchListOptions) ([]*scm.Reference, *scm.Response, error) { + // Gitea doesnt provide support listing based on searchTerm + // Hence calling the ListBranches return s.ListBranches(ctx, repo, opts.PageListOptions) } diff --git a/scm/driver/gitee/git.go b/scm/driver/gitee/git.go index 2f8f93d57..b3377a43c 100644 --- a/scm/driver/gitee/git.go +++ b/scm/driver/gitee/git.go @@ -61,6 +61,8 @@ func (s *gitService) ListBranches(ctx context.Context, repo string, _ scm.ListOp } func (s *gitService) ListBranchesV2(ctx context.Context, repo string, opts scm.BranchListOptions) ([]*scm.Reference, *scm.Response, error) { + // Gitee doesnt provide support listing based on searchTerm + // Hence calling the ListBranches return s.ListBranches(ctx, repo, opts.PageListOptions) } diff --git a/scm/driver/github/git.go b/scm/driver/github/git.go index d6ce73d69..c64ea3430 100644 --- a/scm/driver/github/git.go +++ b/scm/driver/github/git.go @@ -54,6 +54,8 @@ func (s *gitService) ListBranches(ctx context.Context, repo string, opts scm.Lis } func (s *gitService) ListBranchesV2(ctx context.Context, repo string, opts scm.BranchListOptions) ([]*scm.Reference, *scm.Response, error) { + // Github doesnt provide support listing based on searchTerm + // Hence calling the ListBranches return s.ListBranches(ctx, repo, opts.PageListOptions) } diff --git a/scm/driver/gogs/git.go b/scm/driver/gogs/git.go index 15b9e7429..30103cc7b 100644 --- a/scm/driver/gogs/git.go +++ b/scm/driver/gogs/git.go @@ -55,6 +55,8 @@ func (s *gitService) ListBranches(ctx context.Context, repo string, _ scm.ListOp } func (s *gitService) ListBranchesV2(ctx context.Context, repo string, opts scm.BranchListOptions) ([]*scm.Reference, *scm.Response, error) { + // Gogs doesnt provide support listing based on searchTerm + // Hence calling the ListBranches return s.ListBranches(ctx, repo, opts.PageListOptions) } diff --git a/scm/driver/harness/git.go b/scm/driver/harness/git.go index 59c9691cf..787eb4920 100644 --- a/scm/driver/harness/git.go +++ b/scm/driver/harness/git.go @@ -57,6 +57,8 @@ func (s *gitService) ListBranches(ctx context.Context, repo string, opts scm.Lis } func (s *gitService) ListBranchesV2(ctx context.Context, repo string, opts scm.BranchListOptions) ([]*scm.Reference, *scm.Response, error) { + // Harness doesnt provide support listing based on searchTerm + // Hence calling the ListBranches return s.ListBranches(ctx, repo, opts.PageListOptions) } diff --git a/scm/git.go b/scm/git.go index 847020932..5f0d9892a 100644 --- a/scm/git.go +++ b/scm/git.go @@ -72,6 +72,8 @@ type ( // ListBranches returns a list of git branches. ListBranches(ctx context.Context, repo string, opts ListOptions) ([]*Reference, *Response, error) + + // ListBranchesV2 returns a list of git branches based on the searchTerm passed. ListBranchesV2(ctx context.Context, repo string, opts BranchListOptions) ([]*Reference, *Response, error) // ListCommits returns a list of git commits. From 70cccf871a3ece31cf97fef21099f694749d7cb7 Mon Sep 17 00:00:00 2001 From: Adithya Viswanathan Date: Wed, 19 Jul 2023 15:31:06 +0530 Subject: [PATCH 172/282] [feat]: [CDS-73572]: Support List Repo Live Search for all git providers --- scm/client.go | 13 +++ scm/driver/azure/git_test.go | 4 +- scm/driver/azure/repo.go | 6 + ...anchesFilter.json => branches_filter.json} | 0 ...son.golden => branches_filter.json.golden} | 0 scm/driver/bitbucket/git_test.go | 13 +-- scm/driver/bitbucket/repo.go | 12 ++ scm/driver/bitbucket/repo_test.go | 31 +++++ ...anchesFilter.json => branches_filter.json} | 0 ...son.golden => branches_filter.json.golden} | 0 .../bitbucket/testdata/repos_filter.json | 110 ++++++++++++++++++ .../testdata/repos_filter.json.golden | 15 +++ scm/driver/bitbucket/util.go | 33 +++++- scm/driver/gitea/repo.go | 5 + scm/driver/gitee/repo.go | 4 + scm/driver/github/repo.go | 12 ++ scm/driver/github/repo_test.go | 42 +++++++ scm/driver/github/testdata/repos_filter.json | 107 +++++++++++++++++ .../github/testdata/repos_filter.json.golden | 20 ++++ scm/driver/github/util.go | 28 +++++ scm/driver/gitlab/git_test.go | 4 +- scm/driver/gitlab/repo.go | 8 ++ scm/driver/gitlab/repo_test.go | 39 +++++++ ...anchesFilter.json => branches_filter.json} | 0 ...son.golden => branches_filter.json.golden} | 0 scm/driver/gitlab/testdata/repos_filter.json | 59 ++++++++++ .../gitlab/testdata/repos_filter.json.golden | 20 ++++ scm/driver/gitlab/util.go | 31 ++++- scm/driver/gogs/repo.go | 5 + scm/driver/harness/repo.go | 5 + scm/driver/stash/git_test.go | 4 +- scm/driver/stash/repo.go | 12 ++ scm/driver/stash/repo_test.go | 41 +++++++ ...anchesFilter.json => branches_filter.json} | 0 ...son.golden => branches_filter.json.golden} | 0 scm/driver/stash/testdata/repos_filter.json | 49 ++++++++ .../stash/testdata/repos_filter.json.golden | 15 +++ scm/driver/stash/util.go | 37 ++++-- scm/repo.go | 3 + 39 files changed, 757 insertions(+), 30 deletions(-) rename scm/driver/azure/testdata/{branchesFilter.json => branches_filter.json} (100%) rename scm/driver/azure/testdata/{branchesFilter.json.golden => branches_filter.json.golden} (100%) rename scm/driver/bitbucket/testdata/{branchesFilter.json => branches_filter.json} (100%) rename scm/driver/bitbucket/testdata/{branchesFilter.json.golden => branches_filter.json.golden} (100%) create mode 100644 scm/driver/bitbucket/testdata/repos_filter.json create mode 100644 scm/driver/bitbucket/testdata/repos_filter.json.golden create mode 100644 scm/driver/github/testdata/repos_filter.json create mode 100644 scm/driver/github/testdata/repos_filter.json.golden rename scm/driver/gitlab/testdata/{branchesFilter.json => branches_filter.json} (100%) rename scm/driver/gitlab/testdata/{branchesFilter.json.golden => branches_filter.json.golden} (100%) create mode 100644 scm/driver/gitlab/testdata/repos_filter.json create mode 100644 scm/driver/gitlab/testdata/repos_filter.json.golden rename scm/driver/stash/testdata/{branchesFilter.json => branches_filter.json} (100%) rename scm/driver/stash/testdata/{branchesFilter.json.golden => branches_filter.json.golden} (100%) create mode 100644 scm/driver/stash/testdata/repos_filter.json create mode 100644 scm/driver/stash/testdata/repos_filter.json.golden diff --git a/scm/client.go b/scm/client.go index ca3d1cafc..0d05b3b9a 100644 --- a/scm/client.go +++ b/scm/client.go @@ -75,6 +75,19 @@ type ( PageListOptions ListOptions } + // RepoListOptions specifies optional repo search term and pagination + // parameters. + RepoListOptions struct { + ListOptions + RepoSearchTerm + } + + // RepoSearchTerm specifies searchable parameters. + RepoSearchTerm struct { + RepoName string + User string + } + // ListOptions specifies optional pagination // parameters. ListOptions struct { diff --git a/scm/driver/azure/git_test.go b/scm/driver/azure/git_test.go index 846e2b97b..f150dc38e 100644 --- a/scm/driver/azure/git_test.go +++ b/scm/driver/azure/git_test.go @@ -130,7 +130,7 @@ func TestGitListBranchesV2(t *testing.T) { Get("/ORG/PROJ/_apis/git/repositories/REPOID/"). Reply(200). Type("application/json"). - File("testdata/branchesFilter.json") + File("testdata/branches_filter.json") client := NewDefault("ORG", "PROJ") got, _, err := client.Git.ListBranchesV2(context.Background(), "REPOID", scm.BranchListOptions{SearchTerm: "main"}) @@ -140,7 +140,7 @@ func TestGitListBranchesV2(t *testing.T) { } want := []*scm.Reference{} - raw, _ := ioutil.ReadFile("testdata/branchesFilter.json.golden") + raw, _ := ioutil.ReadFile("testdata/branches_filter.json.golden") _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { diff --git a/scm/driver/azure/repo.go b/scm/driver/azure/repo.go index 5d0427fa4..edfd4d876 100644 --- a/scm/driver/azure/repo.go +++ b/scm/driver/azure/repo.go @@ -56,6 +56,12 @@ func (s *RepositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* return convertRepositoryList(out), res, err } +// ListV2 returns the user repository list. +func (s *RepositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions) ([]*scm.Repository, *scm.Response, error) { + // Azure does not support search filters, hence calling List api without search filtering + return s.List(ctx, opts.ListOptions) +} + // ListHooks returns a list or repository hooks. func (s *RepositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/hooks/subscriptions/list?view=azure-devops-rest-6.0 diff --git a/scm/driver/azure/testdata/branchesFilter.json b/scm/driver/azure/testdata/branches_filter.json similarity index 100% rename from scm/driver/azure/testdata/branchesFilter.json rename to scm/driver/azure/testdata/branches_filter.json diff --git a/scm/driver/azure/testdata/branchesFilter.json.golden b/scm/driver/azure/testdata/branches_filter.json.golden similarity index 100% rename from scm/driver/azure/testdata/branchesFilter.json.golden rename to scm/driver/azure/testdata/branches_filter.json.golden diff --git a/scm/driver/bitbucket/git_test.go b/scm/driver/bitbucket/git_test.go index 275707a0b..74928583f 100644 --- a/scm/driver/bitbucket/git_test.go +++ b/scm/driver/bitbucket/git_test.go @@ -216,20 +216,19 @@ func TestGitListBranchesV2(t *testing.T) { MatchParam("pagelen", "30"). Reply(200). Type("application/json"). - File("testdata/branchesFilter.json") + File("testdata/branches_filter.json") client, _ := New("https://api.bitbucket.org") - got, res, err := client.Git.ListBranchesV2(context.Background(), "atlassian/stash-example-plugin", scm.BranchListOptions{SearchTerm: "mast", PageListOptions: struct { - URL string - Page int - Size int - }{Page: 1, Size: 30}}) + got, res, err := client.Git.ListBranchesV2(context.Background(), "atlassian/stash-example-plugin", scm.BranchListOptions{ + SearchTerm: "mast", + PageListOptions: scm.ListOptions{Page: 1, Size: 30}, + }) if err != nil { t.Error(err) } want := []*scm.Reference{} - raw, _ := ioutil.ReadFile("testdata/branchesFilter.json.golden") + raw, _ := ioutil.ReadFile("testdata/branches_filter.json.golden") json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { diff --git a/scm/driver/bitbucket/repo.go b/scm/driver/bitbucket/repo.go index cccae00d5..5929f6080 100644 --- a/scm/driver/bitbucket/repo.go +++ b/scm/driver/bitbucket/repo.go @@ -105,6 +105,18 @@ func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* return convertRepositoryList(out), res, err } +// ListV2 returns the user repository list based on the searchTerm passed. +func (s *repositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions) ([]*scm.Repository, *scm.Response, error) { + path := fmt.Sprintf("2.0/repositories?%s", encodeRepoListOptions(opts)) + if opts.ListOptions.URL != "" { + path = opts.ListOptions.URL + } + out := new(repositories) + res, err := s.client.do(ctx, "GET", path, nil, &out) + copyPagination(out.pagination, res) + return convertRepositoryList(out), res, err +} + // ListHooks returns a list or repository hooks. func (s *repositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { path := fmt.Sprintf("2.0/repositories/%s/hooks?%s", repo, encodeListOptions(opts)) diff --git a/scm/driver/bitbucket/repo_test.go b/scm/driver/bitbucket/repo_test.go index 8b8efd79d..6c1f02b1b 100644 --- a/scm/driver/bitbucket/repo_test.go +++ b/scm/driver/bitbucket/repo_test.go @@ -136,6 +136,37 @@ func TestRepositoryList(t *testing.T) { } } +func TestRepositoryListV2(t *testing.T) { + defer gock.Off() + + gock.New("https://api.bitbucket.org"). + Get("/2.0/repositories"). + MatchParam("q", "name~\\\"plugin1\\\""). + MatchParam("role", "member"). + Reply(200). + Type("application/json"). + File("testdata/repos_filter.json") + + got := []*scm.Repository{} + opts := scm.RepoListOptions{RepoSearchTerm: scm.RepoSearchTerm{RepoName: "plugin1"}} + client, _ := New("https://api.bitbucket.org") + + repos, _, err := client.Repositories.ListV2(context.Background(), opts) + if err != nil { + t.Error(err) + } + got = append(got, repos...) + + want := []*scm.Repository{} + raw, _ := ioutil.ReadFile("testdata/repos_filter.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + func TestStatusList(t *testing.T) { defer gock.Off() diff --git a/scm/driver/bitbucket/testdata/branchesFilter.json b/scm/driver/bitbucket/testdata/branches_filter.json similarity index 100% rename from scm/driver/bitbucket/testdata/branchesFilter.json rename to scm/driver/bitbucket/testdata/branches_filter.json diff --git a/scm/driver/bitbucket/testdata/branchesFilter.json.golden b/scm/driver/bitbucket/testdata/branches_filter.json.golden similarity index 100% rename from scm/driver/bitbucket/testdata/branchesFilter.json.golden rename to scm/driver/bitbucket/testdata/branches_filter.json.golden diff --git a/scm/driver/bitbucket/testdata/repos_filter.json b/scm/driver/bitbucket/testdata/repos_filter.json new file mode 100644 index 000000000..df610e1f4 --- /dev/null +++ b/scm/driver/bitbucket/testdata/repos_filter.json @@ -0,0 +1,110 @@ +{ + "pagelen": 1, + "values": [ + { + "scm": "git", + "website": "", + "has_wiki": false, + "uuid": "{7dd600e6-0d9c-4801-b967-cb4cc17359ff}", + "links": { + "watchers": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin1\/watchers" + }, + "branches": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin1\/refs\/branches" + }, + "tags": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin1\/refs\/tags" + }, + "commits": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin1\/commits" + }, + "clone": [ + { + "href": "https:\/\/brydzewski@bitbucket.org\/atlassian\/stash-example-plugin1.git", + "name": "https" + }, + { + "href": "git@bitbucket.org:atlassian\/stash-example-plugin1.git", + "name": "ssh" + } + ], + "self": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin1" + }, + "source": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin1\/src" + }, + "html": { + "href": "https:\/\/bitbucket.org\/atlassian\/stash-example-plugin1" + }, + "avatar": { + "href": "https:\/\/bytebucket.org\/ravatar\/%7B7dd600e6-0d9c-4801-b967-cb4cc17359ff%7D?ts=default" + }, + "hooks": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin1\/hooks" + }, + "forks": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin1\/forks" + }, + "downloads": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin1\/downloads" + }, + "pullrequests": { + "href": "https:\/\/api.bitbucket.org\/2.0\/repositories\/atlassian\/stash-example-plugin1\/pullrequests" + } + }, + "fork_policy": "allow_forks", + "name": "stash-example-plugin1", + "project": { + "key": "PROJ", + "type": "project", + "uuid": "{8b56daff-dbc7-4cae-a7a3-1228c526906b}", + "links": { + "self": { + "href": "https:\/\/api.bitbucket.org\/2.0\/teams\/atlassian\/projects\/PROJ" + }, + "html": { + "href": "https:\/\/bitbucket.org\/account\/user\/atlassian\/projects\/PROJ" + }, + "avatar": { + "href": "https:\/\/bitbucket.org\/account\/user\/atlassian\/projects\/PROJ\/avatar\/32" + } + }, + "name": "Project: Atlassian" + }, + "language": "", + "created_on": "2013-04-15T03:05:05.595458+00:00", + "mainbranch": { + "type": "branch", + "name": "master" + }, + "full_name": "atlassian\/stash-example-plugin1", + "has_issues": false, + "owner": { + "username": "atlassian", + "display_name": "Atlassian", + "type": "team", + "uuid": "{02b941e3-cfaa-40f9-9a58-cec53e20bdc3}", + "links": { + "self": { + "href": "https:\/\/api.bitbucket.org\/2.0\/teams\/atlassian" + }, + "html": { + "href": "https:\/\/bitbucket.org\/atlassian\/" + }, + "avatar": { + "href": "https:\/\/bitbucket.org\/account\/atlassian\/avatar\/32\/" + } + } + }, + "updated_on": "2018-04-01T16:36:35.970175+00:00", + "size": 1116345, + "type": "repository", + "slug": "stash-example-plugin1", + "is_private": true, + "description": "Examples on how to decorate various pages around Stash." + } + ], + "next": "https:\/\/api.bitbucket.org\/2.0\/repositories?pagelen=1&after=PLACEHOLDER&role=member" +} \ No newline at end of file diff --git a/scm/driver/bitbucket/testdata/repos_filter.json.golden b/scm/driver/bitbucket/testdata/repos_filter.json.golden new file mode 100644 index 000000000..cf1ace3ba --- /dev/null +++ b/scm/driver/bitbucket/testdata/repos_filter.json.golden @@ -0,0 +1,15 @@ +[ + { + "ID": "{7dd600e6-0d9c-4801-b967-cb4cc17359ff}", + "Namespace": "atlassian", + "Name": "stash-example-plugin1", + "Perm": null, + "Branch": "master", + "Private": true, + "Clone": "https://bitbucket.org/atlassian/stash-example-plugin1.git", + "CloneSSH": "git@bitbucket.org:atlassian/stash-example-plugin1.git", + "Link": "https://bitbucket.org/atlassian/stash-example-plugin1", + "Created": "2013-04-15T03:05:05.595458Z", + "Updated": "2018-04-01T16:36:35.970175Z" + } +] \ No newline at end of file diff --git a/scm/driver/bitbucket/util.go b/scm/driver/bitbucket/util.go index b53ba777c..e43ea71cf 100644 --- a/scm/driver/bitbucket/util.go +++ b/scm/driver/bitbucket/util.go @@ -34,11 +34,13 @@ func encodeBranchListOptions(opts scm.BranchListOptions) string { sb.WriteString("\"") params.Set("q", sb.String()) } - if opts.PageListOptions.Page != 0 { - params.Set("page", strconv.Itoa(opts.PageListOptions.Page)) - } - if opts.PageListOptions.Size != 0 { - params.Set("pagelen", strconv.Itoa(opts.PageListOptions.Size)) + if opts.PageListOptions != (scm.ListOptions{}) { + if opts.PageListOptions.Page != 0 { + params.Set("page", strconv.Itoa(opts.PageListOptions.Page)) + } + if opts.PageListOptions.Size != 0 { + params.Set("pagelen", strconv.Itoa(opts.PageListOptions.Size)) + } } return params.Encode() } @@ -66,6 +68,27 @@ func encodeListRoleOptions(opts scm.ListOptions) string { return params.Encode() } +func encodeRepoListOptions(opts scm.RepoListOptions) string { + params := url.Values{} + if opts.RepoSearchTerm.RepoName != "" { + var sb strings.Builder + sb.WriteString("name~\"") + sb.WriteString(opts.RepoSearchTerm.RepoName) + sb.WriteString("\"") + params.Set("q", sb.String()) + } + if opts.ListOptions != (scm.ListOptions{}) { + if opts.ListOptions.Page != 0 { + params.Set("page", strconv.Itoa(opts.ListOptions.Page)) + } + if opts.ListOptions.Size != 0 { + params.Set("pagelen", strconv.Itoa(opts.ListOptions.Size)) + } + } + params.Set("role", "member") + return params.Encode() +} + func encodeCommitListOptions(opts scm.CommitListOptions) string { params := url.Values{} if opts.Page != 0 { diff --git a/scm/driver/gitea/repo.go b/scm/driver/gitea/repo.go index 4a58ef2bc..a678273bf 100644 --- a/scm/driver/gitea/repo.go +++ b/scm/driver/gitea/repo.go @@ -46,6 +46,11 @@ func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* return convertRepositoryList(out), res, err } +func (s *repositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions) ([]*scm.Repository, *scm.Response, error) { + // gitea does not support search filters, hence calling List api without search filtering + return s.List(ctx, opts.ListOptions) +} + func (s *repositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { path := fmt.Sprintf("api/v1/repos/%s/hooks?%s", repo, encodeListOptions(opts)) out := []*hook{} diff --git a/scm/driver/gitee/repo.go b/scm/driver/gitee/repo.go index fa14ab8ea..72c60f567 100644 --- a/scm/driver/gitee/repo.go +++ b/scm/driver/gitee/repo.go @@ -45,6 +45,10 @@ func (s *RepositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* res, err := s.client.do(ctx, "GET", path, nil, &out) return convertRepositoryList(out), res, err } +func (s *RepositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions) ([]*scm.Repository, *scm.Response, error) { + // gitee does not support search filters, hence calling List api without search filtering + return s.List(ctx, opts.ListOptions) +} func (s *RepositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { path := fmt.Sprintf("repos/%s/hooks?%s", repo, encodeListOptions(opts)) diff --git a/scm/driver/github/repo.go b/scm/driver/github/repo.go index cc781cb92..c9f09b7bc 100644 --- a/scm/driver/github/repo.go +++ b/scm/driver/github/repo.go @@ -40,6 +40,10 @@ type repository struct { } `json:"permissions"` } +type searchRepositoryList struct { + Repositories []*repository `json:"items"` +} + type hook struct { ID int `json:"id,omitempty"` Name string `json:"name"` @@ -110,6 +114,14 @@ func (s *RepositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* return convertRepositoryList(out), res, err } +// ListV2 returns the user repository list based on the searchTerm passed. +func (s *RepositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions) ([]*scm.Repository, *scm.Response, error) { + path := fmt.Sprintf("search/repositories?%s", encodeRepoListOptions(opts)) + out := new(searchRepositoryList) + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertRepositoryList(out.Repositories), res, err +} + // List returns the github app installation repository list. func (s *RepositoryService) ListByInstallation(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { path := fmt.Sprintf("installation/repositories?%s", encodeListOptions(opts)) diff --git a/scm/driver/github/repo_test.go b/scm/driver/github/repo_test.go index cd1d7f8b3..6af3dba6a 100644 --- a/scm/driver/github/repo_test.go +++ b/scm/driver/github/repo_test.go @@ -131,6 +131,48 @@ func TestRepositoryList(t *testing.T) { t.Run("Page", testPage(res)) } +func TestRepositoryListV2(t *testing.T) { + defer gock.Off() + + gock.New("https://api.github.com"). + Get("/search/repositories"). + MatchParam("q", "testRepoin:name"). + MatchParam("q", "user:user123"). + MatchParam("page", "1"). + MatchParam("per_page", "30"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + SetHeaders(mockPageHeaders). + File("testdata/repos_filter.json") + + client := NewDefault() + got, res, err := client.Repositories.ListV2(context.Background(), scm.RepoListOptions{ + ListOptions: scm.ListOptions{Page: 1, Size: 30}, + RepoSearchTerm: scm.RepoSearchTerm{ + RepoName: "testRepo", + User: "user123", + }, + }) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Repository{} + raw, _ := ioutil.ReadFile("testdata/repos_filter.json.golden") + _ = json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) + t.Run("Page", testPage(res)) +} + func TestGithubAppInstallationList(t *testing.T) { defer gock.Off() diff --git a/scm/driver/github/testdata/repos_filter.json b/scm/driver/github/testdata/repos_filter.json new file mode 100644 index 000000000..5e724c4a7 --- /dev/null +++ b/scm/driver/github/testdata/repos_filter.json @@ -0,0 +1,107 @@ +{ + "total_count": 5, + "incomplete_results": false, + "items": [ + { + "id": 508719340, + "node_id": "R_kgDOHlJw7A", + "name": "testRepo2", + "full_name": "user123/testRepo2", + "private": false, + "owner": { + "login": "user123", + "id": 103414561, + "node_id": "U_kgDOBin7IQ", + "avatar_url": "https://avatars.githubusercontent.com/u/103414561?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/user123", + "html_url": "https://github.com/user123", + "followers_url": "https://api.github.com/users/user123/followers", + "following_url": "https://api.github.com/users/user123/following{/other_user}", + "gists_url": "https://api.github.com/users/user123/gists{/gist_id}", + "starred_url": "https://api.github.com/users/user123/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/user123/subscriptions", + "organizations_url": "https://api.github.com/users/user123/orgs", + "repos_url": "https://api.github.com/users/user123/repos", + "events_url": "https://api.github.com/users/user123/events{/privacy}", + "received_events_url": "https://api.github.com/users/user123/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/user123/testRepo2", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/user123/testRepo2", + "forks_url": "https://api.github.com/repos/user123/testRepo2/forks", + "keys_url": "https://api.github.com/repos/user123/testRepo2/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/user123/testRepo2/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/user123/testRepo2/teams", + "hooks_url": "https://api.github.com/repos/user123/testRepo2/hooks", + "issue_events_url": "https://api.github.com/repos/user123/testRepo2/issues/events{/number}", + "events_url": "https://api.github.com/repos/user123/testRepo2/events", + "assignees_url": "https://api.github.com/repos/user123/testRepo2/assignees{/user}", + "branches_url": "https://api.github.com/repos/user123/testRepo2/branches{/branch}", + "tags_url": "https://api.github.com/repos/user123/testRepo2/tags", + "blobs_url": "https://api.github.com/repos/user123/testRepo2/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/user123/testRepo2/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/user123/testRepo2/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/user123/testRepo2/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/user123/testRepo2/statuses/{sha}", + "languages_url": "https://api.github.com/repos/user123/testRepo2/languages", + "stargazers_url": "https://api.github.com/repos/user123/testRepo2/stargazers", + "contributors_url": "https://api.github.com/repos/user123/testRepo2/contributors", + "subscribers_url": "https://api.github.com/repos/user123/testRepo2/subscribers", + "subscription_url": "https://api.github.com/repos/user123/testRepo2/subscription", + "commits_url": "https://api.github.com/repos/user123/testRepo2/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/user123/testRepo2/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/user123/testRepo2/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/user123/testRepo2/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/user123/testRepo2/contents/{+path}", + "compare_url": "https://api.github.com/repos/user123/testRepo2/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/user123/testRepo2/merges", + "archive_url": "https://api.github.com/repos/user123/testRepo2/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/user123/testRepo2/downloads", + "issues_url": "https://api.github.com/repos/user123/testRepo2/issues{/number}", + "pulls_url": "https://api.github.com/repos/user123/testRepo2/pulls{/number}", + "milestones_url": "https://api.github.com/repos/user123/testRepo2/milestones{/number}", + "notifications_url": "https://api.github.com/repos/user123/testRepo2/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/user123/testRepo2/labels{/name}", + "releases_url": "https://api.github.com/repos/user123/testRepo2/releases{/id}", + "deployments_url": "https://api.github.com/repos/user123/testRepo2/deployments", + "created_at": "2022-06-29T14:11:36Z", + "updated_at": "2023-06-27T07:10:05Z", + "pushed_at": "2023-06-07T05:36:36Z", + "git_url": "git://github.com/user123/testRepo2.git", + "ssh_url": "git@github.com:user123/testRepo2.git", + "clone_url": "https://github.com/user123/testRepo2.git", + "svn_url": "https://github.com/user123/testRepo2", + "homepage": null, + "size": 53, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 2, + "license": null, + "allow_forking": true, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [], + "visibility": "public", + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "main", + "score": 1.0 + } + ] +} \ No newline at end of file diff --git a/scm/driver/github/testdata/repos_filter.json.golden b/scm/driver/github/testdata/repos_filter.json.golden new file mode 100644 index 000000000..bb164132f --- /dev/null +++ b/scm/driver/github/testdata/repos_filter.json.golden @@ -0,0 +1,20 @@ +[ + { + "ID": "508719340", + "Namespace": "user123", + "Name": "testRepo2", + "Perm": { + "Pull": false, + "Push": false, + "Admin": false + }, + "Branch": "main", + "Private": false, + "Visibility": 1, + "Clone": "https://github.com/user123/testRepo2.git", + "CloneSSH": "git@github.com:user123/testRepo2.git", + "Link": "https://github.com/user123/testRepo2", + "Created": "2022-06-29T14:11:36Z", + "Updated": "2023-06-27T07:10:05Z" + } +] \ No newline at end of file diff --git a/scm/driver/github/util.go b/scm/driver/github/util.go index 5d5fb4741..d06e474e0 100644 --- a/scm/driver/github/util.go +++ b/scm/driver/github/util.go @@ -7,6 +7,7 @@ package github import ( "net/url" "strconv" + "strings" "github.com/drone/go-scm/scm" ) @@ -22,6 +23,33 @@ func encodeListOptions(opts scm.ListOptions) string { return params.Encode() } +func encodeRepoListOptions(opts scm.RepoListOptions) string { + var sb strings.Builder + if opts.RepoSearchTerm != (scm.RepoSearchTerm{}) { + if opts.RepoSearchTerm.RepoName != "" { + sb.WriteString("q=") + sb.WriteString(opts.RepoSearchTerm.RepoName) + sb.WriteString("in:name+user:") + sb.WriteString(opts.RepoSearchTerm.User) + } else { + sb.WriteString("q=") + sb.WriteString("user:") + sb.WriteString(opts.RepoSearchTerm.User) + } + } + if opts.ListOptions != (scm.ListOptions{}) { + if opts.ListOptions.Page != 0 { + sb.WriteString("&page=") + sb.WriteString(strconv.Itoa(opts.ListOptions.Page)) + } + if opts.ListOptions.Size != 0 { + sb.WriteString("&per_page=") + sb.WriteString(strconv.Itoa(opts.ListOptions.Size)) + } + } + return sb.String() +} + func encodeCommitListOptions(opts scm.CommitListOptions) string { params := url.Values{} if opts.Page != 0 { diff --git a/scm/driver/gitlab/git_test.go b/scm/driver/gitlab/git_test.go index ee4595398..49fefee66 100644 --- a/scm/driver/gitlab/git_test.go +++ b/scm/driver/gitlab/git_test.go @@ -215,7 +215,7 @@ func TestGitListBranchesWithBranchFilter(t *testing.T) { Type("application/json"). SetHeaders(mockHeaders). SetHeaders(mockPageHeaders). - File("testdata/branchesFilter.json") + File("testdata/branches_filter.json") client := NewDefault() got, res, err := client.Git.ListBranchesV2(context.Background(), "diaspora/diaspora", scm.BranchListOptions{SearchTerm: "mast"}) @@ -225,7 +225,7 @@ func TestGitListBranchesWithBranchFilter(t *testing.T) { } want := []*scm.Reference{} - raw, _ := ioutil.ReadFile("testdata/branchesFilter.json.golden") + raw, _ := ioutil.ReadFile("testdata/branches_filter.json.golden") json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { diff --git a/scm/driver/gitlab/repo.go b/scm/driver/gitlab/repo.go index 23a04ffc6..dc6f39a7e 100644 --- a/scm/driver/gitlab/repo.go +++ b/scm/driver/gitlab/repo.go @@ -94,6 +94,14 @@ func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* return convertRepositoryList(out), res, err } +func (s *repositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions) ([]*scm.Repository, *scm.Response, error) { + // We pass the repo searchTerm in the query params and gitlab filters repos based on this search term + path := fmt.Sprintf("api/v4/projects?%s", encodeRepoListOptions(opts)) + out := []*repository{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertRepositoryList(out), res, err +} + func (s *repositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { path := fmt.Sprintf("api/v4/projects/%s/hooks?%s", encode(repo), encodeListOptions(opts)) out := []*hook{} diff --git a/scm/driver/gitlab/repo_test.go b/scm/driver/gitlab/repo_test.go index 48e21db6b..293e523ff 100644 --- a/scm/driver/gitlab/repo_test.go +++ b/scm/driver/gitlab/repo_test.go @@ -163,6 +163,45 @@ func TestRepositoryList(t *testing.T) { t.Run("Page", testPage(res)) } +func TestRepositoryListV2(t *testing.T) { + defer gock.Off() + + gock.New("https://gitlab.com"). + Get("/api/v4/projects"). + MatchParam("search", "diaspora"). + MatchParam("page", "1"). + MatchParam("per_page", "30"). + MatchParam("membership", "true"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + SetHeaders(mockPageHeaders). + File("testdata/repos_filter.json") + + client := NewDefault() + got, res, err := client.Repositories.ListV2(context.Background(), scm.RepoListOptions{ + ListOptions: scm.ListOptions{Page: 1, Size: 30}, + RepoSearchTerm: scm.RepoSearchTerm{RepoName: "diaspora"}, + }) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Repository{} + raw, _ := ioutil.ReadFile("testdata/repos_filter.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + + t.Run("Request", testRequest(res)) + t.Run("Rate", testRate(res)) + t.Run("Page", testPage(res)) +} + func TestStatusList(t *testing.T) { defer gock.Off() diff --git a/scm/driver/gitlab/testdata/branchesFilter.json b/scm/driver/gitlab/testdata/branches_filter.json similarity index 100% rename from scm/driver/gitlab/testdata/branchesFilter.json rename to scm/driver/gitlab/testdata/branches_filter.json diff --git a/scm/driver/gitlab/testdata/branchesFilter.json.golden b/scm/driver/gitlab/testdata/branches_filter.json.golden similarity index 100% rename from scm/driver/gitlab/testdata/branchesFilter.json.golden rename to scm/driver/gitlab/testdata/branches_filter.json.golden diff --git a/scm/driver/gitlab/testdata/repos_filter.json b/scm/driver/gitlab/testdata/repos_filter.json new file mode 100644 index 000000000..13f8b4de3 --- /dev/null +++ b/scm/driver/gitlab/testdata/repos_filter.json @@ -0,0 +1,59 @@ +[ + { + "id": 178504, + "description": "", + "default_branch": "master", + "tag_list": [], + "ssh_url_to_repo": "git@gitlab.com:diaspora/diaspora.git", + "http_url_to_repo": "https://gitlab.com/diaspora/diaspora.git", + "web_url": "https://gitlab.com/diaspora/diaspora", + "name": "Diaspora", + "name_with_namespace": "diaspora / Diaspora", + "path": "diaspora", + "path_with_namespace": "diaspora/diaspora", + "avatar_url": null, + "star_count": 0, + "forks_count": 0, + "created_at": "2015-03-03T18:37:05.387Z", + "last_activity_at": "2015-03-03T18:37:20.795Z", + "_links": { + "self": "http://gitlab.com/api/v4/projects/178504", + "issues": "http://gitlab.com/api/v4/projects/178504/issues", + "merge_requests": "http://gitlab.com/api/v4/projects/178504/merge_requests", + "repo_branches": "http://gitlab.com/api/v4/projects/178504/repository/branches", + "labels": "http://gitlab.com/api/v4/projects/178504/labels", + "events": "http://gitlab.com/api/v4/projects/178504/events", + "members": "http://gitlab.com/api/v4/projects/178504/members" + }, + "archived": false, + "visibility": "public", + "resolve_outdated_diff_discussions": null, + "container_registry_enabled": null, + "issues_enabled": true, + "merge_requests_enabled": true, + "wiki_enabled": true, + "jobs_enabled": true, + "snippets_enabled": false, + "shared_runners_enabled": true, + "lfs_enabled": true, + "creator_id": 57658, + "namespace": { + "id": 120836, + "name": "diaspora", + "path": "diaspora", + "kind": "group", + "full_path": "diaspora", + "parent_id": null + }, + "import_status": "finished", + "open_issues_count": 0, + "public_jobs": true, + "ci_config_path": null, + "shared_with_groups": [], + "only_allow_merge_if_pipeline_succeeds": false, + "request_access_enabled": true, + "only_allow_merge_if_all_discussions_are_resolved": null, + "printing_merge_request_link_enabled": true, + "approvals_before_merge": 0 + } +] \ No newline at end of file diff --git a/scm/driver/gitlab/testdata/repos_filter.json.golden b/scm/driver/gitlab/testdata/repos_filter.json.golden new file mode 100644 index 000000000..5780a5ebd --- /dev/null +++ b/scm/driver/gitlab/testdata/repos_filter.json.golden @@ -0,0 +1,20 @@ +[ + { + "ID": "178504", + "Namespace": "diaspora", + "Name": "diaspora", + "Perm": { + "Pull": true, + "Push": false, + "Admin": false + }, + "Branch": "master", + "Private": false, + "Visibility": 1, + "Clone": "https://gitlab.com/diaspora/diaspora.git", + "CloneSSH": "git@gitlab.com:diaspora/diaspora.git", + "Link": "https://gitlab.com/diaspora/diaspora", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + } +] \ No newline at end of file diff --git a/scm/driver/gitlab/util.go b/scm/driver/gitlab/util.go index 55f106f71..eb3f06893 100644 --- a/scm/driver/gitlab/util.go +++ b/scm/driver/gitlab/util.go @@ -29,11 +29,13 @@ func encodeBranchListOptions(opts scm.BranchListOptions) string { if opts.SearchTerm != "" { params.Set("search", opts.SearchTerm) } - if opts.PageListOptions.Page != 0 { - params.Set("page", strconv.Itoa(opts.PageListOptions.Page)) - } - if opts.PageListOptions.Size != 0 { - params.Set("per_page", strconv.Itoa(opts.PageListOptions.Size)) + if opts.PageListOptions != (scm.ListOptions{}) { + if opts.PageListOptions.Page != 0 { + params.Set("page", strconv.Itoa(opts.PageListOptions.Page)) + } + if opts.PageListOptions.Size != 0 { + params.Set("per_page", strconv.Itoa(opts.PageListOptions.Size)) + } } return params.Encode() } @@ -61,6 +63,25 @@ func encodeMemberListOptions(opts scm.ListOptions) string { return params.Encode() } +func encodeRepoListOptions(opts scm.RepoListOptions) string { + params := url.Values{} + params.Set("membership", "true") + if opts.RepoSearchTerm != (scm.RepoSearchTerm{}) { + if opts.RepoSearchTerm.RepoName != "" { + params.Set("search", opts.RepoSearchTerm.RepoName) + } + } + if opts.ListOptions != (scm.ListOptions{}) { + if opts.ListOptions.Page != 0 { + params.Set("page", strconv.Itoa(opts.ListOptions.Page)) + } + if opts.ListOptions.Size != 0 { + params.Set("per_page", strconv.Itoa(opts.ListOptions.Size)) + } + } + return params.Encode() +} + func encodeCommitListOptions(opts scm.CommitListOptions) string { params := url.Values{} if opts.Page != 0 { diff --git a/scm/driver/gogs/repo.go b/scm/driver/gogs/repo.go index d2a29fb3c..5657b5ee7 100644 --- a/scm/driver/gogs/repo.go +++ b/scm/driver/gogs/repo.go @@ -45,6 +45,11 @@ func (s *repositoryService) List(ctx context.Context, _ scm.ListOptions) ([]*scm return convertRepositoryList(out), res, err } +func (s *repositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions) ([]*scm.Repository, *scm.Response, error) { + // Azure does not support search filters, hence calling List api without search filtering + return s.List(ctx, opts.ListOptions) +} + func (s *repositoryService) ListHooks(ctx context.Context, repo string, _ scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { path := fmt.Sprintf("api/v1/repos/%s/hooks", repo) out := []*hook{} diff --git a/scm/driver/harness/repo.go b/scm/driver/harness/repo.go index a55089516..da4237555 100644 --- a/scm/driver/harness/repo.go +++ b/scm/driver/harness/repo.go @@ -52,6 +52,11 @@ func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* return convertRepositoryList(out), res, err } +func (s *repositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions) ([]*scm.Repository, *scm.Response, error) { + // harness does not support search filters, hence calling List api without search filtering + return s.List(ctx, opts.ListOptions) +} + func (s *repositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) path := fmt.Sprintf("api/v1/repos/%s/webhooks?sort=display_name&order=asc&%s", harnessURI, encodeListOptions(opts)) diff --git a/scm/driver/stash/git_test.go b/scm/driver/stash/git_test.go index 720e8fa6f..f93952ace 100644 --- a/scm/driver/stash/git_test.go +++ b/scm/driver/stash/git_test.go @@ -155,7 +155,7 @@ func TestGitListBranchesWithBranchFilter(t *testing.T) { MatchParam("filterText", "mast"). Reply(200). Type("application/json"). - File("testdata/branchesFilter.json") + File("testdata/branches_filter.json") client, _ := New("http://example.com:7990") got, _, err := client.Git.ListBranchesV2(context.Background(), "PRJ/my-repo", scm.BranchListOptions{SearchTerm: "mast"}) @@ -164,7 +164,7 @@ func TestGitListBranchesWithBranchFilter(t *testing.T) { } want := []*scm.Reference{} - raw, _ := ioutil.ReadFile("testdata/branchesFilter.json.golden") + raw, _ := ioutil.ReadFile("testdata/branches_filter.json.golden") _ = json.Unmarshal(raw, &want) if diff := cmp.Diff(got, want); diff != "" { diff --git a/scm/driver/stash/repo.go b/scm/driver/stash/repo.go index 070bfd373..33ba4bc42 100644 --- a/scm/driver/stash/repo.go +++ b/scm/driver/stash/repo.go @@ -180,6 +180,18 @@ func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* return convertRepositoryList(out), res, err } +// ListV2 returns the user repository list based on the searchTerm passed. +func (s *repositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions) ([]*scm.Repository, *scm.Response, error) { + path := fmt.Sprintf("rest/api/1.0/repos?%s", encodeRepoListOptions(opts)) + out := new(repositories) + res, err := s.client.do(ctx, "GET", path, nil, &out) + if res != nil && !out.pagination.LastPage.Bool { + res.Page.First = 1 + res.Page.Next = opts.ListOptions.Page + 1 + } + return convertRepositoryList(out), res, err +} + // listWrite returns the user repository list. func (s *repositoryService) listWrite(ctx context.Context, repo string) ([]*scm.Repository, *scm.Response, error) { _, name := scm.Split(repo) diff --git a/scm/driver/stash/repo_test.go b/scm/driver/stash/repo_test.go index ee337dc24..ff7138df1 100644 --- a/scm/driver/stash/repo_test.go +++ b/scm/driver/stash/repo_test.go @@ -319,6 +319,47 @@ func TestRepositoryList(t *testing.T) { } } +func TestRepositoryListV2(t *testing.T) { + defer gock.Off() + + gock.New("http://example.com:7990"). + Get("/rest/api/1.0/repos"). + MatchParam("name", "quux"). + MatchParam("limit", "25"). + MatchParam("start", "50"). + MatchParam("permission", "REPO_READ"). + Reply(200). + Type("application/json"). + File("testdata/repos_filter.json") + + client, _ := New("http://example.com:7990") + got, res, err := client.Repositories.ListV2(context.Background(), scm.RepoListOptions{ + ListOptions: scm.ListOptions{Page: 3, Size: 25}, + RepoSearchTerm: scm.RepoSearchTerm{ + RepoName: "quux", + }, + }) + if err != nil { + t.Error(err) + } + + if got, want := res.Page.First, 1; got != want { + t.Errorf("Want Page.First %d, got %d", want, got) + } + if got, want := res.Page.Next, 4; got != want { + t.Errorf("Want Page.Next %d, got %d", want, got) + } + + want := []*scm.Repository{} + raw, _ := ioutil.ReadFile("testdata/repos_filter.json.golden") + _ = json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + func TestStatusList(t *testing.T) { client, _ := New("http://example.com:7990") _, _, err := client.Repositories.ListStatus(context.Background(), "PRJ/my-repo", "a6e5e7d797edf751cbd839d6bd4aef86c941eec9", scm.ListOptions{Size: 30, Page: 1}) diff --git a/scm/driver/stash/testdata/branchesFilter.json b/scm/driver/stash/testdata/branches_filter.json similarity index 100% rename from scm/driver/stash/testdata/branchesFilter.json rename to scm/driver/stash/testdata/branches_filter.json diff --git a/scm/driver/stash/testdata/branchesFilter.json.golden b/scm/driver/stash/testdata/branches_filter.json.golden similarity index 100% rename from scm/driver/stash/testdata/branchesFilter.json.golden rename to scm/driver/stash/testdata/branches_filter.json.golden diff --git a/scm/driver/stash/testdata/repos_filter.json b/scm/driver/stash/testdata/repos_filter.json new file mode 100644 index 000000000..80bb1c9a4 --- /dev/null +++ b/scm/driver/stash/testdata/repos_filter.json @@ -0,0 +1,49 @@ +{ + "size": 25, + "limit": 25, + "isLastPage": false, + "values": [ + { + "slug": "quux", + "id": 2, + "name": "quux", + "scmId": "git", + "state": "AVAILABLE", + "statusMessage": "Available", + "forkable": true, + "project": { + "key": "PRJ", + "id": 2, + "name": "different_name", + "public": false, + "type": "NORMAL", + "links": { + "self": [ + { + "href": "http://example.com:7990/projects/PRJ" + } + ] + } + }, + "public": false, + "links": { + "clone": [ + { + "href": "ssh://git@example.com:7999/prj/quux.git", + "name": "ssh" + }, + { + "href": "http://jcitizen@example.com:7990/scm/prj/quux.git", + "name": "http" + } + ], + "self": [ + { + "href": "http://example.com:7990/projects/PRJ/repos/quux/browse" + } + ] + } + } + ], + "start": 0 +} \ No newline at end of file diff --git a/scm/driver/stash/testdata/repos_filter.json.golden b/scm/driver/stash/testdata/repos_filter.json.golden new file mode 100644 index 000000000..34ff2307b --- /dev/null +++ b/scm/driver/stash/testdata/repos_filter.json.golden @@ -0,0 +1,15 @@ +[ + { + "ID": "2", + "Namespace": "PRJ", + "Name": "quux", + "Perm": null, + "Branch": "master", + "Private": true, + "Clone": "http://example.com:7990/scm/prj/quux.git", + "CloneSSH": "ssh://git@example.com:7999/prj/quux.git", + "Link": "http://example.com:7990/projects/PRJ/repos/quux/browse", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + } +] \ No newline at end of file diff --git a/scm/driver/stash/util.go b/scm/driver/stash/util.go index 0de82e3fa..1dbcb71e8 100644 --- a/scm/driver/stash/util.go +++ b/scm/driver/stash/util.go @@ -30,13 +30,15 @@ func encodeBranchListOptions(opts scm.BranchListOptions) string { if opts.SearchTerm != "" { params.Set("filterText", opts.SearchTerm) } - if opts.PageListOptions.Page > 1 { - params.Set("start", strconv.Itoa( - (opts.PageListOptions.Page-1)*opts.PageListOptions.Size), - ) - } - if opts.PageListOptions.Size != 0 { - params.Set("limit", strconv.Itoa(opts.PageListOptions.Size)) + if opts.PageListOptions != (scm.ListOptions{}) { + if opts.PageListOptions.Page > 1 { + params.Set("start", strconv.Itoa( + (opts.PageListOptions.Page-1)*opts.PageListOptions.Size), + ) + } + if opts.PageListOptions.Size != 0 { + params.Set("limit", strconv.Itoa(opts.PageListOptions.Size)) + } } return params.Encode() } @@ -55,6 +57,27 @@ func encodeListRoleOptions(opts scm.ListOptions) string { return params.Encode() } +func encodeRepoListOptions(opts scm.RepoListOptions) string { + params := url.Values{} + if opts.RepoSearchTerm != (scm.RepoSearchTerm{}) { + if opts.RepoSearchTerm.RepoName != "" { + params.Set("name", opts.RepoSearchTerm.RepoName) + } + } + if opts.ListOptions != (scm.ListOptions{}) { + if opts.ListOptions.Page > 1 { + params.Set("start", strconv.Itoa( + (opts.ListOptions.Page-1)*opts.ListOptions.Size), + ) + } + if opts.ListOptions.Size != 0 { + params.Set("limit", strconv.Itoa(opts.ListOptions.Size)) + } + } + params.Set("permission", "REPO_READ") + return params.Encode() +} + func encodePullRequestListOptions(opts scm.PullRequestListOptions) string { params := url.Values{} if opts.Page > 1 { diff --git a/scm/repo.go b/scm/repo.go index b62b53755..1e6218fdc 100644 --- a/scm/repo.go +++ b/scm/repo.go @@ -120,6 +120,9 @@ type ( // List returns a list of repositories. List(context.Context, ListOptions) ([]*Repository, *Response, error) + // ListV2 returns a list of repositories based on the searchTerm passed. + ListV2(context.Context, RepoListOptions) ([]*Repository, *Response, error) + // ListHooks returns a list or repository hooks. ListHooks(context.Context, string, ListOptions) ([]*Hook, *Response, error) From d86848a9e2816cb48647424cfb0ef7b7a0f99926 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Tue, 8 Aug 2023 04:06:58 -0700 Subject: [PATCH 173/282] fix: [CODE-727]: change to gitness from harness --- scm/driver/harness/webhook.go | 4 ++-- scm/driver/harness/webhook_test.go | 2 +- scm/repo.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scm/driver/harness/webhook.go b/scm/driver/harness/webhook.go index fc89148e5..514ddaafa 100644 --- a/scm/driver/harness/webhook.go +++ b/scm/driver/harness/webhook.go @@ -29,7 +29,7 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo } var hook scm.Webhook - switch req.Header.Get("X-Harness-Trigger") { + switch req.Header.Get("X-Gitness-Trigger") { // case "create": // hook, err = s.parseCreateHook(data) // case "delete": @@ -58,7 +58,7 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo } secret := req.FormValue("secret") - signature := req.Header.Get("X-Harness-Signature") + signature := req.Header.Get("X-Gitness-Signature") // fail if no signature passed if signature == "" && secret == "" { diff --git a/scm/driver/harness/webhook_test.go b/scm/driver/harness/webhook_test.go index 4e38687be..48f66daeb 100644 --- a/scm/driver/harness/webhook_test.go +++ b/scm/driver/harness/webhook_test.go @@ -73,7 +73,7 @@ func TestWebhooks(t *testing.T) { buf := bytes.NewBuffer(before) r, _ := http.NewRequest("GET", "/", buf) - r.Header.Set("X-Harness-Trigger", test.event) + r.Header.Set("X-Gitness-Trigger", test.event) s := new(webhookService) o, err := s.Parse(r, secretFunc) diff --git a/scm/repo.go b/scm/repo.go index b62b53755..d7332dbaa 100644 --- a/scm/repo.go +++ b/scm/repo.go @@ -121,7 +121,7 @@ type ( List(context.Context, ListOptions) ([]*Repository, *Response, error) // ListHooks returns a list or repository hooks. - ListHooks(context.Context, string, ListOptions) ([]*Hook, *Response, error) + s(context.Context, string, ListOptions) ([]*Hook, *Response, error) // ListStatus returns a list of commit statuses. ListStatus(context.Context, string, string, ListOptions) ([]*Status, *Response, error) From d363e65a819bed336867c40868605a97a130ac0c Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Tue, 8 Aug 2023 04:07:30 -0700 Subject: [PATCH 174/282] fix: [CODE-727]: change to gitness from harness --- scm/repo.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/repo.go b/scm/repo.go index d7332dbaa..b62b53755 100644 --- a/scm/repo.go +++ b/scm/repo.go @@ -121,7 +121,7 @@ type ( List(context.Context, ListOptions) ([]*Repository, *Response, error) // ListHooks returns a list or repository hooks. - s(context.Context, string, ListOptions) ([]*Hook, *Response, error) + ListHooks(context.Context, string, ListOptions) ([]*Hook, *Response, error) // ListStatus returns a list of commit statuses. ListStatus(context.Context, string, string, ListOptions) ([]*Status, *Response, error) From 0f7857f595d60863eaa512e3c9d6613059d7aefa Mon Sep 17 00:00:00 2001 From: Dheeraj Kumar Date: Thu, 10 Aug 2023 22:06:16 +0530 Subject: [PATCH 175/282] Implemented FindMembership method in organization service for gitea driver (#263) * implementation of FindMembership method in organization service for gitea driver * gitea driver testcase for organization membership --- scm/driver/gitea/org.go | 44 ++++++++++++++++++- scm/driver/gitea/org_test.go | 27 ++++++++++-- .../gitea/testdata/membership.json.golden | 4 ++ scm/driver/gitea/testdata/permissions.json | 7 +++ 4 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 scm/driver/gitea/testdata/membership.json.golden create mode 100644 scm/driver/gitea/testdata/permissions.json diff --git a/scm/driver/gitea/org.go b/scm/driver/gitea/org.go index c7c7efc03..6ca8ec7ea 100644 --- a/scm/driver/gitea/org.go +++ b/scm/driver/gitea/org.go @@ -23,7 +23,13 @@ func (s *organizationService) Find(ctx context.Context, name string) (*scm.Organ } func (s *organizationService) FindMembership(ctx context.Context, name, username string) (*scm.Membership, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + membership := new(membership) + membership.Active = s.checkMembership(ctx, name, username) + out := new(permissions) + path := fmt.Sprintf("api/v1/users/%s/orgs/%s/permissions", username, name) + res, err := s.client.do(ctx, "GET", path, nil, out) + membership.Permissions = out + return convertMembership(membership), res, err } func (s *organizationService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Organization, *scm.Response, error) { @@ -33,6 +39,18 @@ func (s *organizationService) List(ctx context.Context, opts scm.ListOptions) ([ return convertOrgList(out), res, err } +type permissions struct { + IsOwner bool `json:"is_owner"` + IsAdmin bool `json:"is_admin"` + CanWrite bool `json:"can_write"` + CanRead bool `json:"can_read"` + CanCreateRepository bool `json:"can_create_repository"` +} +type membership struct { + Permissions *permissions + Active bool +} + // // native data structures // @@ -60,3 +78,27 @@ func convertOrg(from *org) *scm.Organization { Avatar: from.Avatar, } } + +func (s *organizationService) checkMembership(ctx context.Context, name, username string) bool { + path := fmt.Sprintf("api/v1/orgs/%s/members/%s", name, username) + res, err := s.client.do(ctx, "GET", path, nil, nil) + if err != nil { + return false + } + return res.Status == 204 +} + +func convertMembership(from *membership) *scm.Membership { + to := new(scm.Membership) + to.Active = from.Active + isAdmin := from.Permissions.IsAdmin + isMember := from.Permissions.CanRead || from.Permissions.CanWrite || from.Permissions.CanCreateRepository + if isAdmin { + to.Role = scm.RoleAdmin + } else if isMember { + to.Role = scm.RoleMember + } else { + to.Role = scm.RoleUndefined + } + return to +} diff --git a/scm/driver/gitea/org_test.go b/scm/driver/gitea/org_test.go index 90a0a193c..ceaba401b 100644 --- a/scm/driver/gitea/org_test.go +++ b/scm/driver/gitea/org_test.go @@ -42,10 +42,31 @@ func TestOrgFind(t *testing.T) { } func TestOrganizationFindMembership(t *testing.T) { + defer gock.Off() + + gock.New("https://try.gitea.io"). + Get("/api/v1/orgs/gogits/members/jcitizen"). + Reply(204) + + gock.New("https://try.gitea.io"). + Get("/api/v1/users/jcitizen/orgs/gogits/permissions"). + Reply(200). + Type("application/json"). + File("testdata/permissions.json") + client, _ := New("https://try.gitea.io") - _, _, err := client.Organizations.FindMembership(context.Background(), "gogits", "jcitizen") - if err != scm.ErrNotSupported { - t.Errorf("Expect Not Supported error") + got, _, err := client.Organizations.FindMembership(context.Background(), "gogits", "jcitizen") + if err != nil { + t.Error(err) + } + + want := new(scm.Membership) + raw, _ := ioutil.ReadFile("testdata/membership.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) } } diff --git a/scm/driver/gitea/testdata/membership.json.golden b/scm/driver/gitea/testdata/membership.json.golden new file mode 100644 index 000000000..96ec5685e --- /dev/null +++ b/scm/driver/gitea/testdata/membership.json.golden @@ -0,0 +1,4 @@ +{ + "Active": true, + "Role": 2 +} \ No newline at end of file diff --git a/scm/driver/gitea/testdata/permissions.json b/scm/driver/gitea/testdata/permissions.json new file mode 100644 index 000000000..77e2cff85 --- /dev/null +++ b/scm/driver/gitea/testdata/permissions.json @@ -0,0 +1,7 @@ +{ + "is_owner": true, + "is_admin": true, + "can_write": true, + "can_read": true, + "can_create_repository": true +} From cc305a69c784c50fa91da5de37b4fcad379bd421 Mon Sep 17 00:00:00 2001 From: Scott Walker Date: Mon, 14 Aug 2023 15:32:02 +0100 Subject: [PATCH 176/282] [IAC-941]: PR comment creation for BitBucket (#265) BitBucket doesn't implement support for PR comments or issues comments. The current implementation of "pullService" in BitBucket defers to the implementation of "issueService", which itself returns a "not implemented" error for all comment-related calls. PR comments and issue comments are separate in BitBucket so this commit adds explicit implementations of the comment functions to the "pullService". Most remain "not implemented" with the exception of comment creation which is now supported. --- go.sum | 11 ---- scm/driver/bitbucket/bitbucket.go | 2 +- scm/driver/bitbucket/pr.go | 38 +++++++++++++- scm/driver/bitbucket/pr_test.go | 50 ++++++++++++++++++ scm/driver/bitbucket/testdata/prcomment.json | 52 +++++++++++++++++++ .../bitbucket/testdata/prcomment.json.golden | 12 +++++ scm/driver/bitbucket/webhook.go | 6 +++ 7 files changed, 158 insertions(+), 13 deletions(-) create mode 100644 scm/driver/bitbucket/testdata/prcomment.json create mode 100644 scm/driver/bitbucket/testdata/prcomment.json.golden diff --git a/go.sum b/go.sum index 00f0342cb..6d69376b6 100644 --- a/go.sum +++ b/go.sum @@ -1,17 +1,6 @@ -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/h2non/gock v1.0.9 h1:17gCehSo8ZOgEsFKpQgqHiR7VLyjxdAG3lkhVvO9QZU= github.com/h2non/gock v1.0.9/go.mod h1:CZMcB0Lg5IWnr9bF79pPMg9WeV6WumxQiUJ1UvdO1iE= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/scm/driver/bitbucket/bitbucket.go b/scm/driver/bitbucket/bitbucket.go index d5afda370..f05ab670e 100644 --- a/scm/driver/bitbucket/bitbucket.go +++ b/scm/driver/bitbucket/bitbucket.go @@ -36,7 +36,7 @@ func New(uri string) (*scm.Client, error) { client.Issues = &issueService{client} client.Milestones = &milestoneService{client} client.Organizations = &organizationService{client} - client.PullRequests = &pullService{&issueService{client}} + client.PullRequests = &pullService{client} client.Repositories = &repositoryService{client} client.Releases = &releaseService{client} client.Reviews = &reviewService{client} diff --git a/scm/driver/bitbucket/pr.go b/scm/driver/bitbucket/pr.go index 5cc3e5ba9..ead47a821 100644 --- a/scm/driver/bitbucket/pr.go +++ b/scm/driver/bitbucket/pr.go @@ -13,7 +13,7 @@ import ( ) type pullService struct { - *issueService + client *wrapper } func (s *pullService) Find(ctx context.Context, repo string, number int) (*scm.PullRequest, *scm.Response, error) { @@ -69,6 +69,27 @@ func (s *pullService) Create(ctx context.Context, repo string, input *scm.PullRe return convertPullRequest(out), res, err } +func (s *pullService) FindComment(ctx context.Context, repo string, index, id int) (*scm.Comment, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *pullService) ListComments(ctx context.Context, repo string, index int, opts scm.ListOptions) ([]*scm.Comment, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + +func (s *pullService) CreateComment(ctx context.Context, repo string, number int, input *scm.CommentInput) (*scm.Comment, *scm.Response, error) { + path := fmt.Sprintf("2.0/repositories/%s/pullrequests/%d/comments", repo, number) + in := &prCommentInput{} + in.Content.Raw = input.Body + out := new(prComment) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertPullRequestComment(out), res, err +} + +func (s *pullService) DeleteComment(ctx context.Context, repo string, number, id int) (*scm.Response, error) { + return nil, scm.ErrNotSupported +} + type reference struct { Commit struct { Hash string `json:"hash"` @@ -180,3 +201,18 @@ func convertPullRequest(from *pr) *scm.PullRequest { Updated: from.UpdatedOn, } } + +func convertPullRequestComment(from *prComment) *scm.Comment { + return &scm.Comment{ + ID: from.ID, + Body: from.Content.Raw, + Author: scm.User{ + ID: from.User.UUID, + Login: from.User.Nickname, + Name: from.User.DisplayName, + Avatar: from.User.Links.Avatar.Href, + }, + Created: from.CreatedOn, + Updated: from.UpdatedOn, + } +} diff --git a/scm/driver/bitbucket/pr_test.go b/scm/driver/bitbucket/pr_test.go index 00f112f75..038ec1952 100644 --- a/scm/driver/bitbucket/pr_test.go +++ b/scm/driver/bitbucket/pr_test.go @@ -175,3 +175,53 @@ func TestPullListCommits(t *testing.T) { t.Log(diff) } } + +func TestPullRequestCommentFind(t *testing.T) { + _, _, err := NewDefault().PullRequests.FindComment(context.Background(), "", 0, 0) + if err != scm.ErrNotSupported { + t.Errorf("Expect Not Supported error") + } +} + +func TestPullRequestListComments(t *testing.T) { + _, _, err := NewDefault().PullRequests.ListComments(context.Background(), "", 0, scm.ListOptions{}) + if err != scm.ErrNotSupported { + t.Errorf("Expect Not Supported error") + } +} + +func TestPullRequestCreateComment(t *testing.T) { + defer gock.Off() + + gock.New("https://api.bitbucket.org"). + Post("/2.0/repositories/atlassian/atlaskit/pullrequests/12"). + Reply(201). + Type("application/json"). + File("testdata/prcomment.json") + + input := &scm.CommentInput{ + Body: "Lovely comment", + } + + client, _ := New("https://api.bitbucket.org") + got, _, err := client.PullRequests.CreateComment(context.Background(), "atlassian/atlaskit", 12, input) + if err != nil { + t.Error(err) + } + + want := new(scm.Comment) + raw, _ := ioutil.ReadFile("testdata/prcomment.json.golden") + json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + +func TestPullRequestCommentDelete(t *testing.T) { + _, err := NewDefault().PullRequests.DeleteComment(context.Background(), "", 0, 0) + if err != scm.ErrNotSupported { + t.Errorf("Expect Not Supported error") + } +} diff --git a/scm/driver/bitbucket/testdata/prcomment.json b/scm/driver/bitbucket/testdata/prcomment.json new file mode 100644 index 000000000..953b2d158 --- /dev/null +++ b/scm/driver/bitbucket/testdata/prcomment.json @@ -0,0 +1,52 @@ +{ + "id": 419169807, + "created_on": "2023-08-14T11:38:53.460132+00:00", + "updated_on": "2023-08-14T11:38:53.460205+00:00", + "content": { + "type": "rendered", + "raw": "Lovely comment", + "markup": "markdown", + "html": "

Lovely comment<\/p>" + }, + "user": { + "display_name": "Brian Jacobson", + "links": { + "self": { + "href": "https:\/\/bitbucket.org\/!api\/2.0\/users\/%7B6dff94-1b8b-4f62-b37f-3069e13dfdf33e%7D" + }, + "avatar": { + "href": "http:\/\/localhost:3000\/avatars\/1" + }, + "html": { + "href": "https:\/\/bitbucket.org\/%7B6dff94-1b8b-4f62-b37f-3069e13dfdf33e%7D\/" + } + }, + "type": "user", + "uuid": "{6b408a94-1b8b-4f62-b37f-3069e13bc33e}", + "account_id": "60259ce8164527007100d945", + "nickname": "brian.jacobson" + }, + "deleted": false, + "type": "pullrequest_comment", + "links": { + "self": { + "href": "https:\/\/bitbucket.org\/!api\/2.0\/repositories\/brianharness\/test\/pullrequests\/3\/comments\/419169807" + }, + "html": { + "href": "https:\/\/bitbucket.org\/brianharness\/test\/pull-requests\/3\/_\/diff#comment-419169807" + } + }, + "pullrequest": { + "type": "pullrequest", + "id": 3, + "title": "README.md edited online with Bitbucket", + "links": { + "self": { + "href": "https:\/\/bitbucket.org\/!api\/2.0\/repositories\/brianharness\/test\/pullrequests\/3" + }, + "html": { + "href": "https:\/\/bitbucket.org\/brianharness\/test\/pull-requests\/3" + } + } + } +} \ No newline at end of file diff --git a/scm/driver/bitbucket/testdata/prcomment.json.golden b/scm/driver/bitbucket/testdata/prcomment.json.golden new file mode 100644 index 000000000..e6dea457a --- /dev/null +++ b/scm/driver/bitbucket/testdata/prcomment.json.golden @@ -0,0 +1,12 @@ +{ + "ID": 419169807, + "Body": "Lovely comment", + "Author": { + "ID": "{6b408a94-1b8b-4f62-b37f-3069e13bc33e}", + "Login": "brian.jacobson", + "Name": "Brian Jacobson", + "Avatar": "http://localhost:3000/avatars/1" + }, + "Created": "2023-08-14T11:38:53.460132+00:00", + "Updated": "2023-08-14T11:38:53.460205+00:00" +} diff --git a/scm/driver/bitbucket/webhook.go b/scm/driver/bitbucket/webhook.go index 6d88690ec..d254bba54 100644 --- a/scm/driver/bitbucket/webhook.go +++ b/scm/driver/bitbucket/webhook.go @@ -405,6 +405,12 @@ type ( UUID string `json:"uuid"` } + prCommentInput struct { + Content struct { + Raw string `json:"raw"` + } `json:"content"` + } + prComment struct { Links struct { Self link `json:"self"` From 6906e848dc03143acefe9e5f41c97cd7e13b33a3 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Tue, 15 Aug 2023 10:28:13 +0100 Subject: [PATCH 177/282] (maint) v1.31.0 release prep (#266) Co-authored-by: dependabot-ci --- CHANGELOG.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 872d6396c..b5019f454 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,38 @@ # Changelog +## [v1.31.0](https://github.com/drone/go-scm/tree/v1.31.0) (2023-08-15) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.30.0...v1.31.0) + +**Implemented enhancements:** + +- \[IAC-941\]: PR comment creation for BitBucket [\#265](https://github.com/drone/go-scm/pull/265) ([scottyw-harness](https://github.com/scottyw-harness)) +- Implemented FindMembership method in organization service for gitea driver [\#263](https://github.com/drone/go-scm/pull/263) ([cod3rboy](https://github.com/cod3rboy)) + +**Closed issues:** + +- \(missing feature\) add support to check organization membership in gitea driver [\#262](https://github.com/drone/go-scm/issues/262) + +## [v1.30.0](https://github.com/drone/go-scm/tree/v1.30.0) (2023-07-19) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.29.1...v1.30.0) + +**Implemented enhancements:** + +- \[feat\]: \[CDS-73572\]: Support List Repo Live Search for all git providers [\#261](https://github.com/drone/go-scm/pull/261) ([adivishy1](https://github.com/adivishy1)) +- \[feat\]: \[CDS-73030\]: Support for text based branch filtration [\#260](https://github.com/drone/go-scm/pull/260) ([adivishy1](https://github.com/adivishy1)) +- feat: \[CDS-69341\]: add find user email api for github in go-scm [\#256](https://github.com/drone/go-scm/pull/256) ([shalini-agr](https://github.com/shalini-agr)) + +**Fixed bugs:** + +- fix: \[CDS-67745\]: fix find user email api for bitbucket in go-scm [\#255](https://github.com/drone/go-scm/pull/255) ([shalini-agr](https://github.com/shalini-agr)) +- fix: \[CI-6978\] fixed gitlab webhook parse [\#253](https://github.com/drone/go-scm/pull/253) ([devkimittal](https://github.com/devkimittal)) +- Add required header for bitbucket server in commit API use-case to handle csrf failures [\#252](https://github.com/drone/go-scm/pull/252) ([mohitg0795](https://github.com/mohitg0795)) + +**Merged pull requests:** + +- \(maint\) stash/bitbucket on prem v5 add push webhook test [\#257](https://github.com/drone/go-scm/pull/257) ([tphoney](https://github.com/tphoney)) + ## [v1.29.1](https://github.com/drone/go-scm/tree/v1.29.1) (2023-02-16) [Full Changelog](https://github.com/drone/go-scm/compare/v1.29.0...v1.29.1) From 1579795501b0ae415d6f75594751ffe3ddcaeb76 Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Wed, 23 Aug 2023 14:41:04 +0530 Subject: [PATCH 178/282] Fix compare change api result for harness (#267) * Fix compare change api result for harness --- go.mod | 1 + go.sum | 2 + scm/driver/harness/git.go | 34 +++++++++----- scm/driver/harness/git_test.go | 44 +++++++++++++++++++ scm/driver/harness/testdata/gitdiff.json | 25 +++++++++++ .../harness/testdata/gitdiff.json.golden | 38 ++++++++++++++++ 6 files changed, 133 insertions(+), 11 deletions(-) create mode 100644 scm/driver/harness/testdata/gitdiff.json create mode 100644 scm/driver/harness/testdata/gitdiff.json.golden diff --git a/go.mod b/go.mod index 1a7e7c5ea..61703b6e3 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,7 @@ module github.com/drone/go-scm require ( + github.com/bluekeyes/go-gitdiff v0.7.1 github.com/google/go-cmp v0.2.0 github.com/h2non/gock v1.0.9 github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 // indirect diff --git a/go.sum b/go.sum index 6d69376b6..bce3cf429 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/bluekeyes/go-gitdiff v0.7.1 h1:graP4ElLRshr8ecu0UtqfNTCHrtSyZd3DABQm/DWesQ= +github.com/bluekeyes/go-gitdiff v0.7.1/go.mod h1:QpfYYO1E0fTVHVZAZKiRjtSGY9823iCdvGXBcEzHGbM= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/h2non/gock v1.0.9 h1:17gCehSo8ZOgEsFKpQgqHiR7VLyjxdAG3lkhVvO9QZU= diff --git a/scm/driver/harness/git.go b/scm/driver/harness/git.go index 787eb4920..c5ca6eab1 100644 --- a/scm/driver/harness/git.go +++ b/scm/driver/harness/git.go @@ -7,10 +7,10 @@ package harness import ( "context" "fmt" - "io" "strings" "time" + "github.com/bluekeyes/go-gitdiff/gitdiff" "github.com/drone/go-scm/scm" ) @@ -81,17 +81,9 @@ func (s *gitService) ListChanges(ctx context.Context, repo, ref string, _ scm.Li func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) path := fmt.Sprintf("api/v1/repos/%s/compare/%s...%s", harnessURI, source, target) - res, err := s.client.do(ctx, "GET", path, nil, nil) - // convert response to a string buf := new(strings.Builder) - _, _ = io.Copy(buf, res.Body) - changes := []*scm.Change{ - { - Path: "not implemented", - Sha: buf.String(), - }, - } - return changes, res, err + res, err := s.client.do(ctx, "GET", path, nil, buf) + return convertCompareChanges(buf.String()), res, err } // native data structures @@ -172,6 +164,26 @@ func convertCommitList(src []*commitInfo) []*scm.Commit { return dst } +func convertCompareChanges(src string) []*scm.Change { + files, _, err := gitdiff.Parse(strings.NewReader(src)) + if err != nil { + return nil + } + + changes := make([]*scm.Change, 0) + for _, f := range files { + changes = append(changes, &scm.Change{ + Path: f.NewName, + PrevFilePath: f.OldName, + Added: f.IsNew, + Deleted: f.IsDelete, + Renamed: f.IsRename, + }) + } + + return changes +} + func convertCommitInfo(src *commitInfo) *scm.Commit { return &scm.Commit{ Sha: src.Sha, diff --git a/scm/driver/harness/git_test.go b/scm/driver/harness/git_test.go index 016d65e49..8b5a5cd93 100644 --- a/scm/driver/harness/git_test.go +++ b/scm/driver/harness/git_test.go @@ -7,6 +7,7 @@ package harness import ( "context" "encoding/json" + "fmt" "io/ioutil" "net/http" "testing" @@ -207,3 +208,46 @@ func TestCreateBranch(t *testing.T) { } } + +func TestCompareChanges(t *testing.T) { + source := "a24d87c887957954d6f872bac3676f12cb9f50a2" + target := "5d1eb44a2aae537e5fa649dce3ff8c306af1527e" + defer gock.Off() + + gock.New(gockOrigin). + Get(fmt.Sprintf("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/compare/%s...%s", source, target)). + Reply(200). + Type("application/json"). + File("testdata/gitdiff.json") + + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + got, result, err := client.Git.CompareChanges(context.Background(), harnessRepo, source, target, scm.ListOptions{}) + if err != nil { + t.Error(err) + return + } + + if result.Status != 200 { + t.Errorf("Unexpected Results") + } + + want := []*scm.Change{} + raw, _ := ioutil.ReadFile("testdata/gitdiff.json.golden") + wantErr := json.Unmarshal(raw, &want) + if wantErr != nil { + t.Error(wantErr) + return + } + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} diff --git a/scm/driver/harness/testdata/gitdiff.json b/scm/driver/harness/testdata/gitdiff.json new file mode 100644 index 000000000..d44e597be --- /dev/null +++ b/scm/driver/harness/testdata/gitdiff.json @@ -0,0 +1,25 @@ +diff --git a/five b/five +new file mode 100644 +index 0000000..54f9d6d +--- /dev/null ++++ b/five +@@ -0,0 +1 @@ ++five +diff --git a/two b/four +similarity index 100% +rename from two +rename to four +diff --git a/one b/one +index 5626abf..9c0408b 100644 +--- a/one ++++ b/one +@@ -1 +1,2 @@ + one ++modified to two +diff --git a/three b/three +deleted file mode 100644 +index 2bdf67a..0000000 +--- a/three ++++ /dev/null +@@ -1 +0,0 @@ +-three \ No newline at end of file diff --git a/scm/driver/harness/testdata/gitdiff.json.golden b/scm/driver/harness/testdata/gitdiff.json.golden new file mode 100644 index 000000000..6439c0c09 --- /dev/null +++ b/scm/driver/harness/testdata/gitdiff.json.golden @@ -0,0 +1,38 @@ +[ + { + "Path": "five", + "Added": true, + "Renamed": false, + "Deleted": false, + "Sha": "", + "BlobID": "", + "PrevFilePath": "" + }, + { + "Path": "four", + "Added": false, + "Renamed": true, + "Deleted": false, + "Sha": "", + "BlobID": "", + "PrevFilePath": "two" + }, + { + "Path": "one", + "Added": false, + "Renamed": false, + "Deleted": false, + "Sha": "", + "BlobID": "", + "PrevFilePath": "one" + }, + { + "Path": "", + "Added": false, + "Renamed": false, + "Deleted": true, + "Sha": "", + "BlobID": "", + "PrevFilePath": "three" + } +] \ No newline at end of file From 5098db8648a082d86082116c10d854190e9e3ad3 Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Tue, 29 Aug 2023 14:46:22 +0530 Subject: [PATCH 179/282] Fix api name for fetching diff in harness driver (#268) * Fix api name for fetching diff in harness driver --- scm/driver/harness/git.go | 2 +- scm/driver/harness/git_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scm/driver/harness/git.go b/scm/driver/harness/git.go index c5ca6eab1..bde9965e9 100644 --- a/scm/driver/harness/git.go +++ b/scm/driver/harness/git.go @@ -80,7 +80,7 @@ func (s *gitService) ListChanges(ctx context.Context, repo, ref string, _ scm.Li func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - path := fmt.Sprintf("api/v1/repos/%s/compare/%s...%s", harnessURI, source, target) + path := fmt.Sprintf("api/v1/repos/%s/diff/%s...%s", harnessURI, source, target) buf := new(strings.Builder) res, err := s.client.do(ctx, "GET", path, nil, buf) return convertCompareChanges(buf.String()), res, err diff --git a/scm/driver/harness/git_test.go b/scm/driver/harness/git_test.go index 8b5a5cd93..79dae39eb 100644 --- a/scm/driver/harness/git_test.go +++ b/scm/driver/harness/git_test.go @@ -215,7 +215,7 @@ func TestCompareChanges(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Get(fmt.Sprintf("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/compare/%s...%s", source, target)). + Get(fmt.Sprintf("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/diff/%s...%s", source, target)). Reply(200). Type("application/json"). File("testdata/gitdiff.json") From 8764ac057e4b9b218cda292e1e2a6b49f6f89d7e Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Tue, 29 Aug 2023 18:12:40 +0530 Subject: [PATCH 180/282] Fix diff api response conversion for harness compareChange (#269) * Fix diff api response conversion --- go.mod | 1 - go.sum | 2 - scm/driver/harness/git.go | 54 +++++++------ scm/driver/harness/git_test.go | 4 +- scm/driver/harness/testdata/gitdiff.json | 78 +++++++++++++------ .../harness/testdata/gitdiff.json.golden | 24 +++--- 6 files changed, 99 insertions(+), 64 deletions(-) diff --git a/go.mod b/go.mod index 61703b6e3..1a7e7c5ea 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,6 @@ module github.com/drone/go-scm require ( - github.com/bluekeyes/go-gitdiff v0.7.1 github.com/google/go-cmp v0.2.0 github.com/h2non/gock v1.0.9 github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 // indirect diff --git a/go.sum b/go.sum index bce3cf429..6d69376b6 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -github.com/bluekeyes/go-gitdiff v0.7.1 h1:graP4ElLRshr8ecu0UtqfNTCHrtSyZd3DABQm/DWesQ= -github.com/bluekeyes/go-gitdiff v0.7.1/go.mod h1:QpfYYO1E0fTVHVZAZKiRjtSGY9823iCdvGXBcEzHGbM= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/h2non/gock v1.0.9 h1:17gCehSo8ZOgEsFKpQgqHiR7VLyjxdAG3lkhVvO9QZU= diff --git a/scm/driver/harness/git.go b/scm/driver/harness/git.go index bde9965e9..309a125f7 100644 --- a/scm/driver/harness/git.go +++ b/scm/driver/harness/git.go @@ -7,10 +7,8 @@ package harness import ( "context" "fmt" - "strings" "time" - "github.com/bluekeyes/go-gitdiff/gitdiff" "github.com/drone/go-scm/scm" ) @@ -81,9 +79,9 @@ func (s *gitService) ListChanges(ctx context.Context, repo, ref string, _ scm.Li func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) path := fmt.Sprintf("api/v1/repos/%s/diff/%s...%s", harnessURI, source, target) - buf := new(strings.Builder) - res, err := s.client.do(ctx, "GET", path, nil, buf) - return convertCompareChanges(buf.String()), res, err + out := []*fileDiff{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertChangeList(out), res, err } // native data structures @@ -134,6 +132,20 @@ type ( Name string `json:"name"` Sha string `json:"sha"` } + fileDiff struct { + SHA string `json:"sha"` + OldSHA string `json:"old_sha,omitempty"` + Path string `json:"path"` + OldPath string `json:"old_path,omitempty"` + Status string `json:"status"` + Additions int64 `json:"additions"` + Deletions int64 `json:"deletions"` + Changes int64 `json:"changes"` + ContentURL string `json:"content_url"` + Patch []byte `json:"patch,omitempty"` + IsBinary bool `json:"is_binary"` + IsSubmodule bool `json:"is_submodule"` + } ) // @@ -164,24 +176,12 @@ func convertCommitList(src []*commitInfo) []*scm.Commit { return dst } -func convertCompareChanges(src string) []*scm.Change { - files, _, err := gitdiff.Parse(strings.NewReader(src)) - if err != nil { - return nil - } - - changes := make([]*scm.Change, 0) - for _, f := range files { - changes = append(changes, &scm.Change{ - Path: f.NewName, - PrevFilePath: f.OldName, - Added: f.IsNew, - Deleted: f.IsDelete, - Renamed: f.IsRename, - }) +func convertChangeList(src []*fileDiff) []*scm.Change { + dst := []*scm.Change{} + for _, v := range src { + dst = append(dst, convertChange(v)) } - - return changes + return dst } func convertCommitInfo(src *commitInfo) *scm.Commit { @@ -200,3 +200,13 @@ func convertCommitInfo(src *commitInfo) *scm.Commit { }, } } + +func convertChange(src *fileDiff) *scm.Change { + return &scm.Change{ + Path: src.Path, + PrevFilePath: src.OldPath, + Added: src.Status == "ADDED", + Renamed: src.Status == "RENAMED", + Deleted: src.Status == "DELETED", + } +} diff --git a/scm/driver/harness/git_test.go b/scm/driver/harness/git_test.go index 79dae39eb..515705068 100644 --- a/scm/driver/harness/git_test.go +++ b/scm/driver/harness/git_test.go @@ -210,8 +210,8 @@ func TestCreateBranch(t *testing.T) { } func TestCompareChanges(t *testing.T) { - source := "a24d87c887957954d6f872bac3676f12cb9f50a2" - target := "5d1eb44a2aae537e5fa649dce3ff8c306af1527e" + source := "542ddabd47d7bfa79359b7b4e2af7f975354e35f" + target := "c7d0d4b21d5cfdf47475ff1f6281ef1a91883d" defer gock.Off() gock.New(gockOrigin). diff --git a/scm/driver/harness/testdata/gitdiff.json b/scm/driver/harness/testdata/gitdiff.json index d44e597be..c4dd5768d 100644 --- a/scm/driver/harness/testdata/gitdiff.json +++ b/scm/driver/harness/testdata/gitdiff.json @@ -1,25 +1,53 @@ -diff --git a/five b/five -new file mode 100644 -index 0000000..54f9d6d ---- /dev/null -+++ b/five -@@ -0,0 +1 @@ -+five -diff --git a/two b/four -similarity index 100% -rename from two -rename to four -diff --git a/one b/one -index 5626abf..9c0408b 100644 ---- a/one -+++ b/one -@@ -1 +1,2 @@ - one -+modified to two -diff --git a/three b/three -deleted file mode 100644 -index 2bdf67a..0000000 ---- a/three -+++ /dev/null -@@ -1 +0,0 @@ --three \ No newline at end of file +[ + { + "sha": "c4e897c1fcd1cae04abf761f034ae4c5e210caad", + "old_sha": "0000000000000000000000000000000000000000", + "path": "hello.go", + "old_path": "hello.go", + "status": "ADDED", + "additions": 8, + "deletions": 0, + "changes": 8, + "content_url": "/api/v1/hello.go", + "is_binary": false, + "is_submodule": false + }, + { + "sha": "0000000000000000000000000000000000000000", + "old_sha": "d7fcbf28651697b00add519d8b4402a5ab46ffc2", + "path": "null.go", + "old_path": "null.go", + "status": "DELETED", + "additions": 0, + "deletions": 118, + "changes": 118, + "content_url": "/api/v1/null.go", + "is_binary": false, + "is_submodule": false + }, + { + "sha": "ce5a2cd34b697f7a8507192e7074b33737c6740c", + "old_sha": "7697802e4d16b255e7ea22a86071cfbe9af6aa39", + "path": "version4.go", + "old_path": "version4.go", + "status": "MODIFIED", + "additions": 8, + "deletions": 7, + "changes": 15, + "content_url": "/api/v1/version4.go", + "is_binary": false, + "is_submodule": false + }, + { + "sha": "", + "path": "version_1.go", + "old_path": "version1.go", + "status": "RENAMED", + "additions": 0, + "deletions": 0, + "changes": 0, + "content_url": "/api/v1/version_1.go", + "is_binary": false, + "is_submodule": false + } +] \ No newline at end of file diff --git a/scm/driver/harness/testdata/gitdiff.json.golden b/scm/driver/harness/testdata/gitdiff.json.golden index 6439c0c09..c3258c315 100644 --- a/scm/driver/harness/testdata/gitdiff.json.golden +++ b/scm/driver/harness/testdata/gitdiff.json.golden @@ -1,38 +1,38 @@ [ { - "Path": "five", + "Path": "hello.go", "Added": true, "Renamed": false, "Deleted": false, "Sha": "", "BlobID": "", - "PrevFilePath": "" + "PrevFilePath": "hello.go" }, { - "Path": "four", + "Path": "null.go", "Added": false, - "Renamed": true, - "Deleted": false, + "Renamed": false, + "Deleted": true, "Sha": "", "BlobID": "", - "PrevFilePath": "two" + "PrevFilePath": "null.go" }, { - "Path": "one", + "Path": "version4.go", "Added": false, "Renamed": false, "Deleted": false, "Sha": "", "BlobID": "", - "PrevFilePath": "one" + "PrevFilePath": "version4.go" }, { - "Path": "", + "Path": "version_1.go", "Added": false, - "Renamed": false, - "Deleted": true, + "Renamed": true, + "Deleted": false, "Sha": "", "BlobID": "", - "PrevFilePath": "three" + "PrevFilePath": "version1.go" } ] \ No newline at end of file From bec9362d123d3e8981752a25de9ae63ea46f778d Mon Sep 17 00:00:00 2001 From: Meet Rathod Date: Tue, 29 Aug 2023 21:15:38 +0530 Subject: [PATCH 181/282] [feat]: [CDS-75848]: Add new action type for github provider --- scm/const.go | 5 + .../webhooks/pr_ready_for_review.json | 528 ++++++++++++++++++ .../webhooks/pr_ready_for_review.json.golden | 55 ++ scm/driver/github/webhook.go | 64 ++- scm/driver/github/webhook_test.go | 62 +- 5 files changed, 655 insertions(+), 59 deletions(-) create mode 100644 scm/driver/github/testdata/webhooks/pr_ready_for_review.json create mode 100644 scm/driver/github/testdata/webhooks/pr_ready_for_review.json.golden diff --git a/scm/const.go b/scm/const.go index dca74b699..b55729dd1 100644 --- a/scm/const.go +++ b/scm/const.go @@ -40,6 +40,7 @@ const ( // pull requests ActionSync ActionMerge + ActionReadyForReview // issue comment ActionEdit // release @@ -80,6 +81,8 @@ func (a Action) String() (s string) { return "prereleased" case ActionRelease: return "released" + case ActionReadyForReview: + return "ready_for_review" default: return } @@ -127,6 +130,8 @@ func (a *Action) UnmarshalJSON(data []byte) error { *a = ActionPrerelease case "released": *a = ActionRelease + case "ready_for_review": + *a = ActionReadyForReview } return nil } diff --git a/scm/driver/github/testdata/webhooks/pr_ready_for_review.json b/scm/driver/github/testdata/webhooks/pr_ready_for_review.json new file mode 100644 index 000000000..b9a7e1fdc --- /dev/null +++ b/scm/driver/github/testdata/webhooks/pr_ready_for_review.json @@ -0,0 +1,528 @@ +{ + "action": "ready_for_review", + "number": 38, + "pull_request": { + "url": "https://api.github.com/repos/wings-software/meet-git-sync-test/pulls/38", + "id": 1492580810, + "node_id": "PR_kwDOHbOleM5Y9vnK", + "html_url": "https://github.com/wings-software/meet-git-sync-test/pull/38", + "diff_url": "https://github.com/wings-software/meet-git-sync-test/pull/38.diff", + "patch_url": "https://github.com/wings-software/meet-git-sync-test/pull/38.patch", + "issue_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/issues/38", + "number": 38, + "state": "open", + "locked": false, + "title": "Update dgdggd.me", + "user": { + "login": "rathodmeetsatish", + "id": 84321134, + "node_id": "MDQ6VXNlcjg0MzIxMTM0", + "avatar_url": "https://avatars.githubusercontent.com/u/84321134?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/rathodmeetsatish", + "html_url": "https://github.com/rathodmeetsatish", + "followers_url": "https://api.github.com/users/rathodmeetsatish/followers", + "following_url": "https://api.github.com/users/rathodmeetsatish/following{/other_user}", + "gists_url": "https://api.github.com/users/rathodmeetsatish/gists{/gist_id}", + "starred_url": "https://api.github.com/users/rathodmeetsatish/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/rathodmeetsatish/subscriptions", + "organizations_url": "https://api.github.com/users/rathodmeetsatish/orgs", + "repos_url": "https://api.github.com/users/rathodmeetsatish/repos", + "events_url": "https://api.github.com/users/rathodmeetsatish/events{/privacy}", + "received_events_url": "https://api.github.com/users/rathodmeetsatish/received_events", + "type": "User", + "site_admin": false + }, + "body": null, + "created_at": "2023-08-28T19:15:53Z", + "updated_at": "2023-08-28T19:16:06Z", + "closed_at": null, + "merged_at": null, + "merge_commit_sha": "d427e98e038a88f10e57d48c34f287e3ad20a0bf", + "assignee": null, + "assignees": [ + + ], + "requested_reviewers": [ + + ], + "requested_teams": [ + + ], + "labels": [ + + ], + "milestone": null, + "draft": false, + "commits_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/pulls/38/commits", + "review_comments_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/pulls/38/comments", + "review_comment_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/pulls/comments{/number}", + "comments_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/issues/38/comments", + "statuses_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/statuses/212015fb011c49a2913c4a1a860ce07c0821c362", + "head": { + "label": "wings-software:rathodmeetsatish-patch-25", + "ref": "rathodmeetsatish-patch-25", + "sha": "212015fb011c49a2913c4a1a860ce07c0821c362", + "user": { + "login": "wings-software", + "id": 18273000, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjE4MjczMDAw", + "avatar_url": "https://avatars.githubusercontent.com/u/18273000?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/wings-software", + "html_url": "https://github.com/wings-software", + "followers_url": "https://api.github.com/users/wings-software/followers", + "following_url": "https://api.github.com/users/wings-software/following{/other_user}", + "gists_url": "https://api.github.com/users/wings-software/gists{/gist_id}", + "starred_url": "https://api.github.com/users/wings-software/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/wings-software/subscriptions", + "organizations_url": "https://api.github.com/users/wings-software/orgs", + "repos_url": "https://api.github.com/users/wings-software/repos", + "events_url": "https://api.github.com/users/wings-software/events{/privacy}", + "received_events_url": "https://api.github.com/users/wings-software/received_events", + "type": "Organization", + "site_admin": false + }, + "repo": { + "id": 498312568, + "node_id": "R_kgDOHbOleA", + "name": "meet-git-sync-test", + "full_name": "wings-software/meet-git-sync-test", + "private": true, + "owner": { + "login": "wings-software", + "id": 18273000, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjE4MjczMDAw", + "avatar_url": "https://avatars.githubusercontent.com/u/18273000?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/wings-software", + "html_url": "https://github.com/wings-software", + "followers_url": "https://api.github.com/users/wings-software/followers", + "following_url": "https://api.github.com/users/wings-software/following{/other_user}", + "gists_url": "https://api.github.com/users/wings-software/gists{/gist_id}", + "starred_url": "https://api.github.com/users/wings-software/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/wings-software/subscriptions", + "organizations_url": "https://api.github.com/users/wings-software/orgs", + "repos_url": "https://api.github.com/users/wings-software/repos", + "events_url": "https://api.github.com/users/wings-software/events{/privacy}", + "received_events_url": "https://api.github.com/users/wings-software/received_events", + "type": "Organization", + "site_admin": false + }, + "html_url": "https://github.com/wings-software/meet-git-sync-test", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/wings-software/meet-git-sync-test", + "forks_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/forks", + "keys_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/teams", + "hooks_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/hooks", + "issue_events_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/issues/events{/number}", + "events_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/events", + "assignees_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/assignees{/user}", + "branches_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/branches{/branch}", + "tags_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/tags", + "blobs_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/statuses/{sha}", + "languages_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/languages", + "stargazers_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/stargazers", + "contributors_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/contributors", + "subscribers_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/subscribers", + "subscription_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/subscription", + "commits_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/contents/{+path}", + "compare_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/merges", + "archive_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/downloads", + "issues_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/issues{/number}", + "pulls_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/pulls{/number}", + "milestones_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/milestones{/number}", + "notifications_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/labels{/name}", + "releases_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/releases{/id}", + "deployments_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/deployments", + "created_at": "2022-05-31T11:47:10Z", + "updated_at": "2022-05-31T11:47:35Z", + "pushed_at": "2023-08-28T19:15:54Z", + "git_url": "git://github.com/wings-software/meet-git-sync-test.git", + "ssh_url": "git@github.com:wings-software/meet-git-sync-test.git", + "clone_url": "https://github.com/wings-software/meet-git-sync-test.git", + "svn_url": "https://github.com/wings-software/meet-git-sync-test", + "homepage": null, + "size": 171, + "stargazers_count": 0, + "watchers_count": 0, + "language": "Roff", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 23, + "license": null, + "allow_forking": false, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [ + + ], + "visibility": "private", + "forks": 0, + "open_issues": 23, + "watchers": 0, + "default_branch": "main", + "allow_squash_merge": true, + "allow_merge_commit": true, + "allow_rebase_merge": true, + "allow_auto_merge": false, + "delete_branch_on_merge": false, + "allow_update_branch": false, + "use_squash_pr_title_as_default": false, + "squash_merge_commit_message": "COMMIT_MESSAGES", + "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", + "merge_commit_message": "PR_TITLE", + "merge_commit_title": "MERGE_MESSAGE" + } + }, + "base": { + "label": "wings-software:main", + "ref": "main", + "sha": "8b8d2b3e6a2ee6df108c8429e86c9a750e728f9d", + "user": { + "login": "wings-software", + "id": 18273000, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjE4MjczMDAw", + "avatar_url": "https://avatars.githubusercontent.com/u/18273000?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/wings-software", + "html_url": "https://github.com/wings-software", + "followers_url": "https://api.github.com/users/wings-software/followers", + "following_url": "https://api.github.com/users/wings-software/following{/other_user}", + "gists_url": "https://api.github.com/users/wings-software/gists{/gist_id}", + "starred_url": "https://api.github.com/users/wings-software/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/wings-software/subscriptions", + "organizations_url": "https://api.github.com/users/wings-software/orgs", + "repos_url": "https://api.github.com/users/wings-software/repos", + "events_url": "https://api.github.com/users/wings-software/events{/privacy}", + "received_events_url": "https://api.github.com/users/wings-software/received_events", + "type": "Organization", + "site_admin": false + }, + "repo": { + "id": 498312568, + "node_id": "R_kgDOHbOleA", + "name": "meet-git-sync-test", + "full_name": "wings-software/meet-git-sync-test", + "private": true, + "owner": { + "login": "wings-software", + "id": 18273000, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjE4MjczMDAw", + "avatar_url": "https://avatars.githubusercontent.com/u/18273000?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/wings-software", + "html_url": "https://github.com/wings-software", + "followers_url": "https://api.github.com/users/wings-software/followers", + "following_url": "https://api.github.com/users/wings-software/following{/other_user}", + "gists_url": "https://api.github.com/users/wings-software/gists{/gist_id}", + "starred_url": "https://api.github.com/users/wings-software/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/wings-software/subscriptions", + "organizations_url": "https://api.github.com/users/wings-software/orgs", + "repos_url": "https://api.github.com/users/wings-software/repos", + "events_url": "https://api.github.com/users/wings-software/events{/privacy}", + "received_events_url": "https://api.github.com/users/wings-software/received_events", + "type": "Organization", + "site_admin": false + }, + "html_url": "https://github.com/wings-software/meet-git-sync-test", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/wings-software/meet-git-sync-test", + "forks_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/forks", + "keys_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/teams", + "hooks_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/hooks", + "issue_events_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/issues/events{/number}", + "events_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/events", + "assignees_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/assignees{/user}", + "branches_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/branches{/branch}", + "tags_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/tags", + "blobs_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/statuses/{sha}", + "languages_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/languages", + "stargazers_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/stargazers", + "contributors_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/contributors", + "subscribers_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/subscribers", + "subscription_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/subscription", + "commits_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/contents/{+path}", + "compare_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/merges", + "archive_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/downloads", + "issues_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/issues{/number}", + "pulls_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/pulls{/number}", + "milestones_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/milestones{/number}", + "notifications_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/labels{/name}", + "releases_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/releases{/id}", + "deployments_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/deployments", + "created_at": "2022-05-31T11:47:10Z", + "updated_at": "2022-05-31T11:47:35Z", + "pushed_at": "2023-08-28T19:15:54Z", + "git_url": "git://github.com/wings-software/meet-git-sync-test.git", + "ssh_url": "git@github.com:wings-software/meet-git-sync-test.git", + "clone_url": "https://github.com/wings-software/meet-git-sync-test.git", + "svn_url": "https://github.com/wings-software/meet-git-sync-test", + "homepage": null, + "size": 171, + "stargazers_count": 0, + "watchers_count": 0, + "language": "Roff", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 23, + "license": null, + "allow_forking": false, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [ + + ], + "visibility": "private", + "forks": 0, + "open_issues": 23, + "watchers": 0, + "default_branch": "main", + "allow_squash_merge": true, + "allow_merge_commit": true, + "allow_rebase_merge": true, + "allow_auto_merge": false, + "delete_branch_on_merge": false, + "allow_update_branch": false, + "use_squash_pr_title_as_default": false, + "squash_merge_commit_message": "COMMIT_MESSAGES", + "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", + "merge_commit_message": "PR_TITLE", + "merge_commit_title": "MERGE_MESSAGE" + } + }, + "_links": { + "self": { + "href": "https://api.github.com/repos/wings-software/meet-git-sync-test/pulls/38" + }, + "html": { + "href": "https://github.com/wings-software/meet-git-sync-test/pull/38" + }, + "issue": { + "href": "https://api.github.com/repos/wings-software/meet-git-sync-test/issues/38" + }, + "comments": { + "href": "https://api.github.com/repos/wings-software/meet-git-sync-test/issues/38/comments" + }, + "review_comments": { + "href": "https://api.github.com/repos/wings-software/meet-git-sync-test/pulls/38/comments" + }, + "review_comment": { + "href": "https://api.github.com/repos/wings-software/meet-git-sync-test/pulls/comments{/number}" + }, + "commits": { + "href": "https://api.github.com/repos/wings-software/meet-git-sync-test/pulls/38/commits" + }, + "statuses": { + "href": "https://api.github.com/repos/wings-software/meet-git-sync-test/statuses/212015fb011c49a2913c4a1a860ce07c0821c362" + } + }, + "author_association": "COLLABORATOR", + "auto_merge": null, + "active_lock_reason": null, + "merged": false, + "mergeable": true, + "rebaseable": true, + "mergeable_state": "clean", + "merged_by": null, + "comments": 0, + "review_comments": 0, + "maintainer_can_modify": false, + "commits": 1, + "additions": 4, + "deletions": 1, + "changed_files": 1 + }, + "repository": { + "id": 498312568, + "node_id": "R_kgDOHbOleA", + "name": "meet-git-sync-test", + "full_name": "wings-software/meet-git-sync-test", + "private": true, + "owner": { + "login": "wings-software", + "id": 18273000, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjE4MjczMDAw", + "avatar_url": "https://avatars.githubusercontent.com/u/18273000?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/wings-software", + "html_url": "https://github.com/wings-software", + "followers_url": "https://api.github.com/users/wings-software/followers", + "following_url": "https://api.github.com/users/wings-software/following{/other_user}", + "gists_url": "https://api.github.com/users/wings-software/gists{/gist_id}", + "starred_url": "https://api.github.com/users/wings-software/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/wings-software/subscriptions", + "organizations_url": "https://api.github.com/users/wings-software/orgs", + "repos_url": "https://api.github.com/users/wings-software/repos", + "events_url": "https://api.github.com/users/wings-software/events{/privacy}", + "received_events_url": "https://api.github.com/users/wings-software/received_events", + "type": "Organization", + "site_admin": false + }, + "html_url": "https://github.com/wings-software/meet-git-sync-test", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/wings-software/meet-git-sync-test", + "forks_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/forks", + "keys_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/teams", + "hooks_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/hooks", + "issue_events_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/issues/events{/number}", + "events_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/events", + "assignees_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/assignees{/user}", + "branches_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/branches{/branch}", + "tags_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/tags", + "blobs_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/statuses/{sha}", + "languages_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/languages", + "stargazers_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/stargazers", + "contributors_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/contributors", + "subscribers_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/subscribers", + "subscription_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/subscription", + "commits_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/contents/{+path}", + "compare_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/merges", + "archive_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/downloads", + "issues_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/issues{/number}", + "pulls_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/pulls{/number}", + "milestones_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/milestones{/number}", + "notifications_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/labels{/name}", + "releases_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/releases{/id}", + "deployments_url": "https://api.github.com/repos/wings-software/meet-git-sync-test/deployments", + "created_at": "2022-05-31T11:47:10Z", + "updated_at": "2022-05-31T11:47:35Z", + "pushed_at": "2023-08-28T19:15:54Z", + "git_url": "git://github.com/wings-software/meet-git-sync-test.git", + "ssh_url": "git@github.com:wings-software/meet-git-sync-test.git", + "clone_url": "https://github.com/wings-software/meet-git-sync-test.git", + "svn_url": "https://github.com/wings-software/meet-git-sync-test", + "homepage": null, + "size": 171, + "stargazers_count": 0, + "watchers_count": 0, + "language": "Roff", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "has_discussions": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 23, + "license": null, + "allow_forking": false, + "is_template": false, + "web_commit_signoff_required": false, + "topics": [ + + ], + "visibility": "private", + "forks": 0, + "open_issues": 23, + "watchers": 0, + "default_branch": "main" + }, + "organization": { + "login": "wings-software", + "id": 18273000, + "node_id": "MDEyOk9yZ2FuaXphdGlvbjE4MjczMDAw", + "url": "https://api.github.com/orgs/wings-software", + "repos_url": "https://api.github.com/orgs/wings-software/repos", + "events_url": "https://api.github.com/orgs/wings-software/events", + "hooks_url": "https://api.github.com/orgs/wings-software/hooks", + "issues_url": "https://api.github.com/orgs/wings-software/issues", + "members_url": "https://api.github.com/orgs/wings-software/members{/member}", + "public_members_url": "https://api.github.com/orgs/wings-software/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/18273000?v=4", + "description": "" + }, + "enterprise": { + "id": 6657, + "slug": "harness", + "name": "Harness", + "node_id": "MDEwOkVudGVycHJpc2U2NjU3", + "avatar_url": "https://avatars.githubusercontent.com/b/6657?v=4", + "description": "", + "website_url": "https://harness.io", + "html_url": "https://github.com/enterprises/harness", + "created_at": "2021-04-13T17:56:36Z", + "updated_at": "2023-02-06T20:48:35Z" + }, + "sender": { + "login": "rathodmeetsatish", + "id": 84321134, + "node_id": "MDQ6VXNlcjg0MzIxMTM0", + "avatar_url": "https://avatars.githubusercontent.com/u/84321134?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/rathodmeetsatish", + "html_url": "https://github.com/rathodmeetsatish", + "followers_url": "https://api.github.com/users/rathodmeetsatish/followers", + "following_url": "https://api.github.com/users/rathodmeetsatish/following{/other_user}", + "gists_url": "https://api.github.com/users/rathodmeetsatish/gists{/gist_id}", + "starred_url": "https://api.github.com/users/rathodmeetsatish/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/rathodmeetsatish/subscriptions", + "organizations_url": "https://api.github.com/users/rathodmeetsatish/orgs", + "repos_url": "https://api.github.com/users/rathodmeetsatish/repos", + "events_url": "https://api.github.com/users/rathodmeetsatish/events{/privacy}", + "received_events_url": "https://api.github.com/users/rathodmeetsatish/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/scm/driver/github/testdata/webhooks/pr_ready_for_review.json.golden b/scm/driver/github/testdata/webhooks/pr_ready_for_review.json.golden new file mode 100644 index 000000000..97932e5ab --- /dev/null +++ b/scm/driver/github/testdata/webhooks/pr_ready_for_review.json.golden @@ -0,0 +1,55 @@ +{ + "Action": "ready_for_review", + "Repo": { + "ID": "498312568", + "Namespace": "wings-software", + "Name": "meet-git-sync-test", + "Perm": null, + "Branch": "main", + "Private": true, + "Visibility": 3, + "Clone": "https://github.com/wings-software/meet-git-sync-test.git", + "CloneSSH": "git@github.com:wings-software/meet-git-sync-test.git", + "Link": "https://github.com/wings-software/meet-git-sync-test", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 38, + "Title": "Update dgdggd.me", + "Body": null, + "Sha": "212015fb011c49a2913c4a1a860ce07c0821c362", + "Ref": "refs/pull/38/head", + "Target": "main", + "Source": "rathodmeetsatish-patch-25", + "Fork": "wings-software/meet-git-sync-test", + "Link": "https://github.com/wings-software/meet-git-sync-test/pull/38", + "Diff": "https://github.com/wings-software/meet-git-sync-test/pull/38.diff", + "Closed": null, + "Merged": null, + "Base": { + "Sha": "8b8d2b3e6a2ee6df108c8429e86c9a750e728f9d", + "Path": "refs/heads/main", + "Name": "main" + }, + "Head": { + "Sha": "212015fb011c49a2913c4a1a860ce07c0821c362", + "Path": "refs/heads/rathodmeetsatish-patch-25", + "Name": "rathodmeetsatish-patch-25" + }, + "Author": { + "Login": "rathodmeetsatish", + "Name": "", + "Email": "", + "Avatar": "https://avatars.githubusercontent.com/u/84321134?v=4" + }, + "Created": "2023-08-28T19:15:53Z", + "Updated": "2023-08-28T19:16:06Z" + }, + "Sender": { + "Login": "rathodmeetsatish", + "Name": "", + "Email": "", + "Avatar": "https://avatars.githubusercontent.com/u/84321134?v=4" + } +} diff --git a/scm/driver/github/webhook.go b/scm/driver/github/webhook.go index 57d3ed9ed..9d75d5303 100644 --- a/scm/driver/github/webhook.go +++ b/scm/driver/github/webhook.go @@ -172,7 +172,9 @@ func (s *webhookService) parsePullRequestHook(data []byte) (scm.Webhook, error) dst.Action = scm.ActionReopen case "synchronize": dst.Action = scm.ActionSync - case "assigned", "unassigned", "review_requested", "review_request_removed", "ready_for_review", "locked", "unlocked": + case "ready_for_review": + dst.Action = scm.ActionReadyForReview + case "assigned", "unassigned", "review_requested", "review_request_removed", "locked", "unlocked": dst.Action = scm.ActionUnknown default: dst.Action = scm.ActionUnknown @@ -186,7 +188,7 @@ func (s *webhookService) parseReleaseHook(data []byte) (scm.Webhook, error) { if err != nil { return nil, err } - dst := convertReleaseHook(src) + dst := convertReleaseHook(src) switch src.Action { case "created": dst.Action = scm.ActionCreate @@ -332,24 +334,24 @@ type ( } `json:"comment"` } - // github release webhook payload + // github release webhook payload releaseHook struct { - Action string `json:"action"` - Release struct { - ID int `json:"id"` - Title string `json:"name"` - Description string `json:"body"` - Link string `json:"html_url,omitempty"` - Tag string `json:"tag_name,omitempty"` - Commitish string `json:"target_commitish,omitempty"` - Draft bool `json:"draft"` - Prerelease bool `json:"prerelease"` - Created time.Time `json:"created_at"` - Published time.Time `json:"published_at"` - } `json:"release"` - Repository repository `json:"repository"` - Sender user `json:"sender"` - } + Action string `json:"action"` + Release struct { + ID int `json:"id"` + Title string `json:"name"` + Description string `json:"body"` + Link string `json:"html_url,omitempty"` + Tag string `json:"tag_name,omitempty"` + Commitish string `json:"target_commitish,omitempty"` + Draft bool `json:"draft"` + Prerelease bool `json:"prerelease"` + Created time.Time `json:"created_at"` + Published time.Time `json:"published_at"` + } `json:"release"` + Repository repository `json:"repository"` + Sender user `json:"sender"` + } ) // @@ -551,18 +553,18 @@ func convertIssueCommentHook(src *issueCommentHook) *scm.IssueCommentHook { func convertReleaseHook(src *releaseHook) *scm.ReleaseHook { dst := &scm.ReleaseHook{ - Release: scm.Release{ - ID: src.Release.ID, - Title: src.Release.Title, - Description: src.Release.Description, - Link: src.Release.Link, - Tag: src.Release.Tag, - Commitish: src.Release.Commitish, - Draft: src.Release.Draft, - Prerelease: src.Release.Prerelease, - Created: src.Release.Created, - Published: src.Release.Published, - }, + Release: scm.Release{ + ID: src.Release.ID, + Title: src.Release.Title, + Description: src.Release.Description, + Link: src.Release.Link, + Tag: src.Release.Tag, + Commitish: src.Release.Commitish, + Draft: src.Release.Draft, + Prerelease: src.Release.Prerelease, + Created: src.Release.Created, + Published: src.Release.Published, + }, Repo: scm.Repository{ ID: fmt.Sprint(src.Repository.ID), Namespace: src.Repository.Owner.Login, diff --git a/scm/driver/github/webhook_test.go b/scm/driver/github/webhook_test.go index 7d3621c94..f7c63c3fd 100644 --- a/scm/driver/github/webhook_test.go +++ b/scm/driver/github/webhook_test.go @@ -28,7 +28,6 @@ func TestWebhooks(t *testing.T) { // // push events // - // push hooks { event: "push", @@ -126,6 +125,13 @@ func TestWebhooks(t *testing.T) { after: "testdata/webhooks/pr_sync.json.golden", obj: new(scm.PullRequestHook), }, + // pull request ready for review + { + event: "pull_request", + before: "testdata/webhooks/pr_ready_for_review.json", + after: "testdata/webhooks/pr_ready_for_review.json.golden", + obj: new(scm.PullRequestHook), + }, // pull request opened { event: "pull_request", @@ -185,9 +191,9 @@ func TestWebhooks(t *testing.T) { after: "testdata/webhooks/deployment_commit.json.golden", obj: new(scm.DeployHook), }, - // - // release - // + // + // release + // { event: "release", before: "testdata/webhooks/release_published.json", @@ -195,40 +201,40 @@ func TestWebhooks(t *testing.T) { obj: new(scm.ReleaseHook), }, { - event: "release", - before: "testdata/webhooks/release_unpublished.json", - after: "testdata/webhooks/release_unpublished.json.golden", - obj: new(scm.ReleaseHook), + event: "release", + before: "testdata/webhooks/release_unpublished.json", + after: "testdata/webhooks/release_unpublished.json.golden", + obj: new(scm.ReleaseHook), }, { - event: "release", - before: "testdata/webhooks/release_created.json", - after: "testdata/webhooks/release_created.json.golden", - obj: new(scm.ReleaseHook), + event: "release", + before: "testdata/webhooks/release_created.json", + after: "testdata/webhooks/release_created.json.golden", + obj: new(scm.ReleaseHook), }, { - event: "release", - before: "testdata/webhooks/release_edited.json", - after: "testdata/webhooks/release_edited.json.golden", - obj: new(scm.ReleaseHook), + event: "release", + before: "testdata/webhooks/release_edited.json", + after: "testdata/webhooks/release_edited.json.golden", + obj: new(scm.ReleaseHook), }, { - event: "release", - before: "testdata/webhooks/release_deleted.json", - after: "testdata/webhooks/release_deleted.json.golden", - obj: new(scm.ReleaseHook), + event: "release", + before: "testdata/webhooks/release_deleted.json", + after: "testdata/webhooks/release_deleted.json.golden", + obj: new(scm.ReleaseHook), }, { - event: "release", - before: "testdata/webhooks/release_prereleased.json", - after: "testdata/webhooks/release_prereleased.json.golden", - obj: new(scm.ReleaseHook), + event: "release", + before: "testdata/webhooks/release_prereleased.json", + after: "testdata/webhooks/release_prereleased.json.golden", + obj: new(scm.ReleaseHook), }, { - event: "release", - before: "testdata/webhooks/release_released.json", - after: "testdata/webhooks/release_released.json.golden", - obj: new(scm.ReleaseHook), + event: "release", + before: "testdata/webhooks/release_released.json", + after: "testdata/webhooks/release_released.json.golden", + obj: new(scm.ReleaseHook), }, } From b2bdb6d01452290e4b1a3ea9d37d213c36a261d0 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Wed, 30 Aug 2023 10:45:42 -0700 Subject: [PATCH 182/282] fix: [CODE-727]: change to gitness from harness --- scm/driver/harness/webhook.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/scm/driver/harness/webhook.go b/scm/driver/harness/webhook.go index 514ddaafa..bb7a75a79 100644 --- a/scm/driver/harness/webhook.go +++ b/scm/driver/harness/webhook.go @@ -7,7 +7,6 @@ package harness import ( "crypto/sha256" "encoding/json" - "fmt" "io" "io/ioutil" "net/http" @@ -192,8 +191,8 @@ func convertPullRequestHook(dst *pullRequestHook) *scm.PullRequestHook { Number: dst.PullReq.Number, Title: dst.PullReq.Title, Closed: dst.PullReq.State != "open", - Source: fmt.Sprintf("%d", dst.PullReq.SourceRepoID), - Target: fmt.Sprintf("%d", dst.PullReq.TargetRepoID), + Source: dst.PullReq.SourceBranch, + Target: dst.PullReq.TargetBranch, Fork: "fork", Link: dst.Ref.Repo.GitURL, Sha: dst.Commit.Sha, From c91f42489e53ac72791fd82d460aeef4d142b0dc Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Wed, 30 Aug 2023 10:46:49 -0700 Subject: [PATCH 183/282] fix: [CODE-727]: change to gitness from harness --- scm/driver/harness/webhook_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/driver/harness/webhook_test.go b/scm/driver/harness/webhook_test.go index 48f66daeb..4e38687be 100644 --- a/scm/driver/harness/webhook_test.go +++ b/scm/driver/harness/webhook_test.go @@ -73,7 +73,7 @@ func TestWebhooks(t *testing.T) { buf := bytes.NewBuffer(before) r, _ := http.NewRequest("GET", "/", buf) - r.Header.Set("X-Gitness-Trigger", test.event) + r.Header.Set("X-Harness-Trigger", test.event) s := new(webhookService) o, err := s.Parse(r, secretFunc) From 8d6a8e37135477a664e0912022979b5704c0f6c3 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Wed, 30 Aug 2023 10:47:52 -0700 Subject: [PATCH 184/282] fix: [CODE-727]: change to gitness from harness --- scm/driver/harness/webhook.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scm/driver/harness/webhook.go b/scm/driver/harness/webhook.go index bb7a75a79..1aa2d45fb 100644 --- a/scm/driver/harness/webhook.go +++ b/scm/driver/harness/webhook.go @@ -28,7 +28,7 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo } var hook scm.Webhook - switch req.Header.Get("X-Gitness-Trigger") { + switch req.Header.Get("X-Harness-Trigger") { // case "create": // hook, err = s.parseCreateHook(data) // case "delete": @@ -57,7 +57,7 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo } secret := req.FormValue("secret") - signature := req.Header.Get("X-Gitness-Signature") + signature := req.Header.Get("X-Harness-Signature") // fail if no signature passed if signature == "" && secret == "" { From 13e99fa40ec1514ef0467ea3851a233af0c55a22 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Wed, 30 Aug 2023 10:54:09 -0700 Subject: [PATCH 185/282] fix: [CODE-727]: change to gitness from harness --- .../testdata/webhooks/pull_request_branch_updated.json.golden | 4 ++-- .../harness/testdata/webhooks/pull_request_opened.json.golden | 4 ++-- .../testdata/webhooks/pull_request_reopened.json.golden | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden index d978a3b13..9a768dde2 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden +++ b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden @@ -18,8 +18,8 @@ "Body": "", "Sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef", "Ref": "", - "Source": "13", - "Target": "13", + "Source": "b", + "Target": "main", "Fork": "fork", "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", "Closed": false, diff --git a/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden index 936a53c7a..e45f24bc5 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden +++ b/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden @@ -18,8 +18,8 @@ "Body": "", "Sha": "d74b1ebfe520ac01b209dd9085f005884cc9f4cd", "Ref": "", - "Source": "13", - "Target": "13", + "Source": "b", + "Target": "main", "Fork": "fork", "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", "Closed": false, diff --git a/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden index 17b0f8657..bbea80558 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden +++ b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden @@ -18,8 +18,8 @@ "Body": "", "Sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef", "Ref": "", - "Source": "13", - "Target": "13", + "Source": "b", + "Target": "main", "Fork": "fork", "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", "Closed": false, From 84d449ac1a67a5028ea2fa32bc66c7e5c1ab2a7f Mon Sep 17 00:00:00 2001 From: Meet Rathod Date: Fri, 8 Sep 2023 01:40:14 +0530 Subject: [PATCH 186/282] Add review ready action for gitlab --- scm/const.go | 10 +- .../webhooks/pr_ready_for_review.json.golden | 2 +- scm/driver/github/webhook.go | 2 +- .../webhooks/pull_request_review_ready.json | 154 ++++++++++++++++++ .../pull_request_review_ready.json.golden | 43 +++++ scm/driver/gitlab/webhook.go | 7 + scm/driver/gitlab/webhook_test.go | 6 + 7 files changed, 217 insertions(+), 7 deletions(-) create mode 100644 scm/driver/gitlab/testdata/webhooks/pull_request_review_ready.json create mode 100644 scm/driver/gitlab/testdata/webhooks/pull_request_review_ready.json.golden diff --git a/scm/const.go b/scm/const.go index b55729dd1..73fa7a9e6 100644 --- a/scm/const.go +++ b/scm/const.go @@ -40,7 +40,7 @@ const ( // pull requests ActionSync ActionMerge - ActionReadyForReview + ActionReviewReady // issue comment ActionEdit // release @@ -81,8 +81,8 @@ func (a Action) String() (s string) { return "prereleased" case ActionRelease: return "released" - case ActionReadyForReview: - return "ready_for_review" + case ActionReviewReady: + return "review_ready" default: return } @@ -130,8 +130,8 @@ func (a *Action) UnmarshalJSON(data []byte) error { *a = ActionPrerelease case "released": *a = ActionRelease - case "ready_for_review": - *a = ActionReadyForReview + case "review_ready": + *a = ActionReviewReady } return nil } diff --git a/scm/driver/github/testdata/webhooks/pr_ready_for_review.json.golden b/scm/driver/github/testdata/webhooks/pr_ready_for_review.json.golden index 97932e5ab..653a28b1e 100644 --- a/scm/driver/github/testdata/webhooks/pr_ready_for_review.json.golden +++ b/scm/driver/github/testdata/webhooks/pr_ready_for_review.json.golden @@ -1,5 +1,5 @@ { - "Action": "ready_for_review", + "Action": "review_ready", "Repo": { "ID": "498312568", "Namespace": "wings-software", diff --git a/scm/driver/github/webhook.go b/scm/driver/github/webhook.go index 9d75d5303..6c01a711d 100644 --- a/scm/driver/github/webhook.go +++ b/scm/driver/github/webhook.go @@ -173,7 +173,7 @@ func (s *webhookService) parsePullRequestHook(data []byte) (scm.Webhook, error) case "synchronize": dst.Action = scm.ActionSync case "ready_for_review": - dst.Action = scm.ActionReadyForReview + dst.Action = scm.ActionReviewReady case "assigned", "unassigned", "review_requested", "review_request_removed", "locked", "unlocked": dst.Action = scm.ActionUnknown default: diff --git a/scm/driver/gitlab/testdata/webhooks/pull_request_review_ready.json b/scm/driver/gitlab/testdata/webhooks/pull_request_review_ready.json new file mode 100644 index 000000000..5a25b03ef --- /dev/null +++ b/scm/driver/gitlab/testdata/webhooks/pull_request_review_ready.json @@ -0,0 +1,154 @@ +{ + "object_kind": "merge_request", + "event_type": "merge_request", + "user": { + "id": 13900456, + "name": "Meet Rathod", + "username": "rathod.meetsatish", + "avatar_url": "https://secure.gravatar.com/avatar/0e68aaeb6c49dd6ba280370c96280803?s=80&d=identicon", + "email": "[REDACTED]" + }, + "project": { + "id": 44067058, + "name": "meet", + "description": null, + "web_url": "https://gitlab.com/rathod.meetsatish/meet", + "avatar_url": null, + "git_ssh_url": "git@gitlab.com:rathod.meetsatish/meet.git", + "git_http_url": "https://gitlab.com/rathod.meetsatish/meet.git", + "namespace": "Meet Rathod", + "visibility_level": 0, + "path_with_namespace": "rathod.meetsatish/meet", + "default_branch": "main", + "ci_config_path": "", + "homepage": "https://gitlab.com/rathod.meetsatish/meet", + "url": "git@gitlab.com:rathod.meetsatish/meet.git", + "ssh_url": "git@gitlab.com:rathod.meetsatish/meet.git", + "http_url": "https://gitlab.com/rathod.meetsatish/meet.git" + }, + "object_attributes": { + "assignee_id": null, + "author_id": 13900456, + "created_at": "2023-09-07 19:42:34 UTC", + "description": "", + "draft": true, + "head_pipeline_id": null, + "id": 248466002, + "iid": 3, + "last_edited_at": null, + "last_edited_by_id": null, + "merge_commit_sha": null, + "merge_error": null, + "merge_params": { + "force_remove_source_branch": "1" + }, + "merge_status": "can_be_merged", + "merge_user_id": null, + "merge_when_pipeline_succeeds": false, + "milestone_id": null, + "source_branch": "main1234", + "source_project_id": 44067058, + "state_id": 1, + "target_branch": "main", + "target_project_id": 44067058, + "time_estimate": 0, + "title": "Draft: Update README.md", + "updated_at": "2023-09-07 19:42:45 UTC", + "updated_by_id": 13900456, + "url": "https://gitlab.com/rathod.meetsatish/meet/-/merge_requests/3", + "source": { + "id": 44067058, + "name": "meet", + "description": null, + "web_url": "https://gitlab.com/rathod.meetsatish/meet", + "avatar_url": null, + "git_ssh_url": "git@gitlab.com:rathod.meetsatish/meet.git", + "git_http_url": "https://gitlab.com/rathod.meetsatish/meet.git", + "namespace": "Meet Rathod", + "visibility_level": 0, + "path_with_namespace": "rathod.meetsatish/meet", + "default_branch": "main", + "ci_config_path": "", + "homepage": "https://gitlab.com/rathod.meetsatish/meet", + "url": "git@gitlab.com:rathod.meetsatish/meet.git", + "ssh_url": "git@gitlab.com:rathod.meetsatish/meet.git", + "http_url": "https://gitlab.com/rathod.meetsatish/meet.git" + }, + "target": { + "id": 44067058, + "name": "meet", + "description": null, + "web_url": "https://gitlab.com/rathod.meetsatish/meet", + "avatar_url": null, + "git_ssh_url": "git@gitlab.com:rathod.meetsatish/meet.git", + "git_http_url": "https://gitlab.com/rathod.meetsatish/meet.git", + "namespace": "Meet Rathod", + "visibility_level": 0, + "path_with_namespace": "rathod.meetsatish/meet", + "default_branch": "main", + "ci_config_path": "", + "homepage": "https://gitlab.com/rathod.meetsatish/meet", + "url": "git@gitlab.com:rathod.meetsatish/meet.git", + "ssh_url": "git@gitlab.com:rathod.meetsatish/meet.git", + "http_url": "https://gitlab.com/rathod.meetsatish/meet.git" + }, + "last_commit": { + "id": "ffd71529ecdfb41a530ee13f91b8fdd3e743c754", + "message": "Update README.md", + "title": "Update README.md", + "timestamp": "2023-09-07T19:42:21+00:00", + "url": "https://gitlab.com/rathod.meetsatish/meet/-/commit/ffd71529ecdfb41a530ee13f91b8fdd3e743c754", + "author": { + "name": "Meet Rathod", + "email": "[REDACTED]" + } + }, + "work_in_progress": true, + "total_time_spent": 0, + "time_change": 0, + "human_total_time_spent": null, + "human_time_change": null, + "human_time_estimate": null, + "assignee_ids": [ + + ], + "reviewer_ids": [ + + ], + "labels": [ + + ], + "state": "opened", + "blocking_discussions_resolved": true, + "first_contribution": true, + "detailed_merge_status": "draft_status", + "action": "update" + }, + "labels": [ + + ], + "changes": { + "draft": { + "previous": false, + "current": true + }, + "title": { + "previous": "Update README.md", + "current": "Draft: Update README.md" + }, + "updated_at": { + "previous": "2023-09-07 19:42:35 UTC", + "current": "2023-09-07 19:42:45 UTC" + }, + "updated_by_id": { + "previous": null, + "current": 13900456 + } + }, + "repository": { + "name": "meet", + "url": "git@gitlab.com:rathod.meetsatish/meet.git", + "description": null, + "homepage": "https://gitlab.com/rathod.meetsatish/meet" + } +} diff --git a/scm/driver/gitlab/testdata/webhooks/pull_request_review_ready.json.golden b/scm/driver/gitlab/testdata/webhooks/pull_request_review_ready.json.golden new file mode 100644 index 000000000..c75213032 --- /dev/null +++ b/scm/driver/gitlab/testdata/webhooks/pull_request_review_ready.json.golden @@ -0,0 +1,43 @@ +{ + "Action": "review_ready", + "Repo": { + "ID": "44067058", + "Namespace": "rathod.meetsatish", + "Name": "meet", + "Perm": null, + "Branch": "main", + "Private": false, + "Clone": "https://gitlab.com/rathod.meetsatish/meet.git", + "CloneSSH": "git@gitlab.com:rathod.meetsatish/meet.git", + "Link": "https://gitlab.com/rathod.meetsatish/meet", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 3, + "Title": "Draft: Update README.md", + "Body": "", + "Sha": "ffd71529ecdfb41a530ee13f91b8fdd3e743c754", + "Ref": "refs/merge-requests/3/head", + "Source": "main1234", + "Target": "main", + "Fork": "Meet Rathod/meet", + "Link": "https://gitlab.com/rathod.meetsatish/meet/-/merge_requests/3", + "Closed": false, + "Merged": false, + "Author": { + "Login": "rathod.meetsatish", + "Name": "Meet Rathod", + "Email": "", + "Avatar": "https://secure.gravatar.com/avatar/0e68aaeb6c49dd6ba280370c96280803?s=80&d=identicon" + }, + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Sender": { + "Login": "rathod.meetsatish", + "Name": "Meet Rathod", + "Email": "", + "Avatar": "https://secure.gravatar.com/avatar/0e68aaeb6c49dd6ba280370c96280803?s=80&d=identicon" + } +} diff --git a/scm/driver/gitlab/webhook.go b/scm/driver/gitlab/webhook.go index 56da8f195..3bd8d3008 100644 --- a/scm/driver/gitlab/webhook.go +++ b/scm/driver/gitlab/webhook.go @@ -338,6 +338,9 @@ func convertPullRequestHook(src *pullRequestHook) *scm.PullRequestHook { action = scm.ActionMerge case "update": action = scm.ActionSync + if src.Changes.Draft.Previous.Bool == false { + action = scm.ActionReviewReady + } } fork := scm.Join( src.ObjectAttributes.Source.Namespace, @@ -860,6 +863,10 @@ type ( } `json:"object_attributes"` Labels []interface{} `json:"labels"` Changes struct { + Draft struct { + Previous null.Bool `json:"previous"` + Current null.Bool `json:"current"` + } `json:"draft"` } `json:"changes"` Repository struct { Name string `json:"name"` diff --git a/scm/driver/gitlab/webhook_test.go b/scm/driver/gitlab/webhook_test.go index 1eb6cf527..e766cada4 100644 --- a/scm/driver/gitlab/webhook_test.go +++ b/scm/driver/gitlab/webhook_test.go @@ -97,6 +97,12 @@ func TestWebhooks(t *testing.T) { after: "testdata/webhooks/pull_request_close.json.golden", obj: new(scm.PullRequestHook), }, + { + event: "Merge Request Hook", + before: "testdata/webhooks/pull_request_review_ready.json", + after: "testdata/webhooks/pull_request_review_ready.json.golden", + obj: new(scm.PullRequestHook), + }, { event: "Merge Request Hook", before: "testdata/webhooks/pull_request_reopen.json", From 2d64e5c57c97172a34b674f78fe64a73ffc112fc Mon Sep 17 00:00:00 2001 From: Meet Rathod Date: Tue, 12 Sep 2023 00:36:26 +0530 Subject: [PATCH 187/282] address comments --- scm/driver/gitlab/webhook.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/driver/gitlab/webhook.go b/scm/driver/gitlab/webhook.go index 3bd8d3008..2cc785fb7 100644 --- a/scm/driver/gitlab/webhook.go +++ b/scm/driver/gitlab/webhook.go @@ -338,7 +338,7 @@ func convertPullRequestHook(src *pullRequestHook) *scm.PullRequestHook { action = scm.ActionMerge case "update": action = scm.ActionSync - if src.Changes.Draft.Previous.Bool == false { + if src.Changes.Draft.Previous.Bool == false && src.Changes.Draft.Current.Bool == true { action = scm.ActionReviewReady } } From e0123f7f716d66b83a7c8c78fc8d94286b6ad16e Mon Sep 17 00:00:00 2001 From: dependabot-ci Date: Tue, 12 Sep 2023 11:00:37 +0100 Subject: [PATCH 188/282] (maint) release prep for 1.32.0 --- CHANGELOG.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5019f454..60338158a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog +## [v1.32.0](https://github.com/drone/go-scm/tree/v1.32.0) (2023-09-12) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.31.2...v1.32.0) + +**Implemented enhancements:** + +- \[feat\]: \[CDS-75848\]: Add new action type for github provider [\#270](https://github.com/drone/go-scm/pull/270) ([rathodmeetsatish](https://github.com/rathodmeetsatish)) + +## [v1.31.2](https://github.com/drone/go-scm/tree/v1.31.2) (2023-08-31) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.31.1...v1.31.2) + +**Fixed bugs:** + +- fix: \[CODE-727\]: change branch in source and target for harness provider [\#264](https://github.com/drone/go-scm/pull/264) ([abhinav-harness](https://github.com/abhinav-harness)) + +## [v1.31.1](https://github.com/drone/go-scm/tree/v1.31.1) (2023-08-29) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.31.0...v1.31.1) + +**Fixed bugs:** + +- Fix diff api response conversion for harness compareChange [\#269](https://github.com/drone/go-scm/pull/269) ([shubham149](https://github.com/shubham149)) +- Fix api name for fetching diff in harness driver [\#268](https://github.com/drone/go-scm/pull/268) ([shubham149](https://github.com/shubham149)) +- Fix compare change api result for harness [\#267](https://github.com/drone/go-scm/pull/267) ([shubham149](https://github.com/shubham149)) + ## [v1.31.0](https://github.com/drone/go-scm/tree/v1.31.0) (2023-08-15) [Full Changelog](https://github.com/drone/go-scm/compare/v1.30.0...v1.31.0) @@ -13,6 +39,10 @@ - \(missing feature\) add support to check organization membership in gitea driver [\#262](https://github.com/drone/go-scm/issues/262) +**Merged pull requests:** + +- \(maint\) v1.31.0 release prep [\#266](https://github.com/drone/go-scm/pull/266) ([tphoney](https://github.com/tphoney)) + ## [v1.30.0](https://github.com/drone/go-scm/tree/v1.30.0) (2023-07-19) [Full Changelog](https://github.com/drone/go-scm/compare/v1.29.1...v1.30.0) From 13e5d45573afc53c47d0169cc4d40413aafd4fc7 Mon Sep 17 00:00:00 2001 From: dependabot-ci Date: Tue, 12 Sep 2023 11:18:26 +0100 Subject: [PATCH 189/282] (maint) clean integration testing for stash --- scm/driver/stash/integration/content_test.go | 4 ++-- scm/driver/stash/integration/git_test.go | 16 ++++++++-------- scm/driver/stash/integration/integration.go | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/scm/driver/stash/integration/content_test.go b/scm/driver/stash/integration/content_test.go index a65b1b838..d6a22bbcb 100644 --- a/scm/driver/stash/integration/content_test.go +++ b/scm/driver/stash/integration/content_test.go @@ -11,8 +11,8 @@ import ( ) func TestCreateUpdateDeleteFileStash(t *testing.T) { - if token == "" { - t.Skip("Skipping, Acceptance test") + if token == "" || username == "" { + t.Skip("Skipping, Acceptance test. Missing BITBUCKET_SERVER_TOKEN or BITBUCKET_USERNAME") } client, _ = stash.New(endpoint) client.Client = &http.Client{ diff --git a/scm/driver/stash/integration/git_test.go b/scm/driver/stash/integration/git_test.go index 6ef33fee7..d1607f8de 100644 --- a/scm/driver/stash/integration/git_test.go +++ b/scm/driver/stash/integration/git_test.go @@ -11,8 +11,8 @@ import ( ) func TestCreateBranch(t *testing.T) { - if token == "" { - t.Skip("Skipping, Acceptance test") + if token == "" || username == "" { + t.Skip("Skipping, Acceptance test. Missing BITBUCKET_SERVER_TOKEN or BITBUCKET_USERNAME") } client, _ = stash.New(endpoint) client.Client = &http.Client{ @@ -37,8 +37,8 @@ func TestCreateBranch(t *testing.T) { } func TestGetLatestCommitOfBranch(t *testing.T) { - if token == "" { - t.Skip("Skipping, Acceptance test") + if token == "" || username == "" { + t.Skip("Skipping, Acceptance test. Missing BITBUCKET_SERVER_TOKEN or BITBUCKET_USERNAME") } client, _ = stash.New(endpoint) client.Client = &http.Client{ @@ -64,8 +64,8 @@ func TestGetLatestCommitOfBranch(t *testing.T) { } func TestGetLatestCommitOfNonDefaultBranch(t *testing.T) { - if token == "" { - t.Skip("Skipping, Acceptance test") + if token == "" || username == "" { + t.Skip("Skipping, Acceptance test. Missing BITBUCKET_SERVER_TOKEN or BITBUCKET_USERNAME") } client, _ = stash.New(endpoint) client.Client = &http.Client{ @@ -91,8 +91,8 @@ func TestGetLatestCommitOfNonDefaultBranch(t *testing.T) { } func TestGetLatestCommitOfBranchWhenNoRefPassed(t *testing.T) { - if token == "" { - t.Skip("Skipping, Acceptance test") + if token == "" || username == "" { + t.Skip("Skipping, Acceptance test. Missing BITBUCKET_SERVER_TOKEN or BITBUCKET_USERNAME") } client, _ = stash.New(endpoint) client.Client = &http.Client{ diff --git a/scm/driver/stash/integration/integration.go b/scm/driver/stash/integration/integration.go index 7a3dfce71..56cae697d 100644 --- a/scm/driver/stash/integration/integration.go +++ b/scm/driver/stash/integration/integration.go @@ -13,7 +13,7 @@ var ( endpoint = "https://bitbucket.dev.harness.io/" repoID = "har/scm-integration-test-repo" - username = "harnessadmin" + username = os.Getenv("BITBUCKET_USERNAME") ) func GetCurrentCommitOfBranch(client *scm.Client, branch string) (string, error) { From 3ce608d262be0d22d6a7f45f7993cf5eabc54e32 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Wed, 27 Sep 2023 02:59:06 -0700 Subject: [PATCH 190/282] fix: Gitness get content missing query param --- scm/driver/harness/content.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scm/driver/harness/content.go b/scm/driver/harness/content.go index 7eac5b990..a5a0848d3 100644 --- a/scm/driver/harness/content.go +++ b/scm/driver/harness/content.go @@ -19,7 +19,7 @@ type contentService struct { func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm.Content, *scm.Response, error) { repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - endpoint := fmt.Sprintf("api/v1/repos/%s/content/%s?%s&include_commit=true", repo, path, ref) + endpoint := fmt.Sprintf("api/v1/repos/%s/content/%s?git_ref=%s&include_commit=true", repo, path, ref) out := new(fileContent) res, err := s.client.do(ctx, "GET", endpoint, nil, out) // decode raw output content @@ -94,7 +94,7 @@ func (s *contentService) Delete(ctx context.Context, repo, path string, params * func (s *contentService) List(ctx context.Context, repo, path, ref string, _ scm.ListOptions) ([]*scm.ContentInfo, *scm.Response, error) { repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - endpoint := fmt.Sprintf("api/v1/repos/%s/content/%s?%s&include_commit=true", repo, path, ref) + endpoint := fmt.Sprintf("api/v1/repos/%s/content/%s?git_ref=%s&include_commit=true", repo, path, ref) out := new(contentList) res, err := s.client.do(ctx, "GET", endpoint, nil, &out) return convertContentInfoList(out.Content.Entries), res, err From b66c7e14982b832e9392f8b09aa23bcbad0ee0c0 Mon Sep 17 00:00:00 2001 From: dependabot-ci Date: Wed, 27 Sep 2023 11:16:22 +0100 Subject: [PATCH 191/282] (maint) prep for 1.32.1 --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60338158a..192ce1fe7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [v1.32.1](https://github.com/drone/go-scm/tree/v1.32.1) (2023-09-27) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.32.0...v1.32.1) + +**Fixed bugs:** + +- fix: Gitness get content missing query param [\#275](https://github.com/drone/go-scm/pull/275) ([abhinav-harness](https://github.com/abhinav-harness)) + +**Merged pull requests:** + +- \(maint\) clean integration testing for stash [\#273](https://github.com/drone/go-scm/pull/273) ([tphoney](https://github.com/tphoney)) + ## [v1.32.0](https://github.com/drone/go-scm/tree/v1.32.0) (2023-09-12) [Full Changelog](https://github.com/drone/go-scm/compare/v1.31.2...v1.32.0) @@ -8,6 +20,10 @@ - \[feat\]: \[CDS-75848\]: Add new action type for github provider [\#270](https://github.com/drone/go-scm/pull/270) ([rathodmeetsatish](https://github.com/rathodmeetsatish)) +**Merged pull requests:** + +- \(maint\) release prep for 1.32.0 [\#272](https://github.com/drone/go-scm/pull/272) ([tphoney](https://github.com/tphoney)) + ## [v1.31.2](https://github.com/drone/go-scm/tree/v1.31.2) (2023-08-31) [Full Changelog](https://github.com/drone/go-scm/compare/v1.31.1...v1.31.2) From 3b21a0f7851a60a9103bcc6d489d6dbf28fce48f Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Tue, 3 Oct 2023 03:20:00 -0700 Subject: [PATCH 192/282] fix: Harness list commits api update as per new spec (#277) --- scm/driver/harness/git.go | 14 ++++++--- scm/driver/harness/testdata/commits.json | 40 +++++++++++++----------- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/scm/driver/harness/git.go b/scm/driver/harness/git.go index 309a125f7..85b17bff1 100644 --- a/scm/driver/harness/git.go +++ b/scm/driver/harness/git.go @@ -63,7 +63,7 @@ func (s *gitService) ListBranchesV2(ctx context.Context, repo string, opts scm.B func (s *gitService) ListCommits(ctx context.Context, repo string, _ scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) path := fmt.Sprintf("api/v1/repos/%s/commits", harnessURI) - out := []*commitInfo{} + out := new(commits) res, err := s.client.do(ctx, "GET", path, nil, &out) return convertCommitList(out), res, err } @@ -86,6 +86,10 @@ func (s *gitService) CompareChanges(ctx context.Context, repo, source, target st // native data structures type ( + commits struct { + Commits []commitInfo `json:"commits"` + } + commitInfo struct { Author struct { Identity struct { @@ -168,10 +172,10 @@ func convertBranch(src *branch) *scm.Reference { } } -func convertCommitList(src []*commitInfo) []*scm.Commit { - dst := []*scm.Commit{} - for _, v := range src { - dst = append(dst, convertCommitInfo(v)) +func convertCommitList(src *commits) []*scm.Commit { + var dst []*scm.Commit + for _, v := range src.Commits { + dst = append(dst, convertCommitInfo(&v)) } return dst } diff --git a/scm/driver/harness/testdata/commits.json b/scm/driver/harness/testdata/commits.json index 96576e18f..4045985d6 100644 --- a/scm/driver/harness/testdata/commits.json +++ b/scm/driver/harness/testdata/commits.json @@ -1,21 +1,23 @@ -[ - { - "sha": "1d640265d8bdd818175fa736f0fcbad2c9b716c9", - "title": "delete README.2", - "message": "delete README.2\n\ndelete README.2", - "author": { - "identity": { - "name": "thomas.honey", - "email": "thomas.honey@harness.io" +{ + "commits": [ + { + "sha": "1d640265d8bdd818175fa736f0fcbad2c9b716c9", + "title": "delete README.2", + "message": "delete README.2\n\ndelete README.2", + "author": { + "identity": { + "name": "thomas.honey", + "email": "thomas.honey@harness.io" + }, + "when": "2023-02-08T16:17:50Z" }, - "when": "2023-02-08T16:17:50Z" - }, - "committer": { - "identity": { - "name": "Harness", - "email": "noreply@harness.io" - }, - "when": "2023-02-08T16:17:50Z" + "committer": { + "identity": { + "name": "Harness", + "email": "noreply@harness.io" + }, + "when": "2023-02-08T16:17:50Z" + } } - } -] \ No newline at end of file + ] +} \ No newline at end of file From 166ac922322037bbc30492ebe5c639a492e52759 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Wed, 11 Oct 2023 03:24:49 -0700 Subject: [PATCH 193/282] fix: ref should have pullreq instead of pull for gitness (#278) --- scm/driver/harness/pr.go | 2 +- scm/driver/harness/testdata/pr.json.golden | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scm/driver/harness/pr.go b/scm/driver/harness/pr.go index 6e0266a0d..9b5e05724 100644 --- a/scm/driver/harness/pr.go +++ b/scm/driver/harness/pr.go @@ -182,7 +182,7 @@ func convertPullRequest(src *pr) *scm.PullRequest { Email: src.Author.Email, }, Fork: "fork", - Ref: fmt.Sprintf("refs/pull/%d/head", src.Number), + Ref: fmt.Sprintf("refs/pullreq/%d/head", src.Number), Closed: src.State == "closed", } } diff --git a/scm/driver/harness/testdata/pr.json.golden b/scm/driver/harness/testdata/pr.json.golden index 224b66050..5c4a83864 100644 --- a/scm/driver/harness/testdata/pr.json.golden +++ b/scm/driver/harness/testdata/pr.json.golden @@ -3,7 +3,7 @@ "Title": "pull title", "Body": "pull description", "Sha": "", - "Ref": "refs/pull/1/head", + "Ref": "refs/pullreq/1/head", "Source": "bla", "Target": "main", "Fork": "fork", From 6982ab89b53ef118c8bd52a81e1511d736d46e24 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Wed, 11 Oct 2023 04:03:55 -0700 Subject: [PATCH 194/282] feat: add more parsed data in harness webhook parsing (#279) --- .../webhooks/pull_request_branch_updated.json.golden | 8 ++++---- .../testdata/webhooks/pull_request_opened.json.golden | 8 ++++---- .../testdata/webhooks/pull_request_reopened.json.golden | 8 ++++---- scm/driver/harness/webhook.go | 6 ++++++ 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden index 9a768dde2..6be31bb70 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden +++ b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden @@ -6,7 +6,7 @@ "Name": "", "Branch": "main", "Private": false, - "Clone": "", + "Clone": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", "CloneSSH": "", "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", "Created": "0001-01-01T00:00:00Z", @@ -17,7 +17,7 @@ "Title": "aw", "Body": "", "Sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef", - "Ref": "", + "Ref": "refs/heads/b", "Source": "b", "Target": "main", "Fork": "fork", @@ -26,8 +26,8 @@ "Merged": false, "Author": { "Login": "", - "Name": "", - "Email": "", + "Name": "Admin", + "Email": "admin@harness.io", "Avatar": "" }, "Created": "0001-01-01T00:00:00Z", diff --git a/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden index e45f24bc5..2928bf6a1 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden +++ b/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden @@ -6,7 +6,7 @@ "Name": "", "Branch": "main", "Private": false, - "Clone": "", + "Clone": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", "CloneSSH": "", "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", "Created": "0001-01-01T00:00:00Z", @@ -17,7 +17,7 @@ "Title": "aw", "Body": "", "Sha": "d74b1ebfe520ac01b209dd9085f005884cc9f4cd", - "Ref": "", + "Ref": "refs/heads/b", "Source": "b", "Target": "main", "Fork": "fork", @@ -26,8 +26,8 @@ "Merged": false, "Author": { "Login": "", - "Name": "", - "Email": "", + "Name": "Admin", + "Email": "admin@harness.io", "Avatar": "" }, "Created": "0001-01-01T00:00:00Z", diff --git a/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden index bbea80558..03f8b54df 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden +++ b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden @@ -6,7 +6,7 @@ "Name": "", "Branch": "main", "Private": false, - "Clone": "", + "Clone": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", "CloneSSH": "", "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", "Created": "0001-01-01T00:00:00Z", @@ -17,7 +17,7 @@ "Title": "aw", "Body": "", "Sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef", - "Ref": "", + "Ref": "refs/heads/b", "Source": "b", "Target": "main", "Fork": "fork", @@ -26,8 +26,8 @@ "Merged": false, "Author": { "Login": "", - "Name": "", - "Email": "", + "Name": "Admin", + "Email": "admin@harness.io", "Avatar": "" }, "Created": "0001-01-01T00:00:00Z", diff --git a/scm/driver/harness/webhook.go b/scm/driver/harness/webhook.go index 1aa2d45fb..cc077a6ca 100644 --- a/scm/driver/harness/webhook.go +++ b/scm/driver/harness/webhook.go @@ -196,11 +196,17 @@ func convertPullRequestHook(dst *pullRequestHook) *scm.PullRequestHook { Fork: "fork", Link: dst.Ref.Repo.GitURL, Sha: dst.Commit.Sha, + Ref: dst.Ref.Name, + Author: scm.User{ + Name: dst.Commit.Committer.Identity.Name, + Email: dst.Commit.Committer.Identity.Email, + }, }, Repo: scm.Repository{ ID: dst.Repo.UID, Branch: dst.Repo.DefaultBranch, Link: dst.Repo.GitURL, + Clone: dst.Repo.GitURL, }, Sender: scm.User{ Email: dst.Principal.Email, From a5db7f41d8f7cc95b3077f49d61bb7d795521f19 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Tue, 24 Oct 2023 23:42:54 -0700 Subject: [PATCH 195/282] feat: Add pr_comment webhook for harness (#280) --- .../webhooks/branch_create.json.golden | 17 ++- .../webhooks/pull_request_branch_updated.json | 11 +- .../pull_request_branch_updated.json.golden | 20 ++- .../pull_request_comment_created.json | 63 +++++++++ .../pull_request_comment_created.json.golden | 51 +++++++ .../webhooks/pull_request_opened.json | 11 +- .../webhooks/pull_request_opened.json.golden | 20 ++- .../webhooks/pull_request_reopened.json | 11 +- .../pull_request_reopened.json.golden | 20 ++- scm/driver/harness/webhook.go | 131 ++++++++++++------ scm/driver/harness/webhook_test.go | 7 + 11 files changed, 289 insertions(+), 73 deletions(-) create mode 100644 scm/driver/harness/testdata/webhooks/pull_request_comment_created.json create mode 100644 scm/driver/harness/testdata/webhooks/pull_request_comment_created.json.golden diff --git a/scm/driver/harness/testdata/webhooks/branch_create.json.golden b/scm/driver/harness/testdata/webhooks/branch_create.json.golden index 00e4ce11b..0b0dad736 100644 --- a/scm/driver/harness/testdata/webhooks/branch_create.json.golden +++ b/scm/driver/harness/testdata/webhooks/branch_create.json.golden @@ -3,15 +3,15 @@ "Before": "0000000000000000000000000000000000000000", "After": "aeafa0e2e4ec6909ad75cb8fad57c0b1eb5986e6", "Repo": { - "ID": "", + "ID": "13", "Namespace": "", "Name": "aba", "Perm": null, - "Branch": "", + "Branch": "main", "Private": false, - "Clone": "", + "Clone": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", "CloneSSH": "", - "Link": "", + "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", "Created": "0001-01-01T00:00:00Z", "Updated": "0001-01-01T00:00:00Z" }, @@ -35,9 +35,12 @@ "Link": "" }, "Sender": { - "Login": "", + "ID": "0osgWsTZRsSZ8RWfjLRkEg", + "Login": "0osgWsTZRsSZ8RWfjLRkEg", "Name": "default", - "Email": "", - "Avatar": "" + "Email": "default@harness.io", + "Avatar": "", + "Created": "2023-02-02T18:21:25.38-08:00", + "Updated": "2023-02-02T18:21:25.38-08:00" } } \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json index 7509798e9..2709b46dc 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json +++ b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json @@ -25,7 +25,16 @@ "source_branch": "b", "target_repo_id": 13, "target_branch": "main", - "merge_strategy": null + "merge_strategy": null, + "author": { + "id": 8, + "uid": "0osgWsTZRsSZ8RWfjLRkEg", + "display_name": "Admin", + "email": "admin@harness.io", + "type": "user", + "created": 1675390885380, + "updated": 1675390885380 + } }, "target_ref": { "name": "refs/heads/main", diff --git a/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden index 6be31bb70..05c42eb0f 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden +++ b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden @@ -1,9 +1,9 @@ { "Action": "updated", "Repo": { - "ID": "aba", + "ID": "13", "Namespace": "", - "Name": "", + "Name": "aba", "Branch": "main", "Private": false, "Clone": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", @@ -25,18 +25,24 @@ "Closed": false, "Merged": false, "Author": { - "Login": "", + "ID": "0osgWsTZRsSZ8RWfjLRkEg", + "Login": "0osgWsTZRsSZ8RWfjLRkEg", "Name": "Admin", "Email": "admin@harness.io", - "Avatar": "" + "Avatar": "", + "Created": "2023-02-02T18:21:25.38-08:00", + "Updated": "2023-02-02T18:21:25.38-08:00" }, "Created": "0001-01-01T00:00:00Z", "Updated": "0001-01-01T00:00:00Z" }, "Sender": { - "Login": "", - "Name": "", + "ID": "0osgWsTZRsSZ8RWfjLRkEg", + "Login": "0osgWsTZRsSZ8RWfjLRkEg", + "Name": "default", "Email": "default@harness.io", - "Avatar": "" + "Avatar": "", + "Created": "2023-02-02T18:21:25.38-08:00", + "Updated": "2023-02-02T18:21:25.38-08:00" } } \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_comment_created.json b/scm/driver/harness/testdata/webhooks/pull_request_comment_created.json new file mode 100644 index 000000000..3b39a54fd --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/pull_request_comment_created.json @@ -0,0 +1,63 @@ +{ + "trigger": "pullreq_comment_created", + "repo": { + "id": 18, + "path": "asd/demo", + "uid": "demo", + "default_branch": "main", + "git_url": "http://localhost:3000/git/asd/demo.git" + }, + "principal": { + "id": 3, + "uid": "admin", + "display_name": "Administrator", + "email": "admin@gitness.io", + "type": "user", + "created": 1696332021613, + "updated": 1696332021613 + }, + "pull_req": { + "number": 2, + "state": "open", + "is_draft": false, + "title": "Update test.txt", + "source_repo_id": 18, + "source_branch": "pr2", + "target_repo_id": 18, + "target_branch": "main", + "merge_strategy": null, + "author": { + "id": 8, + "uid": "0osgWsTZRsSZ8RWfjLRkEg", + "display_name": "Admin", + "email": "admin@harness.io", + "type": "user", + "created": 1675390885380, + "updated": 1675390885380 + } + }, + "target_ref": { + "name": "refs/heads/main", + "repo": { + "id": 18, + "path": "asd/demo", + "uid": "demo", + "default_branch": "main", + "git_url": "http://localhost:3000/git/asd/demo.git" + } + }, + "ref": { + "name": "refs/heads/pr2", + "repo": { + "id": 18, + "path": "asd/demo", + "uid": "demo", + "default_branch": "main", + "git_url": "http://localhost:3000/git/asd/demo.git" + } + }, + "comment": { + "id": 1, + "text": "pr comment" + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_comment_created.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_comment_created.json.golden new file mode 100644 index 000000000..ed14715f7 --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/pull_request_comment_created.json.golden @@ -0,0 +1,51 @@ +{ + "Repo": { + "ID": "18", + "Namespace": "", + "Name": "demo", + "Branch": "main", + "Private": false, + "Clone": "http://localhost:3000/git/asd/demo.git", + "CloneSSH": "", + "Link": "http://localhost:3000/git/asd/demo.git", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 2, + "Title": "Update test.txt", + "Body": "", + "Sha": "", + "Ref": "refs/heads/pr2", + "Source": "pr2", + "Target": "main", + "Fork": "fork", + "Link": "http://localhost:3000/git/asd/demo.git", + "Closed": false, + "Merged": false, + "Author": { + "ID": "0osgWsTZRsSZ8RWfjLRkEg", + "Login": "0osgWsTZRsSZ8RWfjLRkEg", + "Name": "Admin", + "Email": "admin@harness.io", + "Avatar": "", + "Created": "2023-02-02T18:21:25.38-08:00", + "Updated": "2023-02-02T18:21:25.38-08:00" + }, + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Comment": { + "ID": 1, + "Body": "pr comment" + }, + "Sender": { + "ID": "admin", + "Login": "admin", + "Name": "Administrator", + "Email": "admin@gitness.io", + "Avatar": "", + "Created": "2023-10-03T04:20:21.613-07:00", + "Updated": "2023-10-03T04:20:21.613-07:00" + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_opened.json b/scm/driver/harness/testdata/webhooks/pull_request_opened.json index a7fd7666b..45b76600c 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_opened.json +++ b/scm/driver/harness/testdata/webhooks/pull_request_opened.json @@ -25,7 +25,16 @@ "source_branch": "b", "target_repo_id": 13, "target_branch": "main", - "merge_strategy": null + "merge_strategy": null, + "author": { + "id": 8, + "uid": "0osgWsTZRsSZ8RWfjLRkEg", + "display_name": "Admin", + "email": "admin@harness.io", + "type": "user", + "created": 1675390885380, + "updated": 1675390885380 + } }, "target_ref": { "name": "refs/heads/main", diff --git a/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden index 2928bf6a1..94b221212 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden +++ b/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden @@ -1,9 +1,9 @@ { "Action": "created", "Repo": { - "ID": "aba", + "ID": "13", "Namespace": "", - "Name": "", + "Name": "aba", "Branch": "main", "Private": false, "Clone": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", @@ -25,18 +25,24 @@ "Closed": false, "Merged": false, "Author": { - "Login": "", + "ID": "0osgWsTZRsSZ8RWfjLRkEg", + "Login": "0osgWsTZRsSZ8RWfjLRkEg", "Name": "Admin", "Email": "admin@harness.io", - "Avatar": "" + "Avatar": "", + "Created": "2023-02-02T18:21:25.38-08:00", + "Updated": "2023-02-02T18:21:25.38-08:00" }, "Created": "0001-01-01T00:00:00Z", "Updated": "0001-01-01T00:00:00Z" }, "Sender": { - "Login": "", - "Name": "", + "ID": "0osgWsTZRsSZ8RWfjLRkEg", + "Login": "0osgWsTZRsSZ8RWfjLRkEg", + "Name": "default", "Email": "default@harness.io", - "Avatar": "" + "Avatar": "", + "Created": "2023-02-02T18:21:25.38-08:00", + "Updated": "2023-02-02T18:21:25.38-08:00" } } \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_reopened.json b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json index c6549d374..d8a8b2d86 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_reopened.json +++ b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json @@ -25,7 +25,16 @@ "source_branch": "b", "target_repo_id": 13, "target_branch": "main", - "merge_strategy": null + "merge_strategy": null, + "author": { + "id": 8, + "uid": "0osgWsTZRsSZ8RWfjLRkEg", + "display_name": "Admin", + "email": "admin@harness.io", + "type": "user", + "created": 1675390885380, + "updated": 1675390885380 + } }, "target_ref": { "name": "refs/heads/main", diff --git a/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden index 03f8b54df..56968a689 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden +++ b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden @@ -1,9 +1,9 @@ { "Action": "reopened", "Repo": { - "ID": "aba", + "ID": "13", "Namespace": "", - "Name": "", + "Name": "aba", "Branch": "main", "Private": false, "Clone": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", @@ -25,18 +25,24 @@ "Closed": false, "Merged": false, "Author": { - "Login": "", + "ID": "0osgWsTZRsSZ8RWfjLRkEg", + "Login": "0osgWsTZRsSZ8RWfjLRkEg", "Name": "Admin", "Email": "admin@harness.io", - "Avatar": "" + "Avatar": "", + "Created": "2023-02-02T18:21:25.38-08:00", + "Updated": "2023-02-02T18:21:25.38-08:00" }, "Created": "0001-01-01T00:00:00Z", "Updated": "0001-01-01T00:00:00Z" }, "Sender": { - "Login": "", - "Name": "", + "ID": "0osgWsTZRsSZ8RWfjLRkEg", + "Login": "0osgWsTZRsSZ8RWfjLRkEg", + "Name": "default", "Email": "default@harness.io", - "Avatar": "" + "Avatar": "", + "Created": "2023-02-02T18:21:25.38-08:00", + "Updated": "2023-02-02T18:21:25.38-08:00" } } \ No newline at end of file diff --git a/scm/driver/harness/webhook.go b/scm/driver/harness/webhook.go index cc077a6ca..1c63738aa 100644 --- a/scm/driver/harness/webhook.go +++ b/scm/driver/harness/webhook.go @@ -10,6 +10,8 @@ import ( "io" "io/ioutil" "net/http" + "strconv" + "time" "github.com/drone/go-scm/scm" "github.com/drone/go-scm/scm/driver/internal/hmac" @@ -39,6 +41,8 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo hook, err = s.parsePushHook(data) case "pullreq_created", "pullreq_reopened", "pullreq_branch_updated": hook, err = s.parsePullRequestHook(data) + case "pullreq_comment_created": + hook, err = s.parsePullRequestCommentHook(data) default: return nil, scm.ErrUnknownEvent } @@ -89,6 +93,12 @@ func (s *webhookService) parsePushHook(data []byte) (scm.Webhook, error) { return convertPushHook(dst), err } +func (s *webhookService) parsePullRequestCommentHook(data []byte) (scm.Webhook, error) { + dst := new(pullRequestCommentHook) + err := json.Unmarshal(data, dst) + return convertPullRequestCommentHook(dst), err +} + // native data structures type ( repo struct { @@ -117,6 +127,7 @@ type ( TargetRepoID int `json:"target_repo_id"` TargetBranch string `json:"target_branch"` MergeStrategy interface{} `json:"merge_strategy"` + Author principal `json:"author"` } targetRef struct { Name string `json:"name"` @@ -156,6 +167,10 @@ type ( When string `json:"when"` } `json:"committer"` } + comment struct { + ID int `json:"id"` + Text string `json:"text"` + } // harness pull request webhook payload pullRequestHook struct { Trigger string `json:"trigger"` @@ -178,61 +193,57 @@ type ( OldSha string `json:"old_sha"` Forced bool `json:"forced"` } + // harness pull request comment webhook payload + pullRequestCommentHook struct { + Trigger string `json:"trigger"` + Repo repo `json:"repo"` + Principal principal `json:"principal"` + PullReq pullReq `json:"pull_req"` + TargetRef targetRef `json:"target_ref"` + Ref ref `json:"ref"` + Sha string `json:"sha"` + Commit hookCommit `json:"commit"` + Comment comment `json:"comment"` + } ) -// // native data structure conversion -// - -func convertPullRequestHook(dst *pullRequestHook) *scm.PullRequestHook { +func convertPullRequestHook(src *pullRequestHook) *scm.PullRequestHook { return &scm.PullRequestHook{ - Action: convertAction(dst.Trigger), - PullRequest: scm.PullRequest{ - Number: dst.PullReq.Number, - Title: dst.PullReq.Title, - Closed: dst.PullReq.State != "open", - Source: dst.PullReq.SourceBranch, - Target: dst.PullReq.TargetBranch, - Fork: "fork", - Link: dst.Ref.Repo.GitURL, - Sha: dst.Commit.Sha, - Ref: dst.Ref.Name, - Author: scm.User{ - Name: dst.Commit.Committer.Identity.Name, - Email: dst.Commit.Committer.Identity.Email, - }, - }, - Repo: scm.Repository{ - ID: dst.Repo.UID, - Branch: dst.Repo.DefaultBranch, - Link: dst.Repo.GitURL, - Clone: dst.Repo.GitURL, - }, - Sender: scm.User{ - Email: dst.Principal.Email, - }, + Action: convertAction(src.Trigger), + PullRequest: convertPullReq(src.PullReq, src.Ref, src.Commit), + Repo: convertRepo(src.Repo), + Sender: convertUser(src.Principal), } } -func convertPushHook(dst *pushHook) *scm.PushHook { +func convertPushHook(src *pushHook) *scm.PushHook { return &scm.PushHook{ - Ref: dst.Sha, - Before: dst.OldSha, - After: dst.Sha, - Repo: scm.Repository{ - Name: dst.Repo.UID, - }, + Ref: src.Sha, + Before: src.OldSha, + After: src.Sha, + Repo: convertRepo(src.Repo), Commit: scm.Commit{ - Sha: dst.Commit.Sha, - Message: dst.Commit.Message, + Sha: src.Commit.Sha, + Message: src.Commit.Message, Author: scm.Signature{ - Name: dst.Commit.Author.Identity.Name, - Email: dst.Commit.Author.Identity.Email, + Name: src.Commit.Author.Identity.Name, + Email: src.Commit.Author.Identity.Email, }, }, - Sender: scm.User{ - Name: dst.Principal.DisplayName, + Sender: convertUser(src.Principal), + } +} + +func convertPullRequestCommentHook(src *pullRequestCommentHook) *scm.PullRequestCommentHook { + return &scm.PullRequestCommentHook{ + PullRequest: convertPullReq(src.PullReq, src.Ref, src.Commit), + Repo: convertRepo(src.Repo), + Comment: scm.Comment{ + Body: src.Comment.Text, + ID: src.Comment.ID, }, + Sender: convertUser(src.Principal), } } @@ -248,3 +259,39 @@ func convertAction(src string) (action scm.Action) { return } } + +func convertPullReq(pr pullReq, ref ref, commit hookCommit) scm.PullRequest { + return scm.PullRequest{ + Number: pr.Number, + Title: pr.Title, + Closed: pr.State != "open", + Source: pr.SourceBranch, + Target: pr.TargetBranch, + Fork: "fork", + Link: ref.Repo.GitURL, + Sha: commit.Sha, + Ref: ref.Name, + Author: convertUser(pr.Author), + } +} + +func convertRepo(repo repo) scm.Repository { + return scm.Repository{ + ID: strconv.Itoa(repo.ID), + Name: repo.UID, + Branch: repo.DefaultBranch, + Link: repo.GitURL, + Clone: repo.GitURL, + } +} + +func convertUser(principal principal) scm.User { + return scm.User{ + Name: principal.DisplayName, + ID: principal.UID, + Login: principal.UID, + Email: principal.Email, + Created: time.Unix(0, principal.Created*int64(time.Millisecond)), + Updated: time.Unix(0, principal.Updated*int64(time.Millisecond)), + } +} diff --git a/scm/driver/harness/webhook_test.go b/scm/driver/harness/webhook_test.go index 4e38687be..175115e61 100644 --- a/scm/driver/harness/webhook_test.go +++ b/scm/driver/harness/webhook_test.go @@ -57,6 +57,13 @@ func TestWebhooks(t *testing.T) { after: "testdata/webhooks/pull_request_branch_updated.json.golden", obj: new(scm.PullRequestHook), }, + // pull request comment created + { + event: "pullreq_comment_created", + before: "testdata/webhooks/pull_request_comment_created.json", + after: "testdata/webhooks/pull_request_comment_created.json.golden", + obj: new(scm.PullRequestCommentHook), + }, } for _, test := range tests { From dc565fcc0b5b0557706473cb5addc60f7ab5c38b Mon Sep 17 00:00:00 2001 From: dependabot-ci Date: Fri, 27 Oct 2023 11:02:48 +0100 Subject: [PATCH 196/282] (maint) prep 1.33.0 --- CHANGELOG.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 192ce1fe7..804c053d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,30 @@ # Changelog +## [v1.33.0](https://github.com/drone/go-scm/tree/v1.33.0) (2023-10-27) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.32.3...v1.33.0) + +**Implemented enhancements:** + +- feat: Add pr\_comment webhook for harness [\#280](https://github.com/drone/go-scm/pull/280) ([abhinav-harness](https://github.com/abhinav-harness)) + +## [v1.32.3](https://github.com/drone/go-scm/tree/v1.32.3) (2023-10-11) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.32.2...v1.32.3) + +**Fixed bugs:** + +- fix: ref should have pullreq instead of pull for gitness [\#279](https://github.com/drone/go-scm/pull/279) ([abhinav-harness](https://github.com/abhinav-harness)) +- fix: ref should have pullreq instead of pull for gitness [\#278](https://github.com/drone/go-scm/pull/278) ([abhinav-harness](https://github.com/abhinav-harness)) + +## [v1.32.2](https://github.com/drone/go-scm/tree/v1.32.2) (2023-10-03) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.32.1...v1.32.2) + +**Implemented enhancements:** + +- feat: Harness list commits api update as per new spec [\#277](https://github.com/drone/go-scm/pull/277) ([abhinav-harness](https://github.com/abhinav-harness)) + ## [v1.32.1](https://github.com/drone/go-scm/tree/v1.32.1) (2023-09-27) [Full Changelog](https://github.com/drone/go-scm/compare/v1.32.0...v1.32.1) @@ -10,6 +35,7 @@ **Merged pull requests:** +- \(maint\) prep for 1.32.1 [\#276](https://github.com/drone/go-scm/pull/276) ([tphoney](https://github.com/tphoney)) - \(maint\) clean integration testing for stash [\#273](https://github.com/drone/go-scm/pull/273) ([tphoney](https://github.com/tphoney)) ## [v1.32.0](https://github.com/drone/go-scm/tree/v1.32.0) (2023-09-12) From a802ce1843efbc49b09d2e88ce6bb97f0e7e20b9 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Thu, 7 Dec 2023 03:26:10 +0530 Subject: [PATCH 197/282] feat: add support for branch update for gitness (#283) --- .../webhooks/branch_create.json.golden | 4 +- .../testdata/webhooks/branch_updated.json | 50 +++++++++++++++++++ .../webhooks/branch_updated.json.golden | 46 +++++++++++++++++ scm/driver/harness/webhook.go | 6 ++- scm/driver/harness/webhook_test.go | 7 +++ 5 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 scm/driver/harness/testdata/webhooks/branch_updated.json create mode 100644 scm/driver/harness/testdata/webhooks/branch_updated.json.golden diff --git a/scm/driver/harness/testdata/webhooks/branch_create.json.golden b/scm/driver/harness/testdata/webhooks/branch_create.json.golden index 0b0dad736..9bc611b39 100644 --- a/scm/driver/harness/testdata/webhooks/branch_create.json.golden +++ b/scm/driver/harness/testdata/webhooks/branch_create.json.golden @@ -26,8 +26,8 @@ "Avatar": "" }, "Committer": { - "Name": "", - "Email": "", + "Name": "Admin", + "Email": "admin@harness.io", "Date": "0001-01-01T00:00:00Z", "Login": "", "Avatar": "" diff --git a/scm/driver/harness/testdata/webhooks/branch_updated.json b/scm/driver/harness/testdata/webhooks/branch_updated.json new file mode 100644 index 000000000..903fea7dd --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/branch_updated.json @@ -0,0 +1,50 @@ +{ + "trigger": "branch_updated", + "repo": { + "id": 68, + "path": "vpCkHKsDSxK9_KYfjCTMKA/default/Repo_With_PR_checks/abhinav-git-sync", + "uid": "abhinav-git-sync", + "default_branch": "master", + "git_url": "https://git.harness.io/vpCkHKsDSxK9_KYfjCTMKA/default/Repo_With_PR_checks/abhinav-git-sync.git" + }, + "principal": { + "id": 59, + "uid": "ec9UfvFwTf663F47Hlqxbg", + "display_name": "abhinav.singh@harness.io", + "email": "abhinav.singh@harness.io", + "type": "user", + "created": 1697617589873, + "updated": 1697617589873 + }, + "ref": { + "name": "refs/heads/master", + "repo": { + "id": 68, + "path": "vpCkHKsDSxK9_KYfjCTMKA/default/Repo_With_PR_checks/abhinav-git-sync", + "uid": "abhinav-git-sync", + "default_branch": "master", + "git_url": "https://git.harness.io/vpCkHKsDSxK9_KYfjCTMKA/default/Repo_With_PR_checks/abhinav-git-sync.git" + } + }, + "sha": "92e21bfcddc1418079cddbb518ad6fd72917798a", + "commit": { + "sha": "92e21bfcddc1418079cddbb518ad6fd72917798a", + "message": "Create asdsad (#2)", + "author": { + "identity": { + "name": "abhinav.singh@harness.io", + "email": "abhinav.singh@harness.io" + }, + "when": "2023-12-05T11:59:39Z" + }, + "committer": { + "identity": { + "name": "Harness", + "email": "noreply@harness.io" + }, + "when": "2023-12-05T11:59:39Z" + } + }, + "old_sha": "a273c385628167932e10caaa58e12550c491f241", + "forced": false +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/branch_updated.json.golden b/scm/driver/harness/testdata/webhooks/branch_updated.json.golden new file mode 100644 index 000000000..1537f8d87 --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/branch_updated.json.golden @@ -0,0 +1,46 @@ +{ + "Ref": "92e21bfcddc1418079cddbb518ad6fd72917798a", + "Before": "a273c385628167932e10caaa58e12550c491f241", + "After": "92e21bfcddc1418079cddbb518ad6fd72917798a", + "Repo": { + "ID": "68", + "Namespace": "", + "Name": "abhinav-git-sync", + "Perm": null, + "Branch": "master", + "Private": false, + "Clone": "https://git.harness.io/vpCkHKsDSxK9_KYfjCTMKA/default/Repo_With_PR_checks/abhinav-git-sync.git", + "CloneSSH": "", + "Link": "https://git.harness.io/vpCkHKsDSxK9_KYfjCTMKA/default/Repo_With_PR_checks/abhinav-git-sync.git", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Commit": { + "Sha": "92e21bfcddc1418079cddbb518ad6fd72917798a", + "Message": "Create asdsad (#2)", + "Author": { + "Name": "abhinav.singh@harness.io", + "Email": "abhinav.singh@harness.io", + "Date" : "0001-01-01T00:00:00Z", + "Login": "", + "Avatar": "" + }, + "Committer": { + "Name": "Harness", + "Email": "noreply@harness.io", + "Date": "0001-01-01T00:00:00Z", + "Login": "", + "Avatar": "" + }, + "Link": "" + }, + "Sender": { + "ID": "ec9UfvFwTf663F47Hlqxbg", + "Login": "ec9UfvFwTf663F47Hlqxbg", + "Name": "abhinav.singh@harness.io", + "Email": "abhinav.singh@harness.io", + "Avatar": "", + "Created": "2023-10-18T13:56:29.873+05:30", + "Updated": "2023-10-18T13:56:29.873+05:30" + } +} \ No newline at end of file diff --git a/scm/driver/harness/webhook.go b/scm/driver/harness/webhook.go index 1c63738aa..d1ce064fd 100644 --- a/scm/driver/harness/webhook.go +++ b/scm/driver/harness/webhook.go @@ -37,7 +37,7 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo // hook, err = s.parseDeleteHook(data) // case "issues": // hook, err = s.parseIssueHook(data) - case "branch_created": + case "branch_created", "branch_updated": hook, err = s.parsePushHook(data) case "pullreq_created", "pullreq_reopened", "pullreq_branch_updated": hook, err = s.parsePullRequestHook(data) @@ -230,6 +230,10 @@ func convertPushHook(src *pushHook) *scm.PushHook { Name: src.Commit.Author.Identity.Name, Email: src.Commit.Author.Identity.Email, }, + Committer: scm.Signature{ + Name: src.Commit.Committer.Identity.Name, + Email: src.Commit.Committer.Identity.Email, + }, }, Sender: convertUser(src.Principal), } diff --git a/scm/driver/harness/webhook_test.go b/scm/driver/harness/webhook_test.go index 175115e61..5e8d7cdf2 100644 --- a/scm/driver/harness/webhook_test.go +++ b/scm/driver/harness/webhook_test.go @@ -33,6 +33,13 @@ func TestWebhooks(t *testing.T) { after: "testdata/webhooks/branch_create.json.golden", obj: new(scm.PushHook), }, + // push branch update + { + event: "branch_updated", + before: "testdata/webhooks/branch_updated.json", + after: "testdata/webhooks/branch_updated.json.golden", + obj: new(scm.PushHook), + }, // // pull request events // From 96d3e4faf81ea872b5abb3db321e6e21d6ca0f68 Mon Sep 17 00:00:00 2001 From: dependabot-ci Date: Thu, 7 Dec 2023 14:50:26 +0000 Subject: [PATCH 198/282] (maint) v1.34.0 prep --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 804c053d6..2c912f256 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [v1.34.0](https://github.com/drone/go-scm/tree/v1.34.0) (2023-12-07) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.33.0...v1.34.0) + +**Implemented enhancements:** + +- feat: add support for branch update for gitness [\#283](https://github.com/drone/go-scm/pull/283) ([abhinav-harness](https://github.com/abhinav-harness)) + ## [v1.33.0](https://github.com/drone/go-scm/tree/v1.33.0) (2023-10-27) [Full Changelog](https://github.com/drone/go-scm/compare/v1.32.3...v1.33.0) @@ -8,6 +16,10 @@ - feat: Add pr\_comment webhook for harness [\#280](https://github.com/drone/go-scm/pull/280) ([abhinav-harness](https://github.com/abhinav-harness)) +**Merged pull requests:** + +- \(maint\) prep 1.33.0 [\#281](https://github.com/drone/go-scm/pull/281) ([tphoney](https://github.com/tphoney)) + ## [v1.32.3](https://github.com/drone/go-scm/tree/v1.32.3) (2023-10-11) [Full Changelog](https://github.com/drone/go-scm/compare/v1.32.2...v1.32.3) From 05fe67f7db9b3a7c664aa7ce697c0e4852a9a00b Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Fri, 8 Dec 2023 14:04:21 +0530 Subject: [PATCH 199/282] fix: use opts for harness list commits --- scm/driver/harness/git.go | 4 ++-- scm/driver/harness/util.go | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/scm/driver/harness/git.go b/scm/driver/harness/git.go index 85b17bff1..25923a56e 100644 --- a/scm/driver/harness/git.go +++ b/scm/driver/harness/git.go @@ -60,9 +60,9 @@ func (s *gitService) ListBranchesV2(ctx context.Context, repo string, opts scm.B return s.ListBranches(ctx, repo, opts.PageListOptions) } -func (s *gitService) ListCommits(ctx context.Context, repo string, _ scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { +func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - path := fmt.Sprintf("api/v1/repos/%s/commits", harnessURI) + path := fmt.Sprintf("api/v1/repos/%s/commits?%s", harnessURI, encodeCommitListOptions(opts)) out := new(commits) res, err := s.client.do(ctx, "GET", path, nil, &out) return convertCommitList(out), res, err diff --git a/scm/driver/harness/util.go b/scm/driver/harness/util.go index fe7778d9e..78fc8cc9e 100644 --- a/scm/driver/harness/util.go +++ b/scm/driver/harness/util.go @@ -114,3 +114,20 @@ func encodeReleaseListOptions(o ListOptions) string { query.Add("limit", fmt.Sprintf("%d", o.PageSize)) return query.Encode() } + +func encodeCommitListOptions(opts scm.CommitListOptions) string { + params := url.Values{} + if opts.Page != 0 { + params.Set("page", strconv.Itoa(opts.Page)) + } + if opts.Size != 0 { + params.Set("limit", strconv.Itoa(opts.Size)) + } + if opts.Ref != "" { + params.Set("git_ref", opts.Ref) + } + if opts.Path != "" { + params.Set("path", opts.Path) + } + return params.Encode() +} From 8ddff1fafaec51daece9145d341464ed1ece804a Mon Sep 17 00:00:00 2001 From: dependabot-ci Date: Fri, 8 Dec 2023 13:22:22 +0000 Subject: [PATCH 200/282] (maint) v1.34.1 release prep --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c912f256..739e13c01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [v1.34.1](https://github.com/drone/go-scm/tree/v1.34.1) (2023-12-08) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.34.0...v1.34.1) + +**Fixed bugs:** + +- fix: use opts for harness list commits [\#286](https://github.com/drone/go-scm/pull/286) ([abhinav-harness](https://github.com/abhinav-harness)) + ## [v1.34.0](https://github.com/drone/go-scm/tree/v1.34.0) (2023-12-07) [Full Changelog](https://github.com/drone/go-scm/compare/v1.33.0...v1.34.0) @@ -8,6 +16,10 @@ - feat: add support for branch update for gitness [\#283](https://github.com/drone/go-scm/pull/283) ([abhinav-harness](https://github.com/abhinav-harness)) +**Merged pull requests:** + +- \(maint\) v1.34.0 prep [\#284](https://github.com/drone/go-scm/pull/284) ([tphoney](https://github.com/tphoney)) + ## [v1.33.0](https://github.com/drone/go-scm/tree/v1.33.0) (2023-10-27) [Full Changelog](https://github.com/drone/go-scm/compare/v1.32.3...v1.33.0) From e6556d14011a4ae33c38f77d211f4f54458e278c Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Wed, 20 Dec 2023 14:58:17 +0530 Subject: [PATCH 201/282] feat: support more events in webhook parse in go-scm for gitness (#289) --- .../webhooks/pull_request_closed.json | 77 ++++++++++++++++++ .../webhooks/pull_request_closed.json.golden | 48 ++++++++++++ .../webhooks/pull_request_merged.json | 78 +++++++++++++++++++ .../webhooks/pull_request_merged.json.golden | 48 ++++++++++++ scm/driver/harness/webhook.go | 7 +- scm/driver/harness/webhook_test.go | 14 ++++ 6 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 scm/driver/harness/testdata/webhooks/pull_request_closed.json create mode 100644 scm/driver/harness/testdata/webhooks/pull_request_closed.json.golden create mode 100644 scm/driver/harness/testdata/webhooks/pull_request_merged.json create mode 100644 scm/driver/harness/testdata/webhooks/pull_request_merged.json.golden diff --git a/scm/driver/harness/testdata/webhooks/pull_request_closed.json b/scm/driver/harness/testdata/webhooks/pull_request_closed.json new file mode 100644 index 000000000..f4f038ce7 --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/pull_request_closed.json @@ -0,0 +1,77 @@ +{ + "trigger": "pullreq_closed", + "repo": { + "id": 22, + "path": "codeowners/asdsad", + "uid": "asdsad", + "default_branch": "main", + "git_url": "http://localhost:3000/git/codeowners/asdsad.git" + }, + "principal": { + "id": 3, + "uid": "admin", + "display_name": "Administrator", + "email": "admin@gitness.io", + "type": "user", + "created": 1696332021613, + "updated": 1696332021613 + }, + "pull_req": { + "number": 6, + "state": "closed", + "is_draft": false, + "title": "Create sad", + "source_repo_id": 22, + "source_branch": "asdxsa", + "target_repo_id": 22, + "target_branch": "main", + "author": { + "id": 3, + "uid": "admin", + "display_name": "Administrator", + "email": "admin@gitness.io", + "type": "user", + "created": 1696332021613, + "updated": 1696332021613 + } + }, + "target_ref": { + "name": "refs/heads/main", + "repo": { + "id": 22, + "path": "codeowners/asdsad", + "uid": "asdsad", + "default_branch": "main", + "git_url": "http://localhost:3000/git/codeowners/asdsad.git" + } + }, + "ref": { + "name": "refs/heads/asdxsa", + "repo": { + "id": 22, + "path": "codeowners/asdsad", + "uid": "asdsad", + "default_branch": "main", + "git_url": "http://localhost:3000/git/codeowners/asdsad.git" + } + }, + "sha": "27822dd2ec788f924c97b0b194c5bfd906f2e574", + "commit": { + "sha": "27822dd2ec788f924c97b0b194c5bfd906f2e574", + "message": "", + "author": { + "identity": { + "name": "Administrator", + "email": "admin@gitness.io" + }, + "when": "2023-12-20T13:10:47+05:30" + }, + "committer": { + "identity": { + "name": "Gitness", + "email": "system@gitness.io" + }, + "when": "2023-12-20T13:10:47+05:30" + } + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_closed.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_closed.json.golden new file mode 100644 index 000000000..fad057ac1 --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/pull_request_closed.json.golden @@ -0,0 +1,48 @@ +{ + "Action": "closed", + "Repo": { + "ID": "22", + "Namespace": "", + "Name": "asdsad", + "Branch": "main", + "Private": false, + "Clone": "http://localhost:3000/git/codeowners/asdsad.git", + "CloneSSH": "", + "Link": "http://localhost:3000/git/codeowners/asdsad.git", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 6, + "Title": "Create sad", + "Body": "", + "Sha": "27822dd2ec788f924c97b0b194c5bfd906f2e574", + "Ref": "refs/heads/asdxsa", + "Source": "asdxsa", + "Target": "main", + "Fork": "fork", + "Link": "http://localhost:3000/git/codeowners/asdsad.git", + "Closed": true, + "Merged": false, + "Author": { + "ID": "admin", + "Login": "admin", + "Name": "Administrator", + "Email": "admin@gitness.io", + "Avatar": "", + "Created": "2023-10-03T16:50:21.613+05:30", + "Updated": "2023-10-03T16:50:21.613+05:30" + }, + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Sender": { + "ID": "admin", + "Login": "admin", + "Name": "Administrator", + "Email": "admin@gitness.io", + "Avatar": "", + "Created": "2023-10-03T16:50:21.613+05:30", + "Updated": "2023-10-03T16:50:21.613+05:30" + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_merged.json b/scm/driver/harness/testdata/webhooks/pull_request_merged.json new file mode 100644 index 000000000..32f2dcc8a --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/pull_request_merged.json @@ -0,0 +1,78 @@ +{ + "trigger": "pullreq_merged", + "repo": { + "id": 22, + "path": "codeowners/asdsad", + "uid": "asdsad", + "default_branch": "main", + "git_url": "http://localhost:3000/git/codeowners/asdsad.git" + }, + "principal": { + "id": 3, + "uid": "admin", + "display_name": "Administrator", + "email": "admin@gitness.io", + "type": "user", + "created": 1696332021613, + "updated": 1696332021613 + }, + "pull_req": { + "number": 10, + "state": "merged", + "is_draft": false, + "title": "Create xxasc", + "source_repo_id": 22, + "source_branch": "xas", + "target_repo_id": 22, + "target_branch": "main", + "merge_strategy": "squash", + "author": { + "id": 3, + "uid": "admin", + "display_name": "Administrator", + "email": "admin@gitness.io", + "type": "user", + "created": 1696332021613, + "updated": 1696332021613 + } + }, + "target_ref": { + "name": "refs/heads/main", + "repo": { + "id": 22, + "path": "codeowners/asdsad", + "uid": "asdsad", + "default_branch": "main", + "git_url": "http://localhost:3000/git/codeowners/asdsad.git" + } + }, + "ref": { + "name": "refs/heads/xas", + "repo": { + "id": 22, + "path": "codeowners/asdsad", + "uid": "asdsad", + "default_branch": "main", + "git_url": "http://localhost:3000/git/codeowners/asdsad.git" + } + }, + "sha": "4ec41187008f77222a60dfa21cdbd980f6490443", + "commit": { + "sha": "4ec41187008f77222a60dfa21cdbd980f6490443", + "message": "", + "author": { + "identity": { + "name": "Administrator", + "email": "admin@gitness.io" + }, + "when": "2023-12-20T13:40:52+05:30" + }, + "committer": { + "identity": { + "name": "Gitness", + "email": "system@gitness.io" + }, + "when": "2023-12-20T13:40:52+05:30" + } + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_merged.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_merged.json.golden new file mode 100644 index 000000000..fe707ce6e --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/pull_request_merged.json.golden @@ -0,0 +1,48 @@ +{ + "Action": "merged", + "Repo": { + "ID": "22", + "Namespace": "", + "Name": "asdsad", + "Branch": "main", + "Private": false, + "Clone": "http://localhost:3000/git/codeowners/asdsad.git", + "CloneSSH": "", + "Link": "http://localhost:3000/git/codeowners/asdsad.git", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 10, + "Title": "Create xxasc", + "Body": "", + "Sha": "4ec41187008f77222a60dfa21cdbd980f6490443", + "Ref": "refs/heads/xas", + "Source": "xas", + "Target": "main", + "Fork": "fork", + "Link": "http://localhost:3000/git/codeowners/asdsad.git", + "Closed": true, + "Merged": true, + "Author": { + "ID": "admin", + "Login": "admin", + "Name": "Administrator", + "Email": "admin@gitness.io", + "Avatar": "", + "Created": "2023-10-03T16:50:21.613+05:30", + "Updated": "2023-10-03T16:50:21.613+05:30" + }, + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Sender": { + "ID": "admin", + "Login": "admin", + "Name": "Administrator", + "Email": "admin@gitness.io", + "Avatar": "", + "Created": "2023-10-03T16:50:21.613+05:30", + "Updated": "2023-10-03T16:50:21.613+05:30" + } +} \ No newline at end of file diff --git a/scm/driver/harness/webhook.go b/scm/driver/harness/webhook.go index d1ce064fd..10f808e9a 100644 --- a/scm/driver/harness/webhook.go +++ b/scm/driver/harness/webhook.go @@ -39,7 +39,7 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo // hook, err = s.parseIssueHook(data) case "branch_created", "branch_updated": hook, err = s.parsePushHook(data) - case "pullreq_created", "pullreq_reopened", "pullreq_branch_updated": + case "pullreq_created", "pullreq_reopened", "pullreq_branch_updated", "pullreq_closed", "pullreq_merged": hook, err = s.parsePullRequestHook(data) case "pullreq_comment_created": hook, err = s.parsePullRequestCommentHook(data) @@ -259,6 +259,10 @@ func convertAction(src string) (action scm.Action) { return scm.ActionUpdate case "pullreq_reopened": return scm.ActionReopen + case "pullreq_closed": + return scm.ActionClose + case "pullreq_merged": + return scm.ActionMerge default: return } @@ -271,6 +275,7 @@ func convertPullReq(pr pullReq, ref ref, commit hookCommit) scm.PullRequest { Closed: pr.State != "open", Source: pr.SourceBranch, Target: pr.TargetBranch, + Merged: pr.State == "merged", Fork: "fork", Link: ref.Repo.GitURL, Sha: commit.Sha, diff --git a/scm/driver/harness/webhook_test.go b/scm/driver/harness/webhook_test.go index 5e8d7cdf2..26966db2b 100644 --- a/scm/driver/harness/webhook_test.go +++ b/scm/driver/harness/webhook_test.go @@ -71,6 +71,20 @@ func TestWebhooks(t *testing.T) { after: "testdata/webhooks/pull_request_comment_created.json.golden", obj: new(scm.PullRequestCommentHook), }, + // pull request closed + { + event: "pullreq_reopened", + before: "testdata/webhooks/pull_request_closed.json", + after: "testdata/webhooks/pull_request_closed.json.golden", + obj: new(scm.PullRequestHook), + }, + // pull request merged + { + event: "pullreq_reopened", + before: "testdata/webhooks/pull_request_merged.json", + after: "testdata/webhooks/pull_request_merged.json.golden", + obj: new(scm.PullRequestHook), + }, } for _, test := range tests { From 2877ffa2539608595859c0e94bf365cc9e94ed90 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Wed, 20 Dec 2023 14:58:29 +0530 Subject: [PATCH 202/282] fix: ref should be branch name for harness code (#288) * fix: ref should be branch name for harness code * fix: add uid for harness webhook --- scm/driver/harness/repo.go | 2 ++ scm/driver/harness/testdata/webhooks/branch_create.json.golden | 2 +- scm/driver/harness/testdata/webhooks/branch_updated.json.golden | 2 +- scm/driver/harness/webhook.go | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/scm/driver/harness/repo.go b/scm/driver/harness/repo.go index da4237555..b467a03db 100644 --- a/scm/driver/harness/repo.go +++ b/scm/driver/harness/repo.go @@ -75,6 +75,7 @@ func (s *repositoryService) CreateHook(ctx context.Context, repo string, input * in := new(hook) in.Enabled = true in.DisplayName = input.Name + in.UID = input.Name in.Secret = input.Secret in.Insecure = input.SkipVerify in.URL = input.Target @@ -134,6 +135,7 @@ type ( HasSecret bool `json:"has_secret"` Secret string `json:"secret"` ID int `json:"id"` + UID string `json:"uid"` Insecure bool `json:"insecure"` LatestExecutionResult string `json:"latest_execution_result"` ParentID int `json:"parent_id"` diff --git a/scm/driver/harness/testdata/webhooks/branch_create.json.golden b/scm/driver/harness/testdata/webhooks/branch_create.json.golden index 9bc611b39..a534de4c2 100644 --- a/scm/driver/harness/testdata/webhooks/branch_create.json.golden +++ b/scm/driver/harness/testdata/webhooks/branch_create.json.golden @@ -1,5 +1,5 @@ { - "Ref": "aeafa0e2e4ec6909ad75cb8fad57c0b1eb5986e6", + "Ref": "refs/heads/new2", "Before": "0000000000000000000000000000000000000000", "After": "aeafa0e2e4ec6909ad75cb8fad57c0b1eb5986e6", "Repo": { diff --git a/scm/driver/harness/testdata/webhooks/branch_updated.json.golden b/scm/driver/harness/testdata/webhooks/branch_updated.json.golden index 1537f8d87..550cf3b1d 100644 --- a/scm/driver/harness/testdata/webhooks/branch_updated.json.golden +++ b/scm/driver/harness/testdata/webhooks/branch_updated.json.golden @@ -1,5 +1,5 @@ { - "Ref": "92e21bfcddc1418079cddbb518ad6fd72917798a", + "Ref": "refs/heads/master", "Before": "a273c385628167932e10caaa58e12550c491f241", "After": "92e21bfcddc1418079cddbb518ad6fd72917798a", "Repo": { diff --git a/scm/driver/harness/webhook.go b/scm/driver/harness/webhook.go index 10f808e9a..73a3d8130 100644 --- a/scm/driver/harness/webhook.go +++ b/scm/driver/harness/webhook.go @@ -219,7 +219,7 @@ func convertPullRequestHook(src *pullRequestHook) *scm.PullRequestHook { func convertPushHook(src *pushHook) *scm.PushHook { return &scm.PushHook{ - Ref: src.Sha, + Ref: src.Ref.Name, Before: src.OldSha, After: src.Sha, Repo: convertRepo(src.Repo), From 93042b767ef7fe212e4636d64491a84e8a69f929 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Thu, 21 Dec 2023 01:51:08 +0530 Subject: [PATCH 203/282] feat: add pr link as coming from new webhook (#290) --- .../harness/testdata/webhooks/pull_request_branch_updated.json | 3 ++- .../testdata/webhooks/pull_request_branch_updated.json.golden | 2 +- scm/driver/harness/testdata/webhooks/pull_request_closed.json | 3 ++- .../harness/testdata/webhooks/pull_request_closed.json.golden | 2 +- .../testdata/webhooks/pull_request_comment_created.json | 3 ++- .../testdata/webhooks/pull_request_comment_created.json.golden | 2 +- scm/driver/harness/testdata/webhooks/pull_request_merged.json | 3 ++- .../harness/testdata/webhooks/pull_request_merged.json.golden | 2 +- scm/driver/harness/testdata/webhooks/pull_request_opened.json | 3 ++- .../harness/testdata/webhooks/pull_request_opened.json.golden | 2 +- .../harness/testdata/webhooks/pull_request_reopened.json | 3 ++- .../testdata/webhooks/pull_request_reopened.json.golden | 2 +- scm/driver/harness/webhook.go | 3 ++- 13 files changed, 20 insertions(+), 13 deletions(-) diff --git a/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json index 2709b46dc..144fc3f3e 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json +++ b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json @@ -34,7 +34,8 @@ "type": "user", "created": 1675390885380, "updated": 1675390885380 - } + }, + "pr_url": "http://localhost:3000/codeowners/asdsad/pulls/14" }, "target_ref": { "name": "refs/heads/main", diff --git a/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden index 05c42eb0f..2b4f2a643 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden +++ b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden @@ -21,7 +21,7 @@ "Source": "b", "Target": "main", "Fork": "fork", - "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", + "Link": "http://localhost:3000/codeowners/asdsad/pulls/14", "Closed": false, "Merged": false, "Author": { diff --git a/scm/driver/harness/testdata/webhooks/pull_request_closed.json b/scm/driver/harness/testdata/webhooks/pull_request_closed.json index f4f038ce7..496e01610 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_closed.json +++ b/scm/driver/harness/testdata/webhooks/pull_request_closed.json @@ -33,7 +33,8 @@ "type": "user", "created": 1696332021613, "updated": 1696332021613 - } + }, + "pr_url": "http://localhost:3000/codeowners/asdsad/pulls/14" }, "target_ref": { "name": "refs/heads/main", diff --git a/scm/driver/harness/testdata/webhooks/pull_request_closed.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_closed.json.golden index fad057ac1..8b5fc2143 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_closed.json.golden +++ b/scm/driver/harness/testdata/webhooks/pull_request_closed.json.golden @@ -21,7 +21,7 @@ "Source": "asdxsa", "Target": "main", "Fork": "fork", - "Link": "http://localhost:3000/git/codeowners/asdsad.git", + "Link": "http://localhost:3000/codeowners/asdsad/pulls/14", "Closed": true, "Merged": false, "Author": { diff --git a/scm/driver/harness/testdata/webhooks/pull_request_comment_created.json b/scm/driver/harness/testdata/webhooks/pull_request_comment_created.json index 3b39a54fd..52ae75598 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_comment_created.json +++ b/scm/driver/harness/testdata/webhooks/pull_request_comment_created.json @@ -34,7 +34,8 @@ "type": "user", "created": 1675390885380, "updated": 1675390885380 - } + }, + "pr_url": "http://localhost:3000/codeowners/asdsad/pulls/14" }, "target_ref": { "name": "refs/heads/main", diff --git a/scm/driver/harness/testdata/webhooks/pull_request_comment_created.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_comment_created.json.golden index ed14715f7..cb96e2634 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_comment_created.json.golden +++ b/scm/driver/harness/testdata/webhooks/pull_request_comment_created.json.golden @@ -20,7 +20,7 @@ "Source": "pr2", "Target": "main", "Fork": "fork", - "Link": "http://localhost:3000/git/asd/demo.git", + "Link": "http://localhost:3000/codeowners/asdsad/pulls/14", "Closed": false, "Merged": false, "Author": { diff --git a/scm/driver/harness/testdata/webhooks/pull_request_merged.json b/scm/driver/harness/testdata/webhooks/pull_request_merged.json index 32f2dcc8a..54beca25c 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_merged.json +++ b/scm/driver/harness/testdata/webhooks/pull_request_merged.json @@ -34,7 +34,8 @@ "type": "user", "created": 1696332021613, "updated": 1696332021613 - } + }, + "pr_url": "http://localhost:3000/codeowners/asdsad/pulls/14" }, "target_ref": { "name": "refs/heads/main", diff --git a/scm/driver/harness/testdata/webhooks/pull_request_merged.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_merged.json.golden index fe707ce6e..3bef4116c 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_merged.json.golden +++ b/scm/driver/harness/testdata/webhooks/pull_request_merged.json.golden @@ -21,7 +21,7 @@ "Source": "xas", "Target": "main", "Fork": "fork", - "Link": "http://localhost:3000/git/codeowners/asdsad.git", + "Link": "http://localhost:3000/codeowners/asdsad/pulls/14", "Closed": true, "Merged": true, "Author": { diff --git a/scm/driver/harness/testdata/webhooks/pull_request_opened.json b/scm/driver/harness/testdata/webhooks/pull_request_opened.json index 45b76600c..abc82426c 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_opened.json +++ b/scm/driver/harness/testdata/webhooks/pull_request_opened.json @@ -34,7 +34,8 @@ "type": "user", "created": 1675390885380, "updated": 1675390885380 - } + }, + "pr_url": "http://localhost:3000/codeowners/asdsad/pulls/14" }, "target_ref": { "name": "refs/heads/main", diff --git a/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden index 94b221212..9ea430e3d 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden +++ b/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden @@ -21,7 +21,7 @@ "Source": "b", "Target": "main", "Fork": "fork", - "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", + "Link": "http://localhost:3000/codeowners/asdsad/pulls/14", "Closed": false, "Merged": false, "Author": { diff --git a/scm/driver/harness/testdata/webhooks/pull_request_reopened.json b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json index d8a8b2d86..ab57a9e14 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_reopened.json +++ b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json @@ -34,7 +34,8 @@ "type": "user", "created": 1675390885380, "updated": 1675390885380 - } + }, + "pr_url": "http://localhost:3000/codeowners/asdsad/pulls/14" }, "target_ref": { "name": "refs/heads/main", diff --git a/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden index 56968a689..32bc95964 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden +++ b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden @@ -21,7 +21,7 @@ "Source": "b", "Target": "main", "Fork": "fork", - "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", + "Link": "http://localhost:3000/codeowners/asdsad/pulls/14", "Closed": false, "Merged": false, "Author": { diff --git a/scm/driver/harness/webhook.go b/scm/driver/harness/webhook.go index 73a3d8130..4a087d629 100644 --- a/scm/driver/harness/webhook.go +++ b/scm/driver/harness/webhook.go @@ -128,6 +128,7 @@ type ( TargetBranch string `json:"target_branch"` MergeStrategy interface{} `json:"merge_strategy"` Author principal `json:"author"` + PrURL string `json:"pr_url"` } targetRef struct { Name string `json:"name"` @@ -277,7 +278,7 @@ func convertPullReq(pr pullReq, ref ref, commit hookCommit) scm.PullRequest { Target: pr.TargetBranch, Merged: pr.State == "merged", Fork: "fork", - Link: ref.Repo.GitURL, + Link: pr.PrURL, Sha: commit.Sha, Ref: ref.Name, Author: convertUser(pr.Author), From 5a98a57b714fee467dbc1368f901d421294c280d Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Mon, 8 Jan 2024 12:01:56 +0530 Subject: [PATCH 204/282] Update content.go --- scm/driver/github/content.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scm/driver/github/content.go b/scm/driver/github/content.go index 709cf705f..19c734e6a 100644 --- a/scm/driver/github/content.go +++ b/scm/driver/github/content.go @@ -8,6 +8,7 @@ import ( "context" "encoding/base64" "fmt" + "net/url" "github.com/drone/go-scm/scm" ) @@ -17,7 +18,8 @@ type contentService struct { } func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm.Content, *scm.Response, error) { - endpoint := fmt.Sprintf("repos/%s/contents/%s?ref=%s", repo, path, ref) + urlEncodedRef := url.QueryEscape(ref) + endpoint := fmt.Sprintf("repos/%s/contents/%s?ref=%s", repo, path, urlEncodedRef) out := new(content) res, err := s.client.do(ctx, "GET", endpoint, nil, out) raw, _ := base64.StdEncoding.DecodeString(out.Content) From b4f0d9b87888f45f782e183a35b1ad8008af920b Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Mon, 8 Jan 2024 15:36:00 +0530 Subject: [PATCH 205/282] Update content.go --- scm/driver/azure/content.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scm/driver/azure/content.go b/scm/driver/azure/content.go index 689f6718f..b300049f6 100644 --- a/scm/driver/azure/content.go +++ b/scm/driver/azure/content.go @@ -8,6 +8,7 @@ import ( "context" "encoding/base64" "fmt" + "net/url" "github.com/drone/go-scm/scm" ) @@ -21,8 +22,9 @@ func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm if s.client.project == "" { return nil, nil, ProjectRequiredError() } + urlEncodedRef := url.QueryEscape(ref) endpoint := fmt.Sprintf("%s/%s/_apis/git/repositories/%s/items?path=%s&includeContent=true&$format=json", s.client.owner, s.client.project, repo, path) - endpoint += generateURIFromRef(ref) + endpoint += generateURIFromRef(urlEncodedRef) endpoint += "&api-version=6.0" out := new(content) res, err := s.client.do(ctx, "GET", endpoint, nil, out) From c1465b7c085af0b07be0c8382923c73ce2b8ac3d Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Tue, 9 Jan 2024 13:47:37 +0530 Subject: [PATCH 206/282] Update content.go --- scm/driver/gitlab/content.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scm/driver/gitlab/content.go b/scm/driver/gitlab/content.go index feef351f1..118802220 100644 --- a/scm/driver/gitlab/content.go +++ b/scm/driver/gitlab/content.go @@ -19,7 +19,8 @@ type contentService struct { } func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm.Content, *scm.Response, error) { - endpoint := fmt.Sprintf("api/v4/projects/%s/repository/files/%s?ref=%s", encode(repo), encodePath(path), ref) + urlEncodedRef := url.QueryEscape(ref) + endpoint := fmt.Sprintf("api/v4/projects/%s/repository/files/%s?ref=%s", encode(repo), encodePath(path), urlEncodedRef) out := new(content) res, err := s.client.do(ctx, "GET", endpoint, nil, out) raw, berr := base64.StdEncoding.DecodeString(out.Content) From 64261e5cdfcadafcd4d4dabfcc2953224eca2ca0 Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Tue, 9 Jan 2024 16:24:26 +0530 Subject: [PATCH 207/282] Update content.go --- scm/driver/bitbucket/content.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scm/driver/bitbucket/content.go b/scm/driver/bitbucket/content.go index 3501de53f..1f9d7e358 100644 --- a/scm/driver/bitbucket/content.go +++ b/scm/driver/bitbucket/content.go @@ -8,6 +8,7 @@ import ( "bytes" "context" "fmt" + "net/url" "github.com/drone/go-scm/scm" ) @@ -17,7 +18,8 @@ type contentService struct { } func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm.Content, *scm.Response, error) { - endpoint := fmt.Sprintf("/2.0/repositories/%s/src/%s/%s", repo, ref, path) + urlEncodedRef := url.QueryEscape(ref) + endpoint := fmt.Sprintf("/2.0/repositories/%s/src/%s/%s", repo, urlEncodedRef, path) out := new(bytes.Buffer) res, err := s.client.do(ctx, "GET", endpoint, nil, out) content := &scm.Content{ From de9fc725c24a2dc72a499cca8c3bdb8e34d760d9 Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Tue, 9 Jan 2024 16:27:52 +0530 Subject: [PATCH 208/282] Update content.go --- scm/driver/bitbucket/content.go | 1 + 1 file changed, 1 insertion(+) diff --git a/scm/driver/bitbucket/content.go b/scm/driver/bitbucket/content.go index 1f9d7e358..1b2bccc86 100644 --- a/scm/driver/bitbucket/content.go +++ b/scm/driver/bitbucket/content.go @@ -18,6 +18,7 @@ type contentService struct { } func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm.Content, *scm.Response, error) { + fmt.Println("ref->", ref) urlEncodedRef := url.QueryEscape(ref) endpoint := fmt.Sprintf("/2.0/repositories/%s/src/%s/%s", repo, urlEncodedRef, path) out := new(bytes.Buffer) From f637c3c3e2a4f8e5852fe9f1bfb39e362bb94c55 Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Tue, 9 Jan 2024 16:32:11 +0530 Subject: [PATCH 209/282] Update content.go --- scm/driver/bitbucket/content.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scm/driver/bitbucket/content.go b/scm/driver/bitbucket/content.go index 1b2bccc86..14b07d160 100644 --- a/scm/driver/bitbucket/content.go +++ b/scm/driver/bitbucket/content.go @@ -21,6 +21,7 @@ func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm fmt.Println("ref->", ref) urlEncodedRef := url.QueryEscape(ref) endpoint := fmt.Sprintf("/2.0/repositories/%s/src/%s/%s", repo, urlEncodedRef, path) + fmt.Println("endpoint->", endpoint) out := new(bytes.Buffer) res, err := s.client.do(ctx, "GET", endpoint, nil, out) content := &scm.Content{ @@ -30,7 +31,7 @@ func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm if err != nil { return content, res, err } - metaEndpoint := fmt.Sprintf("/2.0/repositories/%s/src/%s/%s?format=meta", repo, ref, path) + metaEndpoint := fmt.Sprintf("/2.0/repositories/%s/src/%s/%s?format=meta", repo, urlEncodedRef, path) metaOut := new(metaContent) metaRes, metaErr := s.client.do(ctx, "GET", metaEndpoint, nil, metaOut) if metaErr == nil { From 6ee41cf70bb2094c64a784a0c9546e50cd81009a Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Tue, 9 Jan 2024 16:35:09 +0530 Subject: [PATCH 210/282] Update content.go --- scm/driver/bitbucket/content.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/scm/driver/bitbucket/content.go b/scm/driver/bitbucket/content.go index 14b07d160..3bb2960cf 100644 --- a/scm/driver/bitbucket/content.go +++ b/scm/driver/bitbucket/content.go @@ -18,10 +18,8 @@ type contentService struct { } func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm.Content, *scm.Response, error) { - fmt.Println("ref->", ref) urlEncodedRef := url.QueryEscape(ref) endpoint := fmt.Sprintf("/2.0/repositories/%s/src/%s/%s", repo, urlEncodedRef, path) - fmt.Println("endpoint->", endpoint) out := new(bytes.Buffer) res, err := s.client.do(ctx, "GET", endpoint, nil, out) content := &scm.Content{ From 9982b163bac05f12d55ebf975f1d975d15a9a0fb Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Tue, 9 Jan 2024 16:37:17 +0530 Subject: [PATCH 211/282] Update content.go --- scm/driver/stash/content.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scm/driver/stash/content.go b/scm/driver/stash/content.go index f03b6b1bc..fe921e528 100644 --- a/scm/driver/stash/content.go +++ b/scm/driver/stash/content.go @@ -8,6 +8,7 @@ import ( "bytes" "context" "fmt" + "net/url" "github.com/drone/go-scm/scm" ) @@ -17,8 +18,9 @@ type contentService struct { } func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm.Content, *scm.Response, error) { + urlEncodedRef := url.QueryEscape(ref) namespace, name := scm.Split(repo) - endpoint := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/raw/%s?at=%s", namespace, name, path, ref) + endpoint := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/raw/%s?at=%s", namespace, name, path, urlEncodedRef) out := new(bytes.Buffer) res, err := s.client.do(ctx, "GET", endpoint, nil, out) return &scm.Content{ From da64c1c0c9b3f70d7f3c4a35da9157fe45c020fc Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Tue, 9 Jan 2024 16:38:15 +0530 Subject: [PATCH 212/282] Update content.go --- scm/driver/harness/content.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scm/driver/harness/content.go b/scm/driver/harness/content.go index a5a0848d3..348bd7bde 100644 --- a/scm/driver/harness/content.go +++ b/scm/driver/harness/content.go @@ -9,6 +9,7 @@ import ( "encoding/base64" "fmt" "time" + "net/url" "github.com/drone/go-scm/scm" ) @@ -18,8 +19,9 @@ type contentService struct { } func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm.Content, *scm.Response, error) { + urlEncodedRef := url.QueryEscape(ref) repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - endpoint := fmt.Sprintf("api/v1/repos/%s/content/%s?git_ref=%s&include_commit=true", repo, path, ref) + endpoint := fmt.Sprintf("api/v1/repos/%s/content/%s?git_ref=%s&include_commit=true", repo, path, urlEncodedRef) out := new(fileContent) res, err := s.client.do(ctx, "GET", endpoint, nil, out) // decode raw output content From be2ecb2f4ef98f9ee7626921afb9062f871be52d Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Tue, 9 Jan 2024 20:41:04 +0530 Subject: [PATCH 213/282] Update content.go --- scm/driver/harness/content.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scm/driver/harness/content.go b/scm/driver/harness/content.go index 348bd7bde..a5a0848d3 100644 --- a/scm/driver/harness/content.go +++ b/scm/driver/harness/content.go @@ -9,7 +9,6 @@ import ( "encoding/base64" "fmt" "time" - "net/url" "github.com/drone/go-scm/scm" ) @@ -19,9 +18,8 @@ type contentService struct { } func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm.Content, *scm.Response, error) { - urlEncodedRef := url.QueryEscape(ref) repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - endpoint := fmt.Sprintf("api/v1/repos/%s/content/%s?git_ref=%s&include_commit=true", repo, path, urlEncodedRef) + endpoint := fmt.Sprintf("api/v1/repos/%s/content/%s?git_ref=%s&include_commit=true", repo, path, ref) out := new(fileContent) res, err := s.client.do(ctx, "GET", endpoint, nil, out) // decode raw output content From 474ee0b147fba1e48bed86a99ca844e86c093fca Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Wed, 10 Jan 2024 13:27:52 +0530 Subject: [PATCH 214/282] Added UTs --- scm/driver/azure/content_test.go | 3 ++- scm/driver/github/content_test.go | 29 +++++++++++++++++++++++++++++ scm/driver/gitlab/content_test.go | 29 +++++++++++++++++++++++++++++ scm/driver/stash/content_test.go | 22 ++++++++++++++++++++++ 4 files changed, 82 insertions(+), 1 deletion(-) diff --git a/scm/driver/azure/content_test.go b/scm/driver/azure/content_test.go index e674ccdaf..ad857ccd9 100644 --- a/scm/driver/azure/content_test.go +++ b/scm/driver/azure/content_test.go @@ -17,6 +17,7 @@ func TestContentFind(t *testing.T) { gock.New("https:/dev.azure.com/"). Get("/ORG/PROJ/_apis/git/repositories/REPOID/items"). MatchParam("path", "README"). + MatchParam("versionDescriptor.version", "b1&b2"). Reply(200). Type("application/json"). File("testdata/content.json") @@ -26,7 +27,7 @@ func TestContentFind(t *testing.T) { context.Background(), "REPOID", "README", - "", + "b1&b2", ) if err != nil { t.Error(err) diff --git a/scm/driver/github/content_test.go b/scm/driver/github/content_test.go index 06923bf74..c1e8d4110 100644 --- a/scm/driver/github/content_test.go +++ b/scm/driver/github/content_test.go @@ -47,6 +47,35 @@ func TestContentFind(t *testing.T) { t.Log(diff) } + gock.New("https://api.github.com"). + Get("/repos/octocat/hello-world/contents/README"). + MatchParam("ref", "b1&b2"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/content.json") + + client = NewDefault() + got, res, err = client.Contents.Find( + context.Background(), + "octocat/hello-world", + "README", + "b1&b2", + ) + if err != nil { + t.Error(err) + return + } + + want = new(scm.Content) + raw, _ = ioutil.ReadFile("testdata/content.json.golden") + _ = json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + t.Run("Request", testRequest(res)) t.Run("Rate", testRate(res)) } diff --git a/scm/driver/gitlab/content_test.go b/scm/driver/gitlab/content_test.go index d7baa5bbe..11cfa50a7 100644 --- a/scm/driver/gitlab/content_test.go +++ b/scm/driver/gitlab/content_test.go @@ -48,6 +48,35 @@ func TestContentFind(t *testing.T) { t.Log(diff) } + gock.New("https://gitlab.com"). + Get("/api/v4/projects/diaspora/diaspora/repository/files/app/models/key.rb"). + MatchParam("ref", "b1&b2"). + Reply(200). + Type("application/json"). + SetHeaders(mockHeaders). + File("testdata/content.json") + + client = NewDefault() + got, res, err = client.Contents.Find( + context.Background(), + "diaspora/diaspora", + "app/models/key.rb", + "b1&b2", + ) + if err != nil { + t.Error(err) + return + } + + want = new(scm.Content) + raw, _ = ioutil.ReadFile("testdata/content.json.golden") + json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + t.Run("Request", testRequest(res)) t.Run("Rate", testRate(res)) } diff --git a/scm/driver/stash/content_test.go b/scm/driver/stash/content_test.go index f5ff36965..68f84f050 100644 --- a/scm/driver/stash/content_test.go +++ b/scm/driver/stash/content_test.go @@ -40,6 +40,28 @@ func TestContentFind(t *testing.T) { t.Errorf("Unexpected Results") t.Log(diff) } + + gock.New("http://example.com:7990"). + Get("/rest/api/1.0/projects/PRJ/repos/my-repo/raw/README"). + MatchParam("at", "b1&b2"). + Reply(200). + Type("text/plain"). + File("testdata/content.txt") + + client, _ = New("http://example.com:7990") + got, _, err = client.Contents.Find(context.Background(), "PRJ/my-repo", "README", "b1&b2") + if err != nil { + t.Error(err) + } + + want = new(scm.Content) + raw, _ = ioutil.ReadFile("testdata/content.json.golden") + _ = json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } } func TestContentCreate(t *testing.T) { From f5e5a7510a7bedcd391b0a0e257b261bbaee1601 Mon Sep 17 00:00:00 2001 From: raghavharness Date: Tue, 6 Feb 2024 19:30:46 +0530 Subject: [PATCH 215/282] set query params for pagination in bitbucket server --- scm/driver/stash/pr.go | 2 +- scm/driver/stash/util.go | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/scm/driver/stash/pr.go b/scm/driver/stash/pr.go index 87cdb8fda..e1229e271 100644 --- a/scm/driver/stash/pr.go +++ b/scm/driver/stash/pr.go @@ -67,7 +67,7 @@ func (s *pullService) ListComments(context.Context, string, int, scm.ListOptions func (s *pullService) ListCommits(ctx context.Context, repo string, number int, opts scm.ListOptions) ([]*scm.Commit, *scm.Response, error) { namespace, name := scm.Split(repo) - path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/pull-requests/%d/commits", namespace, name, number) + path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/pull-requests/%d/commits?%s", namespace, name, number, encodeListOptionsV2(opts)) out := new(commits) res, err := s.client.do(ctx, "GET", path, nil, out) if !out.pagination.LastPage.Bool { diff --git a/scm/driver/stash/util.go b/scm/driver/stash/util.go index 1dbcb71e8..c0e1c2825 100644 --- a/scm/driver/stash/util.go +++ b/scm/driver/stash/util.go @@ -12,6 +12,10 @@ import ( "github.com/drone/go-scm/scm" ) +const ( + DEFAULT_LIMIT = 25 +) + func encodeListOptions(opts scm.ListOptions) string { params := url.Values{} if opts.Page > 1 { @@ -25,6 +29,22 @@ func encodeListOptions(opts scm.ListOptions) string { return params.Encode() } +func encodeListOptionsV2(opts scm.ListOptions) string { + params := url.Values{} + limit := DEFAULT_LIMIT + if opts.Size != 0 { + limit = opts.Size + } + params.Set("limit", strconv.Itoa(limit)) + + if opts.Page > 0 { + params.Set("start", strconv.Itoa( + (opts.Page-1)*limit), + ) + } + return params.Encode() +} + func encodeBranchListOptions(opts scm.BranchListOptions) string { params := url.Values{} if opts.SearchTerm != "" { From 8a567836e95de3ded93e368b43260a244a86ac9a Mon Sep 17 00:00:00 2001 From: raghavharness Date: Tue, 6 Feb 2024 20:15:41 +0530 Subject: [PATCH 216/282] set query params for pagination in bitbucket server --- scm/driver/stash/util.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scm/driver/stash/util.go b/scm/driver/stash/util.go index c0e1c2825..f034fb9ff 100644 --- a/scm/driver/stash/util.go +++ b/scm/driver/stash/util.go @@ -13,7 +13,7 @@ import ( ) const ( - DEFAULT_LIMIT = 25 + defaultLimit = 25 ) func encodeListOptions(opts scm.ListOptions) string { @@ -31,7 +31,7 @@ func encodeListOptions(opts scm.ListOptions) string { func encodeListOptionsV2(opts scm.ListOptions) string { params := url.Values{} - limit := DEFAULT_LIMIT + limit := defaultLimit if opts.Size != 0 { limit = opts.Size } From 4f7b529d3ac9fd2260862f56df2e10a9db00e11e Mon Sep 17 00:00:00 2001 From: raghavharness Date: Tue, 6 Feb 2024 20:19:57 +0530 Subject: [PATCH 217/282] set query params for pagination in bitbucket server --- scm/driver/stash/util_test.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/scm/driver/stash/util_test.go b/scm/driver/stash/util_test.go index 86e2e331d..d9e86101c 100644 --- a/scm/driver/stash/util_test.go +++ b/scm/driver/stash/util_test.go @@ -32,6 +32,28 @@ func Test_encodeListOptions(t *testing.T) { } } +func Test_encodeListOptionsV2(t *testing.T) { + tests := []struct { + page int + size int + text string + }{ + {page: 0, size: 30, text: "limit=30"}, + {page: 1, size: 30, text: "limit=30&start=0"}, + {page: 5, size: 30, text: "limit=30&start=120"}, + {page: 2, size: 5, text: "limit=5&start=5"}, + } + for _, test := range tests { + opts := scm.ListOptions{ + Page: test.page, + Size: test.size, + } + if got, want := encodeListOptionsV2(opts), test.text; got != want { + t.Errorf("Want encoded list options %q, got %q", want, got) + } + } +} + func Test_encodePullRequestListOptions(t *testing.T) { t.Parallel() opts := scm.PullRequestListOptions{ From 9d3ec6b9c3ed771602699ca406a825c7e71a9a04 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Sat, 10 Feb 2024 04:58:36 +0530 Subject: [PATCH 218/282] feat: change as per new contract of webhook in harness code (#294) * feat: change as per new contract of webhook in harness code * feat: change as per new contract of webhook in harness code * feat: change as per new contract of webhook in harness code * feat: change as per new contract of webhook in harness code * feat: change as per new contract of webhook in harness code * feat: change as per new contract of webhook in harness code * feat: change as per new contract of webhook in harness code * feat: change as per new contract of webhook in harness code --- scm/driver/harness/git.go | 15 ++- scm/driver/harness/harness.go | 4 - scm/driver/harness/pr.go | 43 +++++++- scm/driver/harness/repo.go | 12 +-- scm/driver/harness/testdata/hook.json | 3 +- scm/driver/harness/testdata/hook.json.golden | 2 +- scm/driver/harness/testdata/hook_create.json | 2 +- scm/driver/harness/testdata/hooks.json | 3 +- scm/driver/harness/testdata/hooks.json.golden | 2 +- .../testdata/webhooks/branch_create.json | 18 ++++ .../testdata/webhooks/branch_updated.json | 18 ++++ .../webhooks/pull_request_branch_updated.json | 18 ++++ .../webhooks/pull_request_closed.json | 18 ++++ .../webhooks/pull_request_merged.json | 18 ++++ .../webhooks/pull_request_opened.json | 18 ++++ .../webhooks/pull_request_reopened.json | 18 ++++ scm/driver/harness/util.go | 8 +- scm/driver/harness/webhook.go | 102 ++++++++++-------- 18 files changed, 252 insertions(+), 70 deletions(-) diff --git a/scm/driver/harness/git.go b/scm/driver/harness/git.go index 25923a56e..0416338b5 100644 --- a/scm/driver/harness/git.go +++ b/scm/driver/harness/git.go @@ -7,6 +7,7 @@ package harness import ( "context" "fmt" + "strings" "time" "github.com/drone/go-scm/scm" @@ -72,8 +73,12 @@ func (s *gitService) ListTags(ctx context.Context, repo string, _ scm.ListOption return nil, nil, scm.ErrNotSupported } -func (s *gitService) ListChanges(ctx context.Context, repo, ref string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported +func (s *gitService) ListChanges(ctx context.Context, repo, ref string, opts scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s/commits/%s/diff?%s", harnessURI, ref, encodeListOptions(opts)) + out := []*fileDiff{} + res, err := s.client.do(ctx, "POST", path, nil, &out) + return convertFileDiffs(out), res, err } func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { @@ -209,8 +214,8 @@ func convertChange(src *fileDiff) *scm.Change { return &scm.Change{ Path: src.Path, PrevFilePath: src.OldPath, - Added: src.Status == "ADDED", - Renamed: src.Status == "RENAMED", - Deleted: src.Status == "DELETED", + Added: strings.EqualFold(src.Status, "ADDED"), + Renamed: strings.EqualFold(src.Status, "RENAMED"), + Deleted: strings.EqualFold(src.Status, "DELETED"), } } diff --git a/scm/driver/harness/harness.go b/scm/driver/harness/harness.go index 9b36f87f3..1feb6a463 100644 --- a/scm/driver/harness/harness.go +++ b/scm/driver/harness/harness.go @@ -9,7 +9,6 @@ import ( "context" "encoding/json" "errors" - "fmt" "io" "net/http" "net/url" @@ -20,9 +19,6 @@ import ( // New returns a new gitness API client. func New(uri, account, organization, project string) (*scm.Client, error) { - if !((organization == "" && account == "" && project == "") || (organization != "" && account != "" && project != "")) { - return nil, fmt.Errorf("harness account, organization and project are required") - } base, err := url.Parse(uri) if err != nil { return nil, err diff --git a/scm/driver/harness/pr.go b/scm/driver/harness/pr.go index 9b5e05724..7acf07124 100644 --- a/scm/driver/harness/pr.go +++ b/scm/driver/harness/pr.go @@ -7,6 +7,7 @@ package harness import ( "context" "fmt" + "strings" "time" "github.com/drone/go-scm/scm" @@ -30,7 +31,11 @@ func (s *pullService) FindComment(context.Context, string, int, int) (*scm.Comme } func (s *pullService) List(ctx context.Context, repo string, opts scm.PullRequestListOptions) ([]*scm.PullRequest, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s/pullreq?%s", harnessURI, encodePullRequestListOptions(opts)) + out := []*pr{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertPullRequestList(out), res, err } func (s *pullService) ListComments(context.Context, string, int, scm.ListOptions) ([]*scm.Comment, *scm.Response, error) { @@ -45,8 +50,12 @@ func (s *pullService) ListCommits(ctx context.Context, repo string, index int, o return convertCommits(out), res, err } -func (s *pullService) ListChanges(context.Context, string, int, scm.ListOptions) ([]*scm.Change, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported +func (s *pullService) ListChanges(ctx context.Context, repo string, number int, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s/pullreq/%d/diff", harnessURI, number) + out := []*fileDiff{} + res, err := s.client.do(ctx, "POST", path, nil, &out) + return convertFileDiffs(out), res, err } func (s *pullService) Create(ctx context.Context, repo string, input *scm.PullRequestInput) (*scm.PullRequest, *scm.Response, error) { @@ -209,3 +218,31 @@ func convertCommit(src *commit) *scm.Commit { }, } } + +func convertFileDiffs(diff []*fileDiff) []*scm.Change { + var dst []*scm.Change + for _, v := range diff { + dst = append(dst, convertFileDiff(v)) + } + return dst +} + +func convertFileDiff(diff *fileDiff) *scm.Change { + return &scm.Change{ + Path: diff.Path, + Added: strings.EqualFold(diff.Status, "ADDED"), + Renamed: strings.EqualFold(diff.Status, "RENAMED"), + Deleted: strings.EqualFold(diff.Status, "DELETED"), + Sha: diff.SHA, + BlobID: "", + PrevFilePath: diff.OldPath, + } +} + +func convertPullRequestList(from []*pr) []*scm.PullRequest { + to := []*scm.PullRequest{} + for _, v := range from { + to = append(to, convertPullRequest(v)) + } + return to +} diff --git a/scm/driver/harness/repo.go b/scm/driver/harness/repo.go index b467a03db..496bc1492 100644 --- a/scm/driver/harness/repo.go +++ b/scm/driver/harness/repo.go @@ -74,8 +74,7 @@ func (s *repositoryService) CreateHook(ctx context.Context, repo string, input * path := fmt.Sprintf("api/v1/repos/%s/webhooks", harnessURI) in := new(hook) in.Enabled = true - in.DisplayName = input.Name - in.UID = input.Name + in.Identifier = input.Name in.Secret = input.Secret in.Insecure = input.SkipVerify in.URL = input.Target @@ -130,12 +129,10 @@ type ( Created int `json:"created"` CreatedBy int `json:"created_by"` Description string `json:"description"` - DisplayName string `json:"display_name"` Enabled bool `json:"enabled"` HasSecret bool `json:"has_secret"` Secret string `json:"secret"` - ID int `json:"id"` - UID string `json:"uid"` + Identifier string `json:"identifier"` Insecure bool `json:"insecure"` LatestExecutionResult string `json:"latest_execution_result"` ParentID int `json:"parent_id"` @@ -184,8 +181,9 @@ func convertHookList(from []*hook) []*scm.Hook { func convertHook(from *hook) *scm.Hook { return &scm.Hook{ - ID: strconv.Itoa(from.ID), - Name: from.DisplayName, + // keeping id same as name + ID: from.Identifier, + Name: from.Identifier, Active: from.Enabled, Target: from.URL, Events: from.Triggers, diff --git a/scm/driver/harness/testdata/hook.json b/scm/driver/harness/testdata/hook.json index 994de6ed8..cfae54972 100644 --- a/scm/driver/harness/testdata/hook.json +++ b/scm/driver/harness/testdata/hook.json @@ -1,12 +1,11 @@ { - "id": 6, "version": 1, "parent_id": 11, "parent_type": "repo", "created_by": 14, "created": 1675867490853, "updated": 1675867531549, - "display_name": "webhookname", + "identifier": "webhookname", "description": "webhookdescription", "url": "http://1.1.1.1", "enabled": true, diff --git a/scm/driver/harness/testdata/hook.json.golden b/scm/driver/harness/testdata/hook.json.golden index 53463fce4..686b5db97 100644 --- a/scm/driver/harness/testdata/hook.json.golden +++ b/scm/driver/harness/testdata/hook.json.golden @@ -1,5 +1,5 @@ { - "ID": "6", + "ID": "webhookname", "Name": "webhookname", "Target": "http://1.1.1.1", "Events": [], diff --git a/scm/driver/harness/testdata/hook_create.json b/scm/driver/harness/testdata/hook_create.json index 131b6d7cb..cd88b4357 100644 --- a/scm/driver/harness/testdata/hook_create.json +++ b/scm/driver/harness/testdata/hook_create.json @@ -6,7 +6,7 @@ "created_by": 14, "created": 1675872629243, "updated": 1675872777592, - "display_name": "drone", + "identifier": "drone", "description": "", "url": "https://example.com", "enabled": true, diff --git a/scm/driver/harness/testdata/hooks.json b/scm/driver/harness/testdata/hooks.json index 372ad34a7..9e539cecd 100644 --- a/scm/driver/harness/testdata/hooks.json +++ b/scm/driver/harness/testdata/hooks.json @@ -1,13 +1,12 @@ [ { - "id": 6, "version": 1, "parent_id": 11, "parent_type": "repo", "created_by": 14, "created": 1675867490853, "updated": 1675867531549, - "display_name": "webhookname", + "identifier": "webhookname", "description": "webhookdescription", "url": "http://1.1.1.1", "enabled": true, diff --git a/scm/driver/harness/testdata/hooks.json.golden b/scm/driver/harness/testdata/hooks.json.golden index f21533cbe..317aa8125 100644 --- a/scm/driver/harness/testdata/hooks.json.golden +++ b/scm/driver/harness/testdata/hooks.json.golden @@ -1,6 +1,6 @@ [ { - "ID": "6", + "ID": "webhookname", "Name": "webhookname", "Target": "http://1.1.1.1", "Events": [], diff --git a/scm/driver/harness/testdata/webhooks/branch_create.json b/scm/driver/harness/testdata/webhooks/branch_create.json index 51ff0b383..426f9c54e 100644 --- a/scm/driver/harness/testdata/webhooks/branch_create.json +++ b/scm/driver/harness/testdata/webhooks/branch_create.json @@ -45,6 +45,24 @@ "when": "2023-02-01T13:21:15-08:00" } }, + "head_commit": { + "sha": "aeafa0e2e4ec6909ad75cb8fad57c0b1eb5986e6", + "message": "version 4", + "author": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-02-01T13:21:15-08:00" + }, + "committer": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-02-01T13:21:15-08:00" + } + }, "old_sha": "0000000000000000000000000000000000000000", "forced": false } \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/branch_updated.json b/scm/driver/harness/testdata/webhooks/branch_updated.json index 903fea7dd..844bcfd03 100644 --- a/scm/driver/harness/testdata/webhooks/branch_updated.json +++ b/scm/driver/harness/testdata/webhooks/branch_updated.json @@ -45,6 +45,24 @@ "when": "2023-12-05T11:59:39Z" } }, + "head_commit": { + "sha": "92e21bfcddc1418079cddbb518ad6fd72917798a", + "message": "Create asdsad (#2)", + "author": { + "identity": { + "name": "abhinav.singh@harness.io", + "email": "abhinav.singh@harness.io" + }, + "when": "2023-12-05T11:59:39Z" + }, + "committer": { + "identity": { + "name": "Harness", + "email": "noreply@harness.io" + }, + "when": "2023-12-05T11:59:39Z" + } + }, "old_sha": "a273c385628167932e10caaa58e12550c491f241", "forced": false } \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json index 144fc3f3e..8a88fc594 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json +++ b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json @@ -76,6 +76,24 @@ "when": "2023-02-01T13:28:55-08:00" } }, + "head_commit": { + "sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef", + "message": "updated b2", + "author": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-02-01T13:28:55-08:00" + }, + "committer": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-02-01T13:28:55-08:00" + } + }, "old_sha": "d74b1ebfe520ac01b209dd9085f005884cc9f4cd", "forced": false } \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_closed.json b/scm/driver/harness/testdata/webhooks/pull_request_closed.json index 496e01610..4f47de5fa 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_closed.json +++ b/scm/driver/harness/testdata/webhooks/pull_request_closed.json @@ -74,5 +74,23 @@ }, "when": "2023-12-20T13:10:47+05:30" } + }, + "head_commit": { + "sha": "27822dd2ec788f924c97b0b194c5bfd906f2e574", + "message": "", + "author": { + "identity": { + "name": "Administrator", + "email": "admin@gitness.io" + }, + "when": "2023-12-20T13:10:47+05:30" + }, + "committer": { + "identity": { + "name": "Gitness", + "email": "system@gitness.io" + }, + "when": "2023-12-20T13:10:47+05:30" + } } } \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_merged.json b/scm/driver/harness/testdata/webhooks/pull_request_merged.json index 54beca25c..f8cd669b8 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_merged.json +++ b/scm/driver/harness/testdata/webhooks/pull_request_merged.json @@ -75,5 +75,23 @@ }, "when": "2023-12-20T13:40:52+05:30" } + }, + "head_commit": { + "sha": "4ec41187008f77222a60dfa21cdbd980f6490443", + "message": "", + "author": { + "identity": { + "name": "Administrator", + "email": "admin@gitness.io" + }, + "when": "2023-12-20T13:40:52+05:30" + }, + "committer": { + "identity": { + "name": "Gitness", + "email": "system@gitness.io" + }, + "when": "2023-12-20T13:40:52+05:30" + } } } \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_opened.json b/scm/driver/harness/testdata/webhooks/pull_request_opened.json index abc82426c..7c1715f19 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_opened.json +++ b/scm/driver/harness/testdata/webhooks/pull_request_opened.json @@ -75,5 +75,23 @@ }, "when": "2023-01-31T22:01:55-08:00" } + }, + "head_commit": { + "sha": "d74b1ebfe520ac01b209dd9085f005884cc9f4cd", + "message": "Update b.txt", + "author": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-01-31T22:01:55-08:00" + }, + "committer": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-01-31T22:01:55-08:00" + } } } \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_reopened.json b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json index ab57a9e14..a7408779f 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_reopened.json +++ b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json @@ -75,5 +75,23 @@ }, "when": "2023-02-01T13:28:55-08:00" } + }, + "head_commit": { + "sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef", + "message": "updated b2", + "author": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-02-01T13:28:55-08:00" + }, + "committer": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-02-01T13:28:55-08:00" + } } } \ No newline at end of file diff --git a/scm/driver/harness/util.go b/scm/driver/harness/util.go index 78fc8cc9e..d094c8257 100644 --- a/scm/driver/harness/util.go +++ b/scm/driver/harness/util.go @@ -15,7 +15,13 @@ import ( func buildHarnessURI(account, organization, project, repo string) (uri string) { if account != "" { - uri = fmt.Sprintf("%s/%s/%s/", account, organization, project) + if project != "" { + uri = fmt.Sprintf("%s/%s/%s/", account, organization, project) + } else if organization != "" { + uri = fmt.Sprintf("%s/%s/", account, organization) + } else { + uri = fmt.Sprintf("%s/", account) + } if repo != "" { uri += fmt.Sprintf("%s/+", repo) } else { diff --git a/scm/driver/harness/webhook.go b/scm/driver/harness/webhook.go index 4a087d629..73e7bd920 100644 --- a/scm/driver/harness/webhook.go +++ b/scm/driver/harness/webhook.go @@ -167,6 +167,9 @@ type ( } `json:"identity"` When string `json:"when"` } `json:"committer"` + Added []string `json:"added"` + Modified []string `json:"modified"` + Removed []string `json:"removed"` } comment struct { ID int `json:"id"` @@ -174,37 +177,41 @@ type ( } // harness pull request webhook payload pullRequestHook struct { - Trigger string `json:"trigger"` - Repo repo `json:"repo"` - Principal principal `json:"principal"` - PullReq pullReq `json:"pull_req"` - TargetRef targetRef `json:"target_ref"` - Ref ref `json:"ref"` - Sha string `json:"sha"` - Commit hookCommit `json:"commit"` + Trigger string `json:"trigger"` + Repo repo `json:"repo"` + Principal principal `json:"principal"` + PullReq pullReq `json:"pull_req"` + TargetRef targetRef `json:"target_ref"` + Ref ref `json:"ref"` + Sha string `json:"sha"` + HeadCommit hookCommit `json:"head_commit"` + Commits []hookCommit `json:"commits"` + TotalCommitsCount int64 `json:"total_commits_count"` } // harness push webhook payload pushHook struct { - Trigger string `json:"trigger"` - Repo repo `json:"repo"` - Principal principal `json:"principal"` - Ref ref `json:"ref"` - Commit hookCommit `json:"commit"` - Sha string `json:"sha"` - OldSha string `json:"old_sha"` - Forced bool `json:"forced"` + Trigger string `json:"trigger"` + Repo repo `json:"repo"` + Principal principal `json:"principal"` + Ref ref `json:"ref"` + HeadCommit hookCommit `json:"head_commit"` + Sha string `json:"sha"` + OldSha string `json:"old_sha"` + Forced bool `json:"forced"` + Commits []hookCommit `json:"commits"` + TotalCommitsCount int64 `json:"total_commits_count"` } // harness pull request comment webhook payload pullRequestCommentHook struct { - Trigger string `json:"trigger"` - Repo repo `json:"repo"` - Principal principal `json:"principal"` - PullReq pullReq `json:"pull_req"` - TargetRef targetRef `json:"target_ref"` - Ref ref `json:"ref"` - Sha string `json:"sha"` - Commit hookCommit `json:"commit"` - Comment comment `json:"comment"` + Trigger string `json:"trigger"` + Repo repo `json:"repo"` + Principal principal `json:"principal"` + PullReq pullReq `json:"pull_req"` + TargetRef targetRef `json:"target_ref"` + Ref ref `json:"ref"` + Sha string `json:"sha"` + HeadCommit hookCommit `json:"head_commit"` + Comment comment `json:"comment"` } ) @@ -212,37 +219,46 @@ type ( func convertPullRequestHook(src *pullRequestHook) *scm.PullRequestHook { return &scm.PullRequestHook{ Action: convertAction(src.Trigger), - PullRequest: convertPullReq(src.PullReq, src.Ref, src.Commit), + PullRequest: convertPullReq(src.PullReq, src.Ref, src.HeadCommit), Repo: convertRepo(src.Repo), Sender: convertUser(src.Principal), } } func convertPushHook(src *pushHook) *scm.PushHook { + var commits []scm.Commit + for _, c := range src.Commits { + commits = append(commits, convertHookCommit(c)) + } return &scm.PushHook{ - Ref: src.Ref.Name, - Before: src.OldSha, - After: src.Sha, - Repo: convertRepo(src.Repo), - Commit: scm.Commit{ - Sha: src.Commit.Sha, - Message: src.Commit.Message, - Author: scm.Signature{ - Name: src.Commit.Author.Identity.Name, - Email: src.Commit.Author.Identity.Email, - }, - Committer: scm.Signature{ - Name: src.Commit.Committer.Identity.Name, - Email: src.Commit.Committer.Identity.Email, - }, + Ref: src.Ref.Name, + Before: src.OldSha, + After: src.Sha, + Repo: convertRepo(src.Repo), + Commit: convertHookCommit(src.HeadCommit), + Sender: convertUser(src.Principal), + Commits: commits, + } +} + +func convertHookCommit(c hookCommit) scm.Commit { + return scm.Commit{ + Sha: c.Sha, + Message: c.Message, + Author: scm.Signature{ + Name: c.Author.Identity.Name, + Email: c.Author.Identity.Email, + }, + Committer: scm.Signature{ + Name: c.Committer.Identity.Name, + Email: c.Committer.Identity.Email, }, - Sender: convertUser(src.Principal), } } func convertPullRequestCommentHook(src *pullRequestCommentHook) *scm.PullRequestCommentHook { return &scm.PullRequestCommentHook{ - PullRequest: convertPullReq(src.PullReq, src.Ref, src.Commit), + PullRequest: convertPullReq(src.PullReq, src.Ref, src.HeadCommit), Repo: convertRepo(src.Repo), Comment: scm.Comment{ Body: src.Comment.Text, From 91387e9cb7fe112a4678a057c8a14dfc58570614 Mon Sep 17 00:00:00 2001 From: Nasser Gonzalez Gonzalez Date: Wed, 21 Feb 2024 08:56:20 +0000 Subject: [PATCH 219/282] Add harness comment (#295) * Add the implementation of CreateComment for Harness Code * Add the implementation of CreateComment for Harness Code --- CHANGELOG.md | 35 ++++++++++ scm/driver/harness/pr.go | 65 ++++++++++++++++++- scm/driver/harness/pr_test.go | 44 +++++++++++++ scm/driver/harness/testdata/comment.json | 25 +++++++ .../harness/testdata/comment.json.golden | 15 +++++ 5 files changed, 182 insertions(+), 2 deletions(-) create mode 100644 scm/driver/harness/testdata/comment.json create mode 100644 scm/driver/harness/testdata/comment.json.golden diff --git a/CHANGELOG.md b/CHANGELOG.md index 739e13c01..d63a81137 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,36 @@ # Changelog +## [Unreleased](https://github.com/drone/go-scm/tree/HEAD) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.34.3...HEAD) + +**Closed issues:** + +- Cron Jobs don't run with Gitea-scm [\#292](https://github.com/drone/go-scm/issues/292) + +**Merged pull requests:** + +- feat: change as per new contract of webhook in harness code [\#294](https://github.com/drone/go-scm/pull/294) ([abhinav-harness](https://github.com/abhinav-harness)) +- Stash pr commits pagination [\#293](https://github.com/drone/go-scm/pull/293) ([raghavharness](https://github.com/raghavharness)) +- Added support for branch names containing '&' and '\#' for GetFile Operations. [\#291](https://github.com/drone/go-scm/pull/291) ([senjucanon2](https://github.com/senjucanon2)) + +## [v1.34.3](https://github.com/drone/go-scm/tree/v1.34.3) (2023-12-20) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.34.2...v1.34.3) + +**Merged pull requests:** + +- feat: add pr link as coming from new webhook [\#290](https://github.com/drone/go-scm/pull/290) ([abhinav-harness](https://github.com/abhinav-harness)) + +## [v1.34.2](https://github.com/drone/go-scm/tree/v1.34.2) (2023-12-20) + +[Full Changelog](https://github.com/drone/go-scm/compare/v1.34.1...v1.34.2) + +**Merged pull requests:** + +- feat: support more events in webhook parse in go-scm for gitness [\#289](https://github.com/drone/go-scm/pull/289) ([abhinav-harness](https://github.com/abhinav-harness)) +- fix: ref should be branch name for harness code [\#288](https://github.com/drone/go-scm/pull/288) ([abhinav-harness](https://github.com/abhinav-harness)) + ## [v1.34.1](https://github.com/drone/go-scm/tree/v1.34.1) (2023-12-08) [Full Changelog](https://github.com/drone/go-scm/compare/v1.34.0...v1.34.1) @@ -8,6 +39,10 @@ - fix: use opts for harness list commits [\#286](https://github.com/drone/go-scm/pull/286) ([abhinav-harness](https://github.com/abhinav-harness)) +**Merged pull requests:** + +- \(maint\) v1.34.1 release prep [\#287](https://github.com/drone/go-scm/pull/287) ([tphoney](https://github.com/tphoney)) + ## [v1.34.0](https://github.com/drone/go-scm/tree/v1.34.0) (2023-12-07) [Full Changelog](https://github.com/drone/go-scm/compare/v1.33.0...v1.34.0) diff --git a/scm/driver/harness/pr.go b/scm/driver/harness/pr.go index 7acf07124..f84012655 100644 --- a/scm/driver/harness/pr.go +++ b/scm/driver/harness/pr.go @@ -7,6 +7,7 @@ package harness import ( "context" "fmt" + "strconv" "strings" "time" @@ -72,8 +73,15 @@ func (s *pullService) Create(ctx context.Context, repo string, input *scm.PullRe return convertPullRequest(out), res, err } -func (s *pullService) CreateComment(context.Context, string, int, *scm.CommentInput) (*scm.Comment, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported +func (s *pullService) CreateComment(ctx context.Context, repo string, prNumber int, input *scm.CommentInput) (*scm.Comment, *scm.Response, error) { + harnessQueryParams := fmt.Sprintf("?accountIdentifier=%s&orgIdentifier=%s&projectIdentifier=%s", s.client.account, s.client.organization, s.client.project) + path := fmt.Sprintf("api/v1/repos/%s/pullreq/%d/comments%s", repo, prNumber, harnessQueryParams) + in := &prComment{ + Text: input.Body, + } + out := new(prCommentResponse) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertComment(out), res, err } func (s *pullService) DeleteComment(context.Context, string, int, int) (*scm.Response, error) { @@ -165,6 +173,42 @@ type ( Sha string `json:"sha"` Title string `json:"title"` } + prComment struct { + LineEnd int `json:"line_end"` + LineEndNew bool `json:"line_end_new"` + LineStart int `json:"line_start"` + LineStartNew bool `json:"line_start_new"` + ParentID int `json:"parent_id"` + Path string `json:"path"` + SourceCommitSha string `json:"source_commit_sha"` + TargetCommitSha string `json:"target_commit_sha"` + Text string `json:"text"` + } + prCommentResponse struct { + Id int `json:"id"` + Created int64 `json:"created"` + Updated int64 `json:"updated"` + Edited int64 `json:"edited"` + ParentId interface{} `json:"parent_id"` + RepoId int `json:"repo_id"` + PullreqId int `json:"pullreq_id"` + Order int `json:"order"` + SubOrder int `json:"sub_order"` + Type string `json:"type"` + Kind string `json:"kind"` + Text string `json:"text"` + Payload struct{} `json:"payload"` + Metadata interface{} `json:"metadata"` + Author struct { + Id int `json:"id"` + Uid string `json:"uid"` + DisplayName string `json:"display_name"` + Email string `json:"email"` + Type string `json:"type"` + Created int64 `json:"created"` + Updated int64 `json:"updated"` + } `json:"author"` + } ) // native data structure conversion @@ -246,3 +290,20 @@ func convertPullRequestList(from []*pr) []*scm.PullRequest { } return to } + +func convertComment(comment *prCommentResponse) *scm.Comment { + return &scm.Comment{ + ID: comment.Id, + Body: comment.Text, + Author: scm.User{ + Login: comment.Author.Uid, + Name: comment.Author.DisplayName, + ID: strconv.Itoa(comment.Author.Id), + Email: comment.Author.Email, + Created: time.UnixMilli(comment.Author.Created), + Updated: time.UnixMilli(comment.Author.Updated), + }, + Created: time.UnixMilli(comment.Created), + Updated: time.UnixMilli(comment.Updated), + } +} diff --git a/scm/driver/harness/pr_test.go b/scm/driver/harness/pr_test.go index b9bc5a631..951690164 100644 --- a/scm/driver/harness/pr_test.go +++ b/scm/driver/harness/pr_test.go @@ -7,6 +7,8 @@ package harness import ( "context" "encoding/json" + "fmt" + "github.com/google/go-cmp/cmp/cmpopts" "io/ioutil" "net/http" "testing" @@ -134,3 +136,45 @@ func TestPullCreate(t *testing.T) { t.Log(diff) } } + +func TestPRComment(t *testing.T) { + defer gock.Off() + gock.New(gockOrigin). + Post(fmt.Sprintf("/gateway/code/api/v1/repos/%s/pullreq/1/comments", harnessRepo)). + MatchParam("accountIdentifier", harnessAccount). + MatchParam("orgIdentifier", harnessOrg). + MatchParam("projectIdentifier", harnessProject). + Reply(201). + Type("plain/text"). + File("testdata/comment.json") + + client, _ := New(gockOrigin, harnessAccount, harnessOrg, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + + input := scm.CommentInput{ + Body: "Comment to be created in the PR", + } + + got, _, err := client.PullRequests.CreateComment(context.Background(), harnessRepo, 1, &input) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Comment) + raw, _ := ioutil.ReadFile("testdata/comment.json.golden") + _ = json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want, + cmpopts.IgnoreFields(scm.Comment{}, "Created", "Updated"), + cmpopts.IgnoreFields(scm.User{}, "Created", "Updated")); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} diff --git a/scm/driver/harness/testdata/comment.json b/scm/driver/harness/testdata/comment.json new file mode 100644 index 000000000..fa1a823f5 --- /dev/null +++ b/scm/driver/harness/testdata/comment.json @@ -0,0 +1,25 @@ +{ + "id": 123, + "created": 1708354973112, + "updated": 1708354973112, + "edited": 1708354973112, + "parent_id": null, + "repo_id": 123, + "pullreq_id": 123, + "order": 1, + "sub_order": 0, + "type": "comment", + "kind": "comment", + "text": "Comment to be created in the PR", + "payload": {}, + "metadata": null, + "author": { + "id": 1, + "uid": "identifier", + "display_name": "displayName", + "email": "email@emailprovider.com", + "type": "service", + "created": 1695706039266, + "updated": 1695706039266 + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/comment.json.golden b/scm/driver/harness/testdata/comment.json.golden new file mode 100644 index 000000000..f2e347a95 --- /dev/null +++ b/scm/driver/harness/testdata/comment.json.golden @@ -0,0 +1,15 @@ +{ + "ID": 123, + "Body": "Comment to be created in the PR", + "Author": { + "ID": "1", + "Login": "identifier", + "Name": "displayName", + "Email": "email@emailprovider.com", + "Avatar": "", + "Created": 1695706039266, + "Updated": 1695706039266 + }, + "Created": 1708354973112, + "Updated": 1708354973112 +} \ No newline at end of file From 290c4aad736c684f14e083dd24d84dab391119db Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Fri, 1 Mar 2024 08:18:18 +0530 Subject: [PATCH 220/282] feat: follow new api convention (#296) * feat: follow new api convention * feat: follow new api convention --- scm/driver/harness/content.go | 40 ++++++++++++++++++++++++--------- scm/driver/harness/git.go | 42 +++++++++++++++++++++++++++++------ scm/driver/harness/pr.go | 38 +++++++++++++++++++++++++------ scm/driver/harness/repo.go | 39 +++++++++++++++++++++++++------- scm/driver/harness/util.go | 35 +++++++++++++++++++++++++++++ 5 files changed, 162 insertions(+), 32 deletions(-) diff --git a/scm/driver/harness/content.go b/scm/driver/harness/content.go index a5a0848d3..91e72ecee 100644 --- a/scm/driver/harness/content.go +++ b/scm/driver/harness/content.go @@ -18,8 +18,12 @@ type contentService struct { } func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm.Content, *scm.Response, error) { - repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - endpoint := fmt.Sprintf("api/v1/repos/%s/content/%s?git_ref=%s&include_commit=true", repo, path, ref) + slug := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + repoId, queryParams, err := getRepoAndQueryParams(slug) + if err != nil { + return nil, nil, err + } + endpoint := fmt.Sprintf("api/v1/repos/%s/content/%s?git_ref=%s&include_commit=true&%s", repoId, path, ref, queryParams) out := new(fileContent) res, err := s.client.do(ctx, "GET", endpoint, nil, out) // decode raw output content @@ -33,8 +37,12 @@ func (s *contentService) Find(ctx context.Context, repo, path, ref string) (*scm } func (s *contentService) Create(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { - repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - endpoint := fmt.Sprintf("api/v1/repos/%s/commits", repo) + slug := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + repoId, queryParams, err := getRepoAndQueryParams(slug) + if err != nil { + return nil, err + } + endpoint := fmt.Sprintf("api/v1/repos/%s/commits?%s", repoId, queryParams) a := action{ Action: "CREATE", Path: path, @@ -53,8 +61,12 @@ func (s *contentService) Create(ctx context.Context, repo, path string, params * } func (s *contentService) Update(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { - repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - endpoint := fmt.Sprintf("api/v1/repos/%s/commits", repo) + slug := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + repoId, queryParams, err := getRepoAndQueryParams(slug) + if err != nil { + return nil, err + } + endpoint := fmt.Sprintf("api/v1/repos/%s/commits?%s", repoId, queryParams) a := action{ Action: "UPDATE", Path: path, @@ -74,8 +86,12 @@ func (s *contentService) Update(ctx context.Context, repo, path string, params * } func (s *contentService) Delete(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) { - repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - endpoint := fmt.Sprintf("api/v1/repos/%s/commits", repo) + slug := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + repoId, queryParams, err := getRepoAndQueryParams(slug) + if err != nil { + return nil, err + } + endpoint := fmt.Sprintf("api/v1/repos/%s/commits?%s", repoId, queryParams) a := action{ Action: "DELETE", Path: path, @@ -93,8 +109,12 @@ func (s *contentService) Delete(ctx context.Context, repo, path string, params * } func (s *contentService) List(ctx context.Context, repo, path, ref string, _ scm.ListOptions) ([]*scm.ContentInfo, *scm.Response, error) { - repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - endpoint := fmt.Sprintf("api/v1/repos/%s/content/%s?git_ref=%s&include_commit=true", repo, path, ref) + slug := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + repoId, queryParams, err := getRepoAndQueryParams(slug) + if err != nil { + return nil, nil, err + } + endpoint := fmt.Sprintf("api/v1/repos/%s/content/%s?git_ref=%s&include_commit=true&%s", repoId, path, ref, queryParams) out := new(contentList) res, err := s.client.do(ctx, "GET", endpoint, nil, &out) return convertContentInfoList(out.Content.Entries), res, err diff --git a/scm/driver/harness/git.go b/scm/driver/harness/git.go index 0416338b5..adbd34c26 100644 --- a/scm/driver/harness/git.go +++ b/scm/driver/harness/git.go @@ -19,7 +19,11 @@ type gitService struct { func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.ReferenceInput) (*scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - path := fmt.Sprintf("api/v1/repos/%s/branches", harnessURI) + repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + if err != nil { + return nil, err + } + path := fmt.Sprintf("api/v1/repos/%s/branches?%s", repoId, queryParams) in := &branchInput{ Name: params.Name, Target: params.Sha, @@ -29,7 +33,11 @@ func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm. func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - path := fmt.Sprintf("api/v1/repos/%s/branches/%s", harnessURI, name) + repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + if err != nil { + return nil, nil, err + } + path := fmt.Sprintf("api/v1/repos/%s/branches/%s?%s", repoId, name, queryParams) out := new(branch) res, err := s.client.do(ctx, "GET", path, nil, out) return convertBranch(out), res, err @@ -37,7 +45,11 @@ func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Re func (s *gitService) FindCommit(ctx context.Context, repo, ref string) (*scm.Commit, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - path := fmt.Sprintf("api/v1/repos/%s/commits/%s", harnessURI, ref) + repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + if err != nil { + return nil, nil, err + } + path := fmt.Sprintf("api/v1/repos/%s/commits/%s?%s", repoId, ref, queryParams) out := new(commitInfo) res, err := s.client.do(ctx, "GET", path, nil, out) return convertCommitInfo(out), res, err @@ -49,7 +61,11 @@ func (s *gitService) FindTag(ctx context.Context, repo, name string) (*scm.Refer func (s *gitService) ListBranches(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - path := fmt.Sprintf("api/v1/repos/%s/branches?%s", harnessURI, encodeListOptions(opts)) + repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + if err != nil { + return nil, nil, err + } + path := fmt.Sprintf("api/v1/repos/%s/branches?%s&%s", repoId, encodeListOptions(opts), queryParams) out := []*branch{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertBranchList(out), res, err @@ -63,7 +79,11 @@ func (s *gitService) ListBranchesV2(ctx context.Context, repo string, opts scm.B func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - path := fmt.Sprintf("api/v1/repos/%s/commits?%s", harnessURI, encodeCommitListOptions(opts)) + repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + if err != nil { + return nil, nil, err + } + path := fmt.Sprintf("api/v1/repos/%s/commits?%s&%s", repoId, encodeCommitListOptions(opts), queryParams) out := new(commits) res, err := s.client.do(ctx, "GET", path, nil, &out) return convertCommitList(out), res, err @@ -75,7 +95,11 @@ func (s *gitService) ListTags(ctx context.Context, repo string, _ scm.ListOption func (s *gitService) ListChanges(ctx context.Context, repo, ref string, opts scm.ListOptions) ([]*scm.Change, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - path := fmt.Sprintf("api/v1/repos/%s/commits/%s/diff?%s", harnessURI, ref, encodeListOptions(opts)) + repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + if err != nil { + return nil, nil, err + } + path := fmt.Sprintf("api/v1/repos/%s/commits/%s/diff?%s&%s", repoId, ref, encodeListOptions(opts), queryParams) out := []*fileDiff{} res, err := s.client.do(ctx, "POST", path, nil, &out) return convertFileDiffs(out), res, err @@ -83,7 +107,11 @@ func (s *gitService) ListChanges(ctx context.Context, repo, ref string, opts scm func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - path := fmt.Sprintf("api/v1/repos/%s/diff/%s...%s", harnessURI, source, target) + repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + if err != nil { + return nil, nil, err + } + path := fmt.Sprintf("api/v1/repos/%s/diff/%s...%s?%s", repoId, source, target, queryParams) out := []*fileDiff{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertChangeList(out), res, err diff --git a/scm/driver/harness/pr.go b/scm/driver/harness/pr.go index f84012655..35cadd20a 100644 --- a/scm/driver/harness/pr.go +++ b/scm/driver/harness/pr.go @@ -20,7 +20,11 @@ type pullService struct { func (s *pullService) Find(ctx context.Context, repo string, index int) (*scm.PullRequest, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - path := fmt.Sprintf("api/v1/repos/%s/pullreq/%d", harnessURI, index) + repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + if err != nil { + return nil, nil, err + } + path := fmt.Sprintf("api/v1/repos/%s/pullreq/%d?%s", repoId, index, queryParams) out := new(pr) res, err := s.client.do(ctx, "GET", path, nil, out) return convertPullRequest(out), res, err @@ -33,7 +37,11 @@ func (s *pullService) FindComment(context.Context, string, int, int) (*scm.Comme func (s *pullService) List(ctx context.Context, repo string, opts scm.PullRequestListOptions) ([]*scm.PullRequest, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - path := fmt.Sprintf("api/v1/repos/%s/pullreq?%s", harnessURI, encodePullRequestListOptions(opts)) + repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + if err != nil { + return nil, nil, err + } + path := fmt.Sprintf("api/v1/repos/%s/pullreq?%s&%s", repoId, encodePullRequestListOptions(opts), queryParams) out := []*pr{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertPullRequestList(out), res, err @@ -45,7 +53,11 @@ func (s *pullService) ListComments(context.Context, string, int, scm.ListOptions func (s *pullService) ListCommits(ctx context.Context, repo string, index int, opts scm.ListOptions) ([]*scm.Commit, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - path := fmt.Sprintf("api/v1/repos/%s/pullreq/%d/commits?%s", harnessURI, index, encodeListOptions(opts)) + repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + if err != nil { + return nil, nil, err + } + path := fmt.Sprintf("api/v1/repos/%s/pullreq/%d/commits?%s&%s", repoId, index, encodeListOptions(opts), queryParams) out := []*commit{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertCommits(out), res, err @@ -53,7 +65,11 @@ func (s *pullService) ListCommits(ctx context.Context, repo string, index int, o func (s *pullService) ListChanges(ctx context.Context, repo string, number int, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - path := fmt.Sprintf("api/v1/repos/%s/pullreq/%d/diff", harnessURI, number) + repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + if err != nil { + return nil, nil, err + } + path := fmt.Sprintf("api/v1/repos/%s/pullreq/%d/diff?%s", repoId, number, queryParams) out := []*fileDiff{} res, err := s.client.do(ctx, "POST", path, nil, &out) return convertFileDiffs(out), res, err @@ -61,7 +77,11 @@ func (s *pullService) ListChanges(ctx context.Context, repo string, number int, func (s *pullService) Create(ctx context.Context, repo string, input *scm.PullRequestInput) (*scm.PullRequest, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - path := fmt.Sprintf("api/v1/repos/%s/pullreq", harnessURI) + repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + if err != nil { + return nil, nil, err + } + path := fmt.Sprintf("api/v1/repos/%s/pullreq?%s", repoId, queryParams) in := &prInput{ Title: input.Title, Description: input.Body, @@ -74,8 +94,12 @@ func (s *pullService) Create(ctx context.Context, repo string, input *scm.PullRe } func (s *pullService) CreateComment(ctx context.Context, repo string, prNumber int, input *scm.CommentInput) (*scm.Comment, *scm.Response, error) { - harnessQueryParams := fmt.Sprintf("?accountIdentifier=%s&orgIdentifier=%s&projectIdentifier=%s", s.client.account, s.client.organization, s.client.project) - path := fmt.Sprintf("api/v1/repos/%s/pullreq/%d/comments%s", repo, prNumber, harnessQueryParams) + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + if err != nil { + return nil, nil, err + } + path := fmt.Sprintf("api/v1/repos/%s/pullreq/%d/comments?%s", repoId, prNumber, queryParams) in := &prComment{ Text: input.Body, } diff --git a/scm/driver/harness/repo.go b/scm/driver/harness/repo.go index 496bc1492..dc489a267 100644 --- a/scm/driver/harness/repo.go +++ b/scm/driver/harness/repo.go @@ -18,8 +18,12 @@ type repositoryService struct { } func (s *repositoryService) Find(ctx context.Context, repo string) (*scm.Repository, *scm.Response, error) { - repo = buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - path := fmt.Sprintf("api/v1/repos/%s", repo) + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + if err != nil { + return nil, nil, err + } + path := fmt.Sprintf("api/v1/repos/%s?%s", repoId, queryParams) out := new(repository) res, err := s.client.do(ctx, "GET", path, nil, out) if err != nil { @@ -34,7 +38,11 @@ func (s *repositoryService) Find(ctx context.Context, repo string) (*scm.Reposit func (s *repositoryService) FindHook(ctx context.Context, repo string, id string) (*scm.Hook, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - path := fmt.Sprintf("api/v1/repos/%s/webhooks/%s", harnessURI, id) + repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + if err != nil { + return nil, nil, err + } + path := fmt.Sprintf("api/v1/repos/%s/webhooks/%s?%s", repoId, id, queryParams) out := new(hook) res, err := s.client.do(ctx, "GET", path, nil, &out) return convertHook(out), res, err @@ -45,8 +53,11 @@ func (s *repositoryService) FindPerms(ctx context.Context, repo string) (*scm.Pe } func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { - harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, "") - path := fmt.Sprintf("api/v1/spaces/%s/repos?sort=path&order=asc&%s", harnessURI, encodeListOptions(opts)) + queryParams := fmt.Sprintf("%s=%s&%s=%s&%s=%s&%s=%s", + projectIdentifier, s.client.project, orgIdentifier, s.client.organization, accountIdentifier, s.client.account, + routingId, s.client.account) + + path := fmt.Sprintf("api/v1/repos?sort=path&order=asc&%s&%s", encodeListOptions(opts), queryParams) out := []*repository{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertRepositoryList(out), res, err @@ -59,7 +70,11 @@ func (s *repositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions func (s *repositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - path := fmt.Sprintf("api/v1/repos/%s/webhooks?sort=display_name&order=asc&%s", harnessURI, encodeListOptions(opts)) + repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + if err != nil { + return nil, nil, err + } + path := fmt.Sprintf("api/v1/repos/%s/webhooks?sort=display_name&order=asc&%s&%s", repoId, encodeListOptions(opts), queryParams) out := []*hook{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertHookList(out), res, err @@ -71,7 +86,11 @@ func (s *repositoryService) ListStatus(ctx context.Context, repo string, ref str func (s *repositoryService) CreateHook(ctx context.Context, repo string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - path := fmt.Sprintf("api/v1/repos/%s/webhooks", harnessURI) + repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + if err != nil { + return nil, nil, err + } + path := fmt.Sprintf("api/v1/repos/%s/webhooks?%s", repoId, queryParams) in := new(hook) in.Enabled = true in.Identifier = input.Name @@ -96,7 +115,11 @@ func (s *repositoryService) UpdateHook(ctx context.Context, repo, id string, inp func (s *repositoryService) DeleteHook(ctx context.Context, repo string, id string) (*scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - path := fmt.Sprintf("api/v1/repos/%s/webhooks/%s", harnessURI, id) + repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + if err != nil { + return nil, err + } + path := fmt.Sprintf("api/v1/repos/%s/webhooks/%s?%s", repoId, id, queryParams) return s.client.do(ctx, "DELETE", path, nil, nil) } diff --git a/scm/driver/harness/util.go b/scm/driver/harness/util.go index d094c8257..4be210068 100644 --- a/scm/driver/harness/util.go +++ b/scm/driver/harness/util.go @@ -13,6 +13,13 @@ import ( "github.com/drone/go-scm/scm" ) +const ( + accountIdentifier = "accountIdentifier" + projectIdentifier = "projectIdentifier" + orgIdentifier = "orgIdentifier" + routingId = "routingId" +) + func buildHarnessURI(account, organization, project, repo string) (uri string) { if account != "" { if project != "" { @@ -32,6 +39,34 @@ func buildHarnessURI(account, organization, project, repo string) (uri string) { return repo } +func getRepoAndQueryParams(slug string) (string, string, error) { + params := url.Values{} + s := strings.TrimSuffix(slug, "/+") + splitSlug := strings.Split(s, "/") + if len(splitSlug) == 0 || len(splitSlug) == 1 { + return "", "", fmt.Errorf("split length: %d is small for slug %s", len(splitSlug), slug) + } + + params.Set(accountIdentifier, splitSlug[0]) + params.Set(routingId, splitSlug[0]) + var repoId string + switch len(splitSlug) { + case 2: + repoId = splitSlug[1] + case 3: + params.Set(orgIdentifier, splitSlug[1]) + repoId = splitSlug[2] + case 4: + params.Set(orgIdentifier, splitSlug[1]) + params.Set(projectIdentifier, splitSlug[2]) + repoId = splitSlug[3] + default: + return "", "", fmt.Errorf("split length more than %d encountered for slug %s", len(splitSlug), slug) + + } + return repoId, params.Encode(), nil +} + func encodeListOptions(opts scm.ListOptions) string { params := url.Values{} if opts.Page != 0 { From fcc8453fa15d03845c2017d0388d9e1e159d0831 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Wed, 13 Mar 2024 05:09:07 +0530 Subject: [PATCH 221/282] fix: tag webhook parse for code (#297) * fix: tag webhook parse for code * fix: tag webhook parse for code * fix: tag webhook parse for code --- .../webhooks/branch_create.json.golden | 27 +---- .../testdata/webhooks/branch_delete.json | 34 ++++++ .../webhooks/branch_delete.json.golden | 29 +++++ .../harness/testdata/webhooks/tag_create.json | 76 +++++++++++++ .../testdata/webhooks/tag_create.json.golden | 29 +++++ .../harness/testdata/webhooks/tag_delete.json | 34 ++++++ .../testdata/webhooks/tag_delete.json.golden | 29 +++++ .../harness/testdata/webhooks/tag_update.json | 100 ++++++++++++++++++ .../testdata/webhooks/tag_update.json.golden | 67 ++++++++++++ scm/driver/harness/webhook.go | 75 ++++++++++++- scm/driver/harness/webhook_test.go | 34 +++++- 11 files changed, 506 insertions(+), 28 deletions(-) create mode 100644 scm/driver/harness/testdata/webhooks/branch_delete.json create mode 100644 scm/driver/harness/testdata/webhooks/branch_delete.json.golden create mode 100644 scm/driver/harness/testdata/webhooks/tag_create.json create mode 100644 scm/driver/harness/testdata/webhooks/tag_create.json.golden create mode 100644 scm/driver/harness/testdata/webhooks/tag_delete.json create mode 100644 scm/driver/harness/testdata/webhooks/tag_delete.json.golden create mode 100644 scm/driver/harness/testdata/webhooks/tag_update.json create mode 100644 scm/driver/harness/testdata/webhooks/tag_update.json.golden diff --git a/scm/driver/harness/testdata/webhooks/branch_create.json.golden b/scm/driver/harness/testdata/webhooks/branch_create.json.golden index a534de4c2..967f51f17 100644 --- a/scm/driver/harness/testdata/webhooks/branch_create.json.golden +++ b/scm/driver/harness/testdata/webhooks/branch_create.json.golden @@ -1,7 +1,9 @@ { - "Ref": "refs/heads/new2", - "Before": "0000000000000000000000000000000000000000", - "After": "aeafa0e2e4ec6909ad75cb8fad57c0b1eb5986e6", + "Ref": { + "Name": "refs/heads/new2", + "Sha": "aeafa0e2e4ec6909ad75cb8fad57c0b1eb5986e6" + }, + "Action": "created", "Repo": { "ID": "13", "Namespace": "", @@ -15,25 +17,6 @@ "Created": "0001-01-01T00:00:00Z", "Updated": "0001-01-01T00:00:00Z" }, - "Commit": { - "Sha": "aeafa0e2e4ec6909ad75cb8fad57c0b1eb5986e6", - "Message": "version 4", - "Author": { - "Name": "Admin", - "Email": "admin@harness.io", - "Date": "0001-01-01T00:00:00Z", - "Login": "", - "Avatar": "" - }, - "Committer": { - "Name": "Admin", - "Email": "admin@harness.io", - "Date": "0001-01-01T00:00:00Z", - "Login": "", - "Avatar": "" - }, - "Link": "" - }, "Sender": { "ID": "0osgWsTZRsSZ8RWfjLRkEg", "Login": "0osgWsTZRsSZ8RWfjLRkEg", diff --git a/scm/driver/harness/testdata/webhooks/branch_delete.json b/scm/driver/harness/testdata/webhooks/branch_delete.json new file mode 100644 index 000000000..ba496b75d --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/branch_delete.json @@ -0,0 +1,34 @@ +{ + "trigger": "branch_deleted", + "repo": { + "id": 16, + "path": "kmpySmUISimoRrJL6NL73w/harness-core", + "identifier": "harness-core", + "default_branch": "develop", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/harness-core.git", + "uid": "harness-core" + }, + "principal": { + "id": 2, + "uid": "lv0euRhKRCyiXWzS7pOg6g", + "display_name": "Admin", + "email": "admin@harness.io", + "type": "user", + "created": 1701091219051, + "updated": 1701091219051 + }, + "ref": { + "name": "refs/heads/das", + "repo": { + "id": 16, + "path": "kmpySmUISimoRrJL6NL73w/harness-core", + "identifier": "harness-core", + "default_branch": "develop", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/harness-core.git", + "uid": "harness-core" + } + }, + "sha": "0000000000000000000000000000000000000000", + "old_sha": "0f1835abe08473e07863540712d8389984b72dad", + "forced": false +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/branch_delete.json.golden b/scm/driver/harness/testdata/webhooks/branch_delete.json.golden new file mode 100644 index 000000000..b9a0ad8f7 --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/branch_delete.json.golden @@ -0,0 +1,29 @@ +{ + "Ref": { + "Name": "refs/heads/das", + "Sha": "0000000000000000000000000000000000000000" + }, + "Action": "deleted", + "Repo": { + "ID": "16", + "Namespace": "", + "Name": "harness-core", + "Perm": null, + "Branch": "develop", + "Private": false, + "Clone": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/harness-core.git", + "CloneSSH": "", + "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/harness-core.git", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Sender": { + "ID": "lv0euRhKRCyiXWzS7pOg6g", + "Login": "lv0euRhKRCyiXWzS7pOg6g", + "Name": "Admin", + "Email": "admin@harness.io", + "Avatar": "", + "Created": "2023-11-27T05:20:19.051-08:00", + "Updated": "2023-11-27T05:20:19.051-08:00" + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/tag_create.json b/scm/driver/harness/testdata/webhooks/tag_create.json new file mode 100644 index 000000000..f67e9700b --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/tag_create.json @@ -0,0 +1,76 @@ +{ + "trigger": "tag_created", + "repo": { + "id": 16, + "path": "kmpySmUISimoRrJL6NL73w/harness-core", + "identifier": "harness-core", + "default_branch": "develop", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/harness-core.git", + "uid": "harness-core" + }, + "principal": { + "id": 2, + "uid": "lv0euRhKRCyiXWzS7pOg6g", + "display_name": "Admin", + "email": "admin@harness.io", + "type": "user", + "created": 1701091219051, + "updated": 1701091219051 + }, + "ref": { + "name": "refs/tags/asd", + "repo": { + "id": 16, + "path": "kmpySmUISimoRrJL6NL73w/harness-core", + "identifier": "harness-core", + "default_branch": "develop", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/harness-core.git", + "uid": "harness-core" + } + }, + "sha": "3e4da2d65c3631c3e84b52fabe714c978aff540b", + "head_commit": { + "sha": "0f1835abe08473e07863540712d8389984b72dad", + "message": "", + "author": { + "identity": { + "name": "admin", + "email": "admin@harness.io" + }, + "when": "2024-03-01T07:54:35-08:00" + }, + "committer": { + "identity": { + "name": "GitHub", + "email": "noreply@github.com" + }, + "when": "2024-03-01T07:54:35-08:00" + }, + "added": [], + "removed": [], + "modified": [] + }, + "commit": { + "sha": "0f1835abe08473e07863540712d8389984b72dad", + "message": "", + "author": { + "identity": { + "name": "Jenny James", + "email": "jenny.james@harness.io" + }, + "when": "2024-03-01T07:54:35-08:00" + }, + "committer": { + "identity": { + "name": "GitHub", + "email": "noreply@github.com" + }, + "when": "2024-03-01T07:54:35-08:00" + }, + "added": [], + "removed": [], + "modified": [] + }, + "old_sha": "0000000000000000000000000000000000000000", + "forced": false +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/tag_create.json.golden b/scm/driver/harness/testdata/webhooks/tag_create.json.golden new file mode 100644 index 000000000..f6a8a53e4 --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/tag_create.json.golden @@ -0,0 +1,29 @@ +{ + "Ref": { + "Name": "refs/tags/asd", + "Sha": "3e4da2d65c3631c3e84b52fabe714c978aff540b" + }, + "Action": "created", + "Repo": { + "ID": "16", + "Namespace": "", + "Name": "harness-core", + "Perm": null, + "Branch": "develop", + "Private": false, + "Clone": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/harness-core.git", + "CloneSSH": "", + "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/harness-core.git", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Sender": { + "ID": "lv0euRhKRCyiXWzS7pOg6g", + "Login": "lv0euRhKRCyiXWzS7pOg6g", + "Name": "Admin", + "Email": "admin@harness.io", + "Avatar": "", + "Created": "2023-11-27T05:20:19.051-08:00", + "Updated": "2023-11-27T05:20:19.051-08:00" + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/tag_delete.json b/scm/driver/harness/testdata/webhooks/tag_delete.json new file mode 100644 index 000000000..3fa9348ee --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/tag_delete.json @@ -0,0 +1,34 @@ +{ + "trigger": "tag_deleted", + "repo": { + "id": 16, + "path": "kmpySmUISimoRrJL6NL73w/harness-core", + "identifier": "harness-core", + "default_branch": "develop", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/harness-core.git", + "uid": "harness-core" + }, + "principal": { + "id": 2, + "uid": "lv0euRhKRCyiXWzS7pOg6g", + "display_name": "Admin", + "email": "admin@harness.io", + "type": "user", + "created": 1701091219051, + "updated": 1701091219051 + }, + "ref": { + "name": "refs/tags/asd", + "repo": { + "id": 16, + "path": "kmpySmUISimoRrJL6NL73w/harness-core", + "identifier": "harness-core", + "default_branch": "develop", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/harness-core.git", + "uid": "harness-core" + } + }, + "sha": "0000000000000000000000000000000000000000", + "old_sha": "3e4da2d65c3631c3e84b52fabe714c978aff540b", + "forced": false +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/tag_delete.json.golden b/scm/driver/harness/testdata/webhooks/tag_delete.json.golden new file mode 100644 index 000000000..cfd67a8b1 --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/tag_delete.json.golden @@ -0,0 +1,29 @@ +{ + "Ref": { + "Name": "refs/tags/asd", + "Sha": "0000000000000000000000000000000000000000" + }, + "Action": "deleted", + "Repo": { + "ID": "16", + "Namespace": "", + "Name": "harness-core", + "Perm": null, + "Branch": "develop", + "Private": false, + "Clone": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/harness-core.git", + "CloneSSH": "", + "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/harness-core.git", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Sender": { + "ID": "lv0euRhKRCyiXWzS7pOg6g", + "Login": "lv0euRhKRCyiXWzS7pOg6g", + "Name": "Admin", + "Email": "admin@harness.io", + "Avatar": "", + "Created": "2023-11-27T05:20:19.051-08:00", + "Updated": "2023-11-27T05:20:19.051-08:00" + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/tag_update.json b/scm/driver/harness/testdata/webhooks/tag_update.json new file mode 100644 index 000000000..b16eac070 --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/tag_update.json @@ -0,0 +1,100 @@ +{ + "trigger": "tag_updated", + "repo": { + "id": 16, + "path": "kmpySmUISimoRrJL6NL73w/harness-core", + "identifier": "harness-core", + "default_branch": "develop", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/harness-core.git", + "uid": "harness-core" + }, + "principal": { + "id": 2, + "uid": "lv0euRhKRCyiXWzS7pOg6g", + "display_name": "Admin", + "email": "admin@harness.io", + "type": "user", + "created": 1701091219051, + "updated": 1701091219051 + }, + "ref": { + "name": "refs/tags/ddxas", + "repo": { + "id": 16, + "path": "kmpySmUISimoRrJL6NL73w/harness-core", + "identifier": "harness-core", + "default_branch": "develop", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/harness-core.git", + "uid": "harness-core" + } + }, + "sha": "700b3dab8e7a5cebf5e1ce54e7dd5bde60099912", + "head_commit": { + "sha": "700b3dab8e7a5cebf5e1ce54e7dd5bde60099912", + "message": "Asd", + "author": { + "identity": { + "name": "Abhinav Singh", + "email": "abhinav.singh@harness.io" + }, + "when": "2024-03-07T03:18:51-08:00" + }, + "committer": { + "identity": { + "name": "Abhinav Singh", + "email": "abhinav.singh@harness.io" + }, + "when": "2024-03-07T03:18:51-08:00" + }, + "added": [], + "removed": [], + "modified": [] + }, + "commits": [ + { + "sha": "700b3dab8e7a5cebf5e1ce54e7dd5bde60099912", + "message": "Asd", + "author": { + "identity": { + "name": "Abhinav Singh", + "email": "abhinav.singh@harness.io" + }, + "when": "2024-03-07T03:18:51-08:00" + }, + "committer": { + "identity": { + "name": "Abhinav Singh", + "email": "abhinav.singh@harness.io" + }, + "when": "2024-03-07T03:18:51-08:00" + }, + "added": [], + "removed": [], + "modified": [] + } + ], + "total_commits_count": 1, + "commit": { + "sha": "700b3dab8e7a5cebf5e1ce54e7dd5bde60099912", + "message": "Asd", + "author": { + "identity": { + "name": "Abhinav Singh", + "email": "abhinav.singh@harness.io" + }, + "when": "2024-03-07T03:18:51-08:00" + }, + "committer": { + "identity": { + "name": "Abhinav Singh", + "email": "abhinav.singh@harness.io" + }, + "when": "2024-03-07T03:18:51-08:00" + }, + "added": [], + "removed": [], + "modified": [] + }, + "old_sha": "0f1835abe08473e07863540712d8389984b72dad", + "forced": true +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/tag_update.json.golden b/scm/driver/harness/testdata/webhooks/tag_update.json.golden new file mode 100644 index 000000000..408447db1 --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/tag_update.json.golden @@ -0,0 +1,67 @@ +{ + "Ref": "refs/tags/ddxas", + "Before": "0f1835abe08473e07863540712d8389984b72dad", + "After": "700b3dab8e7a5cebf5e1ce54e7dd5bde60099912", + "Repo": { + "ID": "16", + "Namespace": "", + "Name": "harness-core", + "Perm": null, + "Branch": "develop", + "Private": false, + "Clone": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/harness-core.git", + "CloneSSH": "", + "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/harness-core.git", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Commit": { + "Sha": "700b3dab8e7a5cebf5e1ce54e7dd5bde60099912", + "Message": "Asd", + "Author": { + "Name": "Abhinav Singh", + "Email": "abhinav.singh@harness.io", + "Date": "0001-01-01T00:00:00Z", + "Login": "", + "Avatar": "" + }, + "Committer": { + "Name": "Abhinav Singh", + "Email": "abhinav.singh@harness.io", + "Date": "0001-01-01T00:00:00Z", + "Login": "", + "Avatar": "" + }, + "Link": "" + }, + "Commits": [ + { + "Sha": "700b3dab8e7a5cebf5e1ce54e7dd5bde60099912", + "Message": "Asd", + "Author": { + "Name": "Abhinav Singh", + "Email": "abhinav.singh@harness.io", + "Date": "0001-01-01T00:00:00Z", + "Login": "", + "Avatar": "" + }, + "Committer": { + "Name": "Abhinav Singh", + "Email": "abhinav.singh@harness.io", + "Date": "0001-01-01T00:00:00Z", + "Login": "", + "Avatar": "" + }, + "Link": "" + } + ], + "Sender": { + "ID": "lv0euRhKRCyiXWzS7pOg6g", + "Login": "lv0euRhKRCyiXWzS7pOg6g", + "Name": "Admin", + "Email": "admin@harness.io", + "Avatar": "", + "Created": "2023-11-27T05:20:19.051-08:00", + "Updated": "2023-11-27T05:20:19.051-08:00" + } +} \ No newline at end of file diff --git a/scm/driver/harness/webhook.go b/scm/driver/harness/webhook.go index 73e7bd920..33be360b4 100644 --- a/scm/driver/harness/webhook.go +++ b/scm/driver/harness/webhook.go @@ -11,6 +11,7 @@ import ( "io/ioutil" "net/http" "strconv" + "strings" "time" "github.com/drone/go-scm/scm" @@ -37,8 +38,12 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo // hook, err = s.parseDeleteHook(data) // case "issues": // hook, err = s.parseIssueHook(data) - case "branch_created", "branch_updated": + case "branch_updated", "tag_updated": hook, err = s.parsePushHook(data) + case "branch_created", "branch_deleted": + hook, err = s.parseBranchHook(data) + case "tag_created", "tag_deleted": + hook, err = s.parseTagHook(data) case "pullreq_created", "pullreq_reopened", "pullreq_branch_updated", "pullreq_closed", "pullreq_merged": hook, err = s.parsePullRequestHook(data) case "pullreq_comment_created": @@ -99,6 +104,20 @@ func (s *webhookService) parsePullRequestCommentHook(data []byte) (scm.Webhook, return convertPullRequestCommentHook(dst), err } +func (s *webhookService) parseBranchHook(data []byte) (scm.Webhook, error) { + // using pushHook object since it is same as branch events + dst := new(pushHook) + err := json.Unmarshal(data, dst) + return convertBranchHook(dst), err +} + +func (s *webhookService) parseTagHook(data []byte) (scm.Webhook, error) { + // using pushHook object since it is same as tag events + dst := new(pushHook) + err := json.Unmarshal(data, dst) + return convertTagHook(dst), err +} + // native data structures type ( repo struct { @@ -218,7 +237,7 @@ type ( // native data structure conversion func convertPullRequestHook(src *pullRequestHook) *scm.PullRequestHook { return &scm.PullRequestHook{ - Action: convertAction(src.Trigger), + Action: convertPRAction(src.Trigger), PullRequest: convertPullReq(src.PullReq, src.Ref, src.HeadCommit), Repo: convertRepo(src.Repo), Sender: convertUser(src.Principal), @@ -267,9 +286,33 @@ func convertPullRequestCommentHook(src *pullRequestCommentHook) *scm.PullRequest Sender: convertUser(src.Principal), } } +func convertBranchHook(dst *pushHook) *scm.BranchHook { + return &scm.BranchHook{ + Ref: convertRef(dst), + Repo: convertRepo(dst.Repo), + Action: convertBranchAction(dst.Trigger), + Sender: convertUser(dst.Principal), + } +} + +func convertTagHook(dst *pushHook) *scm.TagHook { + return &scm.TagHook{ + Ref: convertRef(dst), + Repo: convertRepo(dst.Repo), + Action: convertTagAction(dst.Trigger), + Sender: convertUser(dst.Principal), + } +} -func convertAction(src string) (action scm.Action) { - switch src { +func convertRef(dst *pushHook) scm.Reference { + return scm.Reference{ + Name: dst.Ref.Name, + Sha: dst.Sha, + } +} + +func convertPRAction(src string) (action scm.Action) { + switch strings.ToLower(src) { case "pullreq_created": return scm.ActionCreate case "pullreq_branch_updated": @@ -281,7 +324,29 @@ func convertAction(src string) (action scm.Action) { case "pullreq_merged": return scm.ActionMerge default: - return + return scm.ActionUnknown + } +} + +func convertBranchAction(src string) (action scm.Action) { + switch strings.ToLower(src) { + case "branch_created": + return scm.ActionCreate + case "branch_deleted": + return scm.ActionDelete + default: + return scm.ActionUnknown + } +} + +func convertTagAction(src string) (action scm.Action) { + switch strings.ToLower(src) { + case "tag_created": + return scm.ActionCreate + case "tag_deleted": + return scm.ActionDelete + default: + return scm.ActionUnknown } } diff --git a/scm/driver/harness/webhook_test.go b/scm/driver/harness/webhook_test.go index 26966db2b..a4cf093b1 100644 --- a/scm/driver/harness/webhook_test.go +++ b/scm/driver/harness/webhook_test.go @@ -31,7 +31,7 @@ func TestWebhooks(t *testing.T) { event: "branch_created", before: "testdata/webhooks/branch_create.json", after: "testdata/webhooks/branch_create.json.golden", - obj: new(scm.PushHook), + obj: new(scm.BranchHook), }, // push branch update { @@ -40,6 +40,38 @@ func TestWebhooks(t *testing.T) { after: "testdata/webhooks/branch_updated.json.golden", obj: new(scm.PushHook), }, + // push branch delete + { + event: "branch_deleted", + before: "testdata/webhooks/branch_delete.json", + after: "testdata/webhooks/branch_delete.json.golden", + obj: new(scm.BranchHook), + }, + // + // tag events + // + // push tag create + { + event: "tag_created", + before: "testdata/webhooks/tag_create.json", + after: "testdata/webhooks/tag_create.json.golden", + obj: new(scm.TagHook), + }, + // push tag update + { + event: "tag_updated", + before: "testdata/webhooks/tag_update.json", + after: "testdata/webhooks/tag_update.json.golden", + obj: new(scm.PushHook), + }, + // push tag delete + { + event: "tag_deleted", + before: "testdata/webhooks/tag_delete.json", + after: "testdata/webhooks/tag_delete.json.golden", + obj: new(scm.TagHook), + }, + // // pull request events // From 95e7cdcdc01ff8473366570aa3ff0d6d9f7d7e69 Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Tue, 19 Mar 2024 15:49:14 +0530 Subject: [PATCH 222/282] Update util.go --- scm/driver/github/util.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scm/driver/github/util.go b/scm/driver/github/util.go index d06e474e0..874b63b9a 100644 --- a/scm/driver/github/util.go +++ b/scm/driver/github/util.go @@ -47,7 +47,8 @@ func encodeRepoListOptions(opts scm.RepoListOptions) string { sb.WriteString(strconv.Itoa(opts.ListOptions.Size)) } } - return sb.String() + + return url.QueryEscape(sb.String()) } func encodeCommitListOptions(opts scm.CommitListOptions) string { From 44a195cff382fd4750ebf38424c91b046aaf330a Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Tue, 19 Mar 2024 15:54:00 +0530 Subject: [PATCH 223/282] Update util.go --- scm/driver/github/util.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scm/driver/github/util.go b/scm/driver/github/util.go index 874b63b9a..41caa3e03 100644 --- a/scm/driver/github/util.go +++ b/scm/driver/github/util.go @@ -29,7 +29,7 @@ func encodeRepoListOptions(opts scm.RepoListOptions) string { if opts.RepoSearchTerm.RepoName != "" { sb.WriteString("q=") sb.WriteString(opts.RepoSearchTerm.RepoName) - sb.WriteString("in:name+user:") + sb.WriteString(" in:name+user:") sb.WriteString(opts.RepoSearchTerm.User) } else { sb.WriteString("q=") @@ -47,8 +47,9 @@ func encodeRepoListOptions(opts scm.RepoListOptions) string { sb.WriteString(strconv.Itoa(opts.ListOptions.Size)) } } - - return url.QueryEscape(sb.String()) + urlEncodedRepoListOptions := url.QueryEscape(sb.String()) + fmt.Println(urlEncodedRepoListOptions) + return urlEncodedRepoListOptions } func encodeCommitListOptions(opts scm.CommitListOptions) string { From b43614d6aa35f6c20a79d966e75b783baf8d35b0 Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Tue, 19 Mar 2024 15:55:39 +0530 Subject: [PATCH 224/282] Update util.go --- scm/driver/github/util.go | 1 + 1 file changed, 1 insertion(+) diff --git a/scm/driver/github/util.go b/scm/driver/github/util.go index 41caa3e03..f10d2e031 100644 --- a/scm/driver/github/util.go +++ b/scm/driver/github/util.go @@ -8,6 +8,7 @@ import ( "net/url" "strconv" "strings" + "fmt" "github.com/drone/go-scm/scm" ) From 55f6df5dc458958c0c707161c689ba3610451220 Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Tue, 19 Mar 2024 16:01:34 +0530 Subject: [PATCH 225/282] Update util.go --- scm/driver/github/util.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/scm/driver/github/util.go b/scm/driver/github/util.go index f10d2e031..db9b58100 100644 --- a/scm/driver/github/util.go +++ b/scm/driver/github/util.go @@ -30,7 +30,7 @@ func encodeRepoListOptions(opts scm.RepoListOptions) string { if opts.RepoSearchTerm.RepoName != "" { sb.WriteString("q=") sb.WriteString(opts.RepoSearchTerm.RepoName) - sb.WriteString(" in:name+user:") + sb.WriteString("%20in:name+user:") sb.WriteString(opts.RepoSearchTerm.User) } else { sb.WriteString("q=") @@ -48,9 +48,8 @@ func encodeRepoListOptions(opts scm.RepoListOptions) string { sb.WriteString(strconv.Itoa(opts.ListOptions.Size)) } } - urlEncodedRepoListOptions := url.QueryEscape(sb.String()) - fmt.Println(urlEncodedRepoListOptions) - return urlEncodedRepoListOptions + fmt.Println(sb.String()) + return sb.String() } func encodeCommitListOptions(opts scm.CommitListOptions) string { From 68b549a0a40fc987434ce0344295a99213d5c0fb Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Tue, 19 Mar 2024 16:03:55 +0530 Subject: [PATCH 226/282] Update util.go --- scm/driver/github/util.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/scm/driver/github/util.go b/scm/driver/github/util.go index db9b58100..7f5a04a35 100644 --- a/scm/driver/github/util.go +++ b/scm/driver/github/util.go @@ -8,7 +8,6 @@ import ( "net/url" "strconv" "strings" - "fmt" "github.com/drone/go-scm/scm" ) @@ -48,7 +47,6 @@ func encodeRepoListOptions(opts scm.RepoListOptions) string { sb.WriteString(strconv.Itoa(opts.ListOptions.Size)) } } - fmt.Println(sb.String()) return sb.String() } From d2e8e4eebf20694ac77f8c697a9c245cf1a34f92 Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Tue, 19 Mar 2024 16:07:20 +0530 Subject: [PATCH 227/282] Update util.go --- scm/driver/github/util.go | 1 + 1 file changed, 1 insertion(+) diff --git a/scm/driver/github/util.go b/scm/driver/github/util.go index 7f5a04a35..916f29fb1 100644 --- a/scm/driver/github/util.go +++ b/scm/driver/github/util.go @@ -29,6 +29,7 @@ func encodeRepoListOptions(opts scm.RepoListOptions) string { if opts.RepoSearchTerm.RepoName != "" { sb.WriteString("q=") sb.WriteString(opts.RepoSearchTerm.RepoName) + // %20 is urlEncoding of blank space. sb.WriteString("%20in:name+user:") sb.WriteString(opts.RepoSearchTerm.User) } else { From b23de2cb10d839613b37edefc15a9107986f325a Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Wed, 20 Mar 2024 10:38:09 +0530 Subject: [PATCH 228/282] Update util.go --- scm/driver/github/util.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scm/driver/github/util.go b/scm/driver/github/util.go index 916f29fb1..e8b3935a7 100644 --- a/scm/driver/github/util.go +++ b/scm/driver/github/util.go @@ -8,6 +8,7 @@ import ( "net/url" "strconv" "strings" + "fmt" "github.com/drone/go-scm/scm" ) @@ -29,8 +30,7 @@ func encodeRepoListOptions(opts scm.RepoListOptions) string { if opts.RepoSearchTerm.RepoName != "" { sb.WriteString("q=") sb.WriteString(opts.RepoSearchTerm.RepoName) - // %20 is urlEncoding of blank space. - sb.WriteString("%20in:name+user:") + sb.WriteString("in:name+user:") sb.WriteString(opts.RepoSearchTerm.User) } else { sb.WriteString("q=") @@ -48,7 +48,9 @@ func encodeRepoListOptions(opts scm.RepoListOptions) string { sb.WriteString(strconv.Itoa(opts.ListOptions.Size)) } } - return sb.String() + url := url.QueryEscape(sb.String()) + fmt.Println(url) + return url } func encodeCommitListOptions(opts scm.CommitListOptions) string { From 1eb765587a97b329e29ebc7944abc2328fb0249d Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Wed, 20 Mar 2024 10:42:45 +0530 Subject: [PATCH 229/282] Update util.go --- scm/driver/github/util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/driver/github/util.go b/scm/driver/github/util.go index e8b3935a7..4987a4af4 100644 --- a/scm/driver/github/util.go +++ b/scm/driver/github/util.go @@ -30,7 +30,7 @@ func encodeRepoListOptions(opts scm.RepoListOptions) string { if opts.RepoSearchTerm.RepoName != "" { sb.WriteString("q=") sb.WriteString(opts.RepoSearchTerm.RepoName) - sb.WriteString("in:name+user:") + sb.WriteString(" in:name+user:") sb.WriteString(opts.RepoSearchTerm.User) } else { sb.WriteString("q=") From 39d795fa985a3a40e06eec2040cafac83f56cf3e Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Wed, 20 Mar 2024 10:47:13 +0530 Subject: [PATCH 230/282] Update util.go --- scm/driver/github/util.go | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/scm/driver/github/util.go b/scm/driver/github/util.go index 4987a4af4..721858069 100644 --- a/scm/driver/github/util.go +++ b/scm/driver/github/util.go @@ -9,6 +9,7 @@ import ( "strconv" "strings" "fmt" + "unicode/utf8" "github.com/drone/go-scm/scm" ) @@ -48,7 +49,8 @@ func encodeRepoListOptions(opts scm.RepoListOptions) string { sb.WriteString(strconv.Itoa(opts.ListOptions.Size)) } } - url := url.QueryEscape(sb.String()) + url := encodeString(sb.String()) + // url := url.QueryEscape(sb.String()) fmt.Println(url) return url } @@ -133,3 +135,32 @@ func encodeReleaseListOptions(opts scm.ReleaseListOptions) string { } return params.Encode() } + +func encodeString(s string) string { + var encoded strings.Builder + + for _, r := range s { + if shouldEscape(r) { + encoded.WriteString(fmt.Sprintf("%%%02X", r)) + } else { + encoded.WriteRune(r) + } + } + + return encoded.String() +} + +func shouldEscape(r rune) bool { + switch { + case r >= 'A' && r <= 'Z': + return false + case r >= 'a' && r <= 'z': + return false + case r >= '0' && r <= '9': + return false + case r == '-', '_', '.', '~': + return false + default: + return true + } +} From dcd4b47d080866f852067838d3433d296d6541b5 Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Wed, 20 Mar 2024 10:49:24 +0530 Subject: [PATCH 231/282] Update util.go --- scm/driver/github/util.go | 1 - 1 file changed, 1 deletion(-) diff --git a/scm/driver/github/util.go b/scm/driver/github/util.go index 721858069..9bda47474 100644 --- a/scm/driver/github/util.go +++ b/scm/driver/github/util.go @@ -9,7 +9,6 @@ import ( "strconv" "strings" "fmt" - "unicode/utf8" "github.com/drone/go-scm/scm" ) From c06f5b7d227e0a55319397947f901017e6511bc2 Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Wed, 20 Mar 2024 10:59:04 +0530 Subject: [PATCH 232/282] Update util.go --- scm/driver/github/util.go | 37 +++---------------------------------- 1 file changed, 3 insertions(+), 34 deletions(-) diff --git a/scm/driver/github/util.go b/scm/driver/github/util.go index 9bda47474..45e33130a 100644 --- a/scm/driver/github/util.go +++ b/scm/driver/github/util.go @@ -30,7 +30,7 @@ func encodeRepoListOptions(opts scm.RepoListOptions) string { if opts.RepoSearchTerm.RepoName != "" { sb.WriteString("q=") sb.WriteString(opts.RepoSearchTerm.RepoName) - sb.WriteString(" in:name+user:") + sb.WriteString("+in:name+user:") sb.WriteString(opts.RepoSearchTerm.User) } else { sb.WriteString("q=") @@ -48,10 +48,8 @@ func encodeRepoListOptions(opts scm.RepoListOptions) string { sb.WriteString(strconv.Itoa(opts.ListOptions.Size)) } } - url := encodeString(sb.String()) - // url := url.QueryEscape(sb.String()) - fmt.Println(url) - return url + fmt.Println(sb.string()) + return sb.string() } func encodeCommitListOptions(opts scm.CommitListOptions) string { @@ -134,32 +132,3 @@ func encodeReleaseListOptions(opts scm.ReleaseListOptions) string { } return params.Encode() } - -func encodeString(s string) string { - var encoded strings.Builder - - for _, r := range s { - if shouldEscape(r) { - encoded.WriteString(fmt.Sprintf("%%%02X", r)) - } else { - encoded.WriteRune(r) - } - } - - return encoded.String() -} - -func shouldEscape(r rune) bool { - switch { - case r >= 'A' && r <= 'Z': - return false - case r >= 'a' && r <= 'z': - return false - case r >= '0' && r <= '9': - return false - case r == '-', '_', '.', '~': - return false - default: - return true - } -} From f8119f14e1b861e9fbdf15a8ba58bf78111dc4fc Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Wed, 20 Mar 2024 11:02:35 +0530 Subject: [PATCH 233/282] Update util.go --- scm/driver/github/util.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scm/driver/github/util.go b/scm/driver/github/util.go index 45e33130a..c09f92752 100644 --- a/scm/driver/github/util.go +++ b/scm/driver/github/util.go @@ -48,8 +48,8 @@ func encodeRepoListOptions(opts scm.RepoListOptions) string { sb.WriteString(strconv.Itoa(opts.ListOptions.Size)) } } - fmt.Println(sb.string()) - return sb.string() + fmt.Println(sb.String()) + return sb.String() } func encodeCommitListOptions(opts scm.CommitListOptions) string { From 594c68b442bbeaebf24152713676e461abe2b6b0 Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Wed, 20 Mar 2024 12:02:48 +0530 Subject: [PATCH 234/282] Update util.go --- scm/driver/github/util.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/scm/driver/github/util.go b/scm/driver/github/util.go index c09f92752..24a0c858c 100644 --- a/scm/driver/github/util.go +++ b/scm/driver/github/util.go @@ -8,7 +8,6 @@ import ( "net/url" "strconv" "strings" - "fmt" "github.com/drone/go-scm/scm" ) @@ -48,7 +47,6 @@ func encodeRepoListOptions(opts scm.RepoListOptions) string { sb.WriteString(strconv.Itoa(opts.ListOptions.Size)) } } - fmt.Println(sb.String()) return sb.String() } From 142ee303394e6cf3de0ad1114ea851cfb03368d5 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Thu, 21 Mar 2024 04:14:27 +0530 Subject: [PATCH 235/282] feat: pr harness parse all fields (#302) --- scm/driver/harness/pr.go | 90 ++++++++++++---------- scm/driver/harness/testdata/pr.json | 40 +++++----- scm/driver/harness/testdata/pr.json.golden | 39 ++++++---- 3 files changed, 97 insertions(+), 72 deletions(-) diff --git a/scm/driver/harness/pr.go b/scm/driver/harness/pr.go index 35cadd20a..167ba9bf7 100644 --- a/scm/driver/harness/pr.go +++ b/scm/driver/harness/pr.go @@ -7,6 +7,7 @@ package harness import ( "context" "fmt" + "github.com/drone/go-scm/scm/driver/internal/null" "strconv" "strings" "time" @@ -123,44 +124,38 @@ func (s *pullService) Close(context.Context, string, int) (*scm.Response, error) // native data structures type ( pr struct { - Author struct { - Created int `json:"created"` - DisplayName string `json:"display_name"` - Email string `json:"email"` - ID int `json:"id"` - Type string `json:"type"` - UID string `json:"uid"` - Updated int `json:"updated"` - } `json:"author"` - Created int `json:"created"` - Description string `json:"description"` - Edited int `json:"edited"` - IsDraft bool `json:"is_draft"` - MergeBaseSha string `json:"merge_base_sha"` - MergeHeadSha string `json:"merge_head_sha"` - MergeStrategy string `json:"merge_strategy"` - Merged int `json:"merged"` - Merger struct { - Created int `json:"created"` - DisplayName string `json:"display_name"` - Email string `json:"email"` - ID int `json:"id"` - Type string `json:"type"` - UID string `json:"uid"` - Updated int `json:"updated"` - } `json:"merger"` - Number int `json:"number"` + Author principal `json:"author"` + Created int64 `json:"created"` + Description string `json:"description"` + Edited int64 `json:"edited"` + IsDraft bool `json:"is_draft"` + + MergeTargetSHA null.String `json:"merge_target_sha"` + MergeBaseSha string `json:"merge_base_sha"` + Merged null.Int `json:"merged"` + MergeMethod null.String `json:"merge_method"` + MergeSHA null.String `json:"merge_sha"` + MergeCheckStatus string `json:"merge_check_status"` + MergeConflicts []string `json:"merge_conflicts,omitempty"` + Merger *principal `json:"merger"` + + Number int64 `json:"number"` + SourceBranch string `json:"source_branch"` - SourceRepoID int `json:"source_repo_id"` - State string `json:"state"` - Stats struct { - Commits int `json:"commits"` - Conversations int `json:"conversations"` - FilesChanged int `json:"files_changed"` - } `json:"stats"` + SourceRepoID int64 `json:"source_repo_id"` + SourceSHA string `json:"source_sha"` TargetBranch string `json:"target_branch"` - TargetRepoID int `json:"target_repo_id"` - Title string `json:"title"` + TargetRepoID int64 `json:"target_repo_id"` + + State string `json:"state"` + Stats struct { + Commits null.Int `json:"commits,omitempty"` + Conversations int `json:"conversations,omitempty"` + FilesChanged null.Int `json:"files_changed,omitempty"` + UnresolvedCount int `json:"unresolved_count,omitempty"` + } `json:"stats"` + + Title string `json:"title"` } reference struct { @@ -246,21 +241,34 @@ func convertPullRequests(src []*pr) []*scm.PullRequest { func convertPullRequest(src *pr) *scm.PullRequest { return &scm.PullRequest{ - Number: src.Number, + Number: int(src.Number), Title: src.Title, Body: src.Description, + Sha: src.SourceSHA, Source: src.SourceBranch, Target: src.TargetBranch, - Merged: src.Merged != 0, + Merged: src.Merged.Valid, Author: scm.User{ Login: src.Author.Email, Name: src.Author.DisplayName, ID: src.Author.UID, Email: src.Author.Email, }, - Fork: "fork", - Ref: fmt.Sprintf("refs/pullreq/%d/head", src.Number), - Closed: src.State == "closed", + Head: scm.Reference{ + Name: src.SourceBranch, + Path: scm.ExpandRef(src.SourceBranch, "refs/heads"), + Sha: src.SourceSHA, + }, + Base: scm.Reference{ + Name: src.TargetBranch, + Path: scm.ExpandRef(src.TargetBranch, "refs/heads"), + Sha: src.MergeTargetSHA.String, + }, + Fork: "fork", + Ref: fmt.Sprintf("refs/pullreq/%d/head", src.Number), + Closed: src.State == "closed", + Created: time.UnixMilli(src.Created), + Updated: time.UnixMilli(src.Edited), } } diff --git a/scm/driver/harness/testdata/pr.json b/scm/driver/harness/testdata/pr.json index 89e773b96..57fc7d9de 100644 --- a/scm/driver/harness/testdata/pr.json +++ b/scm/driver/harness/testdata/pr.json @@ -1,32 +1,36 @@ { "number": 1, - "created": 1675960384081, - "edited": 1675960384081, + "created": 1710818863810, + "edited": 1710818863810, "state": "open", "is_draft": false, - "title": "pull title", - "description": "pull description", - "source_repo_id": 11, - "source_branch": "bla", - "target_repo_id": 11, + "title": "feat: self as codeowner can be skipped", + "description": "123", + "source_repo_id": 7, + "source_branch": "abhinav/CODE-1508", + "source_sha": "6c4ab583f5201ed0421d0ef93ee5b0925ac08f62", + "target_repo_id": 7, "target_branch": "main", "merged": null, - "merge_strategy": null, - "merge_head_sha": null, - "merge_base_sha": null, + "merge_method": null, + "merge_check_status": "mergeable", + "merge_target_sha": "b772dca15553986cc90fc6254a0fa47f4047526c", + "merge_base_sha": "b772dca15553986cc90fc6254a0fa47f4047526c", + "merge_sha": "ff13c81504ab3b04bd76b6af71e9c368333181a5", "author": { - "id": 14, - "uid": "0Nnoezs6RGa_fOWvG_Ta4w", - "display_name": "thomas.honey", - "email": "thomas.honey@harness.io", + "id": 27, + "uid": "aqm0RQXGQI6v3m_f7u7C5A", + "display_name": "Abhinav Singh", + "email": "abhinav.singh@harness.io", "type": "user", - "created": 1675248918372, - "updated": 1675248918372 + "created": 1681264009453, + "updated": 1681264009453 }, "merger": null, "stats": { - "conversations": 0, "commits": 1, - "files_changed": 1 + "files_changed": 1, + "conversations": 1, + "unresolved_count": 1 } } \ No newline at end of file diff --git a/scm/driver/harness/testdata/pr.json.golden b/scm/driver/harness/testdata/pr.json.golden index 5c4a83864..ae5dc76da 100644 --- a/scm/driver/harness/testdata/pr.json.golden +++ b/scm/driver/harness/testdata/pr.json.golden @@ -1,20 +1,33 @@ { "Number": 1, - "Title": "pull title", - "Body": "pull description", - "Sha": "", - "Ref": "refs/pullreq/1/head", - "Source": "bla", - "Target": "main", + "Title": "feat: self as codeowner can be skipped", + "Body": "123", + "Sha": "6c4ab583f5201ed0421d0ef93ee5b0925ac08f62", + "Ref": "refs/pullreq/1/head", + "Source": "abhinav/CODE-1508", + "Target": "main", + "Fork": "fork", + "Closed": false, + "Merged": false, "Fork": "fork", "Link": "", "Diff": "", - "Closed": false, - "Merged": false, + "Base": { + "Sha": "b772dca15553986cc90fc6254a0fa47f4047526c", + "Path": "refs/heads/main", + "Name": "main" + }, + "Head": { + "Sha": "6c4ab583f5201ed0421d0ef93ee5b0925ac08f62", + "Path": "refs/heads/abhinav/CODE-1508", + "Name": "abhinav/CODE-1508" + }, "Author": { - "ID": "0Nnoezs6RGa_fOWvG_Ta4w", - "Login": "thomas.honey@harness.io", - "Name": "thomas.honey", - "Email": "thomas.honey@harness.io" - } + "ID": "aqm0RQXGQI6v3m_f7u7C5A", + "Login": "abhinav.singh@harness.io", + "Name": "Abhinav Singh", + "Email": "abhinav.singh@harness.io" + }, + "Created": "2024-03-18T20:27:43.81-07:00", + "Updated": "2024-03-18T20:27:43.81-07:00" } \ No newline at end of file From 845e4451f49fdafd56ff16c4ad8523c7ce4b8f8a Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Tue, 16 Apr 2024 15:00:41 -0400 Subject: [PATCH 236/282] Update .drone.yml --- .drone.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.drone.yml b/.drone.yml index 74ace6a27..f723ac8f8 100644 --- a/.drone.yml +++ b/.drone.yml @@ -8,7 +8,7 @@ pool: steps: - name: vet - image: golang:1.15 + image: golang:1.22 commands: - go vet ./... volumes: @@ -18,7 +18,7 @@ steps: - clone - name: test - image: golang:1.15 + image: golang:1.22 commands: - go test -cover ./... volumes: @@ -28,7 +28,7 @@ steps: - vet - name: check go.mod is up to date - image: golang:1.15 + image: golang:1.22 commands: - cp go.mod go.mod.bak - go mod tidy From 1255b156aedb7dfe7517cd5bdba7e68191b7cbdf Mon Sep 17 00:00:00 2001 From: Hitesh Aringa Date: Tue, 16 Apr 2024 18:09:04 -0700 Subject: [PATCH 237/282] feat: fixed harness UTs based on new API convention (#303) --- scm/driver/harness/content_test.go | 30 ++++++++++++++++++++----- scm/driver/harness/git_test.go | 36 +++++++++++++++++++++++++----- scm/driver/harness/pr_test.go | 21 +++++++++++++---- scm/driver/harness/repo.go | 4 +--- scm/driver/harness/repo_test.go | 36 +++++++++++++++++++++++++----- 5 files changed, 103 insertions(+), 24 deletions(-) diff --git a/scm/driver/harness/content_test.go b/scm/driver/harness/content_test.go index 6a84ec797..f59776f2c 100644 --- a/scm/driver/harness/content_test.go +++ b/scm/driver/harness/content_test.go @@ -32,7 +32,11 @@ func TestContentFind(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/content/README.md"). + Get("/gateway/code/api/v1/repos/thomas/content/README.md"). + MatchParam("accountIdentifier", "px7xd_BFRCi-pfWPYXVjvw"). + MatchParam("orgIdentifier", "default"). + MatchParam("projectIdentifier", "codeciintegration"). + MatchParam("routingId", "px7xd_BFRCi-pfWPYXVjvw"). Reply(200). Type("plain/text"). File("testdata/content.json") @@ -68,7 +72,11 @@ func TestContentCreate(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/commits"). + Post("/gateway/code/api/v1/repos/thomas/commits"). + MatchParam("accountIdentifier", "px7xd_BFRCi-pfWPYXVjvw"). + MatchParam("orgIdentifier", "default"). + MatchParam("projectIdentifier", "codeciintegration"). + MatchParam("routingId", "px7xd_BFRCi-pfWPYXVjvw"). Reply(200). Type("plain/text"). BodyString("{\"commit_id\":\"20ecde1f8c277da0e91750bef9f3b88f228d86db\"}") @@ -105,7 +113,11 @@ func TestContentUpdate(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/commits"). + Post("/gateway/code/api/v1/repos/thomas/commits"). + MatchParam("accountIdentifier", "px7xd_BFRCi-pfWPYXVjvw"). + MatchParam("orgIdentifier", "default"). + MatchParam("projectIdentifier", "codeciintegration"). + MatchParam("routingId", "px7xd_BFRCi-pfWPYXVjvw"). Reply(200). Type("plain/text"). BodyString("{\"commit_id\":\"20ecde1f8c277da0e91750bef9f3b88f228d86db\"}") @@ -143,7 +155,11 @@ func TestContentDelete(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/commits"). + Post("/gateway/code/api/v1/repos/thomas/commits"). + MatchParam("accountIdentifier", "px7xd_BFRCi-pfWPYXVjvw"). + MatchParam("orgIdentifier", "default"). + MatchParam("projectIdentifier", "codeciintegration"). + MatchParam("routingId", "px7xd_BFRCi-pfWPYXVjvw"). Reply(200). Type("plain/text"). BodyString("{\"commit_id\":\"20ecde1f8c277da0e91750bef9f3b88f228d86db\"}") @@ -178,7 +194,11 @@ func TestContentList(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/content/docker"). + Get("/gateway/code/api/v1/repos/thomas/content/docker"). + MatchParam("accountIdentifier", "px7xd_BFRCi-pfWPYXVjvw"). + MatchParam("orgIdentifier", "default"). + MatchParam("projectIdentifier", "codeciintegration"). + MatchParam("routingId", "px7xd_BFRCi-pfWPYXVjvw"). Reply(200). Type("application/json"). File("testdata/content_list.json") diff --git a/scm/driver/harness/git_test.go b/scm/driver/harness/git_test.go index 515705068..dfbd5a99e 100644 --- a/scm/driver/harness/git_test.go +++ b/scm/driver/harness/git_test.go @@ -24,7 +24,11 @@ func TestListCommits(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/commits"). + Get("/gateway/code/api/v1/repos/thomas/commits"). + MatchParam("accountIdentifier", "px7xd_BFRCi-pfWPYXVjvw"). + MatchParam("orgIdentifier", "default"). + MatchParam("projectIdentifier", "codeciintegration"). + MatchParam("routingId", "px7xd_BFRCi-pfWPYXVjvw"). Reply(200). Type("application/json"). File("testdata/commits.json") @@ -66,7 +70,11 @@ func TestFindCommit(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/commits/1d640265d8bdd818175fa736f0fcbad2c9b716c9"). + Get("/gateway/code/api/v1/repos/thomas/commits/1d640265d8bdd818175fa736f0fcbad2c9b716c9"). + MatchParam("accountIdentifier", "px7xd_BFRCi-pfWPYXVjvw"). + MatchParam("orgIdentifier", "default"). + MatchParam("projectIdentifier", "codeciintegration"). + MatchParam("routingId", "px7xd_BFRCi-pfWPYXVjvw"). Reply(200). Type("application/json"). File("testdata/commit.json") @@ -104,7 +112,11 @@ func TestFindBranch(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/branches/main"). + Get("/gateway/code/api/v1/repos/thomas/branches/main"). + MatchParam("accountIdentifier", "px7xd_BFRCi-pfWPYXVjvw"). + MatchParam("orgIdentifier", "default"). + MatchParam("projectIdentifier", "codeciintegration"). + MatchParam("routingId", "px7xd_BFRCi-pfWPYXVjvw"). Reply(200). Type("application/json"). File("testdata/branch.json") @@ -142,7 +154,11 @@ func TestListBranches(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/branches"). + Get("/gateway/code/api/v1/repos/thomas/branches"). + MatchParam("accountIdentifier", "px7xd_BFRCi-pfWPYXVjvw"). + MatchParam("orgIdentifier", "default"). + MatchParam("projectIdentifier", "codeciintegration"). + MatchParam("routingId", "px7xd_BFRCi-pfWPYXVjvw"). Reply(200). Type("application/json"). File("testdata/branches.json") @@ -180,7 +196,11 @@ func TestCreateBranch(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/branches"). + Post("/gateway/code/api/v1/repos/thomas/branches"). + MatchParam("accountIdentifier", "px7xd_BFRCi-pfWPYXVjvw"). + MatchParam("orgIdentifier", "default"). + MatchParam("projectIdentifier", "codeciintegration"). + MatchParam("routingId", "px7xd_BFRCi-pfWPYXVjvw"). Reply(200). Type("application/json"). File("testdata/branch.json") @@ -215,7 +235,11 @@ func TestCompareChanges(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Get(fmt.Sprintf("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/diff/%s...%s", source, target)). + Get(fmt.Sprintf("/gateway/code/api/v1/repos/thomas/diff/%s...%s", source, target)). + MatchParam("accountIdentifier", "px7xd_BFRCi-pfWPYXVjvw"). + MatchParam("orgIdentifier", "default"). + MatchParam("projectIdentifier", "codeciintegration"). + MatchParam("routingId", "px7xd_BFRCi-pfWPYXVjvw"). Reply(200). Type("application/json"). File("testdata/gitdiff.json") diff --git a/scm/driver/harness/pr_test.go b/scm/driver/harness/pr_test.go index 951690164..fa26ebb4c 100644 --- a/scm/driver/harness/pr_test.go +++ b/scm/driver/harness/pr_test.go @@ -8,11 +8,12 @@ import ( "context" "encoding/json" "fmt" - "github.com/google/go-cmp/cmp/cmpopts" "io/ioutil" "net/http" "testing" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/drone/go-scm/scm" "github.com/drone/go-scm/scm/transport" "github.com/google/go-cmp/cmp" @@ -24,7 +25,11 @@ func TestPRFind(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/pullreq/1"). + Get("/gateway/code/api/v1/repos/thomas/pullreq/1"). + MatchParam("accountIdentifier", "px7xd_BFRCi-pfWPYXVjvw"). + MatchParam("orgIdentifier", "default"). + MatchParam("projectIdentifier", "codeciintegration"). + MatchParam("routingId", "px7xd_BFRCi-pfWPYXVjvw"). Reply(200). Type("plain/text"). File("testdata/pr.json") @@ -63,7 +68,11 @@ func TestPRCommits(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/pullreq/1/commits"). + Get("/gateway/code/api/v1/repos/thomas/pullreq/1/commits"). + MatchParam("accountIdentifier", "px7xd_BFRCi-pfWPYXVjvw"). + MatchParam("orgIdentifier", "default"). + MatchParam("projectIdentifier", "codeciintegration"). + MatchParam("routingId", "px7xd_BFRCi-pfWPYXVjvw"). Reply(200). Type("plain/text"). File("testdata/pr_commits.json") @@ -100,7 +109,11 @@ func TestPRCommits(t *testing.T) { func TestPullCreate(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/pullreq"). + Post("/gateway/code/api/v1/repos/thomas/pullreq"). + MatchParam("accountIdentifier", "px7xd_BFRCi-pfWPYXVjvw"). + MatchParam("orgIdentifier", "default"). + MatchParam("projectIdentifier", "codeciintegration"). + MatchParam("routingId", "px7xd_BFRCi-pfWPYXVjvw"). Reply(200). Type("plain/text"). File("testdata/pr.json") diff --git a/scm/driver/harness/repo.go b/scm/driver/harness/repo.go index dc489a267..cef50eff3 100644 --- a/scm/driver/harness/repo.go +++ b/scm/driver/harness/repo.go @@ -97,9 +97,7 @@ func (s *repositoryService) CreateHook(ctx context.Context, repo string, input * in.Secret = input.Secret in.Insecure = input.SkipVerify in.URL = input.Target - in.Triggers = append( - input.NativeEvents, - ) + in.Triggers = input.NativeEvents out := new(hook) res, err := s.client.do(ctx, "POST", path, in, out) return convertHook(out), res, err diff --git a/scm/driver/harness/repo_test.go b/scm/driver/harness/repo_test.go index d482d4bcb..1fc861084 100644 --- a/scm/driver/harness/repo_test.go +++ b/scm/driver/harness/repo_test.go @@ -24,7 +24,11 @@ func TestRepositoryFind(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/demo/+"). + Get("/gateway/code/api/v1/repos/demo"). + MatchParam("accountIdentifier", "px7xd_BFRCi-pfWPYXVjvw"). + MatchParam("orgIdentifier", "default"). + MatchParam("projectIdentifier", "codeciintegration"). + MatchParam("routingId", "px7xd_BFRCi-pfWPYXVjvw"). Reply(200). Type("application/json"). File("testdata/repo.json") @@ -58,11 +62,15 @@ func TestRepositoryList(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Get("/gateway/code/api/v1/spaces/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/+/repos"). + Get("/gateway/code/api/v1/repos"). MatchParam("page", "1"). MatchParam("limit", "20"). MatchParam("sort", "path"). MatchParam("order", "asc"). + MatchParam("accountIdentifier", "px7xd_BFRCi-pfWPYXVjvw"). + MatchParam("orgIdentifier", "default"). + MatchParam("projectIdentifier", "codeciintegration"). + MatchParam("routingId", "px7xd_BFRCi-pfWPYXVjvw"). Reply(200). Type("application/json"). File("testdata/repos.json") @@ -100,7 +108,11 @@ func TestRepositoryHookList(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/webhooks"). + Get("/gateway/code/api/v1/repos/thomas/webhooks"). + MatchParam("accountIdentifier", "px7xd_BFRCi-pfWPYXVjvw"). + MatchParam("orgIdentifier", "default"). + MatchParam("projectIdentifier", "codeciintegration"). + MatchParam("routingId", "px7xd_BFRCi-pfWPYXVjvw"). MatchParam("page", "1"). MatchParam("limit", "30"). MatchParam("sort", "display_name"). @@ -138,7 +150,11 @@ func TestRepositoryFindHook(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/webhooks/6"). + Get("/gateway/code/api/v1/repos/thomas/webhooks/6"). + MatchParam("accountIdentifier", "px7xd_BFRCi-pfWPYXVjvw"). + MatchParam("orgIdentifier", "default"). + MatchParam("projectIdentifier", "codeciintegration"). + MatchParam("routingId", "px7xd_BFRCi-pfWPYXVjvw"). Reply(200). Type("application/json"). File("testdata/hook.json") @@ -172,7 +188,11 @@ func TestRepositoryHookCreateDelete(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/webhooks"). + Post("/gateway/code/api/v1/repos/thomas/webhooks"). + MatchParam("accountIdentifier", "px7xd_BFRCi-pfWPYXVjvw"). + MatchParam("orgIdentifier", "default"). + MatchParam("projectIdentifier", "codeciintegration"). + MatchParam("routingId", "px7xd_BFRCi-pfWPYXVjvw"). Reply(200). Type("application/json"). File("testdata/hook_create.json") @@ -210,7 +230,11 @@ func TestRepositoryHookCreateDelete(t *testing.T) { defer gock.Off() gock.New(gockOrigin). - Delete(fmt.Sprintf("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/webhooks/%s", got.ID)). + Delete(fmt.Sprintf("/gateway/code/api/v1/repos/thomas/webhooks/%s", got.ID)). + MatchParam("accountIdentifier", "px7xd_BFRCi-pfWPYXVjvw"). + MatchParam("orgIdentifier", "default"). + MatchParam("projectIdentifier", "codeciintegration"). + MatchParam("routingId", "px7xd_BFRCi-pfWPYXVjvw"). Reply(204) } client, _ = New(gockOrigin, harnessOrg, harnessAccount, harnessProject) From bf93d79cabce0da539d0b0d63009a2f42961a443 Mon Sep 17 00:00:00 2001 From: Karan Saraswat Date: Mon, 6 May 2024 14:39:27 +0530 Subject: [PATCH 238/282] fix: [CODE-1870]: adding cloneUrl to the convertRepository method for azure driver --- scm/driver/azure/repo.go | 1 + scm/driver/azure/testdata/repo.json.golden | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/scm/driver/azure/repo.go b/scm/driver/azure/repo.go index edfd4d876..8c1882bd0 100644 --- a/scm/driver/azure/repo.go +++ b/scm/driver/azure/repo.go @@ -279,6 +279,7 @@ func convertRepository(from *repository) *scm.Repository { Name: from.Name, Link: from.URL, Branch: scm.TrimRef(from.DefaultBranch), + Clone: from.RemoteURL, } } diff --git a/scm/driver/azure/testdata/repo.json.golden b/scm/driver/azure/testdata/repo.json.golden index 92f3b874a..6ec2a9323 100644 --- a/scm/driver/azure/testdata/repo.json.golden +++ b/scm/driver/azure/testdata/repo.json.golden @@ -2,5 +2,6 @@ "ID": "91f0d4cb-4c36-49a5-b28d-2d72da089c4d", "Name": "test_project", "Branch": "main", - "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/91f0d4cb-4c36-49a5-b28d-2d72da089c4d" + "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/91f0d4cb-4c36-49a5-b28d-2d72da089c4d", + "Clone": "https://tphoney@dev.azure.com/tphoney/test_project/_git/test_project" } \ No newline at end of file From 9de001d92f7f9655b0e8c1e6e59e23a82d350279 Mon Sep 17 00:00:00 2001 From: Karan Saraswat Date: Mon, 6 May 2024 14:47:38 +0530 Subject: [PATCH 239/282] fixed tests --- scm/driver/azure/testdata/repos.json.golden | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scm/driver/azure/testdata/repos.json.golden b/scm/driver/azure/testdata/repos.json.golden index cbe9d840d..5be3b9ae3 100644 --- a/scm/driver/azure/testdata/repos.json.golden +++ b/scm/driver/azure/testdata/repos.json.golden @@ -3,12 +3,14 @@ "ID": "91f0d4cb-4c36-49a5-b28d-2d72da089c4d", "Name": "test_project", "Branch": "main", - "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/91f0d4cb-4c36-49a5-b28d-2d72da089c4d" + "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/91f0d4cb-4c36-49a5-b28d-2d72da089c4d", + "Clone": "https://tphoney@dev.azure.com/tphoney/test_project/_git/test_project" }, { "ID": "fde2d21f-13b9-4864-a995-83329045289a", "Name": "test_repo2", "Branch": "main", - "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a" + "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a", + "Clone": "https://tphoney@dev.azure.com/tphoney/test_project/_git/test_repo2" } ] \ No newline at end of file From 7d4064867b254e019f7888fa46eb93e524fdf44d Mon Sep 17 00:00:00 2001 From: Soumyajit Das Date: Mon, 6 May 2024 21:07:36 +0530 Subject: [PATCH 240/282] [feat]: [CI-12179]: Add support for gitlab basesha --- scm/driver/gitlab/pr.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/scm/driver/gitlab/pr.go b/scm/driver/gitlab/pr.go index b82951d4c..35d44e658 100644 --- a/scm/driver/gitlab/pr.go +++ b/scm/driver/gitlab/pr.go @@ -117,6 +117,11 @@ type pr struct { Updated time.Time `json:"updated_at"` Closed time.Time Labels []string `json:"labels"` + DiffRefs struct { + BaseSha string `json:"base_sha"` + HeadSha string `json:"head_sha"` + StartSha string `json:"start_sha"` + } } type changes struct { @@ -165,6 +170,9 @@ func convertPullRequest(from *pr) *scm.PullRequest { Created: from.Created, Updated: from.Updated, Labels: labels, + Base: scm.Reference{ + Sha: from.DiffRefs.BaseSha, + }, } } From 1cd57db50bb04bd39505354b1a4a3a8653774dc5 Mon Sep 17 00:00:00 2001 From: Soumyajit Das Date: Wed, 8 May 2024 19:42:29 +0530 Subject: [PATCH 241/282] add diff_refs json --- scm/driver/gitlab/pr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/driver/gitlab/pr.go b/scm/driver/gitlab/pr.go index 35d44e658..52548146f 100644 --- a/scm/driver/gitlab/pr.go +++ b/scm/driver/gitlab/pr.go @@ -121,7 +121,7 @@ type pr struct { BaseSha string `json:"base_sha"` HeadSha string `json:"head_sha"` StartSha string `json:"start_sha"` - } + } `json:"diff_refs"` } type changes struct { From 9b7f4379fa10d39d756196285e8ebd3f57bf03dd Mon Sep 17 00:00:00 2001 From: Karan Saraswat Date: Thu, 16 May 2024 00:09:26 +0530 Subject: [PATCH 242/282] feat: [CODE-1907]: Fix go-scm azure driver for getting namespace in the response (#307) --- scm/driver/azure/repo.go | 27 ++++++++++++--------- scm/driver/azure/testdata/repo.json.golden | 1 + scm/driver/azure/testdata/repos.json.golden | 2 ++ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/scm/driver/azure/repo.go b/scm/driver/azure/repo.go index 8c1882bd0..d5b364555 100644 --- a/scm/driver/azure/repo.go +++ b/scm/driver/azure/repo.go @@ -8,6 +8,7 @@ import ( "context" "fmt" "net/url" + "strings" "github.com/drone/go-scm/scm" ) @@ -28,7 +29,7 @@ func (s *RepositoryService) Find(ctx context.Context, repo string) (*scm.Reposit out := new(repository) res, err := s.client.do(ctx, "GET", endpoint, nil, &out) - return convertRepository(out), res, err + return convertRepository(out, s.client.owner), res, err } // FindHook returns a repository hook. @@ -53,7 +54,7 @@ func (s *RepositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* out := new(repositories) res, err := s.client.do(ctx, "GET", endpoint, nil, &out) - return convertRepositoryList(out), res, err + return convertRepositoryList(out, s.client.owner), res, err } // ListV2 returns the user repository list. @@ -261,25 +262,27 @@ type subscription struct { URL string `json:"url"` } -// helper function to convert from the gogs repository list to +// helper function to convert from the azure devops repository list to // the common repository structure. -func convertRepositoryList(from *repositories) []*scm.Repository { +func convertRepositoryList(from *repositories, owner string) []*scm.Repository { to := []*scm.Repository{} for _, v := range from.Value { - to = append(to, convertRepository(v)) + to = append(to, convertRepository(v, owner)) } return to } -// helper function to convert from the gogs repository structure +// helper function to convert from the azure devops repository structure // to the common repository structure. -func convertRepository(from *repository) *scm.Repository { +func convertRepository(from *repository, owner string) *scm.Repository { + namespace := []string{owner, from.Project.Name} return &scm.Repository{ - ID: from.ID, - Name: from.Name, - Link: from.URL, - Branch: scm.TrimRef(from.DefaultBranch), - Clone: from.RemoteURL, + ID: from.ID, + Name: from.Name, + Namespace: strings.Join(namespace, "/"), + Link: from.URL, + Branch: scm.TrimRef(from.DefaultBranch), + Clone: from.RemoteURL, } } diff --git a/scm/driver/azure/testdata/repo.json.golden b/scm/driver/azure/testdata/repo.json.golden index 6ec2a9323..c642b51e2 100644 --- a/scm/driver/azure/testdata/repo.json.golden +++ b/scm/driver/azure/testdata/repo.json.golden @@ -1,6 +1,7 @@ { "ID": "91f0d4cb-4c36-49a5-b28d-2d72da089c4d", "Name": "test_project", + "Namespace": "ORG/test_project", "Branch": "main", "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/91f0d4cb-4c36-49a5-b28d-2d72da089c4d", "Clone": "https://tphoney@dev.azure.com/tphoney/test_project/_git/test_project" diff --git a/scm/driver/azure/testdata/repos.json.golden b/scm/driver/azure/testdata/repos.json.golden index 5be3b9ae3..d4c8b140a 100644 --- a/scm/driver/azure/testdata/repos.json.golden +++ b/scm/driver/azure/testdata/repos.json.golden @@ -2,6 +2,7 @@ { "ID": "91f0d4cb-4c36-49a5-b28d-2d72da089c4d", "Name": "test_project", + "Namespace": "ORG/test_project", "Branch": "main", "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/91f0d4cb-4c36-49a5-b28d-2d72da089c4d", "Clone": "https://tphoney@dev.azure.com/tphoney/test_project/_git/test_project" @@ -9,6 +10,7 @@ { "ID": "fde2d21f-13b9-4864-a995-83329045289a", "Name": "test_repo2", + "Namespace": "ORG/test_project", "Branch": "main", "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a", "Clone": "https://tphoney@dev.azure.com/tphoney/test_project/_git/test_repo2" From 6e98856955497981781bafd6f9b0adf8daf2ffdc Mon Sep 17 00:00:00 2001 From: Vitalie Safronovici Date: Tue, 28 May 2024 13:54:53 +0300 Subject: [PATCH 243/282] feat: [IAC-1930]: fixed ListTags --- scm/driver/bitbucket/git.go | 2 +- scm/driver/github/git.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scm/driver/bitbucket/git.go b/scm/driver/bitbucket/git.go index 8efbe341e..2b77d8907 100644 --- a/scm/driver/bitbucket/git.go +++ b/scm/driver/bitbucket/git.go @@ -81,7 +81,7 @@ func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.Comm } func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { - path := fmt.Sprintf("2.0/repositories/%s/refs/tags?%s", repo, encodeListOptions(opts)) + path := fmt.Sprintf("2.0/repositories/%s/refs/tags", repo) out := new(branches) res, err := s.client.do(ctx, "GET", path, nil, &out) copyPagination(out.pagination, res) diff --git a/scm/driver/github/git.go b/scm/driver/github/git.go index c64ea3430..a6d8ae242 100644 --- a/scm/driver/github/git.go +++ b/scm/driver/github/git.go @@ -67,8 +67,8 @@ func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.Comm } func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { - path := fmt.Sprintf("repos/%s/tags?%s", repo, encodeListOptions(opts)) - out := []*branch{} + path := fmt.Sprintf("repos/%s/git/refs/tags", repo) + out := []*ref{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertTagList(out), res, err } @@ -191,10 +191,10 @@ func convertRef(from *ref) *scm.Reference { } } -func convertTagList(from []*branch) []*scm.Reference { +func convertTagList(from []*ref) []*scm.Reference { to := []*scm.Reference{} for _, v := range from { - to = append(to, convertTag(v)) + to = append(to, convertRef(v)) } return to } From 34f93ff9f866379f4dfadd7023a2c6d9eff3fd36 Mon Sep 17 00:00:00 2001 From: Vitalie Safronovici Date: Thu, 30 May 2024 19:18:54 +0300 Subject: [PATCH 244/282] fixed tests --- scm/driver/bitbucket/git_test.go | 2 -- scm/driver/bitbucket/testdata/tags.json.golden | 4 ++-- scm/driver/github/git.go | 2 +- scm/driver/github/git_test.go | 2 +- scm/driver/github/testdata/tags.json | 17 +++++++++-------- scm/driver/github/testdata/tags.json.golden | 6 +++--- 6 files changed, 16 insertions(+), 17 deletions(-) diff --git a/scm/driver/bitbucket/git_test.go b/scm/driver/bitbucket/git_test.go index 74928583f..5d0e08dbf 100644 --- a/scm/driver/bitbucket/git_test.go +++ b/scm/driver/bitbucket/git_test.go @@ -244,8 +244,6 @@ func TestGitListTags(t *testing.T) { gock.New("https://api.bitbucket.org"). Get("/2.0/repositories/atlassian/atlaskit/refs/tags"). - MatchParam("page", "1"). - MatchParam("pagelen", "30"). Reply(200). Type("application/json"). File("testdata/tags.json") diff --git a/scm/driver/bitbucket/testdata/tags.json.golden b/scm/driver/bitbucket/testdata/tags.json.golden index 8cb6251e0..0e0e95ed0 100644 --- a/scm/driver/bitbucket/testdata/tags.json.golden +++ b/scm/driver/bitbucket/testdata/tags.json.golden @@ -1,7 +1,7 @@ [ { - "Name": "@atlaskit/activity@1.0.3", - "Path": "refs/tags/@atlaskit/activity@1.0.3", + "Name": "@atlaskit\/activity@1.0.3", + "Path": "refs/tags/@atlaskit\/activity@1.0.3", "Sha": "ceb01356c3f062579bdfeb15bc53fe151b9e00f0" } ] \ No newline at end of file diff --git a/scm/driver/github/git.go b/scm/driver/github/git.go index a6d8ae242..f4153423f 100644 --- a/scm/driver/github/git.go +++ b/scm/driver/github/git.go @@ -67,7 +67,7 @@ func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.Comm } func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { - path := fmt.Sprintf("repos/%s/git/refs/tags", repo) + path := fmt.Sprintf("repos/%s/git/refs/tags?%s", repo, encodeListOptions(opts)) out := []*ref{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertTagList(out), res, err diff --git a/scm/driver/github/git_test.go b/scm/driver/github/git_test.go index 36e18e77f..8d1ff4c5c 100644 --- a/scm/driver/github/git_test.go +++ b/scm/driver/github/git_test.go @@ -211,7 +211,7 @@ func TestGitListTags(t *testing.T) { defer gock.Off() gock.New("https://api.github.com"). - Get("/repos/octocat/hello-world/tags"). + Get("/repos/octocat/hello-world/git/refs/tags"). MatchParam("page", "1"). MatchParam("per_page", "30"). Reply(200). diff --git a/scm/driver/github/testdata/tags.json b/scm/driver/github/testdata/tags.json index 8eee0f95a..eac19260c 100644 --- a/scm/driver/github/testdata/tags.json +++ b/scm/driver/github/testdata/tags.json @@ -1,11 +1,12 @@ [ { - "name": "v0.1", - "commit": { - "sha": "c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc", - "url": "https://api.github.com/repos/octocat/Hello-World/commits/c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc" - }, - "zipball_url": "https://github.com/octocat/Hello-World/zipball/v0.1", - "tarball_url": "https://github.com/octocat/Hello-World/tarball/v0.1" - } + "ref": "refs/tags/v1", + "node_id": "REF_kwDOGvVo46xyZWZzL3RhZ3MvdjE", + "url": "https://api.github.com/repos/vitsafronovici/myrepo/git/refs/tags/v1", + "object": { + "sha": "85fd27bdfd87b962d1ed4a742613cbfacd5c3743", + "type": "tag", + "url": "https://api.github.com/repos/vitsafronovici/myrepo/git/tags/85fd27bdfd87b962d1ed4a742613cbfacd5c3743" + } + } ] \ No newline at end of file diff --git a/scm/driver/github/testdata/tags.json.golden b/scm/driver/github/testdata/tags.json.golden index de3d2df17..c533fd7ee 100644 --- a/scm/driver/github/testdata/tags.json.golden +++ b/scm/driver/github/testdata/tags.json.golden @@ -1,7 +1,7 @@ [ { - "Name": "v0.1", - "Path": "refs/tags/v0.1", - "Sha": "c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc" + "Name": "v1", + "Path": "refs/tags/v1", + "Sha": "85fd27bdfd87b962d1ed4a742613cbfacd5c3743" } ] \ No newline at end of file From a2e3a61da3223ec528a8f90c0dca02532dce4cce Mon Sep 17 00:00:00 2001 From: Vitalie Safronovici Date: Thu, 30 May 2024 19:27:24 +0300 Subject: [PATCH 245/282] fixed notes --- scm/driver/github/git.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scm/driver/github/git.go b/scm/driver/github/git.go index f4153423f..11edba432 100644 --- a/scm/driver/github/git.go +++ b/scm/driver/github/git.go @@ -70,7 +70,7 @@ func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOpt path := fmt.Sprintf("repos/%s/git/refs/tags?%s", repo, encodeListOptions(opts)) out := []*ref{} res, err := s.client.do(ctx, "GET", path, nil, &out) - return convertTagList(out), res, err + return convertRefList(out), res, err } func (s *gitService) ListChanges(ctx context.Context, repo, ref string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { @@ -191,7 +191,7 @@ func convertRef(from *ref) *scm.Reference { } } -func convertTagList(from []*ref) []*scm.Reference { +func convertRefList(from []*ref) []*scm.Reference { to := []*scm.Reference{} for _, v := range from { to = append(to, convertRef(v)) From bd0004034c47c814257be2a47558528c0a56edbd Mon Sep 17 00:00:00 2001 From: Vitalie Safronovici Date: Thu, 30 May 2024 20:16:03 +0300 Subject: [PATCH 246/282] fixed notes --- scm/driver/bitbucket/git.go | 10 +++++++++- scm/driver/bitbucket/git_test.go | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/scm/driver/bitbucket/git.go b/scm/driver/bitbucket/git.go index 2b77d8907..36f47bf07 100644 --- a/scm/driver/bitbucket/git.go +++ b/scm/driver/bitbucket/git.go @@ -81,9 +81,17 @@ func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.Comm } func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { - path := fmt.Sprintf("2.0/repositories/%s/refs/tags", repo) + // make page params only with 'pagelen' as there is a bug with 'page' param + updatedOpts := scm.ListOptions{Size: opts.Size, Page: 0} + + path := fmt.Sprintf("2.0/repositories/%s/refs/tags?%s", repo, encodeListOptions(updatedOpts)) + + fmt.Printf("path=%s\n", path) + out := new(branches) res, err := s.client.do(ctx, "GET", path, nil, &out) + + res.Page.Next = 0 copyPagination(out.pagination, res) return convertTagList(out), res, err } diff --git a/scm/driver/bitbucket/git_test.go b/scm/driver/bitbucket/git_test.go index 5d0e08dbf..c04c26d51 100644 --- a/scm/driver/bitbucket/git_test.go +++ b/scm/driver/bitbucket/git_test.go @@ -244,6 +244,7 @@ func TestGitListTags(t *testing.T) { gock.New("https://api.bitbucket.org"). Get("/2.0/repositories/atlassian/atlaskit/refs/tags"). + MatchParam("pagelen", "30"). Reply(200). Type("application/json"). File("testdata/tags.json") From 99ca5aae45b595a2822e2c4ac406ce645fc10c6b Mon Sep 17 00:00:00 2001 From: Vitalie Safronovici Date: Thu, 30 May 2024 20:17:18 +0300 Subject: [PATCH 247/282] removed println --- scm/driver/bitbucket/git.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/scm/driver/bitbucket/git.go b/scm/driver/bitbucket/git.go index 36f47bf07..2e676151d 100644 --- a/scm/driver/bitbucket/git.go +++ b/scm/driver/bitbucket/git.go @@ -83,11 +83,8 @@ func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.Comm func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { // make page params only with 'pagelen' as there is a bug with 'page' param updatedOpts := scm.ListOptions{Size: opts.Size, Page: 0} - path := fmt.Sprintf("2.0/repositories/%s/refs/tags?%s", repo, encodeListOptions(updatedOpts)) - fmt.Printf("path=%s\n", path) - out := new(branches) res, err := s.client.do(ctx, "GET", path, nil, &out) From 9d071724ee90f801135107fc88dcbee565d9f70c Mon Sep 17 00:00:00 2001 From: Vitalie Safronovici Date: Thu, 30 May 2024 20:24:47 +0300 Subject: [PATCH 248/282] fixed notes --- scm/driver/bitbucket/git.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/scm/driver/bitbucket/git.go b/scm/driver/bitbucket/git.go index 2e676151d..181c9fa3a 100644 --- a/scm/driver/bitbucket/git.go +++ b/scm/driver/bitbucket/git.go @@ -82,13 +82,16 @@ func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.Comm func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { // make page params only with 'pagelen' as there is a bug with 'page' param - updatedOpts := scm.ListOptions{Size: opts.Size, Page: 0} - path := fmt.Sprintf("2.0/repositories/%s/refs/tags?%s", repo, encodeListOptions(updatedOpts)) + opts.Page = 0 + path := fmt.Sprintf("2.0/repositories/%s/refs/tags?%s", repo, encodeListOptions(opts)) out := new(branches) res, err := s.client.do(ctx, "GET", path, nil, &out) - res.Page.Next = 0 + if res != nil { + res.Page.Next = 0 + } + copyPagination(out.pagination, res) return convertTagList(out), res, err } From fc4336b333b86e2f1f82fae232e50ac7252e9f27 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Thu, 6 Jun 2024 07:50:13 +0530 Subject: [PATCH 249/282] feat: add list namespace for repos (#309) * feat: add list namespace * feat: add list namespace * feat: add list namespace * add for remaining * add for remaining * Update repo.go * address comment * address comment * Update repo.go --- scm/driver/azure/repo.go | 6 ++++++ scm/driver/bitbucket/repo.go | 11 +++++++++++ scm/driver/gitea/repo.go | 7 +++++++ scm/driver/gitee/repo.go | 4 ++++ scm/driver/github/repo.go | 8 ++++++++ scm/driver/gitlab/repo.go | 7 +++++++ scm/driver/gogs/repo.go | 7 +++++++ scm/driver/harness/repo.go | 5 +++++ scm/driver/stash/repo.go | 12 ++++++++++++ scm/repo.go | 3 +++ 10 files changed, 70 insertions(+) diff --git a/scm/driver/azure/repo.go b/scm/driver/azure/repo.go index d5b364555..25be94b80 100644 --- a/scm/driver/azure/repo.go +++ b/scm/driver/azure/repo.go @@ -63,6 +63,12 @@ func (s *RepositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions return s.List(ctx, opts.ListOptions) } +// ListNamespace is of no use in azure as our client already has project information +func (s *RepositoryService) ListNamespace(ctx context.Context, _ string, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { + // Azure client already has org/proj information + return s.List(ctx, opts) +} + // ListHooks returns a list or repository hooks. func (s *RepositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { // https://docs.microsoft.com/en-us/rest/api/azure/devops/hooks/subscriptions/list?view=azure-devops-rest-6.0 diff --git a/scm/driver/bitbucket/repo.go b/scm/driver/bitbucket/repo.go index 5929f6080..cc942c49a 100644 --- a/scm/driver/bitbucket/repo.go +++ b/scm/driver/bitbucket/repo.go @@ -117,6 +117,17 @@ func (s *repositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions return convertRepositoryList(out), res, err } +func (s *repositoryService) ListNamespace(ctx context.Context, namespace string, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { + path := fmt.Sprintf("2.0/repositories/%s?%s", namespace, encodeListRoleOptions(opts)) + if opts.URL != "" { + path = opts.URL + } + out := new(repositories) + res, err := s.client.do(ctx, "GET", path, nil, &out) + copyPagination(out.pagination, res) + return convertRepositoryList(out), res, err +} + // ListHooks returns a list or repository hooks. func (s *repositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { path := fmt.Sprintf("2.0/repositories/%s/hooks?%s", repo, encodeListOptions(opts)) diff --git a/scm/driver/gitea/repo.go b/scm/driver/gitea/repo.go index a678273bf..81d92a5f5 100644 --- a/scm/driver/gitea/repo.go +++ b/scm/driver/gitea/repo.go @@ -51,6 +51,13 @@ func (s *repositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions return s.List(ctx, opts.ListOptions) } +func (s *repositoryService) ListNamespace(ctx context.Context, namespace string, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { + path := fmt.Sprintf("api/v1/orgs/%s/repos?%s", namespace, encodeListOptions(opts)) + out := []*repository{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertRepositoryList(out), res, err +} + func (s *repositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { path := fmt.Sprintf("api/v1/repos/%s/hooks?%s", repo, encodeListOptions(opts)) out := []*hook{} diff --git a/scm/driver/gitee/repo.go b/scm/driver/gitee/repo.go index 72c60f567..967ab4f59 100644 --- a/scm/driver/gitee/repo.go +++ b/scm/driver/gitee/repo.go @@ -50,6 +50,10 @@ func (s *RepositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions return s.List(ctx, opts.ListOptions) } +func (s *RepositoryService) ListNamespace(ctx context.Context, namespace string, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { + return nil, nil, scm.ErrNotSupported +} + func (s *RepositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { path := fmt.Sprintf("repos/%s/hooks?%s", repo, encodeListOptions(opts)) out := []*hook{} diff --git a/scm/driver/github/repo.go b/scm/driver/github/repo.go index c9f09b7bc..857d0a4f7 100644 --- a/scm/driver/github/repo.go +++ b/scm/driver/github/repo.go @@ -122,6 +122,14 @@ func (s *RepositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions return convertRepositoryList(out.Repositories), res, err } +// ListNamespace returns the user repository list based on searchterm and namespace. +func (s *RepositoryService) ListNamespace(ctx context.Context, namespace string, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { + path := fmt.Sprintf("orgs/%s/repos?%s", namespace, encodeListOptions(opts)) + out := new(searchRepositoryList) + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertRepositoryList(out.Repositories), res, err +} + // List returns the github app installation repository list. func (s *RepositoryService) ListByInstallation(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { path := fmt.Sprintf("installation/repositories?%s", encodeListOptions(opts)) diff --git a/scm/driver/gitlab/repo.go b/scm/driver/gitlab/repo.go index dc6f39a7e..d41776144 100644 --- a/scm/driver/gitlab/repo.go +++ b/scm/driver/gitlab/repo.go @@ -102,6 +102,13 @@ func (s *repositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions return convertRepositoryList(out), res, err } +func (s *repositoryService) ListNamespace(ctx context.Context, namespace string, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { + path := fmt.Sprintf("api/v4/groups/%s/projects?%s", namespace, encodeMemberListOptions(opts)) + out := []*repository{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertRepositoryList(out), res, err +} + func (s *repositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { path := fmt.Sprintf("api/v4/projects/%s/hooks?%s", encode(repo), encodeListOptions(opts)) out := []*hook{} diff --git a/scm/driver/gogs/repo.go b/scm/driver/gogs/repo.go index 5657b5ee7..0f645c1fd 100644 --- a/scm/driver/gogs/repo.go +++ b/scm/driver/gogs/repo.go @@ -50,6 +50,13 @@ func (s *repositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions return s.List(ctx, opts.ListOptions) } +func (s *repositoryService) ListNamespace(ctx context.Context, namespace string, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { + path := fmt.Sprintf("api/v1/orgs/%s/repos", namespace) + out := []*repository{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertRepositoryList(out), res, err +} + func (s *repositoryService) ListHooks(ctx context.Context, repo string, _ scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { path := fmt.Sprintf("api/v1/repos/%s/hooks", repo) out := []*hook{} diff --git a/scm/driver/harness/repo.go b/scm/driver/harness/repo.go index cef50eff3..82f095d21 100644 --- a/scm/driver/harness/repo.go +++ b/scm/driver/harness/repo.go @@ -68,6 +68,11 @@ func (s *repositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions return s.List(ctx, opts.ListOptions) } +func (s *repositoryService) ListNamespace(ctx context.Context, _ string, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { + // Client already has context about namespace + return s.List(ctx, opts) +} + func (s *repositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) repoId, queryParams, err := getRepoAndQueryParams(harnessURI) diff --git a/scm/driver/stash/repo.go b/scm/driver/stash/repo.go index 33ba4bc42..f8093a145 100644 --- a/scm/driver/stash/repo.go +++ b/scm/driver/stash/repo.go @@ -192,6 +192,18 @@ func (s *repositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions return convertRepositoryList(out), res, err } +// ListNamespace returns the user repository list based on searchterm and namespace. +func (s *repositoryService) ListNamespace(ctx context.Context, namespace string, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { + path := fmt.Sprintf("rest/api/1.0/projects/%s/repos?%s", namespace, encodeListRoleOptions(opts)) + out := new(repositories) + res, err := s.client.do(ctx, "GET", path, nil, &out) + if res != nil && !out.pagination.LastPage.Bool { + res.Page.First = 1 + res.Page.Next = opts.Page + 1 + } + return convertRepositoryList(out), res, err +} + // listWrite returns the user repository list. func (s *repositoryService) listWrite(ctx context.Context, repo string) ([]*scm.Repository, *scm.Response, error) { _, name := scm.Split(repo) diff --git a/scm/repo.go b/scm/repo.go index 1e6218fdc..8ec383c37 100644 --- a/scm/repo.go +++ b/scm/repo.go @@ -123,6 +123,9 @@ type ( // ListV2 returns a list of repositories based on the searchTerm passed. ListV2(context.Context, RepoListOptions) ([]*Repository, *Response, error) + // ListNamespace returns a list of repos in namespace + ListNamespace(context.Context, string, ListOptions) ([]*Repository, *Response, error) + // ListHooks returns a list or repository hooks. ListHooks(context.Context, string, ListOptions) ([]*Hook, *Response, error) From 2e2589d4e7a4a4056529d492b56d1a582e865531 Mon Sep 17 00:00:00 2001 From: Karan Saraswat Date: Mon, 17 Jun 2024 22:06:35 +0530 Subject: [PATCH 250/282] fix query params for List PRs API call for stash provider for pagination and state of PRs --- scm/driver/stash/pr.go | 2 +- scm/driver/stash/util.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scm/driver/stash/pr.go b/scm/driver/stash/pr.go index e1229e271..86f88c35c 100644 --- a/scm/driver/stash/pr.go +++ b/scm/driver/stash/pr.go @@ -34,7 +34,7 @@ func (s *pullService) FindComment(ctx context.Context, repo string, number int, func (s *pullService) List(ctx context.Context, repo string, opts scm.PullRequestListOptions) ([]*scm.PullRequest, *scm.Response, error) { namespace, name := scm.Split(repo) - path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/pull-requests", namespace, name) + path := fmt.Sprintf("rest/api/1.0/projects/%s/repos/%s/pull-requests?%s", namespace, name, encodePullRequestListOptions(opts)) out := new(prs) res, err := s.client.do(ctx, "GET", path, nil, out) if !out.pagination.LastPage.Bool { diff --git a/scm/driver/stash/util.go b/scm/driver/stash/util.go index f034fb9ff..5f56e21ed 100644 --- a/scm/driver/stash/util.go +++ b/scm/driver/stash/util.go @@ -111,7 +111,7 @@ func encodePullRequestListOptions(opts scm.PullRequestListOptions) string { if opts.Open && opts.Closed { params.Set("state", "all") } else if opts.Closed { - params.Set("state", "closed") + params.Set("state", "declined") } return params.Encode() } From ced994103824a4dc345503963df111660d4016c2 Mon Sep 17 00:00:00 2001 From: Vitalie Safronovici Date: Fri, 21 Jun 2024 16:12:57 +0300 Subject: [PATCH 251/282] feat: [IAC-2101]: added ListTags for Harness Code --- scm/driver/harness/git.go | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/scm/driver/harness/git.go b/scm/driver/harness/git.go index adbd34c26..01105bd12 100644 --- a/scm/driver/harness/git.go +++ b/scm/driver/harness/git.go @@ -89,8 +89,25 @@ func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.Comm return convertCommitList(out), res, err } -func (s *gitService) ListTags(ctx context.Context, repo string, _ scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported +func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { + fmt.Printf("ListTags %+v\n", opts) + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + if err != nil { + return nil, nil, err + } + path := fmt.Sprintf("api/v1/repos/%s/tags?%s&%s", repoId, encodeListOptions(opts), queryParams) + + fmt.Printf("ListTags path=%s\n", path) + + out := []*branch{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + + fmt.Printf("ListTags res=%+v\n", res) + fmt.Printf("ListTags err=%+v\n", err) + fmt.Printf("ListTags out=%+v\n", out) + + return convertBranchList(out), res, err } func (s *gitService) ListChanges(ctx context.Context, repo, ref string, opts scm.ListOptions) ([]*scm.Change, *scm.Response, error) { From 57ce08315082493d73dc9987bbc2cc85eb18df4b Mon Sep 17 00:00:00 2001 From: Vitalie Safronovici Date: Fri, 21 Jun 2024 18:01:07 +0300 Subject: [PATCH 252/282] removed prints --- scm/driver/harness/git.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/scm/driver/harness/git.go b/scm/driver/harness/git.go index 01105bd12..867735105 100644 --- a/scm/driver/harness/git.go +++ b/scm/driver/harness/git.go @@ -90,23 +90,14 @@ func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.Comm } func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { - fmt.Printf("ListTags %+v\n", opts) harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) repoId, queryParams, err := getRepoAndQueryParams(harnessURI) if err != nil { return nil, nil, err } path := fmt.Sprintf("api/v1/repos/%s/tags?%s&%s", repoId, encodeListOptions(opts), queryParams) - - fmt.Printf("ListTags path=%s\n", path) - out := []*branch{} res, err := s.client.do(ctx, "GET", path, nil, &out) - - fmt.Printf("ListTags res=%+v\n", res) - fmt.Printf("ListTags err=%+v\n", err) - fmt.Printf("ListTags out=%+v\n", out) - return convertBranchList(out), res, err } From 7f588f46cf4ea12f77342eea0bb176917a3911c1 Mon Sep 17 00:00:00 2001 From: Karan Saraswat Date: Tue, 25 Jun 2024 15:52:41 +0530 Subject: [PATCH 253/282] fix unmarshalling array into Go value of type github.searchRepositoryList issue for ListNamespace --- scm/driver/github/repo.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scm/driver/github/repo.go b/scm/driver/github/repo.go index 857d0a4f7..b7b6e3362 100644 --- a/scm/driver/github/repo.go +++ b/scm/driver/github/repo.go @@ -122,12 +122,12 @@ func (s *RepositoryService) ListV2(ctx context.Context, opts scm.RepoListOptions return convertRepositoryList(out.Repositories), res, err } -// ListNamespace returns the user repository list based on searchterm and namespace. +// ListNamespace returns the orgs' repository list. func (s *RepositoryService) ListNamespace(ctx context.Context, namespace string, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) { path := fmt.Sprintf("orgs/%s/repos?%s", namespace, encodeListOptions(opts)) - out := new(searchRepositoryList) + out := []*repository{} res, err := s.client.do(ctx, "GET", path, nil, &out) - return convertRepositoryList(out.Repositories), res, err + return convertRepositoryList(out), res, err } // List returns the github app installation repository list. @@ -230,7 +230,7 @@ func (s *RepositoryService) DeleteHook(ctx context.Context, repo, id string) (*s return s.client.do(ctx, "DELETE", path, nil, nil) } -// helper function to convert from the gogs repository list to +// helper function to convert from the github repository list to // the common repository structure. func convertRepositoryList(from []*repository) []*scm.Repository { to := []*scm.Repository{} @@ -242,7 +242,7 @@ func convertRepositoryList(from []*repository) []*scm.Repository { return to } -// helper function to convert from the gogs repository structure +// helper function to convert from the github repository structure // to the common repository structure. func convertRepository(from *repository) *scm.Repository { if from == nil { From 8ad6b66cd119acd2ed479e1f410c751c25ddb141 Mon Sep 17 00:00:00 2001 From: Karan Saraswat Date: Fri, 5 Jul 2024 16:29:22 +0530 Subject: [PATCH 254/282] setting azure devops repo visibility based on the project's visibility --- scm/driver/azure/repo.go | 23 +++++++++++--------- scm/driver/github/repo.go | 15 +------------ scm/driver/github/webhook.go | 14 ++++++------ scm/driver/gitlab/repo.go | 30 ++++---------------------- scm/driver/gitlab/repo_test.go | 19 ----------------- scm/util.go | 22 +++++++++++++++++++ scm/util_test.go | 39 ++++++++++++++++++++++++++++++++++ 7 files changed, 86 insertions(+), 76 deletions(-) diff --git a/scm/driver/azure/repo.go b/scm/driver/azure/repo.go index 25be94b80..64eead88b 100644 --- a/scm/driver/azure/repo.go +++ b/scm/driver/azure/repo.go @@ -201,10 +201,11 @@ type repository struct { ID string `json:"id"` Name string `json:"name"` Project struct { - ID string `json:"id"` - Name string `json:"name"` - State string `json:"state"` - URL string `json:"url"` + ID string `json:"id"` + Name string `json:"name"` + State string `json:"state"` + URL string `json:"url"` + Visibility string `json:"visibility"` } `json:"project"` RemoteURL string `json:"remoteUrl"` URL string `json:"url"` @@ -283,12 +284,14 @@ func convertRepositoryList(from *repositories, owner string) []*scm.Repository { func convertRepository(from *repository, owner string) *scm.Repository { namespace := []string{owner, from.Project.Name} return &scm.Repository{ - ID: from.ID, - Name: from.Name, - Namespace: strings.Join(namespace, "/"), - Link: from.URL, - Branch: scm.TrimRef(from.DefaultBranch), - Clone: from.RemoteURL, + ID: from.ID, + Name: from.Name, + Namespace: strings.Join(namespace, "/"), + Link: from.URL, + Branch: scm.TrimRef(from.DefaultBranch), + Clone: from.RemoteURL, + Private: scm.ConvertPrivate(from.Project.Visibility), + Visibility: scm.ConvertVisibility(from.Project.Visibility), } } diff --git a/scm/driver/github/repo.go b/scm/driver/github/repo.go index b7b6e3362..cad7f917f 100644 --- a/scm/driver/github/repo.go +++ b/scm/driver/github/repo.go @@ -261,7 +261,7 @@ func convertRepository(from *repository) *scm.Repository { Branch: from.DefaultBranch, Archived: from.Archived, Private: from.Private, - Visibility: convertVisibility(from.Visibility), + Visibility: scm.ConvertVisibility(from.Visibility), Clone: from.CloneURL, CloneSSH: from.SSHURL, Created: from.CreatedAt, @@ -314,19 +314,6 @@ func convertFromHookEvents(from scm.HookEvents) []string { return events } -func convertVisibility(from string) scm.Visibility { - switch from { - case "public": - return scm.VisibilityPublic - case "private": - return scm.VisibilityPrivate - case "internal": - return scm.VisibilityInternal - default: - return scm.VisibilityUndefined - } -} - type status struct { CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` diff --git a/scm/driver/github/webhook.go b/scm/driver/github/webhook.go index 6c01a711d..2fbdae938 100644 --- a/scm/driver/github/webhook.go +++ b/scm/driver/github/webhook.go @@ -408,7 +408,7 @@ func convertPushHook(src *pushHook) *scm.PushHook { Name: src.Repository.Name, Branch: src.Repository.DefaultBranch, Private: src.Repository.Private, - Visibility: convertVisibility(src.Repository.Visibility), + Visibility: scm.ConvertVisibility(src.Repository.Visibility), Clone: src.Repository.CloneURL, CloneSSH: src.Repository.SSHURL, Link: src.Repository.HTMLURL, @@ -435,7 +435,7 @@ func convertBranchHook(src *createDeleteHook) *scm.BranchHook { Name: src.Repository.Name, Branch: src.Repository.DefaultBranch, Private: src.Repository.Private, - Visibility: convertVisibility(src.Repository.Visibility), + Visibility: scm.ConvertVisibility(src.Repository.Visibility), Clone: src.Repository.CloneURL, CloneSSH: src.Repository.SSHURL, Link: src.Repository.HTMLURL, @@ -455,7 +455,7 @@ func convertTagHook(src *createDeleteHook) *scm.TagHook { Name: src.Repository.Name, Branch: src.Repository.DefaultBranch, Private: src.Repository.Private, - Visibility: convertVisibility(src.Repository.Visibility), + Visibility: scm.ConvertVisibility(src.Repository.Visibility), Clone: src.Repository.CloneURL, CloneSSH: src.Repository.SSHURL, Link: src.Repository.HTMLURL, @@ -473,7 +473,7 @@ func convertPullRequestHook(src *pullRequestHook) *scm.PullRequestHook { Name: src.Repository.Name, Branch: src.Repository.DefaultBranch, Private: src.Repository.Private, - Visibility: convertVisibility(src.Repository.Visibility), + Visibility: scm.ConvertVisibility(src.Repository.Visibility), Clone: src.Repository.CloneURL, CloneSSH: src.Repository.SSHURL, Link: src.Repository.HTMLURL, @@ -499,7 +499,7 @@ func convertDeploymentHook(src *deploymentHook) *scm.DeployHook { Name: src.Repository.Name, Branch: src.Repository.DefaultBranch, Private: src.Repository.Private, - Visibility: convertVisibility(src.Repository.Visibility), + Visibility: scm.ConvertVisibility(src.Repository.Visibility), Clone: src.Repository.CloneURL, CloneSSH: src.Repository.SSHURL, Link: src.Repository.HTMLURL, @@ -533,7 +533,7 @@ func convertIssueCommentHook(src *issueCommentHook) *scm.IssueCommentHook { Name: src.Repository.Name, Branch: src.Repository.DefaultBranch, Private: src.Repository.Private, - Visibility: convertVisibility(src.Repository.Visibility), + Visibility: scm.ConvertVisibility(src.Repository.Visibility), Clone: src.Repository.CloneURL, CloneSSH: src.Repository.SSHURL, Link: src.Repository.HTMLURL, @@ -571,7 +571,7 @@ func convertReleaseHook(src *releaseHook) *scm.ReleaseHook { Name: src.Repository.Name, Branch: src.Repository.DefaultBranch, Private: src.Repository.Private, - Visibility: convertVisibility(src.Repository.Visibility), + Visibility: scm.ConvertVisibility(src.Repository.Visibility), Clone: src.Repository.CloneURL, CloneSSH: src.Repository.SSHURL, Link: src.Repository.HTMLURL, diff --git a/scm/driver/gitlab/repo.go b/scm/driver/gitlab/repo.go index d41776144..9a44bc3bc 100644 --- a/scm/driver/gitlab/repo.go +++ b/scm/driver/gitlab/repo.go @@ -178,7 +178,7 @@ func (s *repositoryService) DeleteHook(ctx context.Context, repo string, id stri return s.client.do(ctx, "DELETE", path, nil, nil) } -// helper function to convert from the gogs repository list to +// helper function to convert from the gitlab repository list to // the common repository structure. func convertRepositoryList(from []*repository) []*scm.Repository { to := []*scm.Repository{} @@ -188,7 +188,7 @@ func convertRepositoryList(from []*repository) []*scm.Repository { return to } -// helper function to convert from the gogs repository structure +// helper function to convert from the gitlab repository structure // to the common repository structure. func convertRepository(from *repository) *scm.Repository { to := &scm.Repository{ @@ -197,8 +197,8 @@ func convertRepository(from *repository) *scm.Repository { Name: from.Path, Branch: from.DefaultBranch, Archived: from.Archived, - Private: convertPrivate(from.Visibility), - Visibility: convertVisibility(from.Visibility), + Private: scm.ConvertPrivate(from.Visibility), + Visibility: scm.ConvertVisibility(from.Visibility), Clone: from.HTTPURL, CloneSSH: from.SSHURL, Link: from.WebURL, @@ -317,28 +317,6 @@ func convertFromState(from scm.State) string { } } -func convertPrivate(from string) bool { - switch from { - case "public", "": - return false - default: - return true - } -} - -func convertVisibility(from string) scm.Visibility { - switch from { - case "public": - return scm.VisibilityPublic - case "private": - return scm.VisibilityPrivate - case "internal": - return scm.VisibilityInternal - default: - return scm.VisibilityUndefined - } -} - func canPush(proj *repository) bool { switch { case proj.Permissions.ProjectAccess.AccessLevel >= 30: diff --git a/scm/driver/gitlab/repo_test.go b/scm/driver/gitlab/repo_test.go index 293e523ff..65c175176 100644 --- a/scm/driver/gitlab/repo_test.go +++ b/scm/driver/gitlab/repo_test.go @@ -521,25 +521,6 @@ func TestConvertFromState(t *testing.T) { } } -func TestConvertPrivate(t *testing.T) { - tests := []struct { - in string - out bool - }{ - {"public", false}, - {"", false}, - {"private", true}, - {"internal", true}, - {"invalid", true}, - } - - for _, test := range tests { - if got, want := convertPrivate(test.in), test.out; got != want { - t.Errorf("Want private %v, got %v", want, got) - } - } -} - func TestCanPush(t *testing.T) { tests := []struct { in *repository diff --git a/scm/util.go b/scm/util.go index 0a8c3a2ca..6aa496834 100644 --- a/scm/util.go +++ b/scm/util.go @@ -89,3 +89,25 @@ func IsPullRequest(ref string) bool { func IsHash(s string) bool { return sha1.MatchString(s) || sha256.MatchString(s) } + +func ConvertVisibility(from string) Visibility { + switch from { + case "public": + return VisibilityPublic + case "private": + return VisibilityPrivate + case "internal": + return VisibilityInternal + default: + return VisibilityUndefined + } +} + +func ConvertPrivate(from string) bool { + switch from { + case "public", "": + return false + default: + return true + } +} diff --git a/scm/util_test.go b/scm/util_test.go index 41332276d..c2b87ae74 100644 --- a/scm/util_test.go +++ b/scm/util_test.go @@ -239,3 +239,42 @@ func TestIsHash(t *testing.T) { } } } + +func TestConvertVisibility(t *testing.T) { + tests := []struct { + in string + out Visibility + }{ + {"public", 1}, + {"", 0}, + {"private", 3}, + {"internal", 2}, + {"invalid", 0}, + {"unknown", 0}, + } + + for _, test := range tests { + if got, want := ConvertVisibility(test.in), test.out; got != want { + t.Errorf("Want %d for %v type, got %d", want, test.in, got) + } + } +} + +func TestConvertPrivate(t *testing.T) { + tests := []struct { + in string + out bool + }{ + {"public", false}, + {"", false}, + {"private", true}, + {"internal", true}, + {"invalid", true}, + } + + for _, test := range tests { + if got, want := ConvertPrivate(test.in), test.out; got != want { + t.Errorf("Want private %v, got %v", want, got) + } + } +} From 92b5486bb60f9a142a90cb093702f5b5b31355b9 Mon Sep 17 00:00:00 2001 From: Karan Saraswat Date: Fri, 5 Jul 2024 17:00:34 +0530 Subject: [PATCH 255/282] fixed test --- scm/driver/azure/testdata/repos.json | 2 +- scm/driver/azure/testdata/repos.json.golden | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/scm/driver/azure/testdata/repos.json b/scm/driver/azure/testdata/repos.json index a05b6ce13..e5d7c6a23 100644 --- a/scm/driver/azure/testdata/repos.json +++ b/scm/driver/azure/testdata/repos.json @@ -30,7 +30,7 @@ "url": "https://dev.azure.com/tphoney/_apis/projects/d350c9c0-7749-4ff8-a78f-f9c1f0e56729", "state": "wellFormed", "revision": 11, - "visibility": "private", + "visibility": "public", "lastUpdateTime": "2022-02-24T15:31:27.89Z" }, "defaultBranch": "refs/heads/main", diff --git a/scm/driver/azure/testdata/repos.json.golden b/scm/driver/azure/testdata/repos.json.golden index d4c8b140a..137b73660 100644 --- a/scm/driver/azure/testdata/repos.json.golden +++ b/scm/driver/azure/testdata/repos.json.golden @@ -5,7 +5,9 @@ "Namespace": "ORG/test_project", "Branch": "main", "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/91f0d4cb-4c36-49a5-b28d-2d72da089c4d", - "Clone": "https://tphoney@dev.azure.com/tphoney/test_project/_git/test_project" + "Clone": "https://tphoney@dev.azure.com/tphoney/test_project/_git/test_project", + "Private": true, + "Visibility": 3 }, { "ID": "fde2d21f-13b9-4864-a995-83329045289a", @@ -13,6 +15,8 @@ "Namespace": "ORG/test_project", "Branch": "main", "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a", - "Clone": "https://tphoney@dev.azure.com/tphoney/test_project/_git/test_repo2" + "Clone": "https://tphoney@dev.azure.com/tphoney/test_project/_git/test_repo2", + "Private": false, + "Visibility": 1 } ] \ No newline at end of file From 8df99c4fc1e4305668135888d1f72b2abee83fbb Mon Sep 17 00:00:00 2001 From: Karan Saraswat Date: Fri, 5 Jul 2024 17:07:34 +0530 Subject: [PATCH 256/282] fixed TestRepositoryFind for azure driver --- scm/driver/azure/testdata/repo.json.golden | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scm/driver/azure/testdata/repo.json.golden b/scm/driver/azure/testdata/repo.json.golden index c642b51e2..c65a2d23d 100644 --- a/scm/driver/azure/testdata/repo.json.golden +++ b/scm/driver/azure/testdata/repo.json.golden @@ -4,5 +4,7 @@ "Namespace": "ORG/test_project", "Branch": "main", "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/91f0d4cb-4c36-49a5-b28d-2d72da089c4d", - "Clone": "https://tphoney@dev.azure.com/tphoney/test_project/_git/test_project" + "Clone": "https://tphoney@dev.azure.com/tphoney/test_project/_git/test_project", + "Private": true, + "Visibility": 3 } \ No newline at end of file From 0d2baa2c732bc3f18c7a72c6f095bd25211b6b75 Mon Sep 17 00:00:00 2001 From: Vitalie Safronovici Date: Tue, 16 Jul 2024 18:12:21 +0300 Subject: [PATCH 257/282] fix: [IAC-2201]: fixed looping endless pagination --- scm/driver/bitbucket/git.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/scm/driver/bitbucket/git.go b/scm/driver/bitbucket/git.go index 181c9fa3a..e56f85084 100644 --- a/scm/driver/bitbucket/git.go +++ b/scm/driver/bitbucket/git.go @@ -88,9 +88,12 @@ func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOpt out := new(branches) res, err := s.client.do(ctx, "GET", path, nil, &out) - if res != nil { - res.Page.Next = 0 - } + // if res != nil { + // res.Page.Next = 0 + // } + + fmt.Printf("xxxxx res=%+v", res) + fmt.Printf("xxxxx out=%+v", out) copyPagination(out.pagination, res) return convertTagList(out), res, err From 8aca10b1b3a386a99d79fbbfbd6c7ba782aae243 Mon Sep 17 00:00:00 2001 From: Vitalie Safronovici Date: Tue, 16 Jul 2024 19:37:28 +0300 Subject: [PATCH 258/282] adjust --- scm/driver/bitbucket/git.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/scm/driver/bitbucket/git.go b/scm/driver/bitbucket/git.go index e56f85084..6c703a7b5 100644 --- a/scm/driver/bitbucket/git.go +++ b/scm/driver/bitbucket/git.go @@ -88,14 +88,15 @@ func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOpt out := new(branches) res, err := s.client.do(ctx, "GET", path, nil, &out) - // if res != nil { - // res.Page.Next = 0 - // } + copyPagination(out.pagination, res) + + if res != nil { + res.Page.Next = 0 + } - fmt.Printf("xxxxx res=%+v", res) - fmt.Printf("xxxxx out=%+v", out) + fmt.Printf("xxxxx res=%+v\n", res) + fmt.Printf("xxxxx out=%+v\n", out) - copyPagination(out.pagination, res) return convertTagList(out), res, err } From f3725efa115cc9ee7b7875790ed115daf20805ab Mon Sep 17 00:00:00 2001 From: Vitalie Safronovici Date: Tue, 16 Jul 2024 20:10:22 +0300 Subject: [PATCH 259/282] removed logs --- scm/driver/bitbucket/git.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/scm/driver/bitbucket/git.go b/scm/driver/bitbucket/git.go index 6c703a7b5..e0ecc5542 100644 --- a/scm/driver/bitbucket/git.go +++ b/scm/driver/bitbucket/git.go @@ -94,9 +94,6 @@ func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOpt res.Page.Next = 0 } - fmt.Printf("xxxxx res=%+v\n", res) - fmt.Printf("xxxxx out=%+v\n", out) - return convertTagList(out), res, err } From be67dd5203b89c912dc3dd50dc3e247480418c41 Mon Sep 17 00:00:00 2001 From: Vitalie Safronovici Date: Tue, 16 Jul 2024 20:18:53 +0300 Subject: [PATCH 260/282] fixed UT --- scm/driver/bitbucket/git_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scm/driver/bitbucket/git_test.go b/scm/driver/bitbucket/git_test.go index c04c26d51..e93499808 100644 --- a/scm/driver/bitbucket/git_test.go +++ b/scm/driver/bitbucket/git_test.go @@ -250,7 +250,7 @@ func TestGitListTags(t *testing.T) { File("testdata/tags.json") client, _ := New("https://api.bitbucket.org") - got, res, err := client.Git.ListTags(context.Background(), "atlassian/atlaskit", scm.ListOptions{Page: 1, Size: 30}) + got, _, err := client.Git.ListTags(context.Background(), "atlassian/atlaskit", scm.ListOptions{Page: 1, Size: 30}) if err != nil { t.Error(err) } @@ -264,7 +264,6 @@ func TestGitListTags(t *testing.T) { t.Log(diff) } - t.Run("Page", testPage(res)) } func TestGitListChanges(t *testing.T) { From f23ffd9afa92961b6c8f49597d6203682d5464a4 Mon Sep 17 00:00:00 2001 From: Johannes Batzill Date: Thu, 25 Jul 2024 16:39:33 -0700 Subject: [PATCH 261/282] add support for harness error message --- scm/driver/harness/harness.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/scm/driver/harness/harness.go b/scm/driver/harness/harness.go index 1feb6a463..cf71dd7f5 100644 --- a/scm/driver/harness/harness.go +++ b/scm/driver/harness/harness.go @@ -8,9 +8,7 @@ import ( "bytes" "context" "encoding/json" - "errors" "io" - "net/http" "net/url" "strings" @@ -82,9 +80,9 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface // if an error is encountered, unmarshal and return the // error response. if res.Status > 300 { - return res, errors.New( - http.StatusText(res.Status), - ) + err := new(Error) + json.NewDecoder(res.Body).Decode(err) + return res, err } if out == nil { @@ -102,3 +100,12 @@ func (c *wrapper) do(ctx context.Context, method, path string, in, out interface // the json response. return res, json.NewDecoder(res.Body).Decode(out) } + +// Error represents a Harness CODE error. +type Error struct { + Message string `json:"message"` +} + +func (e *Error) Error() string { + return e.Message +} From 845b0c5cf9d707ed8b175e0c607aa07fe7e329d7 Mon Sep 17 00:00:00 2001 From: Karan Saraswat Date: Fri, 2 Aug 2024 13:21:29 +0530 Subject: [PATCH 262/282] Add draft boolean for github and gitlab PRs --- scm/driver/github/pr.go | 2 ++ scm/driver/github/testdata/pr.json | 1 + scm/driver/github/testdata/pr.json.golden | 1 + scm/driver/github/testdata/pulls.json | 1 + scm/driver/github/testdata/pulls.json.golden | 1 + scm/driver/gitlab/pr.go | 16 +++++++++------- scm/driver/gitlab/testdata/merge.json.golden | 1 + scm/driver/gitlab/testdata/merges.json.golden | 1 + scm/driver/gitlab/webhook.go | 2 ++ scm/pr.go | 1 + 10 files changed, 20 insertions(+), 7 deletions(-) diff --git a/scm/driver/github/pr.go b/scm/driver/github/pr.go index 74da3bbf2..52e980937 100644 --- a/scm/driver/github/pr.go +++ b/scm/driver/github/pr.go @@ -76,6 +76,7 @@ type pr struct { State string `json:"state"` Title string `json:"title"` Body string `json:"body"` + Draft bool `json:"draft"` DiffURL string `json:"diff_url"` HTMLURL string `json:"html_url"` User struct { @@ -154,6 +155,7 @@ func convertPullRequest(from *pr) *scm.PullRequest { Fork: from.Head.Repo.FullName, Link: from.HTMLURL, Diff: from.DiffURL, + Draft: from.Draft, Closed: from.State != "open", Merged: from.MergedAt.String != "", Head: scm.Reference{ diff --git a/scm/driver/github/testdata/pr.json b/scm/driver/github/testdata/pr.json index edcc02d7c..3315fafbc 100644 --- a/scm/driver/github/testdata/pr.json +++ b/scm/driver/github/testdata/pr.json @@ -11,6 +11,7 @@ "comments_url": "https://api.github.com/repos/octocat/Hello-World/issues/1347/comments", "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/6dcb09b5b57875f334f61aebed695e2e4193db5e", "number": 1347, + "draft": false, "state": "open", "title": "new-feature", "body": "Please pull these awesome changes", diff --git a/scm/driver/github/testdata/pr.json.golden b/scm/driver/github/testdata/pr.json.golden index 2ea51c709..5bf11ba0c 100644 --- a/scm/driver/github/testdata/pr.json.golden +++ b/scm/driver/github/testdata/pr.json.golden @@ -9,6 +9,7 @@ "Fork": "octocat/Hello-World", "Link": "https://github.com/octocat/Hello-World/pull/1347", "Diff": "https://github.com/octocat/Hello-World/pull/1347.diff", + "Draft": false, "Closed": false, "Merged": true, "Base": { diff --git a/scm/driver/github/testdata/pulls.json b/scm/driver/github/testdata/pulls.json index 611d7d71d..e1f85a075 100644 --- a/scm/driver/github/testdata/pulls.json +++ b/scm/driver/github/testdata/pulls.json @@ -12,6 +12,7 @@ "comments_url": "https://api.github.com/repos/octocat/Hello-World/issues/1347/comments", "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/6dcb09b5b57875f334f61aebed695e2e4193db5e", "number": 1347, + "draft": false, "state": "open", "title": "new-feature", "body": "Please pull these awesome changes", diff --git a/scm/driver/github/testdata/pulls.json.golden b/scm/driver/github/testdata/pulls.json.golden index 1a6798b98..f2a97473d 100644 --- a/scm/driver/github/testdata/pulls.json.golden +++ b/scm/driver/github/testdata/pulls.json.golden @@ -10,6 +10,7 @@ "Fork": "octocat/Hello-World", "Link": "https://github.com/octocat/Hello-World/pull/1347", "Diff": "https://github.com/octocat/Hello-World/pull/1347.diff", + "Draft": false, "Closed": false, "Merged": true, "Base": { diff --git a/scm/driver/gitlab/pr.go b/scm/driver/gitlab/pr.go index 52548146f..b8f67719a 100644 --- a/scm/driver/gitlab/pr.go +++ b/scm/driver/gitlab/pr.go @@ -99,13 +99,14 @@ func (s *pullService) Close(ctx context.Context, repo string, number int) (*scm. } type pr struct { - Number int `json:"iid"` - Sha string `json:"sha"` - Title string `json:"title"` - Desc string `json:"description"` - State string `json:"state"` - Link string `json:"web_url"` - Author struct { + Number int `json:"iid"` + Sha string `json:"sha"` + Title string `json:"title"` + Desc string `json:"description"` + State string `json:"state"` + WorkInProgress bool `json:"work_in_progress"` + Link string `json:"web_url"` + Author struct { Username string `json:"username"` Email string `json:"email"` Name string `json:"name"` @@ -160,6 +161,7 @@ func convertPullRequest(from *pr) *scm.PullRequest { Source: from.SourceBranch, Target: from.TargetBranch, Link: from.Link, + Draft: from.WorkInProgress, Closed: from.State != "opened", Merged: from.State == "merged", Author: scm.User{ diff --git a/scm/driver/gitlab/testdata/merge.json.golden b/scm/driver/gitlab/testdata/merge.json.golden index 4df0d2492..5864162c3 100644 --- a/scm/driver/gitlab/testdata/merge.json.golden +++ b/scm/driver/gitlab/testdata/merge.json.golden @@ -7,6 +7,7 @@ "Source": "fix", "Target": "master", "Link": "https://gitlab.com/gitlab-org/testme/merge_requests/1", + "Draft": false, "Closed": true, "Merged": false, "Author": { diff --git a/scm/driver/gitlab/testdata/merges.json.golden b/scm/driver/gitlab/testdata/merges.json.golden index 46cb6d7c4..cf605b9ee 100644 --- a/scm/driver/gitlab/testdata/merges.json.golden +++ b/scm/driver/gitlab/testdata/merges.json.golden @@ -8,6 +8,7 @@ "Source": "fix", "Target": "master", "Link": "https://gitlab.com/gitlab-org/testme/merge_requests/1", + "Draft": false, "Closed": true, "Merged": false, "Author": { diff --git a/scm/driver/gitlab/webhook.go b/scm/driver/gitlab/webhook.go index 2cc785fb7..30992e61a 100644 --- a/scm/driver/gitlab/webhook.go +++ b/scm/driver/gitlab/webhook.go @@ -238,6 +238,7 @@ func convertCommentHook(src *commentHook) (*scm.IssueCommentHook, error) { Source: src.MergeRequest.SourceBranch, Target: src.MergeRequest.TargetBranch, Link: src.MergeRequest.URL, + Draft: src.MergeRequest.WorkInProgress, Closed: src.MergeRequest.State != "opened", Merged: src.MergeRequest.State == "merged", Author: *convertUser(&src.User), @@ -359,6 +360,7 @@ func convertPullRequestHook(src *pullRequestHook) *scm.PullRequestHook { Target: src.ObjectAttributes.TargetBranch, Fork: fork, Link: src.ObjectAttributes.URL, + Draft: src.ObjectAttributes.WorkInProgress, Closed: src.ObjectAttributes.State != "opened", Merged: src.ObjectAttributes.State == "merged", // Created : src.ObjectAttributes.CreatedAt, diff --git a/scm/pr.go b/scm/pr.go index 1fd2e5a5b..1e9a74945 100644 --- a/scm/pr.go +++ b/scm/pr.go @@ -22,6 +22,7 @@ type ( Fork string Link string Diff string + Draft bool Closed bool Merged bool Merge string From 0969f30763cb2a2d6f29091be0fa751a4d36f56c Mon Sep 17 00:00:00 2001 From: Karan Saraswat Date: Fri, 2 Aug 2024 13:45:27 +0530 Subject: [PATCH 263/282] added for azure devops too --- scm/driver/azure/pr.go | 2 ++ scm/driver/azure/testdata/pr.json | 1 + scm/driver/azure/testdata/pr.json.golden | 1 + .../testdata/webhooks/pull_request_review_ready.json.golden | 1 + 4 files changed, 5 insertions(+) diff --git a/scm/driver/azure/pr.go b/scm/driver/azure/pr.go index a5bb93479..d2e36c48f 100644 --- a/scm/driver/azure/pr.go +++ b/scm/driver/azure/pr.go @@ -107,6 +107,7 @@ type pr struct { SourceRefName string `json:"sourceRefName"` TargetRefName string `json:"targetRefName"` MergeStatus string `json:"mergeStatus"` + IsDraft bool `json:"isDraft"` MergeID string `json:"mergeId"` LastMergeSourceCommit struct { CommitID string `json:"commitId"` @@ -168,6 +169,7 @@ func convertPullRequest(from *pr) *scm.PullRequest { Source: scm.TrimRef(from.SourceRefName), Target: scm.TrimRef(from.TargetRefName), Link: from.URL, + Draft: from.IsDraft, Closed: from.ClosedDate.Valid, Merged: from.Status == "completed", Ref: fmt.Sprintf("refs/pull/%d/merge", from.PullRequestID), diff --git a/scm/driver/azure/testdata/pr.json b/scm/driver/azure/testdata/pr.json index e419af010..01c08b31e 100644 --- a/scm/driver/azure/testdata/pr.json +++ b/scm/driver/azure/testdata/pr.json @@ -30,6 +30,7 @@ "sourceRefName": "refs/heads/pr_branch", "targetRefName": "refs/heads/main", "mergeStatus": "queued", + "isDraft": false, "mergeId": "36c88bf7-3d14-437f-82aa-e38cce733261", "lastMergeSourceCommit": { "commitId": "01768d964c03e97260af0bd8cd9e5cd1f9ac6356", diff --git a/scm/driver/azure/testdata/pr.json.golden b/scm/driver/azure/testdata/pr.json.golden index 5e59c583b..23330a15e 100644 --- a/scm/driver/azure/testdata/pr.json.golden +++ b/scm/driver/azure/testdata/pr.json.golden @@ -10,6 +10,7 @@ "Fork": "", "Link": "https://dev.azure.com/tphoney/d350c9c0-7749-4ff8-a78f-f9c1f0e56729/_apis/git/repositories/fde2d21f-13b9-4864-a995-83329045289a/pullRequests/19", "Diff": "", + "Draft": false, "Closed": true, "Merged": true, "Base": { diff --git a/scm/driver/gitlab/testdata/webhooks/pull_request_review_ready.json.golden b/scm/driver/gitlab/testdata/webhooks/pull_request_review_ready.json.golden index c75213032..059b6bbd7 100644 --- a/scm/driver/gitlab/testdata/webhooks/pull_request_review_ready.json.golden +++ b/scm/driver/gitlab/testdata/webhooks/pull_request_review_ready.json.golden @@ -23,6 +23,7 @@ "Target": "main", "Fork": "Meet Rathod/meet", "Link": "https://gitlab.com/rathod.meetsatish/meet/-/merge_requests/3", + "Draft": true, "Closed": false, "Merged": false, "Author": { From 122a705e99c5b8690e0e0feb2dc2b19e9f10d520 Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Tue, 6 Aug 2024 13:45:37 +0530 Subject: [PATCH 264/282] Update azure.go --- scm/driver/azure/azure.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/scm/driver/azure/azure.go b/scm/driver/azure/azure.go index 1832e568d..e762a6db1 100644 --- a/scm/driver/azure/azure.go +++ b/scm/driver/azure/azure.go @@ -122,8 +122,5 @@ func ProjectRequiredError() error { } func SanitizeBranchName(name string) string { - if strings.Contains(name, "/") { - return name - } return "refs/heads/" + name } From 01168531237149dd2137bd0379618f02359a7a69 Mon Sep 17 00:00:00 2001 From: Vivek Dixit Date: Wed, 7 Aug 2024 11:25:19 +0530 Subject: [PATCH 265/282] Update azure_test.go --- scm/driver/azure/azure_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scm/driver/azure/azure_test.go b/scm/driver/azure/azure_test.go index 0a4334374..c3cc56732 100644 --- a/scm/driver/azure/azure_test.go +++ b/scm/driver/azure/azure_test.go @@ -54,11 +54,11 @@ func TestSanitizeBranchName(t *testing.T) { "refs/heads/master", }, { - "refs/heads/master", + "feature/main-patch", args{ - "refs/heads/master", + "feature/main-patch", }, - "refs/heads/master", + "refs/heads/feature/main-patch", }, } for _, tt := range tests { From 1eb6efe027dab3d6a47577fdf3bbf93ec392f5da Mon Sep 17 00:00:00 2001 From: Soumyajit Das Date: Thu, 22 Aug 2024 19:56:19 +0530 Subject: [PATCH 266/282] feat: [CI-13826]: add check for bitbucket tag slash --- scm/driver/bitbucket/git.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/scm/driver/bitbucket/git.go b/scm/driver/bitbucket/git.go index e0ecc5542..df16afbcb 100644 --- a/scm/driver/bitbucket/git.go +++ b/scm/driver/bitbucket/git.go @@ -7,6 +7,7 @@ package bitbucket import ( "context" "fmt" + "strings" "time" "github.com/drone/go-scm/scm" @@ -44,7 +45,12 @@ func (s *gitService) FindCommit(ctx context.Context, repo, ref string) (*scm.Com ref = branch.Sha // replace ref with sha } } - path := fmt.Sprintf("2.0/repositories/%s/commit/%s", repo, ref) + var path string + if strings.Contains(ref, "/") { + path = fmt.Sprintf("2.0/repositories/%s/?at=%s", repo, ref) + } else { + path = fmt.Sprintf("2.0/repositories/%s/commit/%s", repo, ref) + } out := new(commit) res, err := s.client.do(ctx, "GET", path, nil, out) return convertCommit(out), res, err From 48eec0e3183d7504438633758dcd06383c0b9670 Mon Sep 17 00:00:00 2001 From: Soumyajit Das Date: Tue, 27 Aug 2024 13:43:33 +0530 Subject: [PATCH 267/282] feat: [CI-13826]: add UTs --- scm/driver/bitbucket/git_test.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/scm/driver/bitbucket/git_test.go b/scm/driver/bitbucket/git_test.go index e93499808..912434bf1 100644 --- a/scm/driver/bitbucket/git_test.go +++ b/scm/driver/bitbucket/git_test.go @@ -41,6 +41,32 @@ func TestGitFindCommit(t *testing.T) { } } +func TestGitFindCommitForTagSlash(t *testing.T) { + defer gock.Off() + + gock.New("https://api.bitbucket.org"). + Get("/2.0/repositories/atlassian/stash-example-plugin"). + MatchParam("at", "ab/cd"). + Reply(200). + Type("application/json"). + File("testdata/commit.json") + + client, _ := New("https://api.bitbucket.org") + got, _, err := client.Git.FindCommit(context.Background(), "atlassian/stash-example-plugin", "ab/cd") + if err != nil { + t.Error(err) + } + + want := new(scm.Commit) + raw, _ := ioutil.ReadFile("testdata/commit.json.golden") + json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} + func TestGitFindCommitForBranch(t *testing.T) { defer gock.Off() From 756f053bb754ff65900b73eef08c599e25e9de38 Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Fri, 30 Aug 2024 02:09:11 +0530 Subject: [PATCH 268/282] feat: bypass branch rules as default for file ops (#321) --- scm/driver/harness/content.go | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/scm/driver/harness/content.go b/scm/driver/harness/content.go index 91e72ecee..40dd24d6c 100644 --- a/scm/driver/harness/content.go +++ b/scm/driver/harness/content.go @@ -50,10 +50,11 @@ func (s *contentService) Create(ctx context.Context, repo, path string, params * Encoding: "string", } in := editFile{ - Branch: params.Branch, - Message: params.Message, - Title: params.Message, - Actions: []action{a}, + Branch: params.Branch, + Message: params.Message, + Title: params.Message, + Actions: []action{a}, + BypassRules: true, } res, err := s.client.do(ctx, "POST", endpoint, in, nil) @@ -75,10 +76,11 @@ func (s *contentService) Update(ctx context.Context, repo, path string, params * Sha: params.BlobID, } in := editFile{ - Branch: params.Branch, - Message: params.Message, - Title: params.Message, - Actions: []action{a}, + Branch: params.Branch, + Message: params.Message, + Title: params.Message, + Actions: []action{a}, + BypassRules: true, } res, err := s.client.do(ctx, "POST", endpoint, in, nil) @@ -98,10 +100,11 @@ func (s *contentService) Delete(ctx context.Context, repo, path string, params * Encoding: "string", } in := editFile{ - Branch: params.Branch, - Message: params.Message, - Title: params.Message, - Actions: []action{a}, + Branch: params.Branch, + Message: params.Message, + Title: params.Message, + Actions: []action{a}, + BypassRules: true, } res, err := s.client.do(ctx, "POST", endpoint, in, nil) @@ -126,6 +129,8 @@ type editFile struct { Message string `json:"message"` NewBranch string `json:"new_branch"` Title string `json:"title"` + + BypassRules bool `json:"bypass_rules"` } type action struct { From 607a21578fafa069083ce96043e2b67516b4265e Mon Sep 17 00:00:00 2001 From: Abhinav Singh Date: Wed, 18 Sep 2024 13:46:08 -0700 Subject: [PATCH 269/282] feat: bypass branch rules as default for create branch ops (#323) * feat: bypass branch rules as default for file ops * feat: bypass branch rules as default for create branch * feat: bypass branch rules as default for create branch --- scm/driver/harness/git.go | 42 ++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/scm/driver/harness/git.go b/scm/driver/harness/git.go index 867735105..f261f7756 100644 --- a/scm/driver/harness/git.go +++ b/scm/driver/harness/git.go @@ -19,25 +19,26 @@ type gitService struct { func (s *gitService) CreateBranch(ctx context.Context, repo string, params *scm.ReferenceInput) (*scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + repoID, queryParams, err := getRepoAndQueryParams(harnessURI) if err != nil { return nil, err } - path := fmt.Sprintf("api/v1/repos/%s/branches?%s", repoId, queryParams) + path := fmt.Sprintf("api/v1/repos/%s/branches?%s", repoID, queryParams) in := &branchInput{ - Name: params.Name, - Target: params.Sha, + Name: params.Name, + Target: params.Sha, + BypassRules: true, } return s.client.do(ctx, "POST", path, in, nil) } func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Reference, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + repoID, queryParams, err := getRepoAndQueryParams(harnessURI) if err != nil { return nil, nil, err } - path := fmt.Sprintf("api/v1/repos/%s/branches/%s?%s", repoId, name, queryParams) + path := fmt.Sprintf("api/v1/repos/%s/branches/%s?%s", repoID, name, queryParams) out := new(branch) res, err := s.client.do(ctx, "GET", path, nil, out) return convertBranch(out), res, err @@ -45,11 +46,11 @@ func (s *gitService) FindBranch(ctx context.Context, repo, name string) (*scm.Re func (s *gitService) FindCommit(ctx context.Context, repo, ref string) (*scm.Commit, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + repoID, queryParams, err := getRepoAndQueryParams(harnessURI) if err != nil { return nil, nil, err } - path := fmt.Sprintf("api/v1/repos/%s/commits/%s?%s", repoId, ref, queryParams) + path := fmt.Sprintf("api/v1/repos/%s/commits/%s?%s", repoID, ref, queryParams) out := new(commitInfo) res, err := s.client.do(ctx, "GET", path, nil, out) return convertCommitInfo(out), res, err @@ -61,11 +62,11 @@ func (s *gitService) FindTag(ctx context.Context, repo, name string) (*scm.Refer func (s *gitService) ListBranches(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + repoID, queryParams, err := getRepoAndQueryParams(harnessURI) if err != nil { return nil, nil, err } - path := fmt.Sprintf("api/v1/repos/%s/branches?%s&%s", repoId, encodeListOptions(opts), queryParams) + path := fmt.Sprintf("api/v1/repos/%s/branches?%s&%s", repoID, encodeListOptions(opts), queryParams) out := []*branch{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertBranchList(out), res, err @@ -79,11 +80,11 @@ func (s *gitService) ListBranchesV2(ctx context.Context, repo string, opts scm.B func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.CommitListOptions) ([]*scm.Commit, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + repoID, queryParams, err := getRepoAndQueryParams(harnessURI) if err != nil { return nil, nil, err } - path := fmt.Sprintf("api/v1/repos/%s/commits?%s&%s", repoId, encodeCommitListOptions(opts), queryParams) + path := fmt.Sprintf("api/v1/repos/%s/commits?%s&%s", repoID, encodeCommitListOptions(opts), queryParams) out := new(commits) res, err := s.client.do(ctx, "GET", path, nil, &out) return convertCommitList(out), res, err @@ -91,11 +92,11 @@ func (s *gitService) ListCommits(ctx context.Context, repo string, opts scm.Comm func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Reference, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + repoID, queryParams, err := getRepoAndQueryParams(harnessURI) if err != nil { return nil, nil, err } - path := fmt.Sprintf("api/v1/repos/%s/tags?%s&%s", repoId, encodeListOptions(opts), queryParams) + path := fmt.Sprintf("api/v1/repos/%s/tags?%s&%s", repoID, encodeListOptions(opts), queryParams) out := []*branch{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertBranchList(out), res, err @@ -103,11 +104,11 @@ func (s *gitService) ListTags(ctx context.Context, repo string, opts scm.ListOpt func (s *gitService) ListChanges(ctx context.Context, repo, ref string, opts scm.ListOptions) ([]*scm.Change, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + repoID, queryParams, err := getRepoAndQueryParams(harnessURI) if err != nil { return nil, nil, err } - path := fmt.Sprintf("api/v1/repos/%s/commits/%s/diff?%s&%s", repoId, ref, encodeListOptions(opts), queryParams) + path := fmt.Sprintf("api/v1/repos/%s/commits/%s/diff?%s&%s", repoID, ref, encodeListOptions(opts), queryParams) out := []*fileDiff{} res, err := s.client.do(ctx, "POST", path, nil, &out) return convertFileDiffs(out), res, err @@ -115,11 +116,11 @@ func (s *gitService) ListChanges(ctx context.Context, repo, ref string, opts scm func (s *gitService) CompareChanges(ctx context.Context, repo, source, target string, _ scm.ListOptions) ([]*scm.Change, *scm.Response, error) { harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) - repoId, queryParams, err := getRepoAndQueryParams(harnessURI) + repoID, queryParams, err := getRepoAndQueryParams(harnessURI) if err != nil { return nil, nil, err } - path := fmt.Sprintf("api/v1/repos/%s/diff/%s...%s?%s", repoId, source, target, queryParams) + path := fmt.Sprintf("api/v1/repos/%s/diff/%s...%s?%s", repoID, source, target, queryParams) out := []*fileDiff{} res, err := s.client.do(ctx, "GET", path, nil, &out) return convertChangeList(out), res, err @@ -151,8 +152,9 @@ type ( Title string `json:"title"` } branchInput struct { - Name string `json:"name"` - Target string `json:"target"` + Name string `json:"name"` + Target string `json:"target"` + BypassRules bool `json:"bypass_rules"` } branch struct { Commit struct { From 63abea20a1babd8a7a686feb79e651e7b859888a Mon Sep 17 00:00:00 2001 From: Deepak Puthraya Date: Mon, 7 Oct 2024 11:29:49 +0530 Subject: [PATCH 270/282] feat:[CDS-101592]: Add support for parsing Gitlab System Hooks (#324) --- scm/driver/gitlab/webhook.go | 27 +++++++++++++ scm/driver/gitlab/webhook_test.go | 67 +++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/scm/driver/gitlab/webhook.go b/scm/driver/gitlab/webhook.go index 30992e61a..c70569471 100644 --- a/scm/driver/gitlab/webhook.go +++ b/scm/driver/gitlab/webhook.go @@ -39,6 +39,8 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo hook, err = parsePullRequestHook(data) case "Note Hook": hook, err = parseIssueCommentHook(data) + case "System Hook": + hook, err = parseSystemHook(data) default: return nil, scm.ErrUnknownEvent } @@ -63,6 +65,26 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo return hook, nil } +func parseSystemHook(data []byte) (scm.Webhook, error) { + src := new(event) + err := json.Unmarshal(data, src) + if err != nil { + return nil, err + } + switch src.ObjectKind { + case "push", "tag_push": + return parsePushHook(data) + case "issue": + return nil, scm.ErrUnknownEvent + case "merge_request": + return parsePullRequestHook(data) + case "note": + return parseIssueCommentHook(data) + default: + return nil, scm.ErrUnknownEvent + } +} + func parseIssueCommentHook(data []byte) (scm.Webhook, error) { src := new(commentHook) err := json.Unmarshal(data, src) @@ -399,6 +421,11 @@ func parseTimeString(timeString string) time.Time { } type ( + // Generic struct to detect event type + event struct { + ObjectKind string `json:"object_kind"` + } + pushHook struct { ObjectKind string `json:"object_kind"` EventName string `json:"event_name"` diff --git a/scm/driver/gitlab/webhook_test.go b/scm/driver/gitlab/webhook_test.go index e766cada4..16041c67d 100644 --- a/scm/driver/gitlab/webhook_test.go +++ b/scm/driver/gitlab/webhook_test.go @@ -38,6 +38,18 @@ func TestWebhooks(t *testing.T) { after: "testdata/webhooks/branch_delete.json.golden", obj: new(scm.BranchHook), }, + { + event: "System Hook", + before: "testdata/webhooks/branch_create.json", + after: "testdata/webhooks/branch_create.json.golden", + obj: new(scm.PushHook), + }, + { + event: "System Hook", + before: "testdata/webhooks/branch_delete.json", + after: "testdata/webhooks/branch_delete.json.golden", + obj: new(scm.BranchHook), + }, // tag hooks { event: "Tag Push Hook", @@ -51,6 +63,18 @@ func TestWebhooks(t *testing.T) { after: "testdata/webhooks/tag_delete.json.golden", obj: new(scm.TagHook), }, + { + event: "System Hook", + before: "testdata/webhooks/tag_create.json", + after: "testdata/webhooks/tag_create.json.golden", + obj: new(scm.PushHook), + }, + { + event: "System Hook", + before: "testdata/webhooks/tag_delete.json", + after: "testdata/webhooks/tag_delete.json.golden", + obj: new(scm.TagHook), + }, // push hooks { event: "Push Hook", @@ -58,6 +82,12 @@ func TestWebhooks(t *testing.T) { after: "testdata/webhooks/push.json.golden", obj: new(scm.PushHook), }, + { + event: "System Hook", + before: "testdata/webhooks/push.json", + after: "testdata/webhooks/push.json.golden", + obj: new(scm.PushHook), + }, // // issue hooks // { // event: "issues", @@ -79,6 +109,13 @@ func TestWebhooks(t *testing.T) { after: "testdata/webhooks/pull_request_create.json.golden", obj: new(scm.PullRequestHook), }, + { + event: "System Hook", + before: "testdata/webhooks/pull_request_create.json", + after: "testdata/webhooks/pull_request_create.json.golden", + obj: new(scm.PullRequestHook), + }, + // { // event: "Merge Request Hook", // before: "testdata/webhooks/pull_request_edited.json", @@ -115,6 +152,30 @@ func TestWebhooks(t *testing.T) { after: "testdata/webhooks/pull_request_merge.json.golden", obj: new(scm.PullRequestHook), }, + { + event: "System Hook", + before: "testdata/webhooks/pull_request_close.json", + after: "testdata/webhooks/pull_request_close.json.golden", + obj: new(scm.PullRequestHook), + }, + { + event: "System Hook", + before: "testdata/webhooks/pull_request_review_ready.json", + after: "testdata/webhooks/pull_request_review_ready.json.golden", + obj: new(scm.PullRequestHook), + }, + { + event: "System Hook", + before: "testdata/webhooks/pull_request_reopen.json", + after: "testdata/webhooks/pull_request_reopen.json.golden", + obj: new(scm.PullRequestHook), + }, + { + event: "System Hook", + before: "testdata/webhooks/pull_request_merge.json", + after: "testdata/webhooks/pull_request_merge.json.golden", + obj: new(scm.PullRequestHook), + }, // Note hook for Gitlab Merge Request comment { event: "Note Hook", @@ -122,6 +183,12 @@ func TestWebhooks(t *testing.T) { after: "testdata/webhooks/merge_request_comment_create.json.golden", obj: new(scm.IssueCommentHook), }, + { + event: "System Hook", + before: "testdata/webhooks/merge_request_comment_create.json", + after: "testdata/webhooks/merge_request_comment_create.json.golden", + obj: new(scm.IssueCommentHook), + }, } for _, test := range tests { From f42f711bde13c46156985153941f880386a598c8 Mon Sep 17 00:00:00 2001 From: atefehmohseni <57154674+atefehmohseni@users.noreply.github.com> Date: Mon, 18 Nov 2024 21:28:54 -0800 Subject: [PATCH 271/282] Update pr.go --- scm/driver/bitbucket/pr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/driver/bitbucket/pr.go b/scm/driver/bitbucket/pr.go index ead47a821..38610bf5e 100644 --- a/scm/driver/bitbucket/pr.go +++ b/scm/driver/bitbucket/pr.go @@ -193,7 +193,7 @@ func convertPullRequest(from *pr) *scm.PullRequest { Sha: from.Destination.Commit.Hash, }, Author: scm.User{ - Login: from.Author.Nickname, + Login: from.Author.UUID, Name: from.Author.DisplayName, Avatar: from.Author.Links.Avatar.Href, }, From ad49c0a6b9215301ac063978682a9e32752a724a Mon Sep 17 00:00:00 2001 From: atefehmohseni <57154674+atefehmohseni@users.noreply.github.com> Date: Mon, 18 Nov 2024 21:47:51 -0800 Subject: [PATCH 272/282] Update prs.json.golden --- scm/driver/bitbucket/testdata/prs.json.golden | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/driver/bitbucket/testdata/prs.json.golden b/scm/driver/bitbucket/testdata/prs.json.golden index 29cafe903..99a5905f3 100644 --- a/scm/driver/bitbucket/testdata/prs.json.golden +++ b/scm/driver/bitbucket/testdata/prs.json.golden @@ -23,7 +23,7 @@ "Name": "Lachlan-Vass/ios-date-picker-component-duplicate-marc-1579222909688" }, "Author": { - "Login": "Lachlan", + "Login": "ef9d9075-f870-417f-b424-83adbc8efa54", "Name": "Lachlan Vass", "Avatar": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/5c7c7b1a0b79db7c3e33eca2/6b6b8178-0da0-4a37-b0dd-f8b5e3628eaa/128" }, From 494c7c7d222363cf025fe38c3b213aac98dba043 Mon Sep 17 00:00:00 2001 From: atefehmohseni <57154674+atefehmohseni@users.noreply.github.com> Date: Mon, 18 Nov 2024 21:48:08 -0800 Subject: [PATCH 273/282] Update pr.json.golden --- scm/driver/bitbucket/testdata/pr.json.golden | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/driver/bitbucket/testdata/pr.json.golden b/scm/driver/bitbucket/testdata/pr.json.golden index 8132df37f..eb0f2c047 100644 --- a/scm/driver/bitbucket/testdata/pr.json.golden +++ b/scm/driver/bitbucket/testdata/pr.json.golden @@ -22,7 +22,7 @@ "Name": "Lachlan-Vass/ios-date-picker-component-duplicate-marc-1579222909688" }, "Author": { - "Login": "Lachlan", + "Login": "ef9d9075-f870-417f-b424-83adbc8efa54", "Name": "Lachlan Vass", "Avatar": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/5c7c7b1a0b79db7c3e33eca2/6b6b8178-0da0-4a37-b0dd-f8b5e3628eaa/128" }, From 2cb72e1be625c5d94790bb7eca362b68684782ee Mon Sep 17 00:00:00 2001 From: atefehmohseni <57154674+atefehmohseni@users.noreply.github.com> Date: Mon, 18 Nov 2024 21:52:57 -0800 Subject: [PATCH 274/282] Update pr.go --- scm/driver/bitbucket/pr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/driver/bitbucket/pr.go b/scm/driver/bitbucket/pr.go index 38610bf5e..4d435c192 100644 --- a/scm/driver/bitbucket/pr.go +++ b/scm/driver/bitbucket/pr.go @@ -193,7 +193,7 @@ func convertPullRequest(from *pr) *scm.PullRequest { Sha: from.Destination.Commit.Hash, }, Author: scm.User{ - Login: from.Author.UUID, + Login: from.Author.AccountID, Name: from.Author.DisplayName, Avatar: from.Author.Links.Avatar.Href, }, From 8f57b646812524037782314137052815b86aeb00 Mon Sep 17 00:00:00 2001 From: atefehmohseni <57154674+atefehmohseni@users.noreply.github.com> Date: Mon, 18 Nov 2024 21:55:43 -0800 Subject: [PATCH 275/282] Update pr.json.golden --- scm/driver/bitbucket/testdata/pr.json.golden | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/driver/bitbucket/testdata/pr.json.golden b/scm/driver/bitbucket/testdata/pr.json.golden index eb0f2c047..541b7b4ca 100644 --- a/scm/driver/bitbucket/testdata/pr.json.golden +++ b/scm/driver/bitbucket/testdata/pr.json.golden @@ -22,7 +22,7 @@ "Name": "Lachlan-Vass/ios-date-picker-component-duplicate-marc-1579222909688" }, "Author": { - "Login": "ef9d9075-f870-417f-b424-83adbc8efa54", + "Login": "5c7c7b1a0b79db7c3e33eca2", "Name": "Lachlan Vass", "Avatar": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/5c7c7b1a0b79db7c3e33eca2/6b6b8178-0da0-4a37-b0dd-f8b5e3628eaa/128" }, From 44d28c751c4e838ee99b0a5a7be7a289334742f9 Mon Sep 17 00:00:00 2001 From: atefehmohseni <57154674+atefehmohseni@users.noreply.github.com> Date: Mon, 18 Nov 2024 21:56:34 -0800 Subject: [PATCH 276/282] Update prs.json.golden --- scm/driver/bitbucket/testdata/prs.json.golden | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/driver/bitbucket/testdata/prs.json.golden b/scm/driver/bitbucket/testdata/prs.json.golden index 99a5905f3..993b68bef 100644 --- a/scm/driver/bitbucket/testdata/prs.json.golden +++ b/scm/driver/bitbucket/testdata/prs.json.golden @@ -23,7 +23,7 @@ "Name": "Lachlan-Vass/ios-date-picker-component-duplicate-marc-1579222909688" }, "Author": { - "Login": "ef9d9075-f870-417f-b424-83adbc8efa54", + "Login": "5c7c7b1a0b79db7c3e33eca2", "Name": "Lachlan Vass", "Avatar": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/5c7c7b1a0b79db7c3e33eca2/6b6b8178-0da0-4a37-b0dd-f8b5e3628eaa/128" }, From a394f0d2cd7ba0bc4cad45d2c7277f974e2a08a5 Mon Sep 17 00:00:00 2001 From: atefehmohseni <57154674+atefehmohseni@users.noreply.github.com> Date: Tue, 19 Nov 2024 07:53:40 -0800 Subject: [PATCH 277/282] Update pr.go --- scm/driver/bitbucket/pr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/driver/bitbucket/pr.go b/scm/driver/bitbucket/pr.go index 4d435c192..54f0b8b18 100644 --- a/scm/driver/bitbucket/pr.go +++ b/scm/driver/bitbucket/pr.go @@ -193,7 +193,7 @@ func convertPullRequest(from *pr) *scm.PullRequest { Sha: from.Destination.Commit.Hash, }, Author: scm.User{ - Login: from.Author.AccountID, + ID: from.Author.AccountID, Name: from.Author.DisplayName, Avatar: from.Author.Links.Avatar.Href, }, From de8ab9207236ee5ef0f3fbd46029b7ecf2008741 Mon Sep 17 00:00:00 2001 From: atefehmohseni <57154674+atefehmohseni@users.noreply.github.com> Date: Tue, 19 Nov 2024 07:54:44 -0800 Subject: [PATCH 278/282] Update pr.json.golden --- scm/driver/bitbucket/testdata/pr.json.golden | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/driver/bitbucket/testdata/pr.json.golden b/scm/driver/bitbucket/testdata/pr.json.golden index 541b7b4ca..1ed8a643f 100644 --- a/scm/driver/bitbucket/testdata/pr.json.golden +++ b/scm/driver/bitbucket/testdata/pr.json.golden @@ -22,7 +22,7 @@ "Name": "Lachlan-Vass/ios-date-picker-component-duplicate-marc-1579222909688" }, "Author": { - "Login": "5c7c7b1a0b79db7c3e33eca2", + "ID": "5c7c7b1a0b79db7c3e33eca2", "Name": "Lachlan Vass", "Avatar": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/5c7c7b1a0b79db7c3e33eca2/6b6b8178-0da0-4a37-b0dd-f8b5e3628eaa/128" }, From 587bff37744f17d407e77508d38831260289aee0 Mon Sep 17 00:00:00 2001 From: atefehmohseni <57154674+atefehmohseni@users.noreply.github.com> Date: Tue, 19 Nov 2024 07:54:56 -0800 Subject: [PATCH 279/282] Update prs.json.golden --- scm/driver/bitbucket/testdata/prs.json.golden | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/driver/bitbucket/testdata/prs.json.golden b/scm/driver/bitbucket/testdata/prs.json.golden index 993b68bef..90a246041 100644 --- a/scm/driver/bitbucket/testdata/prs.json.golden +++ b/scm/driver/bitbucket/testdata/prs.json.golden @@ -23,7 +23,7 @@ "Name": "Lachlan-Vass/ios-date-picker-component-duplicate-marc-1579222909688" }, "Author": { - "Login": "5c7c7b1a0b79db7c3e33eca2", + "ID": "5c7c7b1a0b79db7c3e33eca2", "Name": "Lachlan Vass", "Avatar": "https://avatar-management--avatars.us-west-2.prod.public.atl-paas.net/5c7c7b1a0b79db7c3e33eca2/6b6b8178-0da0-4a37-b0dd-f8b5e3628eaa/128" }, From df651244d043b16a27f42fa401e127c4697b1dd6 Mon Sep 17 00:00:00 2001 From: atefehmohseni <57154674+atefehmohseni@users.noreply.github.com> Date: Tue, 19 Nov 2024 12:24:12 -0800 Subject: [PATCH 280/282] gofmt --- scm/driver/bitbucket/pr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/driver/bitbucket/pr.go b/scm/driver/bitbucket/pr.go index 54f0b8b18..c0282f714 100644 --- a/scm/driver/bitbucket/pr.go +++ b/scm/driver/bitbucket/pr.go @@ -193,7 +193,7 @@ func convertPullRequest(from *pr) *scm.PullRequest { Sha: from.Destination.Commit.Hash, }, Author: scm.User{ - ID: from.Author.AccountID, + ID: from.Author.AccountID, Name: from.Author.DisplayName, Avatar: from.Author.Links.Avatar.Href, }, From d5ed63c1a5888b1378412d5d95c24c866e4bb47c Mon Sep 17 00:00:00 2001 From: Olivier Vernin Date: Thu, 21 Nov 2024 19:21:08 +0100 Subject: [PATCH 281/282] fix: pass gitlab mergerequest param via json body (#322) Signed-off-by: Olivier Vernin --- scm/driver/gitlab/pr.go | 23 ++++++++++++++++------- scm/driver/gitlab/pr_test.go | 4 ---- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/scm/driver/gitlab/pr.go b/scm/driver/gitlab/pr.go index b8f67719a..bb63590a6 100644 --- a/scm/driver/gitlab/pr.go +++ b/scm/driver/gitlab/pr.go @@ -60,14 +60,23 @@ func (s *pullService) ListCommits(ctx context.Context, repo string, number int, } func (s *pullService) Create(ctx context.Context, repo string, input *scm.PullRequestInput) (*scm.PullRequest, *scm.Response, error) { - in := url.Values{} - in.Set("title", input.Title) - in.Set("description", input.Body) - in.Set("source_branch", input.Source) - in.Set("target_branch", input.Target) - path := fmt.Sprintf("api/v4/projects/%s/merge_requests?%s", encode(repo), in.Encode()) + // https://docs.gitlab.com/ee/api/merge_requests.html#create-mr + in := struct { + Title string `json:"title"` + Description string `json:"description"` + SourceBranch string `json:"source_branch"` + TargetBranch string `json:"target_branch"` + }{ + Title: input.Title, + Description: input.Body, + SourceBranch: input.Source, + TargetBranch: input.Target, + } + + path := fmt.Sprintf("api/v4/projects/%s/merge_requests", encode(repo)) + out := new(pr) - res, err := s.client.do(ctx, "POST", path, nil, out) + res, err := s.client.do(ctx, "POST", path, in, out) return convertPullRequest(out), res, err } diff --git a/scm/driver/gitlab/pr_test.go b/scm/driver/gitlab/pr_test.go index fe35f1e8d..c36ab067e 100644 --- a/scm/driver/gitlab/pr_test.go +++ b/scm/driver/gitlab/pr_test.go @@ -162,10 +162,6 @@ func TestPullCreate(t *testing.T) { gock.New("https://gitlab.com"). Post("/api/v4/projects/diaspora/diaspora/merge_requests"). - MatchParam("title", input.Title). - MatchParam("description", input.Body). - MatchParam("source_branch", input.Source). - MatchParam("target_branch", input.Target). Reply(201). Type("application/json"). SetHeaders(mockHeaders). From 31d79c45a9cab727607b88cf8e893c39462e3978 Mon Sep 17 00:00:00 2001 From: Karan Saraswat Date: Mon, 2 Dec 2024 17:19:12 +0530 Subject: [PATCH 282/282] feat: [PIPE-23808]: integrate author details with the harness commits API --- scm/content.go | 4 +- scm/driver/harness/content.go | 196 +++++++++++++++++----------------- 2 files changed, 101 insertions(+), 99 deletions(-) diff --git a/scm/content.go b/scm/content.go index 4f5e4a0e9..2d5cb6fde 100644 --- a/scm/content.go +++ b/scm/content.go @@ -40,13 +40,13 @@ type ( // Find returns the repository file content by path. Find(ctx context.Context, repo, path, ref string) (*Content, *Response, error) - // Create creates a new repositroy file. + // Create creates a new repository file. Create(ctx context.Context, repo, path string, params *ContentParams) (*Response, error) // Update updates a repository file. Update(ctx context.Context, repo, path string, params *ContentParams) (*Response, error) - // Delete deletes a reository file. + // Delete deletes a repository file. Delete(ctx context.Context, repo, path string, params *ContentParams) (*Response, error) // List returns a list of contents in a repository directory by path. It is diff --git a/scm/driver/harness/content.go b/scm/driver/harness/content.go index 40dd24d6c..16159cb53 100644 --- a/scm/driver/harness/content.go +++ b/scm/driver/harness/content.go @@ -55,6 +55,10 @@ func (s *contentService) Create(ctx context.Context, repo, path string, params * Title: params.Message, Actions: []action{a}, BypassRules: true, + Author: identity{ + Name: params.Signature.Name, + Email: params.Signature.Email, + }, } res, err := s.client.do(ctx, "POST", endpoint, in, nil) @@ -81,6 +85,10 @@ func (s *contentService) Update(ctx context.Context, repo, path string, params * Title: params.Message, Actions: []action{a}, BypassRules: true, + Author: identity{ + Name: params.Signature.Name, + Email: params.Signature.Email, + }, } res, err := s.client.do(ctx, "POST", endpoint, in, nil) @@ -105,6 +113,10 @@ func (s *contentService) Delete(ctx context.Context, repo, path string, params * Title: params.Message, Actions: []action{a}, BypassRules: true, + Author: identity{ + Name: params.Signature.Name, + Email: params.Signature.Email, + }, } res, err := s.client.do(ctx, "POST", endpoint, in, nil) @@ -123,109 +135,99 @@ func (s *contentService) List(ctx context.Context, repo, path, ref string, _ scm return convertContentInfoList(out.Content.Entries), res, err } -type editFile struct { - Actions []action `json:"actions"` - Branch string `json:"branch"` - Message string `json:"message"` - NewBranch string `json:"new_branch"` - Title string `json:"title"` +type ( + identity struct { + Name string `json:"name"` + Email string `json:"email"` + } - BypassRules bool `json:"bypass_rules"` -} + editFile struct { + Actions []action `json:"actions"` + Author identity `json:"author"` + Branch string `json:"branch"` + Message string `json:"message"` + NewBranch string `json:"new_branch"` + Title string `json:"title"` -type action struct { - Action string `json:"action"` - Encoding string `json:"encoding"` - Path string `json:"path"` - Payload string `json:"payload"` - Sha string `json:"sha"` -} + BypassRules bool `json:"bypass_rules"` + } -type fileContent struct { - Type string `json:"type"` - Sha string `json:"sha"` - Name string `json:"name"` - Path string `json:"path"` - LatestCommit struct { - Sha string `json:"sha"` - Title string `json:"title"` - Message string `json:"message"` - Author struct { - Identity struct { - Name string `json:"name"` - Email string `json:"email"` - } `json:"identity"` - When time.Time `json:"when"` - } `json:"author"` - Committer struct { - Identity struct { - Name string `json:"name"` - Email string `json:"email"` - } `json:"identity"` - When time.Time `json:"when"` - } `json:"committer"` - } `json:"latest_commit"` - Content struct { + action struct { + Action string `json:"action"` Encoding string `json:"encoding"` - Data string `json:"data"` - Size int `json:"size"` - } `json:"content"` -} + Path string `json:"path"` + Payload string `json:"payload"` + Sha string `json:"sha"` + } -type contentList struct { - Type string `json:"type"` - Sha string `json:"sha"` - Name string `json:"name"` - Path string `json:"path"` - LatestCommit struct { - Sha string `json:"sha"` - Title string `json:"title"` - Message string `json:"message"` - Author struct { - Identity struct { - Name string `json:"name"` - Email string `json:"email"` - } `json:"identity"` - When time.Time `json:"when"` - } `json:"author"` - Committer struct { - Identity struct { - Name string `json:"name"` - Email string `json:"email"` - } `json:"identity"` - When time.Time `json:"when"` - } `json:"committer"` - } `json:"latest_commit"` - Content struct { - Entries []fileEntry `json:"entries"` - } `json:"content"` -} + fileContent struct { + Type string `json:"type"` + Sha string `json:"sha"` + Name string `json:"name"` + Path string `json:"path"` + LatestCommit struct { + Sha string `json:"sha"` + Title string `json:"title"` + Message string `json:"message"` + Author struct { + Identity identity `json:"identity"` + When time.Time `json:"when"` + } `json:"author"` + Committer struct { + Identity identity `json:"identity"` + When time.Time `json:"when"` + } `json:"committer"` + } `json:"latest_commit"` + Content struct { + Encoding string `json:"encoding"` + Data string `json:"data"` + Size int `json:"size"` + } `json:"content"` + } -type fileEntry struct { - Type string `json:"type"` - Sha string `json:"sha"` - Name string `json:"name"` - Path string `json:"path"` - LatestCommit struct { - Sha string `json:"sha"` - Title string `json:"title"` - Message string `json:"message"` - Author struct { - Identity struct { - Name string `json:"name"` - Email string `json:"email"` - } `json:"identity"` - When time.Time `json:"when"` - } `json:"author"` - Committer struct { - Identity struct { - Name string `json:"name"` - Email string `json:"email"` - } `json:"identity"` - When time.Time `json:"when"` - } `json:"committer"` - } `json:"latest_commit"` -} + contentList struct { + Type string `json:"type"` + Sha string `json:"sha"` + Name string `json:"name"` + Path string `json:"path"` + LatestCommit struct { + Sha string `json:"sha"` + Title string `json:"title"` + Message string `json:"message"` + Author struct { + Identity identity `json:"identity"` + When time.Time `json:"when"` + } `json:"author"` + Committer struct { + Identity identity `json:"identity"` + When time.Time `json:"when"` + } `json:"committer"` + } `json:"latest_commit"` + Content struct { + Entries []fileEntry `json:"entries"` + } `json:"content"` + } + + fileEntry struct { + Type string `json:"type"` + Sha string `json:"sha"` + Name string `json:"name"` + Path string `json:"path"` + LatestCommit struct { + Sha string `json:"sha"` + Title string `json:"title"` + Message string `json:"message"` + Author struct { + Identity identity `json:"identity"` + When time.Time `json:"when"` + } `json:"author"` + Committer struct { + Identity identity `json:"identity"` + When time.Time `json:"when"` + } `json:"committer"` + } `json:"latest_commit"` + } +) func convertContentInfoList(from []fileEntry) []*scm.ContentInfo { to := []*scm.ContentInfo{}