diff --git a/lib/parsers/gitea.go b/lib/parsers/gitea.go index 1efa4d1..c350bcd 100644 --- a/lib/parsers/gitea.go +++ b/lib/parsers/gitea.go @@ -1,6 +1,7 @@ package parsers import ( + "encoding/json" "fmt" "io" "net/http" @@ -15,7 +16,7 @@ func giteaWebhookType(r *http.Request) string { } // parseGitea processes a Gitea webhook, extracting branch, repository, and user information. -// Handles "push" events to set relevant fields based on the payload. +// Handles "push" and "delete" events to set relevant fields based on the payload. func (d *Data) parseGitea(c *gin.Context) error { payload, err := io.ReadAll(c.Request.Body) if err != nil { @@ -38,8 +39,38 @@ func (d *Data) parseGitea(c *gin.Context) error { d.RepoUser = e.Repo.Owner.UserName d.Completed = true d.Succeed = true + case "delete": + e, err := parseDeleteHook(payload) + if err != nil { + return api.ErrInvalidReceiveHook + } + d.Branch = e.Ref + d.Deleted = true + d.ModuleName = e.Repo.Name + d.RepoName = e.Repo.FullName + d.RepoUser = e.Repo.Owner.UserName + d.Completed = true + d.Succeed = true default: return fmt.Errorf("unknown event type %s", eventType) } return nil } + +// This function parses a Gitea delete event into a struct of type +// api.DeletePayload for use later. +func parseDeleteHook(raw []byte) (*api.DeletePayload, error) { + hook := new(api.DeletePayload) + if err := json.Unmarshal(raw, hook); err != nil { + return nil, err + } + + switch { + case hook.Repo == nil: + return nil, api.ErrInvalidReceiveHook + case len(hook.Ref) == 0: + return nil, api.ErrInvalidReceiveHook + } + + return hook, nil +} diff --git a/lib/parsers/json/gitea/delete.json b/lib/parsers/json/gitea/delete.json new file mode 100644 index 0000000..417d318 --- /dev/null +++ b/lib/parsers/json/gitea/delete.json @@ -0,0 +1,124 @@ +{ + "ref": "simple-tag", + "ref_type": "branch", + "pusher_type": "user", + "repository": { + "id": 88498, + "owner": { + "id": 28956, + "login": "Codertocat", + "login_name": "", + "source_id": 0, + "full_name": "Codertocat", + "email": "Codertocat@noreply.gitea.com", + "avatar_url": "https://seccdn.libravatar.org/avatar/c046d2737d97e03abb812278e31c1e3d?d=identicon", + "html_url": "https://gitea.com/Codertocat", + "language": "", + "is_admin": false, + "last_login": "0001-01-01T00:00:00Z", + "created": "2021-09-05T21:38:42Z", + "restricted": false, + "active": false, + "prohibit_login": false, + "location": "", + "website": "", + "description": "", + "visibility": "public", + "followers_count": 0, + "following_count": 0, + "starred_repos_count": 0, + "username": "Codertocat" + }, + "name": "Hello-World", + "full_name": "Codertocat/Hello-World", + "description": "", + "empty": false, + "private": true, + "fork": false, + "template": false, + "parent": null, + "mirror": false, + "size": 91, + "language": "", + "languages_url": "https://gitea.com/api/v1/repos/Codertocat/Hello-World/languages", + "html_url": "https://gitea.com/Codertocat/Hello-World", + "url": "https://gitea.com/api/v1/repos/Codertocat/Hello-World", + "link": "", + "ssh_url": "git@gitea.com:Codertocat/Hello-World.git", + "clone_url": "https://gitea.com/Codertocat/Hello-World.git", + "original_url": "", + "website": "", + "stars_count": 0, + "forks_count": 0, + "watchers_count": 1, + "open_issues_count": 0, + "open_pr_counter": 0, + "release_counter": 0, + "default_branch": "main", + "archived": false, + "created_at": "2025-02-03T20:21:08Z", + "updated_at": "2025-02-03T22:33:49Z", + "archived_at": "1970-01-01T00:00:00Z", + "permissions": { + "admin": true, + "push": true, + "pull": true + }, + "has_issues": true, + "internal_tracker": { + "enable_time_tracker": true, + "allow_only_contributors_to_track_time": true, + "enable_issue_dependencies": true + }, + "has_wiki": true, + "has_pull_requests": true, + "has_projects": true, + "projects_mode": "all", + "has_releases": true, + "has_packages": false, + "has_actions": true, + "ignore_whitespace_conflicts": false, + "allow_merge_commits": true, + "allow_rebase": true, + "allow_rebase_explicit": true, + "allow_squash_merge": true, + "allow_fast_forward_only_merge": true, + "allow_rebase_update": true, + "default_delete_branch_after_merge": false, + "default_merge_style": "merge", + "default_allow_maintainer_edit": false, + "avatar_url": "", + "internal": false, + "mirror_interval": "", + "object_format_name": "sha1", + "mirror_updated": "0001-01-01T00:00:00Z", + "repo_transfer": null, + "topics": null, + "licenses": null + }, + "sender": { + "id": 28956, + "login": "Codertocat", + "login_name": "", + "source_id": 0, + "full_name": "Codertocat", + "email": "Codertocat@noreply.gitea.com", + "avatar_url": "https://seccdn.libravatar.org/avatar/c046d2737d97e03abb812278e31c1e3d?d=identicon", + "html_url": "https://gitea.com/Codertocat", + "language": "", + "is_admin": false, + "last_login": "0001-01-01T00:00:00Z", + "created": "2021-09-05T21:38:42Z", + "restricted": false, + "active": false, + "prohibit_login": false, + "location": "", + "website": "", + "description": "", + "visibility": "public", + "followers_count": 0, + "following_count": 0, + "starred_repos_count": 0, + "username": "Codertocat" + } +} diff --git a/lib/parsers/parser_test.go b/lib/parsers/parser_test.go index 713d890..6da4882 100644 --- a/lib/parsers/parser_test.go +++ b/lib/parsers/parser_test.go @@ -477,10 +477,43 @@ func Test_ParseData(t *testing.T) { assert.Error(t, err, "unknown event type fork") }) + + t.Run("Successfully Parsed Delete", func(t *testing.T) { + d := Data{} + + header := []Header{ + { + Name: "X-Gitea-Event", + Value: "delete", + }, + } + + c, _, err := getGinContext("./json/gitea/delete.json", header) + if err != nil { + t.Fatal(err) + } + + err = d.ParseData(c) + + d_base := Data{ + Branch: "simple-tag", + Deleted: true, + ModuleName: "Hello-World", + RepoName: "Codertocat/Hello-World", + RepoUser: "Codertocat", + Completed: true, + Succeed: true, + } + assert.NilError(t, err) + assert.Equal(t, d, d_base) + }) }) } -func getGinContext(filename string, headers []Header) (*gin.Context, *httptest.ResponseRecorder, error) { +func getGinContext( + filename string, + headers []Header, +) (*gin.Context, *httptest.ResponseRecorder, error) { w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w)