diff --git a/forge/webhooks.go b/forge/webhooks.go index 3c3abb1..7b82e70 100644 --- a/forge/webhooks.go +++ b/forge/webhooks.go @@ -3,6 +3,8 @@ package forge import ( + "iter" + forgejo "codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v2" "dappco.re/go/core/log" @@ -43,3 +45,29 @@ func (c *Client) ListRepoWebhooks(owner, repo string) ([]*forgejo.Hook, error) { return all, nil } + +// ListRepoWebhooksIter returns an iterator over webhooks for a repository. +// Usage: ListRepoWebhooksIter(...) +func (c *Client) ListRepoWebhooksIter(owner, repo string) iter.Seq2[*forgejo.Hook, error] { + return func(yield func(*forgejo.Hook, error) bool) { + page := 1 + for { + hooks, resp, err := c.api.ListRepoHooks(owner, repo, forgejo.ListHooksOptions{ + ListOptions: forgejo.ListOptions{Page: page, PageSize: 50}, + }) + if err != nil { + yield(nil, log.E("forge.ListRepoWebhooks", "failed to list repo webhooks", err)) + return + } + for _, hook := range hooks { + if !yield(hook, nil) { + return + } + } + if resp == nil || page >= resp.LastPage { + break + } + page++ + } + } +} diff --git a/forge/webhooks_test.go b/forge/webhooks_test.go index c0f34aa..9ebaa4f 100644 --- a/forge/webhooks_test.go +++ b/forge/webhooks_test.go @@ -3,6 +3,8 @@ package forge import ( + "net/http" + "net/http/httptest" "testing" forgejo "codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v2" @@ -53,3 +55,40 @@ func TestClient_ListRepoWebhooks_Bad_ServerError_Good(t *testing.T) { assert.Error(t, err) assert.Contains(t, err.Error(), "failed to list repo webhooks") } + +func TestClient_ListRepoWebhooksIter_Good_Paginates_Good(t *testing.T) { + mux := http.NewServeMux() + mux.HandleFunc("/api/v1/version", func(w http.ResponseWriter, r *http.Request) { + jsonResponse(w, map[string]string{"version": "1.21.0"}) + }) + mux.HandleFunc("/api/v1/repos/test-org/org-repo/hooks", func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Query().Get("page") { + case "2": + jsonResponse(w, []map[string]any{ + {"id": 2, "type": "forgejo", "active": true, "config": map[string]any{"url": "https://example.com/second"}}, + }) + case "3": + jsonResponse(w, []map[string]any{}) + default: + w.Header().Set("Link", "; rel=\"next\", ; rel=\"last\"") + jsonResponse(w, []map[string]any{ + {"id": 1, "type": "forgejo", "active": true, "config": map[string]any{"url": "https://example.com/hook"}}, + }) + } + }) + + srv := httptest.NewServer(mux) + defer srv.Close() + + client, err := New(srv.URL, "test-token") + require.NoError(t, err) + + var urls []string + for hook, err := range client.ListRepoWebhooksIter("test-org", "org-repo") { + require.NoError(t, err) + urls = append(urls, hook.Config["url"]) + } + + require.Len(t, urls, 2) + assert.Equal(t, []string{"https://example.com/hook", "https://example.com/second"}, urls) +}