From 16252ffc2540299ba3c8706e1d401d27d2c5b1cf Mon Sep 17 00:00:00 2001 From: TP Honey Date: Wed, 8 Feb 2023 13:08:46 +0000 Subject: [PATCH 1/4] (feat) harness, add webhook parsing --- .../testdata/webhooks/branch_create.json | 50 +++ .../webhooks/branch_create.json.golden | 43 ++ .../webhooks/pull_request_branch_updated.json | 71 ++++ .../pull_request_branch_updated.json.golden | 42 ++ .../webhooks/pull_request_opened.json | 225 +++------- .../webhooks/pull_request_opened.json.golden | 51 ++- .../webhooks/pull_request_reopened.json | 69 ++++ .../pull_request_reopened.json.golden | 42 ++ scm/driver/harness/webhook.go | 384 ++++++------------ scm/driver/harness/webhook_test.go | 113 ++++++ 10 files changed, 648 insertions(+), 442 deletions(-) create mode 100644 scm/driver/harness/testdata/webhooks/branch_create.json create mode 100644 scm/driver/harness/testdata/webhooks/branch_create.json.golden create mode 100644 scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json create mode 100644 scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden create mode 100644 scm/driver/harness/testdata/webhooks/pull_request_reopened.json create mode 100644 scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden diff --git a/scm/driver/harness/testdata/webhooks/branch_create.json b/scm/driver/harness/testdata/webhooks/branch_create.json new file mode 100644 index 000000000..51ff0b383 --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/branch_create.json @@ -0,0 +1,50 @@ +{ + "trigger": "branch_created", + "repo": { + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" + }, + "principal": { + "id": 8, + "uid": "0osgWsTZRsSZ8RWfjLRkEg", + "display_name": "default", + "email": "default@harness.io", + "type": "user", + "created": 1675390885380, + "updated": 1675390885380 + }, + "ref": { + "name": "refs/heads/new2", + "repo": { + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" + } + }, + "sha": "aeafa0e2e4ec6909ad75cb8fad57c0b1eb5986e6", + "commit": { + "sha": "aeafa0e2e4ec6909ad75cb8fad57c0b1eb5986e6", + "message": "version 4", + "author": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-02-01T13:21:15-08:00" + }, + "committer": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-02-01T13:21:15-08:00" + } + }, + "old_sha": "0000000000000000000000000000000000000000", + "forced": false +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/branch_create.json.golden b/scm/driver/harness/testdata/webhooks/branch_create.json.golden new file mode 100644 index 000000000..00e4ce11b --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/branch_create.json.golden @@ -0,0 +1,43 @@ +{ + "Ref": "aeafa0e2e4ec6909ad75cb8fad57c0b1eb5986e6", + "Before": "0000000000000000000000000000000000000000", + "After": "aeafa0e2e4ec6909ad75cb8fad57c0b1eb5986e6", + "Repo": { + "ID": "", + "Namespace": "", + "Name": "aba", + "Perm": null, + "Branch": "", + "Private": false, + "Clone": "", + "CloneSSH": "", + "Link": "", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Commit": { + "Sha": "aeafa0e2e4ec6909ad75cb8fad57c0b1eb5986e6", + "Message": "version 4", + "Author": { + "Name": "Admin", + "Email": "admin@harness.io", + "Date": "0001-01-01T00:00:00Z", + "Login": "", + "Avatar": "" + }, + "Committer": { + "Name": "", + "Email": "", + "Date": "0001-01-01T00:00:00Z", + "Login": "", + "Avatar": "" + }, + "Link": "" + }, + "Sender": { + "Login": "", + "Name": "default", + "Email": "", + "Avatar": "" + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json new file mode 100644 index 000000000..7509798e9 --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json @@ -0,0 +1,71 @@ +{ + "trigger": "pullreq_branch_updated", + "repo": { + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" + }, + "principal": { + "id": 8, + "uid": "0osgWsTZRsSZ8RWfjLRkEg", + "display_name": "default", + "email": "default@harness.io", + "type": "user", + "created": 1675390885380, + "updated": 1675390885380 + }, + "pull_req": { + "number": 4, + "state": "open", + "is_draft": false, + "title": "aw", + "source_repo_id": 13, + "source_branch": "b", + "target_repo_id": 13, + "target_branch": "main", + "merge_strategy": null + }, + "target_ref": { + "name": "refs/heads/main", + "repo": { + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" + } + }, + "ref": { + "name": "refs/heads/b", + "repo": { + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" + } + }, + "sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef", + "commit": { + "sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef", + "message": "updated b2", + "author": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-02-01T13:28:55-08:00" + }, + "committer": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-02-01T13:28:55-08:00" + } + }, + "old_sha": "d74b1ebfe520ac01b209dd9085f005884cc9f4cd", + "forced": false +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden new file mode 100644 index 000000000..d978a3b13 --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/pull_request_branch_updated.json.golden @@ -0,0 +1,42 @@ +{ + "Action": "updated", + "Repo": { + "ID": "aba", + "Namespace": "", + "Name": "", + "Branch": "main", + "Private": false, + "Clone": "", + "CloneSSH": "", + "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 4, + "Title": "aw", + "Body": "", + "Sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef", + "Ref": "", + "Source": "13", + "Target": "13", + "Fork": "fork", + "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", + "Closed": false, + "Merged": false, + "Author": { + "Login": "", + "Name": "", + "Email": "", + "Avatar": "" + }, + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Sender": { + "Login": "", + "Name": "", + "Email": "default@harness.io", + "Avatar": "" + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_opened.json b/scm/driver/harness/testdata/webhooks/pull_request_opened.json index 9244c2035..a7fd7666b 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_opened.json +++ b/scm/driver/harness/testdata/webhooks/pull_request_opened.json @@ -1,172 +1,69 @@ { - "secret": "12345", - "action": "opened", - "number": 1, - "pull_request": { - "id": 473, - "url": "", - "number": 1, - "user": { - "id": 6641, - "login": "jcitizen", - "full_name": "", - "email": "jane@example.com", - "avatar_url": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon", - "language": "en-US", - "username": "jcitizen" - }, - "title": "Add License File", - "body": "Using a BSD License", - "labels": [], - "milestone": null, - "assignee": null, - "assignees": null, - "state": "open", - "comments": 0, - "html_url": "https://try.gitea.io/jcitizen/my-repo/pulls/1", - "diff_url": "https://try.gitea.io/jcitizen/my-repo/pulls/1.diff", - "patch_url": "https://try.gitea.io/jcitizen/my-repo/pulls/1.patch", - "mergeable": true, - "merged": false, - "merged_at": null, - "merge_commit_sha": null, - "merged_by": null, - "base": { - "label": "master", - "ref": "master", - "sha": "39af58f1eff02aa308e16913e887c8d50362b474", - "repo_id": 6589, + "trigger": "pullreq_created", + "repo": { + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" + }, + "principal": { + "id": 8, + "uid": "0osgWsTZRsSZ8RWfjLRkEg", + "display_name": "default", + "email": "default@harness.io", + "type": "user", + "created": 1675390885380, + "updated": 1675390885380 + }, + "pull_req": { + "number": 4, + "state": "open", + "is_draft": false, + "title": "aw", + "source_repo_id": 13, + "source_branch": "b", + "target_repo_id": 13, + "target_branch": "main", + "merge_strategy": null + }, + "target_ref": { + "name": "refs/heads/main", "repo": { - "id": 6589, - "owner": { - "id": 6641, - "login": "jcitizen", - "full_name": "", - "email": "jane@example.com", - "avatar_url": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon", - "language": "en-US", - "username": "jcitizen" - }, - "name": "my-repo", - "full_name": "jcitizen/my-repo", - "description": "", - "empty": false, - "private": false, - "fork": false, - "parent": null, - "mirror": false, - "size": 64, - "html_url": "https://try.gitea.io/jcitizen/my-repo", - "ssh_url": "git@try.gitea.io:jcitizen/my-repo.git", - "clone_url": "https://try.gitea.io/jcitizen/my-repo.git", - "website": "", - "stars_count": 0, - "forks_count": 0, - "watchers_count": 1, - "open_issues_count": 0, - "default_branch": "master", - "created_at": "2018-07-06T00:08:02Z", - "updated_at": "2018-07-06T01:06:56Z", - "permissions": { - "admin": false, - "push": false, - "pull": false - } + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" } - }, - "head": { - "label": "feature", - "ref": "feature", - "sha": "2eba238e33607c1fa49253182e9fff42baafa1eb", - "repo_id": 6589, + }, + "ref": { + "name": "refs/heads/b", "repo": { - "id": 6589, - "owner": { - "id": 6641, - "login": "jcitizen", - "full_name": "", - "email": "jane@example.com", - "avatar_url": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon", - "language": "en-US", - "username": "jcitizen" - }, - "name": "my-repo", - "full_name": "jcitizen/my-repo", - "description": "", - "empty": false, - "private": false, - "fork": false, - "parent": null, - "mirror": false, - "size": 64, - "html_url": "https://try.gitea.io/jcitizen/my-repo", - "ssh_url": "git@try.gitea.io:jcitizen/my-repo.git", - "clone_url": "https://try.gitea.io/jcitizen/my-repo.git", - "website": "", - "stars_count": 0, - "forks_count": 0, - "watchers_count": 1, - "open_issues_count": 0, - "default_branch": "master", - "created_at": "2018-07-06T00:08:02Z", - "updated_at": "2018-07-06T01:06:56Z", - "permissions": { - "admin": false, - "push": false, - "pull": false - } + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" } - }, - "merge_base": "39af58f1eff02aa308e16913e887c8d50362b474", - "due_date": null, - "created_at": "2018-07-06T00:37:47Z", - "updated_at": "2018-07-06T00:37:47Z", - "closed_at": null - }, - "repository": { - "id": 6589, - "owner": { - "id": 6641, - "login": "jcitizen", - "full_name": "", - "email": "jane@example.com", - "avatar_url": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon", - "language": "en-US", - "username": "jcitizen" - }, - "name": "my-repo", - "full_name": "jcitizen/my-repo", - "description": "", - "empty": false, - "private": false, - "fork": false, - "parent": null, - "mirror": false, - "size": 64, - "html_url": "https://try.gitea.io/jcitizen/my-repo", - "ssh_url": "git@try.gitea.io:jcitizen/my-repo.git", - "clone_url": "https://try.gitea.io/jcitizen/my-repo.git", - "website": "", - "stars_count": 0, - "forks_count": 0, - "watchers_count": 1, - "open_issues_count": 0, - "default_branch": "master", - "created_at": "2018-07-06T00:08:02Z", - "updated_at": "2018-07-06T01:06:56Z", - "permissions": { - "admin": false, - "push": false, - "pull": false - } }, - "sender": { - "id": 6641, - "login": "jcitizen", - "full_name": "", - "email": "jane@example.com", - "avatar_url": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon", - "language": "en-US", - "username": "jcitizen" + "sha": "d74b1ebfe520ac01b209dd9085f005884cc9f4cd", + "commit": { + "sha": "d74b1ebfe520ac01b209dd9085f005884cc9f4cd", + "message": "Update b.txt", + "author": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-01-31T22:01:55-08:00" + }, + "committer": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-01-31T22:01:55-08:00" + } } } \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden index b44944b2d..936a53c7a 100644 --- a/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden +++ b/scm/driver/harness/testdata/webhooks/pull_request_opened.json.golden @@ -1,47 +1,42 @@ { - "Action": "opened", + "Action": "created", "Repo": { - "ID": "6589", - "Namespace": "jcitizen", - "Name": "my-repo", - "Perm": { - "Pull": false, - "Push": false, - "Admin": false - }, - "Branch": "master", + "ID": "aba", + "Namespace": "", + "Name": "", + "Branch": "main", "Private": false, - "Clone": "https://try.gitea.io/jcitizen/my-repo.git", - "CloneSSH": "git@try.gitea.io:jcitizen/my-repo.git", - "Link": "https://try.gitea.io/jcitizen/my-repo", + "Clone": "", + "CloneSSH": "", + "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", "Created": "0001-01-01T00:00:00Z", "Updated": "0001-01-01T00:00:00Z" }, "PullRequest": { - "Number": 1, - "Title": "Add License File", - "Body": "Using a BSD License", - "Sha": "2eba238e33607c1fa49253182e9fff42baafa1eb", - "Ref": "refs/pull/1/head", - "Source": "feature", - "Target": "master", - "Fork": "jcitizen/my-repo", - "Link": "https://try.gitea.io/jcitizen/my-repo/pulls/1", + "Number": 4, + "Title": "aw", + "Body": "", + "Sha": "d74b1ebfe520ac01b209dd9085f005884cc9f4cd", + "Ref": "", + "Source": "13", + "Target": "13", + "Fork": "fork", + "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", "Closed": false, "Merged": false, "Author": { - "Login": "jcitizen", + "Login": "", "Name": "", - "Email": "jane@example.com", - "Avatar": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon" + "Email": "", + "Avatar": "" }, "Created": "0001-01-01T00:00:00Z", "Updated": "0001-01-01T00:00:00Z" }, "Sender": { - "Login": "jcitizen", + "Login": "", "Name": "", - "Email": "jane@example.com", - "Avatar": "https://secure.gravatar.com/avatar/66f07ff48e6a9cb393de7a34e03bb52a?d=identicon" + "Email": "default@harness.io", + "Avatar": "" } } \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_reopened.json b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json new file mode 100644 index 000000000..c6549d374 --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json @@ -0,0 +1,69 @@ +{ + "trigger": "pullreq_reopened", + "repo": { + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" + }, + "principal": { + "id": 8, + "uid": "0osgWsTZRsSZ8RWfjLRkEg", + "display_name": "default", + "email": "default@harness.io", + "type": "user", + "created": 1675390885380, + "updated": 1675390885380 + }, + "pull_req": { + "number": 4, + "state": "open", + "is_draft": false, + "title": "aw", + "source_repo_id": 13, + "source_branch": "b", + "target_repo_id": 13, + "target_branch": "main", + "merge_strategy": null + }, + "target_ref": { + "name": "refs/heads/main", + "repo": { + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" + } + }, + "ref": { + "name": "refs/heads/b", + "repo": { + "id": 13, + "path": "kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba", + "uid": "aba", + "default_branch": "main", + "git_url": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git" + } + }, + "sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef", + "commit": { + "sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef", + "message": "updated b2", + "author": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-02-01T13:28:55-08:00" + }, + "committer": { + "identity": { + "name": "Admin", + "email": "admin@harness.io" + }, + "when": "2023-02-01T13:28:55-08:00" + } + } +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden new file mode 100644 index 000000000..17b0f8657 --- /dev/null +++ b/scm/driver/harness/testdata/webhooks/pull_request_reopened.json.golden @@ -0,0 +1,42 @@ +{ + "Action": "reopened", + "Repo": { + "ID": "aba", + "Namespace": "", + "Name": "", + "Branch": "main", + "Private": false, + "Clone": "", + "CloneSSH": "", + "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "PullRequest": { + "Number": 4, + "Title": "aw", + "Body": "", + "Sha": "f74f3d2a88d1b7cb19ff3bf069aa423763d341ef", + "Ref": "", + "Source": "13", + "Target": "13", + "Fork": "fork", + "Link": "http://localhost:3000/git/kmpySmUISimoRrJL6NL73w/myOrg/myProject/aba.git", + "Closed": false, + "Merged": false, + "Author": { + "Login": "", + "Name": "", + "Email": "", + "Avatar": "" + }, + "Created": "0001-01-01T00:00:00Z", + "Updated": "0001-01-01T00:00:00Z" + }, + "Sender": { + "Login": "", + "Name": "", + "Email": "default@harness.io", + "Avatar": "" + } +} \ No newline at end of file diff --git a/scm/driver/harness/webhook.go b/scm/driver/harness/webhook.go index 4f7bc187c..6b8c2777e 100644 --- a/scm/driver/harness/webhook.go +++ b/scm/driver/harness/webhook.go @@ -29,18 +29,16 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo } var hook scm.Webhook - switch req.Header.Get("X-Gitea-Event") { - case "push": + switch req.Header.Get("X-Harness-Trigger") { + // case "create": + // hook, err = s.parseCreateHook(data) + // case "delete": + // hook, err = s.parseDeleteHook(data) + // case "issues": + // hook, err = s.parseIssueHook(data) + case "branch_created": hook, err = s.parsePushHook(data) - case "create": - hook, err = s.parseCreateHook(data) - case "delete": - hook, err = s.parseDeleteHook(data) - case "issues": - hook, err = s.parseIssueHook(data) - case "issue_comment": - hook, err = s.parseIssueCommentHook(data) - case "pull_request": + case "pullreq_created", "pullreq_reopened", "pullreq_branch_updated": hook, err = s.parsePullRequestHook(data) default: return nil, scm.ErrUnknownEvent @@ -80,102 +78,106 @@ func (s *webhookService) Parse(req *http.Request, fn scm.SecretFunc) (scm.Webhoo return hook, nil } -func (s *webhookService) parsePushHook(data []byte) (scm.Webhook, error) { - dst := new(pushHook) - err := json.Unmarshal(data, dst) - return convertPushHook(dst), err -} - -func (s *webhookService) parseCreateHook(data []byte) (scm.Webhook, error) { - dst := new(createHook) - err := json.Unmarshal(data, dst) - switch dst.RefType { - case "tag": - return convertTagHook(dst, scm.ActionCreate), err - case "branch": - return convertBranchHook(dst, scm.ActionCreate), err - default: - return nil, scm.ErrUnknownEvent - } -} - -func (s *webhookService) parseDeleteHook(data []byte) (scm.Webhook, error) { - dst := new(createHook) - err := json.Unmarshal(data, dst) - switch dst.RefType { - case "tag": - return convertTagHook(dst, scm.ActionDelete), err - case "branch": - return convertBranchHook(dst, scm.ActionDelete), err - default: - return nil, scm.ErrUnknownEvent - } -} - -func (s *webhookService) parseIssueHook(data []byte) (scm.Webhook, error) { - dst := new(issueHook) - err := json.Unmarshal(data, dst) - return convertIssueHook(dst), err -} - -func (s *webhookService) parseIssueCommentHook(data []byte) (scm.Webhook, error) { - dst := new(issueHook) - err := json.Unmarshal(data, dst) - if dst.Issue.PullRequest != nil { - return convertPullRequestCommentHook(dst), err - } - return convertIssueCommentHook(dst), err -} - func (s *webhookService) parsePullRequestHook(data []byte) (scm.Webhook, error) { dst := new(pullRequestHook) err := json.Unmarshal(data, dst) return convertPullRequestHook(dst), err } -// -// native data structures -// +func (s *webhookService) parsePushHook(data []byte) (scm.Webhook, error) { + dst := new(pushHook) + err := json.Unmarshal(data, dst) + return convertPushHook(dst), err +} +// native data structures type ( - // gitea push webhook payload - pushHook struct { - Ref string `json:"ref"` - Before string `json:"before"` - After string `json:"after"` - Compare string `json:"compare_url"` - Commits []commit `json:"commits"` - Repository repository `json:"repository"` - Pusher user `json:"pusher"` - Sender user `json:"sender"` - } - - // gitea create webhook payload - createHook struct { - Ref string `json:"ref"` - RefType string `json:"ref_type"` - Sha string `json:"sha"` - DefaultBranch string `json:"default_branch"` - Repository repository `json:"repository"` - Sender user `json:"sender"` - } - - // gitea issue webhook payload - issueHook struct { - Action string `json:"action"` - Issue issue `json:"issue"` - Comment issueComment `json:"comment"` - Repository repository `json:"repository"` - Sender user `json:"sender"` - } - - // gitea pull request webhook payload + repo struct { + ID int `json:"id"` + Path string `json:"path"` + UID string `json:"uid"` + DefaultBranch string `json:"default_branch"` + GitURL string `json:"git_url"` + } + principal struct { + ID int `json:"id"` + UID string `json:"uid"` + DisplayName string `json:"display_name"` + Email string `json:"email"` + Type string `json:"type"` + Created int64 `json:"created"` + Updated int64 `json:"updated"` + } + pullReq struct { + Number int `json:"number"` + State string `json:"state"` + IsDraft bool `json:"is_draft"` + Title string `json:"title"` + SourceRepoID int `json:"source_repo_id"` + SourceBranch string `json:"source_branch"` + TargetRepoID int `json:"target_repo_id"` + TargetBranch string `json:"target_branch"` + MergeStrategy interface{} `json:"merge_strategy"` + } + targetRef struct { + Name string `json:"name"` + Repo struct { + ID int `json:"id"` + Path string `json:"path"` + UID string `json:"uid"` + DefaultBranch string `json:"default_branch"` + GitURL string `json:"git_url"` + } `json:"repo"` + } + ref struct { + Name string `json:"name"` + Repo struct { + ID int `json:"id"` + Path string `json:"path"` + UID string `json:"uid"` + DefaultBranch string `json:"default_branch"` + GitURL string `json:"git_url"` + } `json:"repo"` + } + hookCommit struct { + Sha string `json:"sha"` + Message string `json:"message"` + Author struct { + Identity struct { + Name string `json:"name"` + Email string `json:"email"` + } `json:"identity"` + When string `json:"when"` + } `json:"author"` + Committer struct { + Identity struct { + Name string `json:"name"` + Email string `json:"email"` + } `json:"identity"` + When string `json:"when"` + } `json:"committer"` + } + // harness pull request webhook payload pullRequestHook struct { - Action string `json:"action"` - Number int `json:"number"` - PullRequest pr `json:"pull_request"` - Repository repository `json:"repository"` - Sender user `json:"sender"` + Trigger string `json:"trigger"` + Repo repo `json:"repo"` + Principal principal `json:"principal"` + PullReq pullReq `json:"pull_req"` + TargetRef targetRef `json:"target_ref"` + Ref ref `json:"ref"` + Sha string `json:"sha"` + Commit hookCommit `json:"commit"` + } + // harness push webhook payload + pushHook struct { + Trigger string `json:"trigger"` + Repo repo `json:"repo"` + Principal principal `json:"principal"` + Ref ref `json:"ref"` + Commit hookCommit `json:"commit"` + Sha string `json:"sha"` + OldSha string `json:"old_sha"` + Forced bool `json:"forced"` } ) @@ -183,178 +185,60 @@ type ( // native data structure conversion // -func convertTagHook(dst *createHook, action scm.Action) *scm.TagHook { - return &scm.TagHook{ - Action: action, - Ref: scm.Reference{ - Name: dst.Ref, - Sha: dst.Sha, +func convertPullRequestHook(dst *pullRequestHook) *scm.PullRequestHook { + return &scm.PullRequestHook{ + Action: convertAction(dst.Trigger), + PullRequest: scm.PullRequest{ + Number: dst.PullReq.Number, + Title: dst.PullReq.Title, + Closed: dst.PullReq.State != "open", + Source: fmt.Sprintf("%d", dst.PullReq.SourceRepoID), + Target: fmt.Sprintf("%d", dst.PullReq.TargetRepoID), + Fork: "fork", + Link: dst.Ref.Repo.GitURL, + Sha: dst.Commit.Sha, }, - Repo: *convertRepository(&dst.Repository), - Sender: *convertUser(&dst.Sender), - } -} - -func convertBranchHook(dst *createHook, action scm.Action) *scm.BranchHook { - return &scm.BranchHook{ - Action: action, - Ref: scm.Reference{ - Name: dst.Ref, + Repo: scm.Repository{ + ID: dst.Repo.UID, + Branch: dst.Repo.DefaultBranch, + Link: dst.Repo.GitURL, + }, + Sender: scm.User{ + Email: dst.Principal.Email, }, - Repo: *convertRepository(&dst.Repository), - Sender: *convertUser(&dst.Sender), } } func convertPushHook(dst *pushHook) *scm.PushHook { - if len(dst.Commits) > 0 { - var commits []scm.Commit - for _, c := range dst.Commits { - commits = append(commits, - scm.Commit{ - Sha: c.ID, - Message: c.Message, - Link: c.URL, - Author: scm.Signature{ - Login: c.Author.Username, - Email: c.Author.Email, - Name: c.Author.Name, - Date: c.Timestamp, - }, - Committer: scm.Signature{ - Login: c.Committer.Username, - Email: c.Committer.Email, - Name: c.Committer.Name, - Date: c.Timestamp, - }, - }) - } - - return &scm.PushHook{ - Ref: dst.Ref, - Before: dst.Before, - Commit: scm.Commit{ - Sha: dst.After, - Message: dst.Commits[0].Message, - Link: dst.Compare, - Author: scm.Signature{ - Login: dst.Commits[0].Author.Username, - Email: dst.Commits[0].Author.Email, - Name: dst.Commits[0].Author.Name, - Date: dst.Commits[0].Timestamp, - }, - Committer: scm.Signature{ - Login: dst.Commits[0].Committer.Username, - Email: dst.Commits[0].Committer.Email, - Name: dst.Commits[0].Committer.Name, - Date: dst.Commits[0].Timestamp, - }, - }, - Commits: commits, - Repo: *convertRepository(&dst.Repository), - Sender: *convertUser(&dst.Sender), - } - } return &scm.PushHook{ - Ref: dst.Ref, + Ref: dst.Sha, + Before: dst.OldSha, + After: dst.Sha, + Repo: scm.Repository{ + Name: dst.Repo.UID, + }, Commit: scm.Commit{ - Sha: dst.After, - Link: dst.Compare, + Sha: dst.Commit.Sha, + Message: dst.Commit.Message, Author: scm.Signature{ - Login: dst.Pusher.Login, - Email: dst.Pusher.Email, - Name: dst.Pusher.Fullname, - }, - Committer: scm.Signature{ - Login: dst.Pusher.Login, - Email: dst.Pusher.Email, - Name: dst.Pusher.Fullname, + Name: dst.Commit.Author.Identity.Name, + Email: dst.Commit.Author.Identity.Email, }, }, - Repo: *convertRepository(&dst.Repository), - Sender: *convertUser(&dst.Sender), - } -} - -func convertPullRequestHook(dst *pullRequestHook) *scm.PullRequestHook { - return &scm.PullRequestHook{ - Action: convertAction(dst.Action), - PullRequest: scm.PullRequest{ - Number: dst.PullRequest.Number, - Title: dst.PullRequest.Title, - Body: dst.PullRequest.Body, - Closed: dst.PullRequest.State == "closed", - Author: scm.User{ - Login: dst.PullRequest.User.Login, - Email: dst.PullRequest.User.Email, - Avatar: dst.PullRequest.User.Avatar, - }, - Merged: dst.PullRequest.Merged, - // Created: nil, - // Updated: nil, - Source: dst.PullRequest.Head.Name, - Target: dst.PullRequest.Base.Name, - Fork: "fork", - Link: dst.PullRequest.HTMLURL, - Ref: fmt.Sprintf("refs/pull/%d/head", dst.PullRequest.Number), - Sha: dst.PullRequest.Head.Sha, + Sender: scm.User{ + Name: dst.Principal.DisplayName, }, - Repo: *convertRepository(&dst.Repository), - Sender: *convertUser(&dst.Sender), - } -} - -func convertPullRequestCommentHook(dst *issueHook) *scm.PullRequestCommentHook { - return &scm.PullRequestCommentHook{ - Action: convertAction(dst.Action), - PullRequest: *convertPullRequestFromIssue(&dst.Issue), - Comment: *convertIssueComment(&dst.Comment), - Repo: *convertRepository(&dst.Repository), - Sender: *convertUser(&dst.Sender), - } -} - -func convertIssueHook(dst *issueHook) *scm.IssueHook { - return &scm.IssueHook{ - Action: convertAction(dst.Action), - Issue: *convertIssue(&dst.Issue), - Repo: *convertRepository(&dst.Repository), - Sender: *convertUser(&dst.Sender), - } -} - -func convertIssueCommentHook(dst *issueHook) *scm.IssueCommentHook { - return &scm.IssueCommentHook{ - Action: convertAction(dst.Action), - Issue: *convertIssue(&dst.Issue), - Comment: *convertIssueComment(&dst.Comment), - Repo: *convertRepository(&dst.Repository), - Sender: *convertUser(&dst.Sender), } } func convertAction(src string) (action scm.Action) { switch src { - case "create", "created": + case "pullreq_created": return scm.ActionCreate - case "delete", "deleted": - return scm.ActionDelete - case "update", "updated", "edit", "edited": + case "pullreq_branch_updated": return scm.ActionUpdate - case "open", "opened": - return scm.ActionOpen - case "reopen", "reopened": + case "pullreq_reopened": return scm.ActionReopen - case "close", "closed": - return scm.ActionClose - case "label", "labeled": - return scm.ActionLabel - case "unlabel", "unlabeled": - return scm.ActionUnlabel - case "merge", "merged": - return scm.ActionMerge - case "synchronize", "synchronized": - return scm.ActionSync default: return } diff --git a/scm/driver/harness/webhook_test.go b/scm/driver/harness/webhook_test.go index 5d232e2ff..4e38687be 100644 --- a/scm/driver/harness/webhook_test.go +++ b/scm/driver/harness/webhook_test.go @@ -3,3 +3,116 @@ // license that can be found in the LICENSE file. package harness + +import ( + "bytes" + "encoding/json" + "io/ioutil" + "net/http" + "os" + "testing" + + "github.com/drone/go-scm/scm" + "github.com/google/go-cmp/cmp" +) + +func TestWebhooks(t *testing.T) { + tests := []struct { + event string + before string + after string + obj interface{} + }{ + // + // branch events + // + // push branch create + { + event: "branch_created", + before: "testdata/webhooks/branch_create.json", + after: "testdata/webhooks/branch_create.json.golden", + obj: new(scm.PushHook), + }, + // + // pull request events + // + // pull request opened + { + event: "pullreq_created", + before: "testdata/webhooks/pull_request_opened.json", + after: "testdata/webhooks/pull_request_opened.json.golden", + obj: new(scm.PullRequestHook), + }, + // pull request reopened + { + event: "pullreq_reopened", + before: "testdata/webhooks/pull_request_reopened.json", + after: "testdata/webhooks/pull_request_reopened.json.golden", + obj: new(scm.PullRequestHook), + }, + // pull request branch updated + { + event: "pullreq_branch_updated", + before: "testdata/webhooks/pull_request_branch_updated.json", + after: "testdata/webhooks/pull_request_branch_updated.json.golden", + obj: new(scm.PullRequestHook), + }, + } + + for _, test := range tests { + before, err := ioutil.ReadFile(test.before) + if err != nil { + t.Error(err) + continue + } + after, err := ioutil.ReadFile(test.after) + if err != nil { + t.Error(err) + continue + } + + buf := bytes.NewBuffer(before) + r, _ := http.NewRequest("GET", "/", buf) + r.Header.Set("X-Harness-Trigger", test.event) + + s := new(webhookService) + o, err := s.Parse(r, secretFunc) + if err != nil && err != scm.ErrSignatureInvalid { + t.Error(err) + continue + } + + err = json.Unmarshal(after, test.obj) + if err != nil { + t.Error(err) + continue + } + + if diff := cmp.Diff(test.obj, o); diff != "" { + t.Errorf("Error unmarshaling %s", test.before) + t.Log(diff) + + // debug only. remove once implemented + _ = json.NewEncoder(os.Stdout).Encode(o) + + } + + // switch event := o.(type) { + // case *scm.PushHook: + // if !strings.HasPrefix(event.Ref, "refs/") { + // t.Errorf("Push hook reference must start with refs/") + // } + // case *scm.BranchHook: + // if strings.HasPrefix(event.Ref.Name, "refs/") { + // t.Errorf("Branch hook reference must not start with refs/") + // } + // case *scm.TagHook: + // if strings.HasPrefix(event.Ref.Name, "refs/") { + // t.Errorf("Branch hook reference must not start with refs/") + // } + // } + } +} +func secretFunc(scm.Webhook) (string, error) { + return "topsecret", nil +} From ff7deab27e87e4fede0a76c9443163e164f4322c Mon Sep 17 00:00:00 2001 From: TP Honey Date: Wed, 8 Feb 2023 14:51:40 +0000 Subject: [PATCH 2/4] (feat) harness, add list webhooks --- scm/driver/harness/repo.go | 42 ++++++++++++++++++- scm/driver/harness/repo_test.go | 38 +++++++++++++++++ scm/driver/harness/testdata/hooks.json | 19 +++++++++ scm/driver/harness/testdata/hooks.json.golden | 10 +++++ 4 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 scm/driver/harness/testdata/hooks.json create mode 100644 scm/driver/harness/testdata/hooks.json.golden diff --git a/scm/driver/harness/repo.go b/scm/driver/harness/repo.go index 33fbc832c..5046d56c2 100644 --- a/scm/driver/harness/repo.go +++ b/scm/driver/harness/repo.go @@ -49,7 +49,11 @@ func (s *repositoryService) List(ctx context.Context, opts scm.ListOptions) ([]* } func (s *repositoryService) ListHooks(ctx context.Context, repo string, opts scm.ListOptions) ([]*scm.Hook, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s/webhooks?sort=display_name&order=asc&%s", harnessURI, encodeListOptions(opts)) + out := []*hook{} + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertHookList(out), res, err } func (s *repositoryService) ListStatus(ctx context.Context, repo string, ref string, opts scm.ListOptions) ([]*scm.Status, *scm.Response, error) { @@ -97,6 +101,23 @@ type ( NumMergedPulls int `json:"num_merged_pulls"` GitURL string `json:"git_url"` } + hook struct { + Created int `json:"created"` + CreatedBy int `json:"created_by"` + Description string `json:"description"` + DisplayName string `json:"display_name"` + Enabled bool `json:"enabled"` + HasSecret bool `json:"has_secret"` + ID int `json:"id"` + Insecure bool `json:"insecure"` + LatestExecutionResult string `json:"latest_execution_result"` + ParentID int `json:"parent_id"` + ParentType string `json:"parent_type"` + Triggers []string `json:"triggers"` + Updated int `json:"updated"` + URL string `json:"url"` + Version int `json:"version"` + } ) // @@ -125,3 +146,22 @@ func convertRepository(src *repository) *scm.Repository { // Updated: time.Unix(src.Updated, 0), } } + +func convertHookList(from []*hook) []*scm.Hook { + to := []*scm.Hook{} + for _, v := range from { + to = append(to, convertHook(v)) + } + return to +} + +func convertHook(from *hook) *scm.Hook { + return &scm.Hook{ + ID: strconv.Itoa(from.ID), + Name: from.DisplayName, + Active: from.Enabled, + Target: from.URL, + Events: from.Triggers, + SkipVerify: from.Insecure, + } +} diff --git a/scm/driver/harness/repo_test.go b/scm/driver/harness/repo_test.go index 812866cba..777aadbc2 100644 --- a/scm/driver/harness/repo_test.go +++ b/scm/driver/harness/repo_test.go @@ -89,3 +89,41 @@ func TestRepositoryList(t *testing.T) { t.Log(diff) } } + +func TestRepositoryHookList(t *testing.T) { + if harnessPAT == "" { + defer gock.Off() + + gock.New(gockOrigin). + Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/webhooks"). + MatchParam("page", "1"). + MatchParam("limit", "30"). + MatchParam("sort", "display_name"). + MatchParam("order", "asc"). + Reply(200). + Type("application/json"). + File("testdata/hooks.json") + } + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + got, _, err := client.Repositories.ListHooks(context.Background(), harnessRepo, scm.ListOptions{Page: 1, Size: 30}) + if err != nil { + t.Error(err) + return + } + + want := []*scm.Hook{} + raw, _ := ioutil.ReadFile("testdata/hooks.json.golden") + _ = json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} diff --git a/scm/driver/harness/testdata/hooks.json b/scm/driver/harness/testdata/hooks.json new file mode 100644 index 000000000..372ad34a7 --- /dev/null +++ b/scm/driver/harness/testdata/hooks.json @@ -0,0 +1,19 @@ +[ + { + "id": 6, + "version": 1, + "parent_id": 11, + "parent_type": "repo", + "created_by": 14, + "created": 1675867490853, + "updated": 1675867531549, + "display_name": "webhookname", + "description": "webhookdescription", + "url": "http://1.1.1.1", + "enabled": true, + "insecure": true, + "triggers": [], + "latest_execution_result": "success", + "has_secret": true + } +] \ No newline at end of file diff --git a/scm/driver/harness/testdata/hooks.json.golden b/scm/driver/harness/testdata/hooks.json.golden new file mode 100644 index 000000000..f21533cbe --- /dev/null +++ b/scm/driver/harness/testdata/hooks.json.golden @@ -0,0 +1,10 @@ +[ + { + "ID": "6", + "Name": "webhookname", + "Target": "http://1.1.1.1", + "Events": [], + "Active": true, + "SkipVerify": true + } +] \ No newline at end of file From b8eea16f4bb0ef6038e0b6747511fbf12d2ec41f Mon Sep 17 00:00:00 2001 From: TP Honey Date: Wed, 8 Feb 2023 15:34:10 +0000 Subject: [PATCH 3/4] (feat) harness, add find hook --- scm/driver/harness/repo.go | 6 +++- scm/driver/harness/repo_test.go | 34 ++++++++++++++++++++ scm/driver/harness/testdata/hook.json | 17 ++++++++++ scm/driver/harness/testdata/hook.json.golden | 8 +++++ 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 scm/driver/harness/testdata/hook.json create mode 100644 scm/driver/harness/testdata/hook.json.golden diff --git a/scm/driver/harness/repo.go b/scm/driver/harness/repo.go index 5046d56c2..289d85e23 100644 --- a/scm/driver/harness/repo.go +++ b/scm/driver/harness/repo.go @@ -33,7 +33,11 @@ func (s *repositoryService) Find(ctx context.Context, repo string) (*scm.Reposit } func (s *repositoryService) FindHook(ctx context.Context, repo string, id string) (*scm.Hook, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s/webhooks/%s", harnessURI, id) + out := new(hook) + res, err := s.client.do(ctx, "GET", path, nil, &out) + return convertHook(out), res, err } func (s *repositoryService) FindPerms(ctx context.Context, repo string) (*scm.Perm, *scm.Response, error) { diff --git a/scm/driver/harness/repo_test.go b/scm/driver/harness/repo_test.go index 777aadbc2..082dbb4f1 100644 --- a/scm/driver/harness/repo_test.go +++ b/scm/driver/harness/repo_test.go @@ -127,3 +127,37 @@ func TestRepositoryHookList(t *testing.T) { t.Log(diff) } } + +func TestRepositoryFindHook(t *testing.T) { + if harnessPAT == "" { + defer gock.Off() + + gock.New(gockOrigin). + Get("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/webhooks/6"). + Reply(200). + Type("application/json"). + File("testdata/hook.json") + } + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + got, _, err := client.Repositories.FindHook(context.Background(), harnessRepo, "6") + if err != nil { + t.Error(err) + return + } + + want := new(scm.Hook) + raw, _ := ioutil.ReadFile("testdata/hook.json.golden") + _ = json.Unmarshal(raw, &want) + + if diff := cmp.Diff(got, want); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } +} diff --git a/scm/driver/harness/testdata/hook.json b/scm/driver/harness/testdata/hook.json new file mode 100644 index 000000000..994de6ed8 --- /dev/null +++ b/scm/driver/harness/testdata/hook.json @@ -0,0 +1,17 @@ +{ + "id": 6, + "version": 1, + "parent_id": 11, + "parent_type": "repo", + "created_by": 14, + "created": 1675867490853, + "updated": 1675867531549, + "display_name": "webhookname", + "description": "webhookdescription", + "url": "http://1.1.1.1", + "enabled": true, + "insecure": true, + "triggers": [], + "latest_execution_result": "success", + "has_secret": true +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/hook.json.golden b/scm/driver/harness/testdata/hook.json.golden new file mode 100644 index 000000000..53463fce4 --- /dev/null +++ b/scm/driver/harness/testdata/hook.json.golden @@ -0,0 +1,8 @@ +{ + "ID": "6", + "Name": "webhookname", + "Target": "http://1.1.1.1", + "Events": [], + "Active": true, + "SkipVerify": true +} \ No newline at end of file From d6e3618f2eb2e2762cbbda158c7ce9aa67e20bf8 Mon Sep 17 00:00:00 2001 From: TP Honey Date: Wed, 8 Feb 2023 16:18:32 +0000 Subject: [PATCH 4/4] (feat) harness, add create / delete webhook --- scm/driver/harness/repo.go | 20 +++++- scm/driver/harness/repo_test.go | 64 +++++++++++++++++++ scm/driver/harness/testdata/hook_create.json | 17 +++++ .../harness/testdata/hook_create.json.golden | 8 +++ 4 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 scm/driver/harness/testdata/hook_create.json create mode 100644 scm/driver/harness/testdata/hook_create.json.golden diff --git a/scm/driver/harness/repo.go b/scm/driver/harness/repo.go index 289d85e23..a55089516 100644 --- a/scm/driver/harness/repo.go +++ b/scm/driver/harness/repo.go @@ -65,7 +65,20 @@ func (s *repositoryService) ListStatus(ctx context.Context, repo string, ref str } func (s *repositoryService) CreateHook(ctx context.Context, repo string, input *scm.HookInput) (*scm.Hook, *scm.Response, error) { - return nil, nil, scm.ErrNotSupported + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s/webhooks", harnessURI) + in := new(hook) + in.Enabled = true + in.DisplayName = input.Name + in.Secret = input.Secret + in.Insecure = input.SkipVerify + in.URL = input.Target + in.Triggers = append( + input.NativeEvents, + ) + out := new(hook) + res, err := s.client.do(ctx, "POST", path, in, out) + return convertHook(out), res, err } func (s *repositoryService) CreateStatus(ctx context.Context, repo string, ref string, input *scm.StatusInput) (*scm.Status, *scm.Response, error) { @@ -77,7 +90,9 @@ func (s *repositoryService) UpdateHook(ctx context.Context, repo, id string, inp } func (s *repositoryService) DeleteHook(ctx context.Context, repo string, id string) (*scm.Response, error) { - return nil, scm.ErrNotSupported + harnessURI := buildHarnessURI(s.client.account, s.client.organization, s.client.project, repo) + path := fmt.Sprintf("api/v1/repos/%s/webhooks/%s", harnessURI, id) + return s.client.do(ctx, "DELETE", path, nil, nil) } // @@ -112,6 +127,7 @@ type ( DisplayName string `json:"display_name"` Enabled bool `json:"enabled"` HasSecret bool `json:"has_secret"` + Secret string `json:"secret"` ID int `json:"id"` Insecure bool `json:"insecure"` LatestExecutionResult string `json:"latest_execution_result"` diff --git a/scm/driver/harness/repo_test.go b/scm/driver/harness/repo_test.go index 082dbb4f1..8cd9a3a22 100644 --- a/scm/driver/harness/repo_test.go +++ b/scm/driver/harness/repo_test.go @@ -7,6 +7,7 @@ package harness import ( "context" "encoding/json" + "fmt" "io/ioutil" "net/http" "testing" @@ -14,6 +15,7 @@ import ( "github.com/drone/go-scm/scm" "github.com/drone/go-scm/scm/transport" "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" "github.com/h2non/gock" ) @@ -161,3 +163,65 @@ func TestRepositoryFindHook(t *testing.T) { t.Log(diff) } } + +func TestRepositoryHookCreateDelete(t *testing.T) { + if harnessPAT == "" { + defer gock.Off() + + gock.New(gockOrigin). + Post("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/webhooks"). + Reply(200). + Type("application/json"). + File("testdata/hook_create.json") + } + client, _ := New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + in := &scm.HookInput{ + Name: "drone", + Target: "https://example.com", + Secret: "topsecret", + SkipVerify: true, + } + got, _, err := client.Repositories.CreateHook(context.Background(), harnessRepo, in) + if err != nil { + t.Error(err) + return + } + + want := new(scm.Hook) + raw, _ := ioutil.ReadFile("testdata/hook_create.json.golden") + _ = json.Unmarshal(raw, want) + + if diff := cmp.Diff(got, want, cmpopts.IgnoreFields(scm.Hook{}, "ID")); diff != "" { + t.Errorf("Unexpected Results") + t.Log(diff) + } + // delete webhook + if harnessPAT == "" { + defer gock.Off() + + gock.New(gockOrigin). + Delete(fmt.Sprintf("/gateway/code/api/v1/repos/px7xd_BFRCi-pfWPYXVjvw/default/codeciintegration/thomas/+/webhooks/%s", got.ID)). + Reply(204) + } + client, _ = New(gockOrigin, harnessOrg, harnessAccount, harnessProject) + client.Client = &http.Client{ + Transport: &transport.Custom{ + Before: func(r *http.Request) { + r.Header.Set("x-api-key", harnessPAT) + }, + }, + } + + _, deleteErr := client.Repositories.DeleteHook(context.Background(), harnessRepo, got.ID) + if deleteErr != nil { + t.Error(deleteErr) + return + } +} diff --git a/scm/driver/harness/testdata/hook_create.json b/scm/driver/harness/testdata/hook_create.json new file mode 100644 index 000000000..131b6d7cb --- /dev/null +++ b/scm/driver/harness/testdata/hook_create.json @@ -0,0 +1,17 @@ +{ + "id": 9, + "version": 1, + "parent_id": 11, + "parent_type": "repo", + "created_by": 14, + "created": 1675872629243, + "updated": 1675872777592, + "display_name": "drone", + "description": "", + "url": "https://example.com", + "enabled": true, + "insecure": true, + "triggers": [], + "latest_execution_result": "success", + "has_secret": true +} \ No newline at end of file diff --git a/scm/driver/harness/testdata/hook_create.json.golden b/scm/driver/harness/testdata/hook_create.json.golden new file mode 100644 index 000000000..06e9a45dc --- /dev/null +++ b/scm/driver/harness/testdata/hook_create.json.golden @@ -0,0 +1,8 @@ +{ + "ID": "9", + "Name": "drone", + "Target": "https://example.com", + "Events": [], + "Active": true, + "SkipVerify": true +} \ No newline at end of file