",
+ "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/branches_filter.json.golden b/scm/driver/bitbucket/testdata/branches_filter.json.golden
new file mode 100644
index 000000000..79754a78f
--- /dev/null
+++ b/scm/driver/bitbucket/testdata/branches_filter.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/testdata/pr.json.golden b/scm/driver/bitbucket/testdata/pr.json.golden
index 8132df37f..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": "Lachlan",
+ "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"
},
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/testdata/prs.json.golden b/scm/driver/bitbucket/testdata/prs.json.golden
index 29cafe903..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": "Lachlan",
+ "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"
},
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/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/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/testdata/webhooks/pipeline_hook_created.json b/scm/driver/bitbucket/testdata/webhooks/pipeline_hook_created.json
new file mode 100644
index 000000000..02c506c67
--- /dev/null
+++ b/scm/driver/bitbucket/testdata/webhooks/pipeline_hook_created.json
@@ -0,0 +1,175 @@
+{
+ "repository": {
+ "type": "repository",
+ "full_name": "automationtestharness/testrepo",
+ "links": {
+ "self": {
+ "href": "https://api.bitbucket.org/2.0/repositories/automationtestharness/testrepo"
+ },
+ "html": {
+ "href": "https://bitbucket.org/automationtestharness/testrepo"
+ },
+ "avatar": {
+ "href": "https://bytebucket.org/ravatar/%7B2b922c6d-3824-4e91-a7be-90c8b8392f84%7D?ts=default"
+ }
+ },
+ "name": "testRepo",
+ "scm": "git",
+ "website": null,
+ "owner": {
+ "display_name": "Automationtestharness",
+ "links": {
+ "self": {
+ "href": "https://api.bitbucket.org/2.0/workspaces/%7B612f7b18-b167-4bff-8ee9-d43570117ff1%7D"
+ },
+ "avatar": {
+ "href": "https://bitbucket.org/account/automationtestharness/avatar/"
+ },
+ "html": {
+ "href": "https://bitbucket.org/%7B612f7b18-b167-4bff-8ee9-d43570117ff1%7D/"
+ }
+ },
+ "type": "team",
+ "uuid": "{612f7b18-b167-4bff-8ee9-d43570117ff1}",
+ "username": "automationtestharness"
+ },
+ "workspace": {
+ "type": "workspace",
+ "uuid": "{612f7b18-b167-4bff-8ee9-d43570117ff1}",
+ "name": "Automationtestharness",
+ "slug": "automationtestharness",
+ "links": {
+ "avatar": {
+ "href": "https://bitbucket.org/workspaces/automationtestharness/avatar/?ts=1740994558"
+ },
+ "html": {
+ "href": "https://bitbucket.org/automationtestharness/"
+ },
+ "self": {
+ "href": "https://api.bitbucket.org/2.0/workspaces/automationtestharness"
+ }
+ }
+ },
+ "is_private": true,
+ "project": {
+ "type": "project",
+ "key": "TEST",
+ "uuid": "{af6d7f47-6ce6-48b6-9beb-d5ad6b674ba0}",
+ "name": "test",
+ "links": {
+ "self": {
+ "href": "https://api.bitbucket.org/2.0/workspaces/automationtestharness/projects/TEST"
+ },
+ "html": {
+ "href": "https://bitbucket.org/automationtestharness/workspace/projects/TEST"
+ },
+ "avatar": {
+ "href": "https://bitbucket.org/automationtestharness/workspace/projects/TEST/avatar/32?ts=1738907820"
+ }
+ }
+ },
+ "uuid": "{2b922c6d-3824-4e91-a7be-90c8b8392f84}",
+ "parent": null
+ },
+ "actor": {
+ "display_name": "Automationtestharness",
+ "links": {
+ "self": {
+ "href": "https://api.bitbucket.org/2.0/workspaces/%7B612f7b18-b167-4bff-8ee9-d43570117ff1%7D"
+ },
+ "avatar": {
+ "href": "https://bitbucket.org/account/automationtestharness/avatar/"
+ },
+ "html": {
+ "href": "https://bitbucket.org/%7B612f7b18-b167-4bff-8ee9-d43570117ff1%7D/"
+ }
+ },
+ "type": "team",
+ "uuid": "{612f7b18-b167-4bff-8ee9-d43570117ff1}",
+ "username": "automationtestharness"
+ },
+ "commit_status": {
+ "key": "3343801",
+ "type": "build",
+ "state": "INPROGRESS",
+ "name": "Pipeline #4 for main",
+ "refname": "main",
+ "commit": {
+ "type": "commit",
+ "hash": "bdf6fac0519ffd1562461eb82e018ff62efffbc9",
+ "date": "2025-03-24T08:48:15+00:00",
+ "author": {
+ "type": "author",
+ "raw": "Shivam Negi ",
+ "user": {
+ "display_name": "Shivam Negi",
+ "links": {
+ "self": {
+ "href": "https://api.bitbucket.org/2.0/users/%7Bce7d5dfc-83c9-4878-beaf-7b91610e104a%7D"
+ },
+ "avatar": {
+ "href": "https://secure.gravatar.com/avatar/39b64ab2df0f61fcce00db05f94c600b?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FSN-2.png"
+ },
+ "html": {
+ "href": "https://bitbucket.org/%7Bce7d5dfc-83c9-4878-beaf-7b91610e104a%7D/"
+ }
+ },
+ "type": "user",
+ "uuid": "{ce7d5dfc-83c9-4878-beaf-7b91610e104a}",
+ "account_id": "601ba1bdb7bda90068ed5d1b",
+ "nickname": "Shivam Negi"
+ }
+ },
+ "message": "Merged in Shivam-Negi/testyaml-edited-online-with-bitbucket-1742806076994 (pull request #13)\n\ntest.yaml edited online with Bitbucket\n",
+ "links": {
+ "self": {
+ "href": "https://api.bitbucket.org/2.0/repositories/automationtestharness/testrepo/commit/bdf6fac0519ffd1562461eb82e018ff62efffbc9"
+ },
+ "html": {
+ "href": "https://bitbucket.org/automationtestharness/testrepo/commits/bdf6fac0519ffd1562461eb82e018ff62efffbc9"
+ },
+ "diff": {
+ "href": "https://api.bitbucket.org/2.0/repositories/automationtestharness/testrepo/diff/bdf6fac0519ffd1562461eb82e018ff62efffbc9"
+ },
+ "approve": {
+ "href": "https://api.bitbucket.org/2.0/repositories/automationtestharness/testrepo/commit/bdf6fac0519ffd1562461eb82e018ff62efffbc9/approve"
+ },
+ "comments": {
+ "href": "https://api.bitbucket.org/2.0/repositories/automationtestharness/testrepo/commit/bdf6fac0519ffd1562461eb82e018ff62efffbc9/comments"
+ },
+ "statuses": {
+ "href": "https://api.bitbucket.org/2.0/repositories/automationtestharness/testrepo/commit/bdf6fac0519ffd1562461eb82e018ff62efffbc9/statuses"
+ }
+ }
+ },
+ "url": "https://bitbucket.org/automationtestharness/testrepo/addon/pipelines/home#!/results/4",
+ "repository": {
+ "type": "repository",
+ "full_name": "automationtestharness/testrepo",
+ "links": {
+ "self": {
+ "href": "https://api.bitbucket.org/2.0/repositories/automationtestharness/testrepo"
+ },
+ "html": {
+ "href": "https://bitbucket.org/automationtestharness/testrepo"
+ },
+ "avatar": {
+ "href": "https://bytebucket.org/ravatar/%7B2b922c6d-3824-4e91-a7be-90c8b8392f84%7D?ts=default"
+ }
+ },
+ "name": "testRepo",
+ "uuid": "{2b922c6d-3824-4e91-a7be-90c8b8392f84}"
+ },
+ "description": "",
+ "created_on": "2025-03-24T08:48:56.572438+00:00",
+ "updated_on": "2025-03-24T08:48:56.572450+00:00",
+ "links": {
+ "self": {
+ "href": "https://api.bitbucket.org/2.0/repositories/automationtestharness/testrepo/commit/bdf6fac0519ffd1562461eb82e018ff62efffbc9/statuses/build/3343801"
+ },
+ "commit": {
+ "href": "https://api.bitbucket.org/2.0/repositories/automationtestharness/testrepo/commit/bdf6fac0519ffd1562461eb82e018ff62efffbc9"
+ }
+ }
+ }
+ }
\ No newline at end of file
diff --git a/scm/driver/bitbucket/testdata/webhooks/pipeline_hook_created.json.golden b/scm/driver/bitbucket/testdata/webhooks/pipeline_hook_created.json.golden
new file mode 100644
index 000000000..b0e6c2a38
--- /dev/null
+++ b/scm/driver/bitbucket/testdata/webhooks/pipeline_hook_created.json.golden
@@ -0,0 +1,39 @@
+{
+ "Repo": {
+ "ID": "{2b922c6d-3824-4e91-a7be-90c8b8392f84}",
+ "Namespace": "automationtestharness",
+ "Name": "testrepo",
+ "Clone": "https://bitbucket.org/automationtestharness/testrepo",
+ "CloneSSH": "",
+ "Branch": "main",
+ "Private": true
+ },
+ "Commit": {
+ "Sha": "bdf6fac0519ffd1562461eb82e018ff62efffbc9",
+ "Message": "Merged in Shivam-Negi/testyaml-edited-online-with-bitbucket-1742806076994 (pull request #13)\n\ntest.yaml edited online with Bitbucket\n",
+ "Author": {
+ "Name": "Shivam Negi",
+ "Email": "shivamnegi94@gmail.com",
+ "Avatar": "https://secure.gravatar.com/avatar/39b64ab2df0f61fcce00db05f94c600b?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FSN-2.png"
+ },
+ "Committer": {
+ "Name": "Shivam Negi",
+ "Email": "shivamnegi94@gmail.com",
+ "Avatar": "https://secure.gravatar.com/avatar/39b64ab2df0f61fcce00db05f94c600b?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FSN-2.png"
+ },
+ "Link": "https://bitbucket.org/automationtestharness/testrepo/commits/bdf6fac0519ffd1562461eb82e018ff62efffbc9"
+ },
+ "Execution": {
+ "Number": 4,
+ "Status": "running",
+ "Created": "2025-03-24T08:48:56.572438+00:00",
+ "URL": "https://bitbucket.org/automationtestharness/testrepo/addon/pipelines/home#!/results/4"
+ },
+ "Sender": {
+ "Login": "automationtestharness",
+ "Name": "Automationtestharness",
+ "Email": "",
+ "Avatar": "https://bitbucket.org/account/automationtestharness/avatar/",
+ "ID": "{612f7b18-b167-4bff-8ee9-d43570117ff1}"
+ }
+}
diff --git a/scm/driver/bitbucket/testdata/webhooks/pipeline_hook_update.json b/scm/driver/bitbucket/testdata/webhooks/pipeline_hook_update.json
new file mode 100644
index 000000000..10655dd05
--- /dev/null
+++ b/scm/driver/bitbucket/testdata/webhooks/pipeline_hook_update.json
@@ -0,0 +1,175 @@
+{
+ "repository": {
+ "type": "repository",
+ "full_name": "automationtestharness/testrepo",
+ "links": {
+ "self": {
+ "href": "https://api.bitbucket.org/2.0/repositories/automationtestharness/testrepo"
+ },
+ "html": {
+ "href": "https://bitbucket.org/automationtestharness/testrepo"
+ },
+ "avatar": {
+ "href": "https://bytebucket.org/ravatar/%7B2b922c6d-3824-4e91-a7be-90c8b8392f84%7D?ts=default"
+ }
+ },
+ "name": "testRepo",
+ "scm": "git",
+ "website": null,
+ "owner": {
+ "display_name": "Automationtestharness",
+ "links": {
+ "self": {
+ "href": "https://api.bitbucket.org/2.0/workspaces/%7B612f7b18-b167-4bff-8ee9-d43570117ff1%7D"
+ },
+ "avatar": {
+ "href": "https://bitbucket.org/account/automationtestharness/avatar/"
+ },
+ "html": {
+ "href": "https://bitbucket.org/%7B612f7b18-b167-4bff-8ee9-d43570117ff1%7D/"
+ }
+ },
+ "type": "team",
+ "uuid": "{612f7b18-b167-4bff-8ee9-d43570117ff1}",
+ "username": "automationtestharness"
+ },
+ "workspace": {
+ "type": "workspace",
+ "uuid": "{612f7b18-b167-4bff-8ee9-d43570117ff1}",
+ "name": "Automationtestharness",
+ "slug": "automationtestharness",
+ "links": {
+ "avatar": {
+ "href": "https://bitbucket.org/workspaces/automationtestharness/avatar/?ts=1740994558"
+ },
+ "html": {
+ "href": "https://bitbucket.org/automationtestharness/"
+ },
+ "self": {
+ "href": "https://api.bitbucket.org/2.0/workspaces/automationtestharness"
+ }
+ }
+ },
+ "is_private": true,
+ "project": {
+ "type": "project",
+ "key": "TEST",
+ "uuid": "{af6d7f47-6ce6-48b6-9beb-d5ad6b674ba0}",
+ "name": "test",
+ "links": {
+ "self": {
+ "href": "https://api.bitbucket.org/2.0/workspaces/automationtestharness/projects/TEST"
+ },
+ "html": {
+ "href": "https://bitbucket.org/automationtestharness/workspace/projects/TEST"
+ },
+ "avatar": {
+ "href": "https://bitbucket.org/automationtestharness/workspace/projects/TEST/avatar/32?ts=1738907820"
+ }
+ }
+ },
+ "uuid": "{2b922c6d-3824-4e91-a7be-90c8b8392f84}",
+ "parent": null
+ },
+ "actor": {
+ "display_name": "Automationtestharness",
+ "links": {
+ "self": {
+ "href": "https://api.bitbucket.org/2.0/workspaces/%7B612f7b18-b167-4bff-8ee9-d43570117ff1%7D"
+ },
+ "avatar": {
+ "href": "https://bitbucket.org/account/automationtestharness/avatar/"
+ },
+ "html": {
+ "href": "https://bitbucket.org/%7B612f7b18-b167-4bff-8ee9-d43570117ff1%7D/"
+ }
+ },
+ "type": "team",
+ "uuid": "{612f7b18-b167-4bff-8ee9-d43570117ff1}",
+ "username": "automationtestharness"
+ },
+ "commit_status": {
+ "key": "3343801",
+ "type": "build",
+ "state": "SUCCESSFUL",
+ "name": "Pipeline #4 for main",
+ "refname": "main",
+ "commit": {
+ "type": "commit",
+ "hash": "bdf6fac0519ffd1562461eb82e018ff62efffbc9",
+ "date": "2025-03-24T08:48:15+00:00",
+ "author": {
+ "type": "author",
+ "raw": "Shivam Negi ",
+ "user": {
+ "display_name": "Shivam Negi",
+ "links": {
+ "self": {
+ "href": "https://api.bitbucket.org/2.0/users/%7Bce7d5dfc-83c9-4878-beaf-7b91610e104a%7D"
+ },
+ "avatar": {
+ "href": "https://secure.gravatar.com/avatar/39b64ab2df0f61fcce00db05f94c600b?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FSN-2.png"
+ },
+ "html": {
+ "href": "https://bitbucket.org/%7Bce7d5dfc-83c9-4878-beaf-7b91610e104a%7D/"
+ }
+ },
+ "type": "user",
+ "uuid": "{ce7d5dfc-83c9-4878-beaf-7b91610e104a}",
+ "account_id": "601ba1bdb7bda90068ed5d1b",
+ "nickname": "Shivam Negi"
+ }
+ },
+ "message": "Merged in Shivam-Negi/testyaml-edited-online-with-bitbucket-1742806076994 (pull request #13)\n\ntest.yaml edited online with Bitbucket\n",
+ "links": {
+ "self": {
+ "href": "https://api.bitbucket.org/2.0/repositories/automationtestharness/testrepo/commit/bdf6fac0519ffd1562461eb82e018ff62efffbc9"
+ },
+ "html": {
+ "href": "https://bitbucket.org/automationtestharness/testrepo/commits/bdf6fac0519ffd1562461eb82e018ff62efffbc9"
+ },
+ "diff": {
+ "href": "https://api.bitbucket.org/2.0/repositories/automationtestharness/testrepo/diff/bdf6fac0519ffd1562461eb82e018ff62efffbc9"
+ },
+ "approve": {
+ "href": "https://api.bitbucket.org/2.0/repositories/automationtestharness/testrepo/commit/bdf6fac0519ffd1562461eb82e018ff62efffbc9/approve"
+ },
+ "comments": {
+ "href": "https://api.bitbucket.org/2.0/repositories/automationtestharness/testrepo/commit/bdf6fac0519ffd1562461eb82e018ff62efffbc9/comments"
+ },
+ "statuses": {
+ "href": "https://api.bitbucket.org/2.0/repositories/automationtestharness/testrepo/commit/bdf6fac0519ffd1562461eb82e018ff62efffbc9/statuses"
+ }
+ }
+ },
+ "url": "https://bitbucket.org/automationtestharness/testrepo/addon/pipelines/home#!/results/4",
+ "repository": {
+ "type": "repository",
+ "full_name": "automationtestharness/testrepo",
+ "links": {
+ "self": {
+ "href": "https://api.bitbucket.org/2.0/repositories/automationtestharness/testrepo"
+ },
+ "html": {
+ "href": "https://bitbucket.org/automationtestharness/testrepo"
+ },
+ "avatar": {
+ "href": "https://bytebucket.org/ravatar/%7B2b922c6d-3824-4e91-a7be-90c8b8392f84%7D?ts=default"
+ }
+ },
+ "name": "testRepo",
+ "uuid": "{2b922c6d-3824-4e91-a7be-90c8b8392f84}"
+ },
+ "description": "",
+ "created_on": "2025-03-24T08:48:56.572438+00:00",
+ "updated_on": "2025-03-24T08:49:42.838984+00:00",
+ "links": {
+ "self": {
+ "href": "https://api.bitbucket.org/2.0/repositories/automationtestharness/testrepo/commit/bdf6fac0519ffd1562461eb82e018ff62efffbc9/statuses/build/3343801"
+ },
+ "commit": {
+ "href": "https://api.bitbucket.org/2.0/repositories/automationtestharness/testrepo/commit/bdf6fac0519ffd1562461eb82e018ff62efffbc9"
+ }
+ }
+ }
+ }
\ No newline at end of file
diff --git a/scm/driver/bitbucket/testdata/webhooks/pipeline_hook_update.json.golden b/scm/driver/bitbucket/testdata/webhooks/pipeline_hook_update.json.golden
new file mode 100644
index 000000000..1b0b7623f
--- /dev/null
+++ b/scm/driver/bitbucket/testdata/webhooks/pipeline_hook_update.json.golden
@@ -0,0 +1,39 @@
+{
+ "Repo": {
+ "ID": "{2b922c6d-3824-4e91-a7be-90c8b8392f84}",
+ "Namespace": "automationtestharness",
+ "Name": "testrepo",
+ "Clone": "https://bitbucket.org/automationtestharness/testrepo",
+ "CloneSSH": "",
+ "Branch": "main",
+ "Private": true
+ },
+ "Commit": {
+ "Sha": "bdf6fac0519ffd1562461eb82e018ff62efffbc9",
+ "Message": "Merged in Shivam-Negi/testyaml-edited-online-with-bitbucket-1742806076994 (pull request #13)\n\ntest.yaml edited online with Bitbucket\n",
+ "Author": {
+ "Name": "Shivam Negi",
+ "Email": "shivamnegi94@gmail.com",
+ "Avatar": "https://secure.gravatar.com/avatar/39b64ab2df0f61fcce00db05f94c600b?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FSN-2.png"
+ },
+ "Committer": {
+ "Name": "Shivam Negi",
+ "Email": "shivamnegi94@gmail.com",
+ "Avatar": "https://secure.gravatar.com/avatar/39b64ab2df0f61fcce00db05f94c600b?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FSN-2.png"
+ },
+ "Link": "https://bitbucket.org/automationtestharness/testrepo/commits/bdf6fac0519ffd1562461eb82e018ff62efffbc9"
+ },
+ "Execution": {
+ "Number": 4,
+ "Status": "success",
+ "Created": "2025-03-24T08:48:56.572438+00:00",
+ "URL": "https://bitbucket.org/automationtestharness/testrepo/addon/pipelines/home#!/results/4"
+ },
+ "Sender": {
+ "Login": "automationtestharness",
+ "Name": "Automationtestharness",
+ "Email": "",
+ "Avatar": "https://bitbucket.org/account/automationtestharness/avatar/",
+ "ID": "{612f7b18-b167-4bff-8ee9-d43570117ff1}"
+ }
+}
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/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 1cc60a2f0..642fe2a9f 100644
--- a/scm/driver/bitbucket/testdata/webhooks/pr_fulfilled.json.golden
+++ b/scm/driver/bitbucket/testdata/webhooks/pr_fulfilled.json.golden
@@ -18,6 +18,7 @@
"Title": "Awesome new feature",
"Body": "made some changes",
"Sha": "0704fc5beccc",
+ "Merge": "4f8f6de9d0ff",
"Ref": "refs/pull-requests/1/from",
"Source": "develop",
"Target": "master",
@@ -35,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.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 068c597b5..d835008c1 100644
--- a/scm/driver/bitbucket/testdata/webhooks/push_branch_create.json.golden
+++ b/scm/driver/bitbucket/testdata/webhooks/push_branch_create.json.golden
@@ -18,6 +18,7 @@
},
"Action": "created",
"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_create.json.golden b/scm/driver/bitbucket/testdata/webhooks/push_tag_create.json.golden
index 0f965056d..906d992ed 100644
--- a/scm/driver/bitbucket/testdata/webhooks/push_tag_create.json.golden
+++ b/scm/driver/bitbucket/testdata/webhooks/push_tag_create.json.golden
@@ -18,6 +18,7 @@
},
"Action": "created",
"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/user.go b/scm/driver/bitbucket/user.go
index 949d88b65..718811fb8 100644
--- a/scm/driver/bitbucket/user.go
+++ b/scm/driver/bitbucket/user.go
@@ -6,7 +6,6 @@ package bitbucket
import (
"context"
- "errors"
"fmt"
"github.com/drone/go-scm/scm"
@@ -31,23 +30,23 @@ func (s *userService) FindLogin(ctx context.Context, login string) (*scm.User, *
func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, error) {
out := new(emails)
- res, err := s.client.do(ctx, "GET", "2.0/user/emails", nil, out)
- if err != nil {
- return "", res, err
- }
-
- for _, emailObj := range out.Values {
- if emailObj.IsPrimary {
- return emailObj.Email, res, nil
- }
- }
- return "", res, errors.New("no primary email found")
+ 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:
@@ -65,12 +64,13 @@ type user struct {
UUID string `json:"uuid"`
}
+type email struct {
+ Email string `json:"email"`
+ IsPrimary bool `json:"is_primary"`
+}
+
type emails struct {
- Values []struct {
- IsPrimary bool `json:"is_primary"`
- IsConfirmed bool `json:"is_confirmed"`
- Email string `json:"email"`
- } `json:"values"`
+ Values []*email `json:"values"`
}
func convertUser(from *user) *scm.User {
diff --git a/scm/driver/bitbucket/user_test.go b/scm/driver/bitbucket/user_test.go
index 3e2d82c68..4e6b3c9f4 100644
--- a/scm/driver/bitbucket/user_test.go
+++ b/scm/driver/bitbucket/user_test.go
@@ -67,18 +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").
+ Get("/2.0/user/emails").
Reply(200).
Type("application/json").
- File("testdata/email.json")
+ File("testdata/userEmail.json")
client, _ := New("https://api.bitbucket.org")
got, _, err := client.Users.FindEmail(context.Background())
if err != nil {
- t.Errorf("Unexpected error")
+ t.Error(err)
}
- if got != "primary@example.com" {
+
+ want := "test@harness.io"
+
+ if diff := cmp.Diff(got, want); diff != "" {
t.Errorf("Unexpected Results")
+ t.Log(diff)
}
}
diff --git a/scm/driver/bitbucket/util.go b/scm/driver/bitbucket/util.go
index 03c5eaae4..e43ea71cf 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,26 @@ 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 != (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()
+}
+
func encodeListOptions(opts scm.ListOptions) string {
params := url.Values{}
if opts.Page != 0 {
@@ -47,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/bitbucket/webhook.go b/scm/driver/bitbucket/webhook.go
index 0b3780d10..bfd491edc 100644
--- a/scm/driver/bitbucket/webhook.go
+++ b/scm/driver/bitbucket/webhook.go
@@ -11,6 +11,8 @@ import (
"io"
"io/ioutil"
"net/http"
+ "regexp"
+ "strconv"
"time"
"github.com/drone/go-scm/scm"
@@ -53,6 +55,25 @@ 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
+ }
+ case "repo:commit_status_updated", "repo:commit_status_created":
+ hook, err = s.parsePipelineHook(data)
}
if err != nil {
return nil, err
@@ -78,6 +99,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)
@@ -115,6 +142,15 @@ func (s *webhookService) parsePullRequestHook(data []byte) (*scm.PullRequestHook
}
}
+func (s *webhookService) parsePipelineHook(data []byte) (*scm.PipelineHook, error) {
+ dst := new(pipelineHook)
+ err := json.Unmarshal(data, dst)
+ if err != nil {
+ return nil, err
+ }
+ return convertBitbucketHook(dst), err
+}
+
//
// native data structures
//
@@ -381,6 +417,278 @@ type (
} `json:"links"`
UUID string `json:"uuid"`
}
+
+ prCommentInput struct {
+ Content struct {
+ Raw string `json:"raw"`
+ } `json:"content"`
+ }
+
+ 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"`
+ }
+
+ pipelineHook struct {
+ Repository webhookRepository `json:"repository"`
+ Actor actor `json:"actor"`
+ CommitStatus struct {
+ Key string `json:"key"`
+ Type string `json:"type"`
+ State string `json:"state"`
+ Name string `json:"name"`
+ RefName string `json:"refname"`
+ Commit struct {
+ Type string `json:"type"`
+ Hash string `json:"hash"`
+ Date time.Time `json:"date"`
+ Author author `json:"author"`
+ Message string `json:"message"`
+ Links struct {
+ Self href `json:"self"`
+ HTML href `json:"html"`
+ Avatar href `json:"avatar"`
+ } `json:"links"`
+ } `json:"commit"`
+ URL string `json:"url"`
+ Repository info `json:"repository"`
+ Description string `json:"description"`
+ CreatedOn time.Time `json:"created_on"`
+ UpdatedOn time.Time `json:"updated_on"`
+ Links struct {
+ Self href `json:"self"`
+ Commit href `json:"commit"`
+ } `json:"links"`
+ } `json:"commit_status"`
+ }
+
+ href struct {
+ Href string `json:"href"`
+ }
+
+ actor struct {
+ DisplayName string `json:"display_name"`
+ Links struct {
+ Self href `json:"self"`
+ HTML href `json:"html"`
+ Avatar href `json:"avatar"`
+ } `json:"links"`
+ Type string `json:"type"`
+ UUID string `json:"uuid"`
+ Username string `json:"username"`
+ }
+
+ author struct {
+ Type string `json:"type"`
+ Raw string `json:"raw"`
+ User struct {
+ DisplayName string `json:"display_name"`
+ Links struct {
+ Self href `json:"self"`
+ HTML href `json:"html"`
+ Avatar href `json:"avatar"`
+ } `json:"links"`
+ Type string `json:"type"`
+ UUID string `json:"uuid"`
+ AccountID string `json:"account_id"`
+ Nickname string `json:"nickname"`
+ } `json:"user"`
+ }
+
+ info struct {
+ Type string `json:"type"`
+ FullName string `json:"full_name"`
+ Links struct {
+ Self href `json:"self"`
+ HTML href `json:"html"`
+ Avatar href `json:"avatar"`
+ } `json:"links"`
+ Name string `json:"name"`
+ UUID string `json:"uuid"`
+ }
)
//
@@ -446,6 +754,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,
@@ -478,6 +787,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,
@@ -505,6 +815,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,
@@ -532,6 +843,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,
@@ -559,6 +871,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,
@@ -579,6 +892,7 @@ func convertPullRequestHook(src *webhook) *scm.PullRequestHook {
Title: src.PullRequest.Title,
Body: src.PullRequest.Description,
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,
@@ -604,9 +918,136 @@ 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,
},
}
}
+
+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
+}
+
+func convertBitbucketHook(src *pipelineHook) *scm.PipelineHook {
+ if src.CommitStatus.Type == "" || src.CommitStatus.Type != "build" {
+ return nil
+ }
+ namespace, name := scm.Split(src.Repository.FullName)
+
+ return &scm.PipelineHook{
+ Repo: scm.Repository{
+ ID: src.Repository.UUID,
+ Namespace: namespace,
+ Name: name,
+ Clone: src.Repository.Links.HTML.Href, // Assuming HTML link as Clone URL
+ Branch: src.CommitStatus.RefName,
+ Private: src.Repository.IsPrivate,
+ },
+ Commit: scm.Commit{
+ Sha: src.CommitStatus.Commit.Hash,
+ Message: src.CommitStatus.Commit.Message,
+ Author: scm.Signature{
+ Name: src.CommitStatus.Commit.Author.User.DisplayName,
+ Email: extractEmail(src.CommitStatus.Commit.Author.Raw),
+ Avatar: src.CommitStatus.Commit.Author.User.Links.Avatar.Href,
+ },
+ Committer: scm.Signature{
+ Name: src.CommitStatus.Commit.Author.User.DisplayName,
+ Email: extractEmail(src.CommitStatus.Commit.Author.Raw),
+ Avatar: src.CommitStatus.Commit.Author.User.Links.Avatar.Href,
+ },
+ Link: src.CommitStatus.Commit.Links.HTML.Href,
+ },
+ Execution: scm.Execution{
+ Number: extractExecutionId(src.CommitStatus.URL),
+ Status: scm.ConvertExecutionStatus(src.CommitStatus.State),
+ Created: src.CommitStatus.CreatedOn,
+ URL: src.CommitStatus.URL,
+ },
+ Sender: scm.User{
+ Login: src.Actor.Username,
+ Name: src.Actor.DisplayName,
+ Avatar: src.Actor.Links.Avatar.Href,
+ ID: src.Actor.UUID,
+ },
+ PullRequest: scm.PullRequest{},
+ }
+}
+
+func extractExecutionId(url string) int {
+ re := regexp.MustCompile(`/results/(\d+)`)
+ match := re.FindStringSubmatch(url)
+ if len(match) > 1 {
+ id, err := strconv.Atoi(match[1])
+ if err == nil {
+ return id
+ }
+ }
+ return -1
+}
diff --git a/scm/driver/bitbucket/webhook_test.go b/scm/driver/bitbucket/webhook_test.go
index f8ecaccd7..65efed852 100644
--- a/scm/driver/bitbucket/webhook_test.go
+++ b/scm/driver/bitbucket/webhook_test.go
@@ -132,6 +132,34 @@ 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),
+ },
+ {
+ sig: "71295b197fa25f4356d2fb9965df3f2379d903d7",
+ event: "repo:commit_status_created",
+ before: "testdata/webhooks/pipeline_hook_created.json",
+ after: "testdata/webhooks/pipeline_hook_created.json.golden",
+ obj: new(scm.PipelineHook),
+ },
+ {
+ sig: "71295b197fa25f4356d2fb9965df3f2379d903d7",
+ event: "repo:commit_status_updated",
+ before: "testdata/webhooks/pipeline_hook_update.json",
+ after: "testdata/webhooks/pipeline_hook_update.json.golden",
+ obj: new(scm.PipelineHook),
+ },
}
for _, test := range tests {
diff --git a/scm/driver/gitea/git.go b/scm/driver/gitea/git.go
index 8382b8cad..aaa58134f 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
}
@@ -59,6 +59,12 @@ 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) {
+ // Gitea doesnt provide support listing based on searchTerm
+ // Hence calling the ListBranches
+ 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/gitea/org.go b/scm/driver/gitea/org.go
index 103031dca..b8fe15471 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) ListMemberships(ctx context.Context, orgNameList []string, username string, opts scm.ListOptions) ([]*scm.Membership, *scm.Response, error) {
@@ -37,6 +43,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
//
@@ -64,3 +82,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/repo.go b/scm/driver/gitea/repo.go
index 04a630591..e5cdcb09f 100644
--- a/scm/driver/gitea/repo.go
+++ b/scm/driver/gitea/repo.go
@@ -46,6 +46,18 @@ 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) 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) List2(ctx context.Context, orgSlug string, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) {
return nil, nil, scm.ErrNotSupported
}
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
+}
diff --git a/scm/driver/gitee/git.go b/scm/driver/gitee/git.go
index 6b2933b67..b3377a43c 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,
@@ -60,6 +60,12 @@ 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) {
+ // Gitee doesnt provide support listing based on searchTerm
+ // Hence calling the ListBranches
+ 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/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/gitee/repo.go b/scm/driver/gitee/repo.go
index d656d2e73..453947879 100644
--- a/scm/driver/gitee/repo.go
+++ b/scm/driver/gitee/repo.go
@@ -45,6 +45,14 @@ 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) ListNamespace(ctx context.Context, namespace string, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) {
+ return nil, nil, scm.ErrNotSupported
+}
func (s *RepositoryService) List2(ctx context.Context, orgSlug string, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) {
return nil, nil, scm.ErrNotSupported
@@ -167,7 +175,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,
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)
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/github/git.go b/scm/driver/github/git.go
index 0ef94db44..11edba432 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"),
@@ -53,6 +53,12 @@ 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) {
+ // Github doesnt provide support listing based on searchTerm
+ // Hence calling the ListBranches
+ 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{}
@@ -61,10 +67,10 @@ 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?%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) {
@@ -185,10 +191,10 @@ func convertRef(from *ref) *scm.Reference {
}
}
-func convertTagList(from []*branch) []*scm.Reference {
+func convertRefList(from []*ref) []*scm.Reference {
to := []*scm.Reference{}
for _, v := range from {
- to = append(to, convertTag(v))
+ to = append(to, convertRef(v))
}
return to
}
diff --git a/scm/driver/github/git_test.go b/scm/driver/github/git_test.go
index 65c2562c9..8d1ff4c5c 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",
}
@@ -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/pr.go b/scm/driver/github/pr.go
index 2dc083b4c..52e980937 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
@@ -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/repo.go b/scm/driver/github/repo.go
index 58e6d03bd..d32867d50 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 repositoryList2 struct {
Repositories []*repository `json:"repositories"`
}
@@ -57,6 +61,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 {
@@ -109,6 +118,30 @@ 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
+}
+
+// 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 := []*repository{}
+ res, err := s.client.do(ctx, "GET", path, nil, &out)
+ return convertRepositoryList(out), 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))
+ out := new(repositoryList)
+ res, err := s.client.do(ctx, "GET", path, nil, out)
+ return convertRepositoryList(out.Repositories), res, err
+}
+
func (s *RepositoryService) List2(ctx context.Context, installationID string, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) {
path := fmt.Sprintf("user/installations/%s/repositories?%s", installationID, encodeListOptions(opts))
out := new(repositoryList2)
@@ -215,7 +248,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{}
@@ -227,7 +260,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 {
@@ -246,7 +279,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,
@@ -299,19 +332,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/repo_test.go b/scm/driver/github/repo_test.go
index 214ceb6e5..02627c4d3 100644
--- a/scm/driver/github/repo_test.go
+++ b/scm/driver/github/repo_test.go
@@ -131,6 +131,82 @@ 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()
+
+ 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/github_app_repos.json")
+
+ client := NewDefault()
+ got, res, err := client.Repositories.(*RepositoryService).ListByInstallation(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 TestRepositoryList2(t *testing.T) {
defer gock.Off()
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
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/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/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
diff --git a/scm/driver/github/testdata/webhooks/pipeline_hook.json b/scm/driver/github/testdata/webhooks/pipeline_hook.json
new file mode 100644
index 000000000..3a7fd0c92
--- /dev/null
+++ b/scm/driver/github/testdata/webhooks/pipeline_hook.json
@@ -0,0 +1,389 @@
+{
+ "action": "in_progress",
+ "workflow_run": {
+ "id": 14030131450,
+ "name": "CI",
+ "node_id": "WFR_kwLOE_pLVc8AAAADRELQ-g",
+ "head_branch": "shivamnegi94-patch-27",
+ "head_sha": "f4229db4b70a8dadeb687f5ccce5fd327c04461a",
+ "path": ".github/workflows/blank.yml",
+ "display_title": "Update NewSre_v1.yaml",
+ "run_number": 2,
+ "event": "pull_request",
+ "status": "completed",
+ "conclusion": "success",
+ "workflow_id": 151617408,
+ "check_suite_id": 36111489428,
+ "check_suite_node_id": "CS_kwDOE_pLVc8AAAAIaGmZlA",
+ "url": "https://api.github.com/repos/shivamnegi94/testrepo/actions/runs/14030131450",
+ "html_url": "https://github.com/shivamnegi94/testrepo/actions/runs/14030131450",
+ "pull_requests": [
+ {
+ "url": "https://api.github.com/repos/shivamnegi94/testrepo/pulls/164",
+ "id": 2412967773,
+ "number": 164,
+ "head": {
+ "ref": "shivamnegi94-patch-27",
+ "sha": "f4229db4b70a8dadeb687f5ccce5fd327c04461a",
+ "repo": {
+ "id": 335170389,
+ "url": "https://api.github.com/repos/shivamnegi94/testrepo",
+ "name": "testrepo"
+ }
+ },
+ "base": {
+ "ref": "main",
+ "sha": "ded75dda298abfbf9f1900092e92b43f23bdd6d2",
+ "repo": {
+ "id": 335170389,
+ "url": "https://api.github.com/repos/shivamnegi94/testrepo",
+ "name": "testrepo"
+ }
+ }
+ }
+ ],
+ "created_at": "2025-03-24T08:03:42Z",
+ "updated_at": "2025-03-24T08:03:46Z",
+ "actor": {
+ "login": "shivamnegi94",
+ "id": 58415634,
+ "node_id": "MDQ6VXNlcjU4NDE1NjM0",
+ "avatar_url": "https://avatars.githubusercontent.com/u/58415634?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/shivamnegi94",
+ "html_url": "https://github.com/shivamnegi94",
+ "followers_url": "https://api.github.com/users/shivamnegi94/followers",
+ "following_url": "https://api.github.com/users/shivamnegi94/following{/other_user}",
+ "gists_url": "https://api.github.com/users/shivamnegi94/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/shivamnegi94/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/shivamnegi94/subscriptions",
+ "organizations_url": "https://api.github.com/users/shivamnegi94/orgs",
+ "repos_url": "https://api.github.com/users/shivamnegi94/repos",
+ "events_url": "https://api.github.com/users/shivamnegi94/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/shivamnegi94/received_events",
+ "type": "User",
+ "user_view_type": "public",
+ "site_admin": false
+ },
+ "run_attempt": 1,
+ "referenced_workflows": [
+
+ ],
+ "run_started_at": "2025-03-24T08:03:42Z",
+ "triggering_actor": {
+ "login": "shivamnegi94",
+ "id": 58415634,
+ "node_id": "MDQ6VXNlcjU4NDE1NjM0",
+ "avatar_url": "https://avatars.githubusercontent.com/u/58415634?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/shivamnegi94",
+ "html_url": "https://github.com/shivamnegi94",
+ "followers_url": "https://api.github.com/users/shivamnegi94/followers",
+ "following_url": "https://api.github.com/users/shivamnegi94/following{/other_user}",
+ "gists_url": "https://api.github.com/users/shivamnegi94/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/shivamnegi94/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/shivamnegi94/subscriptions",
+ "organizations_url": "https://api.github.com/users/shivamnegi94/orgs",
+ "repos_url": "https://api.github.com/users/shivamnegi94/repos",
+ "events_url": "https://api.github.com/users/shivamnegi94/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/shivamnegi94/received_events",
+ "type": "User",
+ "user_view_type": "public",
+ "site_admin": false
+ },
+ "jobs_url": "https://api.github.com/repos/shivamnegi94/testrepo/actions/runs/14030131450/jobs",
+ "logs_url": "https://api.github.com/repos/shivamnegi94/testrepo/actions/runs/14030131450/logs",
+ "check_suite_url": "https://api.github.com/repos/shivamnegi94/testrepo/check-suites/36111489428",
+ "artifacts_url": "https://api.github.com/repos/shivamnegi94/testrepo/actions/runs/14030131450/artifacts",
+ "cancel_url": "https://api.github.com/repos/shivamnegi94/testrepo/actions/runs/14030131450/cancel",
+ "rerun_url": "https://api.github.com/repos/shivamnegi94/testrepo/actions/runs/14030131450/rerun",
+ "previous_attempt_url": null,
+ "workflow_url": "https://api.github.com/repos/shivamnegi94/testrepo/actions/workflows/151617408",
+ "head_commit": {
+ "id": "f4229db4b70a8dadeb687f5ccce5fd327c04461a",
+ "tree_id": "36698bb567243f3d104f398e3b6e1a339570d3dc",
+ "message": "Update NewSre_v1.yaml",
+ "timestamp": "2025-03-24T08:03:33Z",
+ "author": {
+ "name": "Shivam Negi",
+ "email": "shivam.negi@harness.io"
+ },
+ "committer": {
+ "name": "GitHub",
+ "email": "noreply@github.com"
+ }
+ },
+ "repository": {
+ "id": 335170389,
+ "node_id": "MDEwOlJlcG9zaXRvcnkzMzUxNzAzODk=",
+ "name": "testrepo",
+ "full_name": "shivamnegi94/testrepo",
+ "private": false,
+ "owner": {
+ "login": "shivamnegi94",
+ "id": 58415634,
+ "node_id": "MDQ6VXNlcjU4NDE1NjM0",
+ "avatar_url": "https://avatars.githubusercontent.com/u/58415634?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/shivamnegi94",
+ "html_url": "https://github.com/shivamnegi94",
+ "followers_url": "https://api.github.com/users/shivamnegi94/followers",
+ "following_url": "https://api.github.com/users/shivamnegi94/following{/other_user}",
+ "gists_url": "https://api.github.com/users/shivamnegi94/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/shivamnegi94/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/shivamnegi94/subscriptions",
+ "organizations_url": "https://api.github.com/users/shivamnegi94/orgs",
+ "repos_url": "https://api.github.com/users/shivamnegi94/repos",
+ "events_url": "https://api.github.com/users/shivamnegi94/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/shivamnegi94/received_events",
+ "type": "User",
+ "user_view_type": "public",
+ "site_admin": false
+ },
+ "html_url": "https://github.com/shivamnegi94/testrepo",
+ "description": null,
+ "fork": false,
+ "url": "https://api.github.com/repos/shivamnegi94/testrepo",
+ "forks_url": "https://api.github.com/repos/shivamnegi94/testrepo/forks",
+ "keys_url": "https://api.github.com/repos/shivamnegi94/testrepo/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/shivamnegi94/testrepo/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/shivamnegi94/testrepo/teams",
+ "hooks_url": "https://api.github.com/repos/shivamnegi94/testrepo/hooks",
+ "issue_events_url": "https://api.github.com/repos/shivamnegi94/testrepo/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/shivamnegi94/testrepo/events",
+ "assignees_url": "https://api.github.com/repos/shivamnegi94/testrepo/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/shivamnegi94/testrepo/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/shivamnegi94/testrepo/tags",
+ "blobs_url": "https://api.github.com/repos/shivamnegi94/testrepo/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/shivamnegi94/testrepo/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/shivamnegi94/testrepo/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/shivamnegi94/testrepo/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/shivamnegi94/testrepo/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/shivamnegi94/testrepo/languages",
+ "stargazers_url": "https://api.github.com/repos/shivamnegi94/testrepo/stargazers",
+ "contributors_url": "https://api.github.com/repos/shivamnegi94/testrepo/contributors",
+ "subscribers_url": "https://api.github.com/repos/shivamnegi94/testrepo/subscribers",
+ "subscription_url": "https://api.github.com/repos/shivamnegi94/testrepo/subscription",
+ "commits_url": "https://api.github.com/repos/shivamnegi94/testrepo/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/shivamnegi94/testrepo/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/shivamnegi94/testrepo/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/shivamnegi94/testrepo/issues/comments{/number}",
+ "contents_url": "https://api.github.com/repos/shivamnegi94/testrepo/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/shivamnegi94/testrepo/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/shivamnegi94/testrepo/merges",
+ "archive_url": "https://api.github.com/repos/shivamnegi94/testrepo/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/shivamnegi94/testrepo/downloads",
+ "issues_url": "https://api.github.com/repos/shivamnegi94/testrepo/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/shivamnegi94/testrepo/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/shivamnegi94/testrepo/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/shivamnegi94/testrepo/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/shivamnegi94/testrepo/labels{/name}",
+ "releases_url": "https://api.github.com/repos/shivamnegi94/testrepo/releases{/id}",
+ "deployments_url": "https://api.github.com/repos/shivamnegi94/testrepo/deployments"
+ },
+ "head_repository": {
+ "id": 335170389,
+ "node_id": "MDEwOlJlcG9zaXRvcnkzMzUxNzAzODk=",
+ "name": "testrepo",
+ "full_name": "shivamnegi94/testrepo",
+ "private": false,
+ "owner": {
+ "login": "shivamnegi94",
+ "id": 58415634,
+ "node_id": "MDQ6VXNlcjU4NDE1NjM0",
+ "avatar_url": "https://avatars.githubusercontent.com/u/58415634?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/shivamnegi94",
+ "html_url": "https://github.com/shivamnegi94",
+ "followers_url": "https://api.github.com/users/shivamnegi94/followers",
+ "following_url": "https://api.github.com/users/shivamnegi94/following{/other_user}",
+ "gists_url": "https://api.github.com/users/shivamnegi94/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/shivamnegi94/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/shivamnegi94/subscriptions",
+ "organizations_url": "https://api.github.com/users/shivamnegi94/orgs",
+ "repos_url": "https://api.github.com/users/shivamnegi94/repos",
+ "events_url": "https://api.github.com/users/shivamnegi94/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/shivamnegi94/received_events",
+ "type": "User",
+ "user_view_type": "public",
+ "site_admin": false
+ },
+ "html_url": "https://github.com/shivamnegi94/testrepo",
+ "description": null,
+ "fork": false,
+ "url": "https://api.github.com/repos/shivamnegi94/testrepo",
+ "forks_url": "https://api.github.com/repos/shivamnegi94/testrepo/forks",
+ "keys_url": "https://api.github.com/repos/shivamnegi94/testrepo/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/shivamnegi94/testrepo/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/shivamnegi94/testrepo/teams",
+ "hooks_url": "https://api.github.com/repos/shivamnegi94/testrepo/hooks",
+ "issue_events_url": "https://api.github.com/repos/shivamnegi94/testrepo/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/shivamnegi94/testrepo/events",
+ "assignees_url": "https://api.github.com/repos/shivamnegi94/testrepo/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/shivamnegi94/testrepo/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/shivamnegi94/testrepo/tags",
+ "blobs_url": "https://api.github.com/repos/shivamnegi94/testrepo/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/shivamnegi94/testrepo/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/shivamnegi94/testrepo/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/shivamnegi94/testrepo/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/shivamnegi94/testrepo/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/shivamnegi94/testrepo/languages",
+ "stargazers_url": "https://api.github.com/repos/shivamnegi94/testrepo/stargazers",
+ "contributors_url": "https://api.github.com/repos/shivamnegi94/testrepo/contributors",
+ "subscribers_url": "https://api.github.com/repos/shivamnegi94/testrepo/subscribers",
+ "subscription_url": "https://api.github.com/repos/shivamnegi94/testrepo/subscription",
+ "commits_url": "https://api.github.com/repos/shivamnegi94/testrepo/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/shivamnegi94/testrepo/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/shivamnegi94/testrepo/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/shivamnegi94/testrepo/issues/comments{/number}",
+ "contents_url": "https://api.github.com/repos/shivamnegi94/testrepo/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/shivamnegi94/testrepo/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/shivamnegi94/testrepo/merges",
+ "archive_url": "https://api.github.com/repos/shivamnegi94/testrepo/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/shivamnegi94/testrepo/downloads",
+ "issues_url": "https://api.github.com/repos/shivamnegi94/testrepo/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/shivamnegi94/testrepo/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/shivamnegi94/testrepo/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/shivamnegi94/testrepo/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/shivamnegi94/testrepo/labels{/name}",
+ "releases_url": "https://api.github.com/repos/shivamnegi94/testrepo/releases{/id}",
+ "deployments_url": "https://api.github.com/repos/shivamnegi94/testrepo/deployments"
+ }
+ },
+ "workflow": {
+ "id": 151617408,
+ "node_id": "W_kwDOE_pLVc4JCX-A",
+ "name": "CI",
+ "path": ".github/workflows/blank.yml",
+ "state": "active",
+ "created_at": "2025-03-24T08:01:34.000Z",
+ "updated_at": "2025-03-24T08:01:34.000Z",
+ "url": "https://api.github.com/repos/shivamnegi94/testrepo/actions/workflows/151617408",
+ "html_url": "https://github.com/shivamnegi94/testrepo/blob/main/.github/workflows/blank.yml",
+ "badge_url": "https://github.com/shivamnegi94/testrepo/workflows/CI/badge.svg"
+ },
+ "repository": {
+ "id": 335170389,
+ "node_id": "MDEwOlJlcG9zaXRvcnkzMzUxNzAzODk=",
+ "name": "testrepo",
+ "full_name": "shivamnegi94/testrepo",
+ "private": false,
+ "owner": {
+ "login": "shivamnegi94",
+ "id": 58415634,
+ "node_id": "MDQ6VXNlcjU4NDE1NjM0",
+ "avatar_url": "https://avatars.githubusercontent.com/u/58415634?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/shivamnegi94",
+ "html_url": "https://github.com/shivamnegi94",
+ "followers_url": "https://api.github.com/users/shivamnegi94/followers",
+ "following_url": "https://api.github.com/users/shivamnegi94/following{/other_user}",
+ "gists_url": "https://api.github.com/users/shivamnegi94/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/shivamnegi94/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/shivamnegi94/subscriptions",
+ "organizations_url": "https://api.github.com/users/shivamnegi94/orgs",
+ "repos_url": "https://api.github.com/users/shivamnegi94/repos",
+ "events_url": "https://api.github.com/users/shivamnegi94/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/shivamnegi94/received_events",
+ "type": "User",
+ "user_view_type": "public",
+ "site_admin": false
+ },
+ "html_url": "https://github.com/shivamnegi94/testrepo",
+ "description": null,
+ "fork": false,
+ "url": "https://api.github.com/repos/shivamnegi94/testrepo",
+ "forks_url": "https://api.github.com/repos/shivamnegi94/testrepo/forks",
+ "keys_url": "https://api.github.com/repos/shivamnegi94/testrepo/keys{/key_id}",
+ "collaborators_url": "https://api.github.com/repos/shivamnegi94/testrepo/collaborators{/collaborator}",
+ "teams_url": "https://api.github.com/repos/shivamnegi94/testrepo/teams",
+ "hooks_url": "https://api.github.com/repos/shivamnegi94/testrepo/hooks",
+ "issue_events_url": "https://api.github.com/repos/shivamnegi94/testrepo/issues/events{/number}",
+ "events_url": "https://api.github.com/repos/shivamnegi94/testrepo/events",
+ "assignees_url": "https://api.github.com/repos/shivamnegi94/testrepo/assignees{/user}",
+ "branches_url": "https://api.github.com/repos/shivamnegi94/testrepo/branches{/branch}",
+ "tags_url": "https://api.github.com/repos/shivamnegi94/testrepo/tags",
+ "blobs_url": "https://api.github.com/repos/shivamnegi94/testrepo/git/blobs{/sha}",
+ "git_tags_url": "https://api.github.com/repos/shivamnegi94/testrepo/git/tags{/sha}",
+ "git_refs_url": "https://api.github.com/repos/shivamnegi94/testrepo/git/refs{/sha}",
+ "trees_url": "https://api.github.com/repos/shivamnegi94/testrepo/git/trees{/sha}",
+ "statuses_url": "https://api.github.com/repos/shivamnegi94/testrepo/statuses/{sha}",
+ "languages_url": "https://api.github.com/repos/shivamnegi94/testrepo/languages",
+ "stargazers_url": "https://api.github.com/repos/shivamnegi94/testrepo/stargazers",
+ "contributors_url": "https://api.github.com/repos/shivamnegi94/testrepo/contributors",
+ "subscribers_url": "https://api.github.com/repos/shivamnegi94/testrepo/subscribers",
+ "subscription_url": "https://api.github.com/repos/shivamnegi94/testrepo/subscription",
+ "commits_url": "https://api.github.com/repos/shivamnegi94/testrepo/commits{/sha}",
+ "git_commits_url": "https://api.github.com/repos/shivamnegi94/testrepo/git/commits{/sha}",
+ "comments_url": "https://api.github.com/repos/shivamnegi94/testrepo/comments{/number}",
+ "issue_comment_url": "https://api.github.com/repos/shivamnegi94/testrepo/issues/comments{/number}",
+ "contents_url": "https://api.github.com/repos/shivamnegi94/testrepo/contents/{+path}",
+ "compare_url": "https://api.github.com/repos/shivamnegi94/testrepo/compare/{base}...{head}",
+ "merges_url": "https://api.github.com/repos/shivamnegi94/testrepo/merges",
+ "archive_url": "https://api.github.com/repos/shivamnegi94/testrepo/{archive_format}{/ref}",
+ "downloads_url": "https://api.github.com/repos/shivamnegi94/testrepo/downloads",
+ "issues_url": "https://api.github.com/repos/shivamnegi94/testrepo/issues{/number}",
+ "pulls_url": "https://api.github.com/repos/shivamnegi94/testrepo/pulls{/number}",
+ "milestones_url": "https://api.github.com/repos/shivamnegi94/testrepo/milestones{/number}",
+ "notifications_url": "https://api.github.com/repos/shivamnegi94/testrepo/notifications{?since,all,participating}",
+ "labels_url": "https://api.github.com/repos/shivamnegi94/testrepo/labels{/name}",
+ "releases_url": "https://api.github.com/repos/shivamnegi94/testrepo/releases{/id}",
+ "deployments_url": "https://api.github.com/repos/shivamnegi94/testrepo/deployments",
+ "created_at": "2021-02-02T04:41:22Z",
+ "updated_at": "2025-03-24T08:01:37Z",
+ "pushed_at": "2025-03-24T08:03:33Z",
+ "git_url": "git://github.com/shivamnegi94/testrepo.git",
+ "ssh_url": "git@github.com:shivamnegi94/testrepo.git",
+ "clone_url": "https://github.com/shivamnegi94/testrepo.git",
+ "svn_url": "https://github.com/shivamnegi94/testrepo",
+ "homepage": null,
+ "size": 209,
+ "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": 56,
+ "license": null,
+ "allow_forking": true,
+ "is_template": false,
+ "web_commit_signoff_required": false,
+ "topics": [
+
+ ],
+ "visibility": "public",
+ "forks": 0,
+ "open_issues": 56,
+ "watchers": 0,
+ "default_branch": "main"
+ },
+ "sender": {
+ "login": "shivamnegi94",
+ "id": 58415634,
+ "node_id": "MDQ6VXNlcjU4NDE1NjM0",
+ "avatar_url": "https://avatars.githubusercontent.com/u/58415634?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/shivamnegi94",
+ "html_url": "https://github.com/shivamnegi94",
+ "followers_url": "https://api.github.com/users/shivamnegi94/followers",
+ "following_url": "https://api.github.com/users/shivamnegi94/following{/other_user}",
+ "gists_url": "https://api.github.com/users/shivamnegi94/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/shivamnegi94/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/shivamnegi94/subscriptions",
+ "organizations_url": "https://api.github.com/users/shivamnegi94/orgs",
+ "repos_url": "https://api.github.com/users/shivamnegi94/repos",
+ "events_url": "https://api.github.com/users/shivamnegi94/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/shivamnegi94/received_events",
+ "type": "User",
+ "user_view_type": "public",
+ "site_admin": false
+ }
+}
\ No newline at end of file
diff --git a/scm/driver/github/testdata/webhooks/pipeline_hook.json.golden b/scm/driver/github/testdata/webhooks/pipeline_hook.json.golden
new file mode 100644
index 000000000..b56869de0
--- /dev/null
+++ b/scm/driver/github/testdata/webhooks/pipeline_hook.json.golden
@@ -0,0 +1,50 @@
+{
+ "Repo": {
+ "ID": "335170389",
+ "Namespace": "shivamnegi94",
+ "Name": "testrepo",
+ "Clone": "https://github.com/shivamnegi94/testrepo.git",
+ "CloneSSH": "git@github.com:shivamnegi94/testrepo.git",
+ "Link": "https://github.com/shivamnegi94/testrepo",
+ "Branch": "main",
+ "Created": "2021-02-02T04:41:22Z",
+ "Updated": "2025-03-24T08:01:37Z",
+ "Private": false,
+ "Visibility": 1,
+ "Perm": {}
+ },
+ "Commit": {
+ "Sha": "f4229db4b70a8dadeb687f5ccce5fd327c04461a",
+ "Message": "Update NewSre_v1.yaml",
+ "Author": {
+ "Name": "Shivam Negi",
+ "Email": "shivam.negi@harness.io"
+ },
+ "Committer": {
+ "Name": "GitHub",
+ "Email": "noreply@github.com"
+ }
+ },
+ "Execution": {
+ "Number": 2,
+ "Status": "success",
+ "Created": "2025-03-24T08:03:42Z",
+ "URL": "https://api.github.com/repos/shivamnegi94/testrepo/actions/runs/14030131450"
+ },
+ "Sender": {
+ "Login": "shivamnegi94",
+ "Avatar": "https://avatars.githubusercontent.com/u/58415634?v=4"
+ },
+ "PullRequest": {
+ "Number": 164,
+ "Sha": "f4229db4b70a8dadeb687f5ccce5fd327c04461a",
+ "Ref": "shivamnegi94-patch-27",
+ "Source": "shivamnegi94-patch-27",
+ "Target": "main",
+ "Link": "https://api.github.com/repos/shivamnegi94/testrepo/pulls/164",
+ "Created": "2025-03-24T08:03:42Z",
+ "Draft": false,
+ "Closed": false,
+ "Merged": false
+ }
+}
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..653a28b1e
--- /dev/null
+++ b/scm/driver/github/testdata/webhooks/pr_ready_for_review.json.golden
@@ -0,0 +1,55 @@
+{
+ "Action": "review_ready",
+ "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/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/user.go b/scm/driver/github/user.go
index dfccdc8c9..db34ade76 100644
--- a/scm/driver/github/user.go
+++ b/scm/driver/github/user.go
@@ -31,16 +31,8 @@ func (s *userService) FindLogin(ctx context.Context, login string) (*scm.User, *
}
func (s *userService) FindEmail(ctx context.Context) (string, *scm.Response, error) {
- out := []*email{}
- res, err := s.client.do(ctx, "GET", "user/emails", nil, &out)
- email := ""
- for i := range out {
- if out[i].Primary {
- email = out[i].Email
- break
- }
- }
- return 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) {
@@ -78,6 +70,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 b0b121c8e..a197c762a 100644
--- a/scm/driver/github/user_test.go
+++ b/scm/driver/github/user_test.go
@@ -87,6 +87,7 @@ func TestUserEmailFind(t *testing.T) {
defer gock.Off()
gock.New("https://api.github.com").
+ Get("/user/emails").
Get("/user/emails").
Reply(200).
Type("application/json").
@@ -94,7 +95,7 @@ func TestUserEmailFind(t *testing.T) {
SetHeader("X-RateLimit-Limit", "60").
SetHeader("X-RateLimit-Remaining", "59").
SetHeader("X-RateLimit-Reset", "1512076018").
- File("testdata/useremails.json")
+ File("testdata/emails.json")
client := NewDefault()
result, res, err := client.Users.FindEmail(context.Background())
diff --git a/scm/driver/github/util.go b/scm/driver/github/util.go
index 5d5fb4741..24a0c858c 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/github/webhook.go b/scm/driver/github/webhook.go
index 2d2dae333..a4d7265ea 100644
--- a/scm/driver/github/webhook.go
+++ b/scm/driver/github/webhook.go
@@ -48,6 +48,10 @@ 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)
+ case "workflow_run":
+ hook, err = s.parsePipelineHook(data)
default:
return nil, scm.ErrUnknownEvent
}
@@ -172,7 +176,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.ActionReviewReady
+ case "assigned", "unassigned", "review_requested", "review_request_removed", "locked", "unlocked":
dst.Action = scm.ActionUnknown
default:
dst.Action = scm.ActionUnknown
@@ -180,6 +186,90 @@ func (s *webhookService) parsePullRequestHook(data []byte) (scm.Webhook, error)
return dst, nil
}
+func (s *webhookService) parsePipelineHook(data []byte) (scm.Webhook, error) {
+ src := new(pipelineHook)
+ err := json.Unmarshal(data, src)
+ if err != nil {
+ return nil, err
+ }
+ dst, err := convertPipelineHook(src), nil
+ return dst, nil
+}
+
+func convertPipelineHook(src *pipelineHook) *scm.PipelineHook {
+ pr := scm.PullRequest{}
+ if len(src.WorkflowRun.PullRequests) > 0 {
+ pr = scm.PullRequest{
+ Number: src.WorkflowRun.PullRequests[0].Number,
+ Sha: src.WorkflowRun.PullRequests[0].Head.SHA,
+ Ref: src.WorkflowRun.PullRequests[0].Head.Ref,
+ Source: src.WorkflowRun.PullRequests[0].Head.Ref,
+ Target: src.WorkflowRun.PullRequests[0].Base.Ref,
+ Link: src.WorkflowRun.PullRequests[0].URL,
+ Created: src.WorkflowRun.CreatedAt,
+ }
+ }
+
+ var execution_status string
+ if src.WorkflowRun.Status == "completed" {
+ execution_status = src.WorkflowRun.Conclusion.String
+ } else {
+ execution_status = src.WorkflowRun.Status
+ }
+
+ return &scm.PipelineHook{
+ Repo: *convertRepository(&src.Repository),
+ Commit: scm.Commit{
+ Sha: src.WorkflowRun.HeadCommit.ID,
+ Message: src.WorkflowRun.HeadCommit.Message,
+ Author: scm.Signature{
+ Name: src.WorkflowRun.HeadCommit.Author.Name,
+ Email: src.WorkflowRun.HeadCommit.Author.Email,
+ },
+ Committer: scm.Signature{
+ Name: src.WorkflowRun.HeadCommit.Committer.Name,
+ Email: src.WorkflowRun.HeadCommit.Committer.Email,
+ },
+ },
+ Execution: scm.Execution{
+ Number: int(src.WorkflowRun.RunNumber),
+ Status: scm.ConvertExecutionStatus(execution_status),
+ Created: src.WorkflowRun.CreatedAt,
+ URL: src.WorkflowRun.URL,
+ },
+ Sender: *convertUser(&src.Sender),
+ PullRequest: pr,
+ }
+}
+
+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
+}
+
func (s *webhookService) parsePingHook(data []byte) (scm.Webhook, error) {
src := new(pingHook)
err := json.Unmarshal(data, src)
@@ -319,6 +409,99 @@ 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"`
+ }
+
+ pipelineHook struct {
+ Action string `json:"action"`
+ Sender user
+ WorkflowRun struct {
+ ID int64 `json:"id"`
+ Name string `json:"name"`
+ NodeID string `json:"node_id"`
+ HeadBranch string `json:"head_branch"`
+ HeadSHA string `json:"head_sha"`
+ Path string `json:"path"`
+ DisplayTitle string `json:"display_title"`
+ RunNumber int `json:"run_number"`
+ Event string `json:"event"`
+ Status string `json:"status"`
+ Conclusion null.String `json:"conclusion"`
+ WorkflowID int64 `json:"workflow_id"`
+ CheckSuiteID int64 `json:"check_suite_id"`
+ CheckSuiteNodeID string `json:"check_suite_node_id"`
+ URL string `json:"url"`
+ HtmlURL string `json:"html_url"`
+ PullRequests []struct {
+ URL string `json:"url"`
+ ID int64 `json:"id"`
+ Number int `json:"number"`
+ Head gitRef `json:"head"`
+ Base gitRef `json:"base"`
+ } `json:"pull_requests"`
+ CreatedAt time.Time `json:"created_at"`
+ UpdatedAt time.Time `json:"updated_at"`
+ Actor owner `json:"actor"`
+ RunAttempt int `json:"run_attempt"`
+ RunStartedAt time.Time `json:"run_started_at"`
+ TriggeringActor owner `json:"triggering_actor"`
+ JobsURL string `json:"jobs_url"`
+ LogsURL string `json:"logs_url"`
+ CheckSuiteURL string `json:"check_suite_url"`
+ ArtifactsURL string `json:"artifacts_url"`
+ CancelURL string `json:"cancel_url"`
+ RerunURL string `json:"rerun_url"`
+ PreviousAttemptURL null.String `json:"previous_attempt_url"`
+ WorkflowURL string `json:"workflow_url"`
+ HeadCommit struct {
+ ID string `json:"id"`
+ TreeID string `json:"tree_id"`
+ Message string `json:"message"`
+ Timestamp time.Time `json:"timestamp"`
+ Author author `json:"author"`
+ Committer author `json:"committer"`
+ } `json:"head_commit"`
+ } `json:"workflow_run"`
+ Repository repository `json:"repository"`
+ }
+
+ gitRef struct {
+ Ref string `json:"ref"`
+ SHA string `json:"sha"`
+ Repo repository `json:"repo"`
+ }
+
+ owner struct {
+ Login string `json:"login"`
+ ID int64 `json:"id"`
+ NodeID string `json:"node_id"`
+ AvatarURL string `json:"avatar_url"`
+ HTMLURL string `json:"html_url"`
+ Type string `json:"type"`
+ SiteAdmin bool `json:"site_admin"`
+ }
+
+ author struct {
+ Name string `json:"name"`
+ Email string `json:"email"`
+ }
)
//
@@ -378,7 +561,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,
@@ -405,7 +588,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,
@@ -425,7 +608,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,
@@ -443,7 +626,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,
@@ -469,7 +652,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,
@@ -518,7 +701,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,
@@ -536,6 +719,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: scm.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..f30804fa3 100644
--- a/scm/driver/github/webhook_test.go
+++ b/scm/driver/github/webhook_test.go
@@ -25,9 +25,7 @@ func TestWebhooks(t *testing.T) {
after string
obj interface{}
}{
- //
// push events
- //
// push hooks
{
@@ -126,6 +124,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,6 +190,57 @@ 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),
+ },
+ {
+ event: "workflow_run",
+ before: "testdata/webhooks/pipeline_hook.json",
+ after: "testdata/webhooks/pipeline_hook.json.golden",
+ obj: new(scm.PipelineHook),
+ },
}
for _, test := range tests {
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)
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/gitlab/git.go b/scm/driver/gitlab/git.go
index e9a1cffef..3bc37ef7d 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"
@@ -16,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,
@@ -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)
@@ -53,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 6315b85b9..49fefee66 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",
}
@@ -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/branches_filter.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/branches_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 TestGitListTags(t *testing.T) {
defer gock.Off()
diff --git a/scm/driver/gitlab/pr.go b/scm/driver/gitlab/pr.go
index 2d4d46720..f161cf28b 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
}
@@ -99,13 +108,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"`
@@ -118,9 +128,9 @@ type pr struct {
Closed time.Time
Labels []string `json:"labels"`
DiffRefs struct {
- BaseCommit string `json:"base_sha"`
- HeadCommit string `json:"head_sha"`
- StartCommit string `json:"start_sha"`
+ BaseSha string `json:"base_sha"`
+ HeadSha string `json:"head_sha"`
+ StartSha string `json:"start_sha"`
} `json:"diff_refs"`
}
type changes struct {
@@ -159,6 +169,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{
@@ -169,8 +180,14 @@ func convertPullRequest(from *pr) *scm.PullRequest {
Created: from.Created,
Updated: from.Updated,
Labels: labels,
- Base: scm.Reference{Name: from.TargetBranch, Sha: from.DiffRefs.BaseCommit},
- Head: scm.Reference{Name: from.SourceBranch, Sha: from.DiffRefs.HeadCommit},
+ Base: scm.Reference{
+ Name: from.TargetBranch,
+ Sha: from.DiffRefs.BaseSha,
+ },
+ Head: scm.Reference{
+ Name: from.SourceBranch,
+ Sha: from.DiffRefs.HeadSha,
+ },
}
}
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).
diff --git a/scm/driver/gitlab/repo.go b/scm/driver/gitlab/repo.go
index b6af634be..bd8314aa7 100644
--- a/scm/driver/gitlab/repo.go
+++ b/scm/driver/gitlab/repo.go
@@ -94,6 +94,21 @@ 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) 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) List2(ctx context.Context, orgSlug string, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) {
return nil, nil, scm.ErrNotSupported
}
@@ -147,6 +162,9 @@ func (s *repositoryService) CreateHook(ctx context.Context, repo string, input *
if input.Events.Tag {
params.Set("tag_push_events", "true")
}
+ if input.Events.Pipeline {
+ params.Set("pipeline_events", "true")
+ }
path := fmt.Sprintf("api/v4/projects/%s/hooks?%s", encode(repo), params.Encode())
out := new(hook)
@@ -175,7 +193,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{}
@@ -185,7 +203,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{
@@ -194,8 +212,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,
@@ -314,28 +332,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 48e21db6b..65c175176 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()
@@ -482,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/driver/gitlab/testdata/branches_filter.json b/scm/driver/gitlab/testdata/branches_filter.json
new file mode 100644
index 000000000..c5072e736
--- /dev/null
+++ b/scm/driver/gitlab/testdata/branches_filter.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/branches_filter.json.golden b/scm/driver/gitlab/testdata/branches_filter.json.golden
new file mode 100644
index 000000000..d6f1a9210
--- /dev/null
+++ b/scm/driver/gitlab/testdata/branches_filter.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/testdata/merge.json.golden b/scm/driver/gitlab/testdata/merge.json.golden
index cd2e71b11..0dee18b16 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 05680dbec..8b67a09bd 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/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/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 1c611bcf2..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": "2017-12-10T08:28:36-08:00",
+ "Date": "2017-12-10T08:28:36Z",
"Login": "",
"Avatar": ""
},
"Committer": {
"Name": "Sid Sijbrandij",
"Email": "noreply@gitlab.com",
- "Date": "2017-12-10T08:28:36-08:00",
+ "Date": "2017-12-10T08:28:36Z",
"Login": "",
"Avatar": ""
},
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..dcc3e2448
--- /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/merge_requests/1",
+ "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/pipeline_hook.json b/scm/driver/gitlab/testdata/webhooks/pipeline_hook.json
new file mode 100644
index 000000000..6deec0b0e
--- /dev/null
+++ b/scm/driver/gitlab/testdata/webhooks/pipeline_hook.json
@@ -0,0 +1,115 @@
+{
+ "object_kind": "pipeline",
+ "object_attributes":{
+ "id": 31,
+ "iid": 3,
+ "name": "Pipeline for branch: master",
+ "ref": "master",
+ "tag": false,
+ "sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
+ "before_sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
+ "source": "merge_request_event",
+ "status": "success",
+ "stages":[
+ "build",
+ "test",
+ "deploy"
+ ],
+ "created_at": "2016-08-12 15:23:28 UTC",
+ "finished_at": "2016-08-12 15:26:29 UTC",
+ "duration": 63,
+ "variables": [
+ {
+ "key": "NESTOR_PROD_ENVIRONMENT",
+ "value": "us-west-1"
+ }
+ ],
+ "url": "http://example.com/gitlab-org/gitlab-test/-/pipelines/31"
+ },
+ "merge_request": {
+ "id": 371997275,
+ "iid": 15,
+ "title": "Edit test.txt",
+ "source_branch": "shivamnegi94-main-patch-62619",
+ "source_project_id": 27743392,
+ "target_branch": "main",
+ "target_project_id": 27743392,
+ "state": "opened",
+ "merge_status": "can_be_merged",
+ "detailed_merge_status": "mergeable",
+ "url": "https://gitlab.com/shivamnegi94/test/-/merge_requests/15"
+ },
+ "user":{
+ "id": 1,
+ "name": "Administrator",
+ "username": "root",
+ "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon",
+ "email": "user_email@gitlab.com"
+ },
+ "project":{
+ "id": 1,
+ "name": "Gitlab Test",
+ "description": "Atque in sunt eos similique dolores voluptatem.",
+ "web_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test",
+ "avatar_url": null,
+ "git_ssh_url": "git@192.168.64.1:gitlab-org/gitlab-test.git",
+ "git_http_url": "http://192.168.64.1:3005/gitlab-org/gitlab-test.git",
+ "namespace": "Gitlab Org",
+ "visibility_level": 20,
+ "path_with_namespace": "gitlab-org/gitlab-test",
+ "default_branch": "master"
+ },
+ "commit":{
+ "id": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
+ "message": "test\n",
+ "timestamp": "2016-08-12T17:23:21+02:00",
+ "url": "http://example.com/gitlab-org/gitlab-test/commit/bcbb5ec396a2c0f828686f14fac9b80b780504f2",
+ "author":{
+ "name": "User",
+ "email": "user@gitlab.com"
+ }
+ },
+ "source_pipeline":{
+ "project":{
+ "id": 41,
+ "web_url": "https://gitlab.example.com/gitlab-org/upstream-project",
+ "path_with_namespace": "gitlab-org/upstream-project"
+ },
+ "pipeline_id": 30,
+ "job_id": 3401
+ },
+ "builds":[
+ {
+ "id": 380,
+ "stage": "deploy",
+ "name": "production",
+ "status": "skipped",
+ "created_at": "2016-08-12 15:23:28 UTC",
+ "started_at": null,
+ "finished_at": null,
+ "duration": null,
+ "queued_duration": null,
+ "failure_reason": null,
+ "when": "manual",
+ "manual": true,
+ "allow_failure": false,
+ "user":{
+ "id": 1,
+ "name": "Administrator",
+ "username": "root",
+ "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon",
+ "email": "admin@example.com"
+ },
+ "runner": null,
+ "artifacts_file":{
+ "filename": null,
+ "size": null
+ },
+ "environment": {
+ "name": "production",
+ "action": "start",
+ "deployment_tier": "production"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/scm/driver/gitlab/testdata/webhooks/pipeline_hook.json.golden b/scm/driver/gitlab/testdata/webhooks/pipeline_hook.json.golden
new file mode 100644
index 000000000..8e70f4b6b
--- /dev/null
+++ b/scm/driver/gitlab/testdata/webhooks/pipeline_hook.json.golden
@@ -0,0 +1,50 @@
+{
+ "repo": {
+ "id": "1",
+ "namespace": "gitlab-org",
+ "name": "gitlab-test",
+ "clone": "http://192.168.64.1:3005/gitlab-org/gitlab-test.git",
+ "cloneSSH": "git@192.168.64.1:gitlab-org/gitlab-test.git",
+ "link": "http://192.168.64.1:3005/gitlab-org/gitlab-test",
+ "branch": "master",
+ "private": false
+ },
+ "commit": {
+ "sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
+ "message": "test\n",
+ "author": {
+ "name": "User",
+ "email": "user@gitlab.com"
+ },
+ "committer": {
+ "name": "User",
+ "email": "user@gitlab.com"
+ },
+ "link": "http://example.com/gitlab-org/gitlab-test/commit/bcbb5ec396a2c0f828686f14fac9b80b780504f2"
+ },
+ "Execution": {
+ "Number": 31,
+ "status": "success",
+ "Created": "2016-08-12T15:23:28Z",
+ "URL": "http://example.com/gitlab-org/gitlab-test/-/pipelines/31"
+ },
+ "sender": {
+ "login": "root",
+ "name": "Administrator",
+ "email": "user_email@gitlab.com",
+ "avatar": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80&d=identicon"
+ },
+ "PullRequest": {
+ "Number": 371997275,
+ "Title": "Edit test.txt",
+ "Sha": "bcbb5ec396a2c0f828686f14fac9b80b780504f2",
+ "Ref": "master",
+ "Source": "shivamnegi94-main-patch-62619",
+ "Target": "main",
+ "Link": "https://gitlab.com/shivamnegi94/test/-/merge_requests/15",
+ "Created": "2016-08-12T15:23:28Z",
+ "Draft": false,
+ "Closed": false,
+ "Merged": false
+ }
+}
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/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..059b6bbd7
--- /dev/null
+++ b/scm/driver/gitlab/testdata/webhooks/pull_request_review_ready.json.golden
@@ -0,0 +1,44 @@
+{
+ "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",
+ "Draft": true,
+ "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/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 d7829ecc3..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": "2017-12-10T08:26:38-08:00",
+ "Date": "2017-12-10T08:26:38Z",
"Login": "",
"Avatar": ""
},
"Committer": {
"Name": "Sid Sijbrandij",
"Email": "noreply@gitlab.com",
- "Date": "2017-12-10T08:26:38-08:00",
+ "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 381bd190e..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": "2017-12-10T08:26:38-08:00",
+ "Date": "2017-12-10T08:26:38Z",
"Login": "",
"Avatar": ""
},
"Committer": {
"Name": "Sid Sijbrandij",
"Email": "noreply@gitlab.com",
- "Date": "2017-12-10T08:26:38-08:00",
+ "Date": "2017-12-10T08:26:38Z",
"Login": "",
"Avatar": ""
},
diff --git a/scm/driver/gitlab/user.go b/scm/driver/gitlab/user.go
index e57a73a29..7f182bfca 100644
--- a/scm/driver/gitlab/user.go
+++ b/scm/driver/gitlab/user.go
@@ -49,7 +49,7 @@ func (s *userService) ListEmail(ctx context.Context, opts scm.ListOptions) ([]*s
}
type user struct {
- ID int `json:"ID"`
+ ID int `json:"id"`
Username string `json:"username"`
Name string `json:"name"`
Email null.String `json:"email"`
diff --git a/scm/driver/gitlab/util.go b/scm/driver/gitlab/util.go
index 05670bcd2..eb3f06893 100644
--- a/scm/driver/gitlab/util.go
+++ b/scm/driver/gitlab/util.go
@@ -24,6 +24,22 @@ 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 != (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()
+}
+
func encodeListOptions(opts scm.ListOptions) string {
params := url.Values{}
if opts.Page != 0 {
@@ -47,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/gitlab/webhook.go b/scm/driver/gitlab/webhook.go
index 439b6ac72..c76f33f79 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"
"github.com/drone/go-scm/scm/driver/internal/null"
@@ -36,6 +37,12 @@ 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)
+ case "System Hook":
+ hook, err = parseSystemHook(data)
+ case "Pipeline Hook":
+ return parsePipelineHook(data)
default:
return nil, scm.ErrUnknownEvent
}
@@ -60,6 +67,49 @@ 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)
+ if err != nil {
+ return nil, err
+ }
+ dst, err := convertCommentHook(src)
+ if err != nil {
+ return nil, err
+ }
+ return dst, nil
+}
+
+func parsePipelineHook(data []byte) (scm.Webhook, error) {
+ src := new(pipelineHook)
+ err := json.Unmarshal(data, src)
+ if err != nil {
+ return nil, err
+ }
+ dst, err := convertPipelineHook(src), nil
+ return dst, nil
+}
+
func parsePushHook(data []byte) (scm.Webhook, error) {
src := new(pushHook)
err := json.Unmarshal(data, src)
@@ -205,6 +255,78 @@ 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.MergeRequest.URL,
+ Draft: src.MergeRequest.WorkInProgress,
+ 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
@@ -251,6 +373,9 @@ func convertPullRequestHook(src *pullRequestHook) *scm.PullRequestHook {
action = scm.ActionMerge
case "update":
action = scm.ActionSync
+ if src.Changes.Draft.Previous.Bool == false && src.Changes.Draft.Current.Bool == true {
+ action = scm.ActionReviewReady
+ }
}
fork := scm.Join(
src.ObjectAttributes.Source.Namespace,
@@ -269,10 +394,9 @@ 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,
- // Updated : src.ObjectAttributes.UpdatedAt, // 2017-12-10 17:01:11 UTC
Author: scm.User{
Login: src.User.Username,
Name: src.User.Name,
@@ -299,7 +423,70 @@ 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
+}
+
+func convertPipelineHook(src *pipelineHook) *scm.PipelineHook {
+ namespace, name := scm.Split(src.Project.PathWithNamespace)
+ return &scm.PipelineHook{
+ Repo: scm.Repository{
+ ID: strconv.Itoa(src.Project.ID),
+ Namespace: namespace,
+ Name: name,
+ Clone: src.Project.GitHTTPURL,
+ CloneSSH: src.Project.GitSSHURL,
+ Link: src.Project.WebURL,
+ Branch: src.Project.DefaultBranch,
+ Private: false,
+ },
+ Commit: scm.Commit{
+ Sha: src.ObjectAttributes.SHA,
+ Message: src.Commit.Message,
+ Author: scm.Signature{
+ Name: src.Commit.Author.Name,
+ Email: src.Commit.Author.Email,
+ },
+ Committer: scm.Signature{
+ Name: src.Commit.Author.Name,
+ Email: src.Commit.Author.Email,
+ },
+ Link: src.Commit.URL,
+ },
+ Execution: scm.Execution{
+ Number: src.ObjectAttributes.ID,
+ Status: scm.ConvertExecutionStatus(src.ObjectAttributes.Status),
+ Created: parseTimeString(src.ObjectAttributes.CreatedAt),
+ URL: src.ObjectAttributes.URL,
+ },
+ Sender: scm.User{
+ Login: src.User.Username,
+ Name: src.User.Name,
+ Email: src.User.Email,
+ Avatar: src.User.AvatarURL,
+ },
+ PullRequest: scm.PullRequest{
+ Number: src.MergeRequest.ID,
+ Title: src.MergeRequest.Title,
+ Sha: src.ObjectAttributes.SHA,
+ Ref: src.ObjectAttributes.Ref,
+ Source: src.MergeRequest.SourceBranch,
+ Target: src.MergeRequest.TargetBranch,
+ Link: src.MergeRequest.URL,
+ Created: parseTimeString(src.ObjectAttributes.CreatedAt),
+ },
+ }
+}
+
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"`
@@ -359,13 +546,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"`
@@ -384,56 +568,29 @@ type (
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"`
+ 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 {
Name string `json:"name"`
@@ -442,34 +599,44 @@ type (
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 {
+ 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"`
@@ -515,10 +682,18 @@ 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"`
}
@@ -778,6 +953,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"`
@@ -786,4 +965,131 @@ type (
Homepage string `json:"homepage"`
} `json:"repository"`
}
+
+ pipelineHook struct {
+ ObjectKind string `json:"object_kind"`
+ ObjectAttributes struct {
+ ID int `json:"id"`
+ IID int `json:"iid"`
+ Name string `json:"name"`
+ Ref string `json:"ref"`
+ Tag bool `json:"tag"`
+ SHA string `json:"sha"`
+ BeforeSHA string `json:"before_sha"`
+ Source string `json:"source"`
+ Status string `json:"status"`
+ Stages []string `json:"stages"`
+ CreatedAt string `json:"created_at"`
+ FinishedAt string `json:"finished_at"`
+ Duration int `json:"duration"`
+ Variables []variable `json:"variables"`
+ URL string `json:"url"`
+ } `json:"object_attributes"`
+ MergeRequest struct {
+ ID int `json:"id"`
+ IID int `json:"iid"`
+ Title string `json:"title"`
+ SourceBranch string `json:"source_branch"`
+ SourceProjectID int `json:"source_project_id"`
+ TargetBranch string `json:"target_branch"`
+ TargetProjectID int `json:"target_project_id"`
+ State string `json:"state"`
+ MergeStatus string `json:"merge_status"`
+ DetailedMergeStatus string `json:"detailed_merge_status"`
+ URL string `json:"url"`
+ } `json:"merge_request"`
+ User struct {
+ ID int `json:"id"`
+ Name string `json:"name"`
+ Username string `json:"username"`
+ AvatarURL string `json:"avatar_url"`
+ Email string `json:"email"`
+ } `json:"user"`
+ Project struct {
+ ID int `json:"id"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ WebURL string `json:"web_url"`
+ AvatarURL null.String `json:"avatar_url"`
+ GitSSHURL string `json:"git_ssh_url"`
+ GitHTTPURL string `json:"git_http_url"`
+ Namespace string `json:"namespace"`
+ VisibilityLevel int `json:"visibility_level"`
+ PathWithNamespace string `json:"path_with_namespace"`
+ DefaultBranch string `json:"default_branch"`
+ } `json:"project"`
+ Commit struct {
+ ID string `json:"id"`
+ Message string `json:"message"`
+ Timestamp string `json:"timestamp"`
+ URL string `json:"url"`
+ Author author `json:"author"`
+ } `json:"commit"`
+ SourcePipeline struct {
+ Project struct {
+ ID int `json:"id"`
+ WebURL string `json:"web_url"`
+ PathWithNamespace string `json:"path_with_namespace"`
+ } `json:"project"`
+ PipelineID int `json:"pipeline_id"`
+ JobID int `json:"job_id"`
+ } `json:"source_pipeline"`
+ Builds []build `json:"builds"`
+ }
+
+ variable struct {
+ Key string `json:"key"`
+ Value string `json:"value"`
+ }
+
+ author struct {
+ Name string `json:"name"`
+ Email string `json:"email"`
+ }
+
+ build struct {
+ ID int `json:"id"`
+ Stage string `json:"stage"`
+ Name string `json:"name"`
+ Status string `json:"status"`
+ CreatedAt string `json:"created_at"`
+ StartedAt null.String `json:"started_at"`
+ FinishedAt null.String `json:"finished_at"`
+ Duration float64 `json:"duration"`
+ QueuedDuration float64 `json:"queued_duration"`
+ FailureReason null.String `json:"failure_reason"`
+ When string `json:"when"`
+ Manual bool `json:"manual"`
+ AllowFailure bool `json:"allow_failure"`
+ User struct {
+ ID int `json:"id"`
+ Name string `json:"name"`
+ Username string `json:"username"`
+ AvatarURL string `json:"avatar_url"`
+ Email string `json:"email"`
+ } `json:"user"`
+ Runner runner `json:"runner"`
+ ArtifactsFile artifacts `json:"artifacts_file"`
+ Environment environment `json:"environment"`
+ }
+
+ runner struct {
+ ID int `json:"id"`
+ Description string `json:"description"`
+ Active bool `json:"active"`
+ RunnerType string `json:"runner_type"`
+ IsShared bool `json:"is_shared"`
+ Tags []string `json:"tags"`
+ }
+
+ artifacts struct {
+ Filename null.String `json:"filename"`
+ Size null.Int `json:"size"`
+ }
+
+ environment struct {
+ Name string `json:"name"`
+ Action string `json:"action"`
+ DeploymentTier string `json:"deployment_tier"`
+ }
)
diff --git a/scm/driver/gitlab/webhook_test.go b/scm/driver/gitlab/webhook_test.go
index 1f153f20d..e238a615c 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",
@@ -97,6 +134,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",
@@ -109,13 +152,49 @@ 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),
- // },
+ {
+ 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",
+ before: "testdata/webhooks/merge_request_comment_create.json",
+ 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),
+ },
+ {
+ event: "Pipeline Hook",
+ before: "testdata/webhooks/pipeline_hook.json",
+ after: "testdata/webhooks/pipeline_hook.json.golden",
+ obj: new(scm.PipelineHook),
+ },
}
for _, test := range tests {
diff --git a/scm/driver/gogs/git.go b/scm/driver/gogs/git.go
index 2cb3c687e..30103cc7b 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
}
@@ -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)
@@ -45,6 +54,12 @@ 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) {
+ // Gogs doesnt provide support listing based on searchTerm
+ // Hence calling the ListBranches
+ 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/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{})
diff --git a/scm/driver/gogs/repo.go b/scm/driver/gogs/repo.go
index f7ee5b2eb..c9930b858 100644
--- a/scm/driver/gogs/repo.go
+++ b/scm/driver/gogs/repo.go
@@ -45,6 +45,18 @@ 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) 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) List2(ctx context.Context, orgSlug string, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) {
return nil, nil, scm.ErrNotSupported
}
diff --git a/scm/driver/harness/content.go b/scm/driver/harness/content.go
new file mode 100644
index 000000000..16159cb53
--- /dev/null
+++ b/scm/driver/harness/content.go
@@ -0,0 +1,255 @@
+// 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) {
+ 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
+ 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) {
+ 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,
+ Payload: string(params.Data),
+ Encoding: "string",
+ }
+ in := editFile{
+ Branch: params.Branch,
+ Message: params.Message,
+ 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)
+ return res, err
+}
+
+func (s *contentService) Update(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) {
+ 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,
+ Payload: string(params.Data),
+ Encoding: "string",
+ Sha: params.BlobID,
+ }
+ in := editFile{
+ Branch: params.Branch,
+ Message: params.Message,
+ 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)
+ return res, err
+}
+
+func (s *contentService) Delete(ctx context.Context, repo, path string, params *scm.ContentParams) (*scm.Response, error) {
+ 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,
+ Encoding: "string",
+ }
+ in := editFile{
+ Branch: params.Branch,
+ Message: params.Message,
+ 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)
+ return res, err
+}
+
+func (s *contentService) List(ctx context.Context, repo, path, ref string, _ scm.ListOptions) ([]*scm.ContentInfo, *scm.Response, error) {
+ 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
+}
+
+type (
+ identity struct {
+ Name string `json:"name"`
+ Email string `json:"email"`
+ }
+
+ 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"`
+
+ BypassRules bool `json:"bypass_rules"`
+ }
+
+ action struct {
+ Action string `json:"action"`
+ Encoding string `json:"encoding"`
+ Path string `json:"path"`
+ Payload string `json:"payload"`
+ Sha string `json:"sha"`
+ }
+
+ 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"`
+ }
+
+ 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{}
+ 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..f59776f2c
--- /dev/null
+++ b/scm/driver/harness/content_test.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 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 = "thomas"
+ harnessPAT = ""
+)
+
+func TestContentFind(t *testing.T) {
+ if harnessPAT == "" {
+ defer gock.Off()
+
+ gock.New(gockOrigin).
+ 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")
+ }
+ 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), "project") {
+ t.Errorf("Want file Data %q, must contain 'project'", result.Data)
+ }
+}
+
+func TestContentCreate(t *testing.T) {
+ if harnessPAT == "" {
+ defer gock.Off()
+
+ gock.New(gockOrigin).
+ 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\"}")
+ }
+ 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) {
+ if harnessPAT == "" {
+ defer gock.Off()
+
+ gock.New(gockOrigin).
+ 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\"}")
+ }
+ 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",
+ BlobID: "95d09f2b10159347eece71399a7e2e907ea3df4f",
+ },
+ )
+ if err != nil {
+ t.Error(err)
+ }
+
+ if result.Status != 200 {
+ t.Errorf("Unexpected Results")
+ }
+}
+
+func TestContentDelete(t *testing.T) {
+ if harnessPAT == "" {
+ defer gock.Off()
+
+ gock.New(gockOrigin).
+ 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\"}")
+ }
+ 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/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")
+
+ 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..f261f7756
--- /dev/null
+++ b/scm/driver/harness/git.go
@@ -0,0 +1,259 @@
+// 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"
+ "strings"
+ "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) {
+ harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo)
+ 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,
+ 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)
+ 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
+}
+
+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)
+ 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
+}
+
+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) {
+ 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/branches?%s&%s", repoID, encodeListOptions(opts), queryParams)
+ out := []*branch{}
+ res, err := s.client.do(ctx, "GET", path, nil, &out)
+ return convertBranchList(out), res, err
+}
+
+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)
+}
+
+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)
+ 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
+}
+
+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)
+ if err != nil {
+ return nil, nil, err
+ }
+ 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
+}
+
+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)
+ 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
+}
+
+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)
+ 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
+}
+
+// native data structures
+type (
+ commits struct {
+ Commits []commitInfo `json:"commits"`
+ }
+
+ commitInfo 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"`
+ }
+ branchInput struct {
+ Name string `json:"name"`
+ Target string `json:"target"`
+ BypassRules bool `json:"bypass_rules"`
+ }
+ 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"`
+ }
+ 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"`
+ }
+)
+
+//
+// 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: src.Name,
+ Path: scm.ExpandRef(src.Name, "refs/heads/"),
+ Sha: src.Sha,
+ }
+}
+
+func convertCommitList(src *commits) []*scm.Commit {
+ var dst []*scm.Commit
+ for _, v := range src.Commits {
+ dst = append(dst, convertCommitInfo(&v))
+ }
+ return dst
+}
+
+func convertChangeList(src []*fileDiff) []*scm.Change {
+ dst := []*scm.Change{}
+ for _, v := range src {
+ dst = append(dst, convertChange(v))
+ }
+ return dst
+}
+
+func convertCommitInfo(src *commitInfo) *scm.Commit {
+ return &scm.Commit{
+ 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,
+ },
+ }
+}
+
+func convertChange(src *fileDiff) *scm.Change {
+ return &scm.Change{
+ Path: src.Path,
+ PrevFilePath: src.OldPath,
+ Added: strings.EqualFold(src.Status, "ADDED"),
+ Renamed: strings.EqualFold(src.Status, "RENAMED"),
+ Deleted: strings.EqualFold(src.Status, "DELETED"),
+ }
+}
diff --git a/scm/driver/harness/git_test.go b/scm/driver/harness/git_test.go
new file mode 100644
index 000000000..dfbd5a99e
--- /dev/null
+++ b/scm/driver/harness/git_test.go
@@ -0,0 +1,277 @@
+// 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"
+ "fmt"
+ "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/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")
+ }
+ 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/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")
+ }
+ 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/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")
+ }
+ 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/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")
+ }
+ 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)
+ }
+}
+
+func TestCreateBranch(t *testing.T) {
+
+ defer gock.Off()
+
+ gock.New(gockOrigin).
+ 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")
+
+ 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")
+ }
+
+}
+
+func TestCompareChanges(t *testing.T) {
+ source := "542ddabd47d7bfa79359b7b4e2af7f975354e35f"
+ target := "c7d0d4b21d5cfdf47475ff1f6281ef1a91883d"
+ defer gock.Off()
+
+ gock.New(gockOrigin).
+ 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")
+
+ 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/harness.go b/scm/driver/harness/harness.go
new file mode 100644
index 000000000..cf71dd7f5
--- /dev/null
+++ b/scm/driver/harness/harness.go
@@ -0,0 +1,111 @@
+// 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"
+ "io"
+ "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) {
+ 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.DriverHarness
+ 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 {
+ err := new(Error)
+ json.NewDecoder(res.Body).Decode(err)
+ return res, err
+ }
+
+ 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)
+}
+
+// Error represents a Harness CODE error.
+type Error struct {
+ Message string `json:"message"`
+}
+
+func (e *Error) Error() string {
+ return e.Message
+}
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..99d904791
--- /dev/null
+++ b/scm/driver/harness/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 harness
+
+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, 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
+}
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..718aa77dd
--- /dev/null
+++ b/scm/driver/harness/org.go
@@ -0,0 +1,61 @@
+// 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
+
+}
+
+func (s *organizationService) ListMemberships(ctx context.Context, orgNameList []string, username string, opts scm.ListOptions) ([]*scm.Membership, *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..167ba9bf7
--- /dev/null
+++ b/scm/driver/harness/pr.go
@@ -0,0 +1,341 @@
+// 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"
+ "github.com/drone/go-scm/scm/driver/internal/null"
+ "strconv"
+ "strings"
+ "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) {
+ 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?%s", repoId, index, queryParams)
+ out := new(pr)
+ res, err := s.client.do(ctx, "GET", path, nil, out)
+ return convertPullRequest(out), res, err
+
+}
+
+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) {
+ 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?%s&%s", repoId, encodePullRequestListOptions(opts), queryParams)
+ 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) {
+ 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)
+ 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
+}
+
+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)
+ 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
+}
+
+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)
+ 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,
+ 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(ctx context.Context, repo string, prNumber int, input *scm.CommentInput) (*scm.Comment, *scm.Response, error) {
+ 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,
+ }
+ 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) {
+ 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 {
+ 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 int64 `json:"source_repo_id"`
+ SourceSHA string `json:"source_sha"`
+ TargetBranch string `json:"target_branch"`
+ 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 {
+ Repo repository `json:"repo"`
+ Name string `json:"ref"`
+ Sha string `json:"sha"`
+ }
+
+ prInput struct {
+ 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 {
+ 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"`
+ }
+ 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
+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 {
+ return &scm.PullRequest{
+ Number: int(src.Number),
+ Title: src.Title,
+ Body: src.Description,
+ Sha: src.SourceSHA,
+ Source: src.SourceBranch,
+ Target: src.TargetBranch,
+ Merged: src.Merged.Valid,
+ Author: scm.User{
+ Login: src.Author.Email,
+ Name: src.Author.DisplayName,
+ ID: src.Author.UID,
+ Email: src.Author.Email,
+ },
+ 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),
+ }
+}
+
+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,
+ },
+ }
+}
+
+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
+}
+
+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
new file mode 100644
index 000000000..fa26ebb4c
--- /dev/null
+++ b/scm/driver/harness/pr_test.go
@@ -0,0 +1,193 @@
+// 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"
+ "fmt"
+ "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"
+ "github.com/h2non/gock"
+)
+
+func TestPRFind(t *testing.T) {
+ if harnessPAT == "" {
+ defer gock.Off()
+
+ gock.New(gockOrigin).
+ 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")
+ }
+ 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)
+ }
+ 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/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")
+ }
+ 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")
+ t.Log(diff)
+ }
+}
+
+func TestPullCreate(t *testing.T) {
+ defer gock.Off()
+ gock.New(gockOrigin).
+ 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")
+
+ 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)
+ }
+}
+
+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/release.go b/scm/driver/harness/release.go
new file mode 100644
index 000000000..66d62cdb3
--- /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 *string `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..2ef3ceca6
--- /dev/null
+++ b/scm/driver/harness/repo.go
@@ -0,0 +1,225 @@
+// 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"
+ "errors"
+ "fmt"
+ "strconv"
+
+ "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) {
+ 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 {
+ 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) {
+ 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/webhooks/%s?%s", repoId, id, queryParams)
+ 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) {
+ return nil, nil, scm.ErrNotSupported
+}
+
+func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) {
+ 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
+}
+
+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) 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)
+ 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
+}
+
+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) {
+ 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/webhooks?%s", repoId, queryParams)
+ in := new(hook)
+ in.Enabled = true
+ in.Identifier = input.Name
+ in.Secret = input.Secret
+ in.Insecure = input.SkipVerify
+ in.URL = input.Target
+ in.Triggers = input.NativeEvents
+ out := new(hook)
+ res, err := s.client.do(ctx, "POST", path, in, out)
+ return convertHook(out), res, err
+}
+
+func (s *repositoryService) List2(ctx context.Context, orgSlug string, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) {
+ return nil, nil, scm.ErrNotSupported
+}
+func (s *repositoryService) ListRepoLanguages(context.Context, string) (map[string]float64, *scm.Response, error) {
+ return nil, nil, scm.ErrNotSupported
+}
+
+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) {
+ harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo)
+ 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)
+}
+
+//
+// native data structures
+//
+
+type (
+ // harness repository resource.
+ repository struct {
+ 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"`
+ }
+ hook struct {
+ Created int `json:"created"`
+ CreatedBy int `json:"created_by"`
+ Description string `json:"description"`
+ Enabled bool `json:"enabled"`
+ HasSecret bool `json:"has_secret"`
+ Secret string `json:"secret"`
+ Identifier string `json:"identifier"`
+ 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"`
+ }
+)
+
+//
+// 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: src.Path,
+ Name: src.UID,
+ Branch: src.DefaultBranch,
+ 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 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{
+ // keeping id same as name
+ ID: from.Identifier,
+ Name: from.Identifier,
+ 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
new file mode 100644
index 000000000..1fc861084
--- /dev/null
+++ b/scm/driver/harness/repo_test.go
@@ -0,0 +1,254 @@
+// 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"
+ "fmt"
+ "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 TestRepositoryFind(t *testing.T) {
+ if harnessPAT == "" {
+ defer gock.Off()
+
+ gock.New(gockOrigin).
+ 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")
+ }
+ 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) {
+ if harnessPAT == "" {
+ defer gock.Off()
+
+ gock.New(gockOrigin).
+ 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")
+ }
+ 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 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)
+ }
+}
+
+func TestRepositoryHookList(t *testing.T) {
+ if harnessPAT == "" {
+ defer gock.Off()
+
+ gock.New(gockOrigin).
+ 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").
+ 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)
+ }
+}
+
+func TestRepositoryFindHook(t *testing.T) {
+ if harnessPAT == "" {
+ defer gock.Off()
+
+ gock.New(gockOrigin).
+ 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")
+ }
+ 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)
+ }
+}
+
+func TestRepositoryHookCreateDelete(t *testing.T) {
+ if harnessPAT == "" {
+ defer gock.Off()
+
+ gock.New(gockOrigin).
+ 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")
+ }
+ 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/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)
+ 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/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/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..2490e4ae3
--- /dev/null
+++ b/scm/driver/harness/testdata/branches.json
@@ -0,0 +1,71 @@
+[
+ {
+ "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": "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",
+ "commit": {
+ "sha": "de2837f8911710cfb7bbb323d0de285fd2ef9155",
+ "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"
+ }
+ }
+ }
+]
\ 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..3f2458b08
--- /dev/null
+++ b/scm/driver/harness/testdata/branches.json.golden
@@ -0,0 +1,17 @@
+[
+ {
+ "Name": "bla",
+ "Path": "refs/heads/bla",
+ "Sha": "0c221fd126b9457d0ad2037641416083549f59c5"
+ },
+ {
+ "Name": "branch3",
+ "Path": "refs/heads/branch3",
+ "Sha": "59e1cdf0e421fd14b106f4861fb02dfd56b4dc34"
+ },
+ {
+ "Name": "main",
+ "Path": "refs/heads/main",
+ "Sha": "1d640265d8bdd818175fa736f0fcbad2c9b716c9"
+ }
+]
\ No newline at end of file
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
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..4045985d6
--- /dev/null
+++ b/scm/driver/harness/testdata/commits.json
@@ -0,0 +1,23 @@
+{
+ "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"
+ },
+ "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
diff --git a/scm/driver/harness/testdata/content.json b/scm/driver/harness/testdata/content.json
new file mode 100644
index 000000000..fbcda4f5f
--- /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": "IyB0aG9tYXMKUGxheWdyb3VuZCBwcm9qZWN0IGZvciBUaG9tYXM=",
+ "size": 38
+ }
+}
\ 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/gitdiff.json b/scm/driver/harness/testdata/gitdiff.json
new file mode 100644
index 000000000..c4dd5768d
--- /dev/null
+++ b/scm/driver/harness/testdata/gitdiff.json
@@ -0,0 +1,53 @@
+[
+ {
+ "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
new file mode 100644
index 000000000..c3258c315
--- /dev/null
+++ b/scm/driver/harness/testdata/gitdiff.json.golden
@@ -0,0 +1,38 @@
+[
+ {
+ "Path": "hello.go",
+ "Added": true,
+ "Renamed": false,
+ "Deleted": false,
+ "Sha": "",
+ "BlobID": "",
+ "PrevFilePath": "hello.go"
+ },
+ {
+ "Path": "null.go",
+ "Added": false,
+ "Renamed": false,
+ "Deleted": true,
+ "Sha": "",
+ "BlobID": "",
+ "PrevFilePath": "null.go"
+ },
+ {
+ "Path": "version4.go",
+ "Added": false,
+ "Renamed": false,
+ "Deleted": false,
+ "Sha": "",
+ "BlobID": "",
+ "PrevFilePath": "version4.go"
+ },
+ {
+ "Path": "version_1.go",
+ "Added": false,
+ "Renamed": true,
+ "Deleted": false,
+ "Sha": "",
+ "BlobID": "",
+ "PrevFilePath": "version1.go"
+ }
+]
\ No newline at end of file
diff --git a/scm/driver/harness/testdata/hook.json b/scm/driver/harness/testdata/hook.json
new file mode 100644
index 000000000..cfae54972
--- /dev/null
+++ b/scm/driver/harness/testdata/hook.json
@@ -0,0 +1,16 @@
+{
+ "version": 1,
+ "parent_id": 11,
+ "parent_type": "repo",
+ "created_by": 14,
+ "created": 1675867490853,
+ "updated": 1675867531549,
+ "identifier": "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..686b5db97
--- /dev/null
+++ b/scm/driver/harness/testdata/hook.json.golden
@@ -0,0 +1,8 @@
+{
+ "ID": "webhookname",
+ "Name": "webhookname",
+ "Target": "http://1.1.1.1",
+ "Events": [],
+ "Active": true,
+ "SkipVerify": true
+}
\ No newline at end of file
diff --git a/scm/driver/harness/testdata/hook_create.json b/scm/driver/harness/testdata/hook_create.json
new file mode 100644
index 000000000..cd88b4357
--- /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,
+ "identifier": "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
diff --git a/scm/driver/harness/testdata/hooks.json b/scm/driver/harness/testdata/hooks.json
new file mode 100644
index 000000000..9e539cecd
--- /dev/null
+++ b/scm/driver/harness/testdata/hooks.json
@@ -0,0 +1,18 @@
+[
+ {
+ "version": 1,
+ "parent_id": 11,
+ "parent_type": "repo",
+ "created_by": 14,
+ "created": 1675867490853,
+ "updated": 1675867531549,
+ "identifier": "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..317aa8125
--- /dev/null
+++ b/scm/driver/harness/testdata/hooks.json.golden
@@ -0,0 +1,10 @@
+[
+ {
+ "ID": "webhookname",
+ "Name": "webhookname",
+ "Target": "http://1.1.1.1",
+ "Events": [],
+ "Active": true,
+ "SkipVerify": true
+ }
+]
\ No newline at end of file
diff --git a/scm/driver/harness/testdata/pr.json b/scm/driver/harness/testdata/pr.json
new file mode 100644
index 000000000..57fc7d9de
--- /dev/null
+++ b/scm/driver/harness/testdata/pr.json
@@ -0,0 +1,36 @@
+{
+ "number": 1,
+ "created": 1710818863810,
+ "edited": 1710818863810,
+ "state": "open",
+ "is_draft": false,
+ "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_method": null,
+ "merge_check_status": "mergeable",
+ "merge_target_sha": "b772dca15553986cc90fc6254a0fa47f4047526c",
+ "merge_base_sha": "b772dca15553986cc90fc6254a0fa47f4047526c",
+ "merge_sha": "ff13c81504ab3b04bd76b6af71e9c368333181a5",
+ "author": {
+ "id": 27,
+ "uid": "aqm0RQXGQI6v3m_f7u7C5A",
+ "display_name": "Abhinav Singh",
+ "email": "abhinav.singh@harness.io",
+ "type": "user",
+ "created": 1681264009453,
+ "updated": 1681264009453
+ },
+ "merger": null,
+ "stats": {
+ "commits": 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
new file mode 100644
index 000000000..ae5dc76da
--- /dev/null
+++ b/scm/driver/harness/testdata/pr.json.golden
@@ -0,0 +1,33 @@
+{
+ "Number": 1,
+ "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": "",
+ "Base": {
+ "Sha": "b772dca15553986cc90fc6254a0fa47f4047526c",
+ "Path": "refs/heads/main",
+ "Name": "main"
+ },
+ "Head": {
+ "Sha": "6c4ab583f5201ed0421d0ef93ee5b0925ac08f62",
+ "Path": "refs/heads/abhinav/CODE-1508",
+ "Name": "abhinav/CODE-1508"
+ },
+ "Author": {
+ "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
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
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
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/testdata/user.json b/scm/driver/harness/testdata/user.json
new file mode 100644
index 000000000..21ea693f2
--- /dev/null
+++ b/scm/driver/harness/testdata/user.json
@@ -0,0 +1,47 @@
+{
+ "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
new file mode 100644
index 000000000..5f81bfeba
--- /dev/null
+++ b/scm/driver/harness/testdata/user.json.golden
@@ -0,0 +1,7 @@
+{
+ "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/testdata/webhooks/branch_create.json b/scm/driver/harness/testdata/webhooks/branch_create.json
new file mode 100644
index 000000000..426f9c54e
--- /dev/null
+++ b/scm/driver/harness/testdata/webhooks/branch_create.json
@@ -0,0 +1,68 @@
+{
+ "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"
+ }
+ },
+ "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_create.json.golden b/scm/driver/harness/testdata/webhooks/branch_create.json.golden
new file mode 100644
index 000000000..967f51f17
--- /dev/null
+++ b/scm/driver/harness/testdata/webhooks/branch_create.json.golden
@@ -0,0 +1,29 @@
+{
+ "Ref": {
+ "Name": "refs/heads/new2",
+ "Sha": "aeafa0e2e4ec6909ad75cb8fad57c0b1eb5986e6"
+ },
+ "Action": "created",
+ "Repo": {
+ "ID": "13",
+ "Namespace": "",
+ "Name": "aba",
+ "Perm": null,
+ "Branch": "main",
+ "Private": false,
+ "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",
+ "Updated": "0001-01-01T00:00:00Z"
+ },
+ "Sender": {
+ "ID": "0osgWsTZRsSZ8RWfjLRkEg",
+ "Login": "0osgWsTZRsSZ8RWfjLRkEg",
+ "Name": "default",
+ "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/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/branch_updated.json b/scm/driver/harness/testdata/webhooks/branch_updated.json
new file mode 100644
index 000000000..844bcfd03
--- /dev/null
+++ b/scm/driver/harness/testdata/webhooks/branch_updated.json
@@ -0,0 +1,68 @@
+{
+ "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"
+ }
+ },
+ "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/branch_updated.json.golden b/scm/driver/harness/testdata/webhooks/branch_updated.json.golden
new file mode 100644
index 000000000..550cf3b1d
--- /dev/null
+++ b/scm/driver/harness/testdata/webhooks/branch_updated.json.golden
@@ -0,0 +1,46 @@
+{
+ "Ref": "refs/heads/master",
+ "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/testdata/webhooks/pull_request_branch_updated.json b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json
new file mode 100644
index 000000000..dec4c06f6
--- /dev/null
+++ b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json
@@ -0,0 +1,100 @@
+{
+ "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,
+ "merge_base_sha": "5473eebbc0ce1d08981c955161b07a7989566b7b",
+ "author": {
+ "id": 8,
+ "uid": "0osgWsTZRsSZ8RWfjLRkEg",
+ "display_name": "Admin",
+ "email": "admin@harness.io",
+ "type": "user",
+ "created": 1675390885380,
+ "updated": 1675390885380
+ },
+ "pr_url": "http://localhost:3000/codeowners/asdsad/pulls/14"
+ },
+ "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"
+ }
+ },
+ "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_branch_updated.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden
new file mode 100644
index 000000000..0cc22af45
--- /dev/null
+++ b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden
@@ -0,0 +1,58 @@
+{
+ "Action": "updated",
+ "Repo": {
+ "ID": "13",
+ "Namespace": "",
+ "Name": "aba",
+ "Branch": "main",
+ "Private": false,
+ "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",
+ "Updated": "0001-01-01T00:00:00Z"
+ },
+ "PullRequest": {
+ "Number": 4,
+ "Title": "aw",
+ "Body": "",
+ "Sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef",
+ "Ref": "refs/heads/b",
+ "Source": "b",
+ "Target": "main",
+ "Fork": "fork",
+ "Link": "http://localhost:3000/codeowners/asdsad/pulls/14",
+ "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"
+ },
+ "Base": {
+ "Name": "main",
+ "Path": "refs/heads/main",
+ "Sha": "5473eebbc0ce1d08981c955161b07a7989566b7b"
+ },
+ "Head": {
+ "Name": "b",
+ "Path": "refs/heads/b",
+ "Sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef"
+ },
+ "Created": "0001-01-01T00:00:00Z",
+ "Updated": "0001-01-01T00:00:00Z"
+ },
+ "Sender": {
+ "ID": "0osgWsTZRsSZ8RWfjLRkEg",
+ "Login": "0osgWsTZRsSZ8RWfjLRkEg",
+ "Name": "default",
+ "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_closed.json b/scm/driver/harness/testdata/webhooks/pull_request_closed.json
new file mode 100644
index 000000000..4039bc208
--- /dev/null
+++ b/scm/driver/harness/testdata/webhooks/pull_request_closed.json
@@ -0,0 +1,97 @@
+{
+ "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",
+ "merge_base_sha": "5473eebbc0ce1d08981c955161b07a7989566b7b",
+ "author": {
+ "id": 3,
+ "uid": "admin",
+ "display_name": "Administrator",
+ "email": "admin@gitness.io",
+ "type": "user",
+ "created": 1696332021613,
+ "updated": 1696332021613
+ },
+ "pr_url": "http://localhost:3000/codeowners/asdsad/pulls/14"
+ },
+ "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"
+ }
+ },
+ "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_closed.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_closed.json.golden
new file mode 100644
index 000000000..bfd493649
--- /dev/null
+++ b/scm/driver/harness/testdata/webhooks/pull_request_closed.json.golden
@@ -0,0 +1,58 @@
+{
+ "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/codeowners/asdsad/pulls/14",
+ "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"
+ },
+ "Base": {
+ "Name": "main",
+ "Path": "refs/heads/main",
+ "Sha": "5473eebbc0ce1d08981c955161b07a7989566b7b"
+ },
+ "Head": {
+ "Name": "asdxsa",
+ "Path": "refs/heads/asdxsa",
+ "Sha": "27822dd2ec788f924c97b0b194c5bfd906f2e574"
+ },
+ "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_comment_created.json b/scm/driver/harness/testdata/webhooks/pull_request_comment_created.json
new file mode 100644
index 000000000..cc69241e8
--- /dev/null
+++ b/scm/driver/harness/testdata/webhooks/pull_request_comment_created.json
@@ -0,0 +1,105 @@
+{
+ "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,
+ "merge_base_sha": "5473eebbc0ce1d08981c955161b07a7989566b7b",
+ "author": {
+ "id": 8,
+ "uid": "0osgWsTZRsSZ8RWfjLRkEg",
+ "display_name": "Admin",
+ "email": "admin@harness.io",
+ "type": "user",
+ "created": 1675390885380,
+ "updated": 1675390885380
+ },
+ "pr_url": "http://localhost:3000/codeowners/asdsad/pulls/14"
+ },
+ "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"
+ }
+ },
+ "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"
+ }
+ },
+ "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"
+ }
+ },
+ "comment": {
+ "id": 1,
+ "text": "pr comment",
+ "created": 1745471063621,
+ "updated": 1745471063621,
+ "kind": "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..a10e6efb6
--- /dev/null
+++ b/scm/driver/harness/testdata/webhooks/pull_request_comment_created.json.golden
@@ -0,0 +1,61 @@
+{
+ "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": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef",
+ "Ref": "refs/heads/pr2",
+ "Source": "pr2",
+ "Target": "main",
+ "Fork": "fork",
+ "Link": "http://localhost:3000/codeowners/asdsad/pulls/14",
+ "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"
+ },
+ "Base": {
+ "Name": "main",
+ "Path": "refs/heads/main",
+ "Sha": "5473eebbc0ce1d08981c955161b07a7989566b7b"
+ },
+ "Head": {
+ "Name": "pr2",
+ "Path": "refs/heads/pr2",
+ "Sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef"
+ },
+ "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_merged.json b/scm/driver/harness/testdata/webhooks/pull_request_merged.json
new file mode 100644
index 000000000..dac50c97f
--- /dev/null
+++ b/scm/driver/harness/testdata/webhooks/pull_request_merged.json
@@ -0,0 +1,98 @@
+{
+ "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",
+ "merge_base_sha": "5473eebbc0ce1d08981c955161b07a7989566b7b",
+ "author": {
+ "id": 3,
+ "uid": "admin",
+ "display_name": "Administrator",
+ "email": "admin@gitness.io",
+ "type": "user",
+ "created": 1696332021613,
+ "updated": 1696332021613
+ },
+ "pr_url": "http://localhost:3000/codeowners/asdsad/pulls/14"
+ },
+ "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"
+ }
+ },
+ "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_merged.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_merged.json.golden
new file mode 100644
index 000000000..7237cea0d
--- /dev/null
+++ b/scm/driver/harness/testdata/webhooks/pull_request_merged.json.golden
@@ -0,0 +1,58 @@
+{
+ "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/codeowners/asdsad/pulls/14",
+ "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"
+ },
+ "Base": {
+ "Name": "main",
+ "Path": "refs/heads/main",
+ "Sha": "5473eebbc0ce1d08981c955161b07a7989566b7b"
+ },
+ "Head": {
+ "Name": "xas",
+ "Path": "refs/heads/xas",
+ "Sha": "4ec41187008f77222a60dfa21cdbd980f6490443"
+ },
+ "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_opened.json b/scm/driver/harness/testdata/webhooks/pull_request_opened.json
new file mode 100644
index 000000000..bfafcef5a
--- /dev/null
+++ b/scm/driver/harness/testdata/webhooks/pull_request_opened.json
@@ -0,0 +1,98 @@
+{
+ "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,
+ "merge_base_sha": "5473eebbc0ce1d08981c955161b07a7989566b7b",
+ "author": {
+ "id": 8,
+ "uid": "0osgWsTZRsSZ8RWfjLRkEg",
+ "display_name": "Admin",
+ "email": "admin@harness.io",
+ "type": "user",
+ "created": 1675390885380,
+ "updated": 1675390885380
+ },
+ "pr_url": "http://localhost:3000/codeowners/asdsad/pulls/14"
+ },
+ "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": "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"
+ }
+ },
+ "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_opened.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden
new file mode 100644
index 000000000..a1fe53904
--- /dev/null
+++ b/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden
@@ -0,0 +1,58 @@
+{
+ "Action": "created",
+ "Repo": {
+ "ID": "13",
+ "Namespace": "",
+ "Name": "aba",
+ "Branch": "main",
+ "Private": false,
+ "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",
+ "Updated": "0001-01-01T00:00:00Z"
+ },
+ "PullRequest": {
+ "Number": 4,
+ "Title": "aw",
+ "Body": "",
+ "Sha": "d74b1ebfe520ac01b209dd9085f005884cc9f4cd",
+ "Ref": "refs/heads/b",
+ "Source": "b",
+ "Target": "main",
+ "Fork": "fork",
+ "Link": "http://localhost:3000/codeowners/asdsad/pulls/14",
+ "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"
+ },
+ "Base": {
+ "Name": "main",
+ "Path": "refs/heads/main",
+ "Sha": "5473eebbc0ce1d08981c955161b07a7989566b7b"
+ },
+ "Head": {
+ "Name": "b",
+ "Path": "refs/heads/b",
+ "Sha": "d74b1ebfe520ac01b209dd9085f005884cc9f4cd"
+ },
+ "Created": "0001-01-01T00:00:00Z",
+ "Updated": "0001-01-01T00:00:00Z"
+ },
+ "Sender": {
+ "ID": "0osgWsTZRsSZ8RWfjLRkEg",
+ "Login": "0osgWsTZRsSZ8RWfjLRkEg",
+ "Name": "default",
+ "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_reopened.json b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json
new file mode 100644
index 000000000..3915d0b45
--- /dev/null
+++ b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json
@@ -0,0 +1,98 @@
+{
+ "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,
+ "merge_base_sha": "5473eebbc0ce1d08981c955161b07a7989566b7b",
+ "author": {
+ "id": 8,
+ "uid": "0osgWsTZRsSZ8RWfjLRkEg",
+ "display_name": "Admin",
+ "email": "admin@harness.io",
+ "type": "user",
+ "created": 1675390885380,
+ "updated": 1675390885380
+ },
+ "pr_url": "http://localhost:3000/codeowners/asdsad/pulls/14"
+ },
+ "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"
+ }
+ },
+ "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/testdata/webhooks/pull_request_reopened.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden
new file mode 100644
index 000000000..3c00c475c
--- /dev/null
+++ b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden
@@ -0,0 +1,58 @@
+{
+ "Action": "reopened",
+ "Repo": {
+ "ID": "13",
+ "Namespace": "",
+ "Name": "aba",
+ "Branch": "main",
+ "Private": false,
+ "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",
+ "Updated": "0001-01-01T00:00:00Z"
+ },
+ "PullRequest": {
+ "Number": 4,
+ "Title": "aw",
+ "Body": "",
+ "Sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef",
+ "Ref": "refs/heads/b",
+ "Source": "b",
+ "Target": "main",
+ "Fork": "fork",
+ "Link": "http://localhost:3000/codeowners/asdsad/pulls/14",
+ "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"
+ },
+ "Base": {
+ "Name": "main",
+ "Path": "refs/heads/main",
+ "Sha": "5473eebbc0ce1d08981c955161b07a7989566b7b"
+ },
+ "Head": {
+ "Name": "b",
+ "Path": "refs/heads/b",
+ "Sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef"
+ },
+ "Created": "0001-01-01T00:00:00Z",
+ "Updated": "0001-01-01T00:00:00Z"
+ },
+ "Sender": {
+ "ID": "0osgWsTZRsSZ8RWfjLRkEg",
+ "Login": "0osgWsTZRsSZ8RWfjLRkEg",
+ "Name": "default",
+ "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/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/user.go b/scm/driver/harness/user.go
new file mode 100644
index 000000000..500cad249
--- /dev/null
+++ b/scm/driver/harness/user.go
@@ -0,0 +1,100 @@
+// 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"
+ "strings"
+
+ "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(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) {
+ 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 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 convertHarnessUser(src *harnessUser) *scm.User {
+ return &scm.User{
+ 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
new file mode 100644
index 000000000..886494c13
--- /dev/null
+++ b/scm/driver/harness/user_test.go
@@ -0,0 +1,59 @@
+// 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"
+)
+
+func TestUsersFind(t *testing.T) {
+ if harnessPAT == "" {
+ defer gock.Off()
+
+ 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{
+ 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)
+ }
+}
diff --git a/scm/driver/harness/util.go b/scm/driver/harness/util.go
new file mode 100644
index 000000000..4be210068
--- /dev/null
+++ b/scm/driver/harness/util.go
@@ -0,0 +1,174 @@
+// 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"
+)
+
+const (
+ accountIdentifier = "accountIdentifier"
+ projectIdentifier = "projectIdentifier"
+ orgIdentifier = "orgIdentifier"
+ routingId = "routingId"
+)
+
+func buildHarnessURI(account, organization, project, repo string) (uri string) {
+ if account != "" {
+ 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 {
+ uri += "+"
+ }
+ return uri
+ }
+ 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 {
+ 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()
+}
+
+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()
+}
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..cb79b71fa
--- /dev/null
+++ b/scm/driver/harness/webhook.go
@@ -0,0 +1,404 @@
+// 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"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "strconv"
+ "strings"
+ "time"
+
+ "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-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_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":
+ hook, err = s.parsePullRequestCommentHook(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-Harness-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) parsePullRequestHook(data []byte) (scm.Webhook, error) {
+ dst := new(pullRequestHook)
+ err := json.Unmarshal(data, dst)
+ return convertPullRequestHook(dst), err
+}
+
+func (s *webhookService) parsePushHook(data []byte) (scm.Webhook, error) {
+ dst := new(pushHook)
+ err := json.Unmarshal(data, dst)
+ 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
+}
+
+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 {
+ 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"`
+ Description string `json:"description"`
+ SourceRepoID int `json:"source_repo_id"`
+ SourceBranch string `json:"source_branch"`
+ TargetRepoID int `json:"target_repo_id"`
+ TargetBranch string `json:"target_branch"`
+ MergeBaseSHA string `json:"merge_base_sha"`
+ MergeStrategy interface{} `json:"merge_strategy"`
+ Author principal `json:"author"`
+ PrURL string `json:"pr_url"`
+ }
+ 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"`
+ URL string `json:"url"`
+ 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"`
+ Added []string `json:"added"`
+ Modified []string `json:"modified"`
+ Removed []string `json:"removed"`
+ }
+ comment struct {
+ ID int `json:"id"`
+ Text string `json:"text"`
+ }
+ // 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"`
+ 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"`
+ 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"`
+ HeadCommit hookCommit `json:"head_commit"`
+ Comment comment `json:"comment"`
+ }
+)
+
+// native data structure conversion
+func convertPullRequestHook(src *pullRequestHook) *scm.PullRequestHook {
+ return &scm.PullRequestHook{
+ Action: convertPRAction(src.Trigger),
+ 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: 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,
+ },
+ Link: c.URL,
+ }
+}
+
+func convertPullRequestCommentHook(src *pullRequestCommentHook) *scm.PullRequestCommentHook {
+ return &scm.PullRequestCommentHook{
+ PullRequest: convertPullReq(src.PullReq, src.Ref, src.HeadCommit),
+ Repo: convertRepo(src.Repo),
+ Comment: scm.Comment{
+ Body: src.Comment.Text,
+ ID: src.Comment.ID,
+ },
+ 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 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":
+ return scm.ActionUpdate
+ case "pullreq_reopened":
+ return scm.ActionReopen
+ case "pullreq_closed":
+ return scm.ActionClose
+ case "pullreq_merged":
+ return scm.ActionMerge
+ default:
+ 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
+ }
+}
+
+func convertPullReq(pr pullReq, ref ref, commit hookCommit) scm.PullRequest {
+ return scm.PullRequest{
+ Number: pr.Number,
+ Title: pr.Title,
+ Body: pr.Description,
+ Closed: pr.State != "open",
+ Source: pr.SourceBranch,
+ Target: pr.TargetBranch,
+ Merged: pr.State == "merged",
+ Fork: "fork",
+ Link: pr.PrURL,
+ Draft: pr.IsDraft,
+ Sha: commit.Sha,
+ Ref: ref.Name,
+ Author: convertUser(pr.Author),
+ Head: scm.Reference{
+ Name: pr.SourceBranch,
+ Path: scm.ExpandRef(pr.SourceBranch, "refs/heads"),
+ Sha: commit.Sha,
+ },
+ Base: scm.Reference{
+ Name: pr.TargetBranch,
+ Path: scm.ExpandRef(pr.TargetBranch, "refs/heads"),
+ Sha: pr.MergeBaseSHA,
+ },
+ }
+}
+
+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
new file mode 100644
index 000000000..a4cf093b1
--- /dev/null
+++ b/scm/driver/harness/webhook_test.go
@@ -0,0 +1,178 @@
+// 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"
+ "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.BranchHook),
+ },
+ // push branch update
+ {
+ event: "branch_updated",
+ before: "testdata/webhooks/branch_updated.json",
+ 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
+ //
+ // 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),
+ },
+ // 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),
+ },
+ // 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 {
+ 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
+}
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{
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) {
diff --git a/scm/driver/stash/git.go b/scm/driver/stash/git.go
index 2c38c4cd4..221b59911 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{
@@ -79,13 +79,22 @@ 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
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..f93952ace 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")
@@ -146,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/branches_filter.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/branches_filter.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()
@@ -238,7 +267,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/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 bd5933f25..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{
@@ -23,7 +23,7 @@ func TestCreateBranch(t *testing.T) {
}
commitId, _ := GetCurrentCommitOfBranch(client, "master")
- input := &scm.CreateBranch{
+ input := &scm.ReferenceInput{
Name: "test_branch",
Sha: commitId,
}
@@ -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{
@@ -62,3 +62,57 @@ func TestGetLatestCommitOfBranch(t *testing.T) {
}
}
}
+
+func TestGetLatestCommitOfNonDefaultBranch(t *testing.T) {
+ if token == "" || username == "" {
+ t.Skip("Skipping, Acceptance test. Missing BITBUCKET_SERVER_TOKEN or BITBUCKET_USERNAME")
+ }
+ 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 == "" || username == "" {
+ t.Skip("Skipping, Acceptance test. Missing BITBUCKET_SERVER_TOKEN or BITBUCKET_USERNAME")
+ }
+ 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)
+ }
+ }
+}
diff --git a/scm/driver/stash/integration/testSettings.go b/scm/driver/stash/integration/integration.go
similarity index 92%
rename from scm/driver/stash/integration/testSettings.go
rename to scm/driver/stash/integration/integration.go
index 7a3dfce71..56cae697d 100644
--- a/scm/driver/stash/integration/testSettings.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) {
diff --git a/scm/driver/stash/pr.go b/scm/driver/stash/pr.go
index 836c5392b..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 {
@@ -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 {
@@ -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 {
@@ -221,6 +227,7 @@ func convertPullRequest(from *pr) *scm.PullRequest {
Title: from.Title,
Body: from.Description,
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/repo.go b/scm/driver/stash/repo.go
index 27e9b02b7..d7b864a0a 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"`
}
@@ -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.
@@ -168,6 +180,30 @@ 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
+}
+
+// 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
+}
+
func (s *repositoryService) List2(ctx context.Context, orgSlug string, opts scm.ListOptions) ([]*scm.Repository, *scm.Response, error) {
return nil, nil, scm.ErrNotSupported
}
diff --git a/scm/driver/stash/repo_test.go b/scm/driver/stash/repo_test.go
index 83924a8ba..ff7138df1 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 {
@@ -289,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/stash.go b/scm/driver/stash/stash.go
index 440cf3844..62db1c7fd 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-check"},
},
}
// if we are posting or putting data, we need to
@@ -94,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)
diff --git a/scm/driver/stash/testdata/branches_filter.json b/scm/driver/stash/testdata/branches_filter.json
new file mode 100644
index 000000000..f6b88ab8f
--- /dev/null
+++ b/scm/driver/stash/testdata/branches_filter.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/branches_filter.json.golden b/scm/driver/stash/testdata/branches_filter.json.golden
new file mode 100644
index 000000000..a158fbac2
--- /dev/null
+++ b/scm/driver/stash/testdata/branches_filter.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/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",
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/testdata/webhooks/pr_merged.json.golden b/scm/driver/stash/testdata/webhooks/pr_merged.json.golden
index 344032d2c..2b3367535 100644
--- a/scm/driver/stash/testdata/webhooks/pr_merged.json.golden
+++ b/scm/driver/stash/testdata/webhooks/pr_merged.json.golden
@@ -18,6 +18,7 @@
"Title": "Develop",
"Body": "* added LICENSE\r\n* add COPYING file",
"Sha": "b9eaed50a03c073b20dfa82e5e753d295e7f0e56",
+ "Merge": "83f836ca538dc4f43d29fda46a5b85ea49f1b8e7",
"Ref": "refs/pull-requests/3/from",
"Source": "develop",
"Target": "master",
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/util.go b/scm/driver/stash/util.go
index 64e982ba2..5f56e21ed 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 (
+ defaultLimit = 25
+)
+
func encodeListOptions(opts scm.ListOptions) string {
params := url.Values{}
if opts.Page > 1 {
@@ -25,6 +29,40 @@ func encodeListOptions(opts scm.ListOptions) string {
return params.Encode()
}
+func encodeListOptionsV2(opts scm.ListOptions) string {
+ params := url.Values{}
+ limit := defaultLimit
+ 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 != "" {
+ params.Set("filterText", opts.SearchTerm)
+ }
+ 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()
+}
+
func encodeListRoleOptions(opts scm.ListOptions) string {
params := url.Values{}
if opts.Page > 1 {
@@ -39,6 +77,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 {
@@ -52,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()
}
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{
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
//
diff --git a/scm/git.go b/scm/git.go
index 21da2bc4a..b2d125136 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,10 +59,19 @@ type (
Avatar string
}
+ // Pipeline Execution details
+ Execution struct {
+ Number int
+ Status ExecutionStatus
+ Created time.Time
+ Updated time.Time
+ URL string
+ }
+
// 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)
@@ -76,6 +85,9 @@ 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.
ListCommits(ctx context.Context, repo string, opts CommitListOptions) ([]*Commit, *Response, error)
@@ -91,4 +103,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
)
diff --git a/scm/pr.go b/scm/pr.go
index b36254a34..1e9a74945 100644
--- a/scm/pr.go
+++ b/scm/pr.go
@@ -22,8 +22,10 @@ type (
Fork string
Link string
Diff string
+ Draft bool
Closed bool
Merged bool
+ Merge string
Base Reference
Head Reference
Author User
diff --git a/scm/repo.go b/scm/repo.go
index 29055dbd2..16e97e7fc 100644
--- a/scm/repo.go
+++ b/scm/repo.go
@@ -65,6 +65,7 @@ type (
Deployment bool
Issue bool
IssueComment bool
+ Pipeline bool
PullRequest bool
PullRequestComment bool
Push bool
@@ -120,6 +121,12 @@ 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)
+
+ // ListNamespace returns a list of repos in namespace
+ ListNamespace(context.Context, string, ListOptions) ([]*Repository, *Response, error)
+
// List2 returns a list of repositories .
List2(context.Context, string, ListOptions) ([]*Repository, *Response, error)
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
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
diff --git a/scm/util.go b/scm/util.go
index 0a8c3a2ca..4e72f524f 100644
--- a/scm/util.go
+++ b/scm/util.go
@@ -89,3 +89,42 @@ 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 ConvertExecutionStatus(from string) ExecutionStatus {
+ switch from {
+ case "running", "in_progress", "INPROGRESS":
+ return StatusRunning
+ case "success", "completed", "SUCCESSFUL":
+ return StatusSuccess
+ case "Failed", "failure", "FAILED":
+ return StatusFailed
+ case "Canceled", "cancelled", "STOPPED":
+ return StatusCanceled
+ case "pending", "queued":
+ return StatusPending
+ default:
+ return StatusUnknown
+ }
+}
+
+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)
+ }
+ }
+}
diff --git a/scm/webhook.go b/scm/webhook.go
index f84023288..07bb62d9b 100644
--- a/scm/webhook.go
+++ b/scm/webhook.go
@@ -37,6 +37,15 @@ type (
Commits []Commit
}
+ // PipelineHook
+ PipelineHook struct {
+ Commit Commit
+ Execution Execution
+ PullRequest PullRequest
+ Repo Repository
+ Sender User
+ }
+
// BranchHook represents a branch or tag event,
// eg create and delete github event types.
BranchHook struct {
@@ -115,6 +124,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
+ }
+
// PingHook represents a ping hook, eg ping events.
PingHook struct {
Repo Repository
@@ -146,4 +164,6 @@ 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 }
+func (h *PipelineHook) Repository() Repository { return h.Repo }
func (h *PingHook) Repository() Repository { return h.Repo }