From 3ed3ecaf3dd6ba74b53e1a54854c3b8e99eb7445 Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 2 Apr 2026 01:46:07 +0000 Subject: [PATCH] Add repository activity feed listing Co-Authored-By: Virgil --- repos.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ repos_test.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/repos.go b/repos.go index ffb3583..99333ac 100644 --- a/repos.go +++ b/repos.go @@ -6,6 +6,7 @@ import ( "net/http" "net/url" "strconv" + "time" "dappco.re/go/core/forge/types" ) @@ -40,6 +41,20 @@ func (o RepoKeyListOptions) queryParams() map[string]string { return query } +// ActivityFeedListOptions controls filtering for repository activity feeds. +type ActivityFeedListOptions struct { + Date *time.Time +} + +func (o ActivityFeedListOptions) queryParams() map[string]string { + if o.Date == nil { + return nil + } + return map[string]string{ + "date": o.Date.Format("2006-01-02"), + } +} + func newRepoService(c *Client) *RepoService { return &RepoService{ Resource: *NewResource[types.Repository, types.CreateRepoOption, types.EditRepoOption]( @@ -359,6 +374,18 @@ func (s *RepoService) ListIssueTemplates(ctx context.Context, owner, repo string return ListAll[types.IssueTemplate](ctx, s.client, path, nil) } +// ListActivityFeeds returns the repository's activity feed entries. +func (s *RepoService) ListActivityFeeds(ctx context.Context, owner, repo string, filters ...ActivityFeedListOptions) ([]types.Activity, error) { + path := ResolvePath("/api/v1/repos/{owner}/{repo}/activities/feeds", pathParams("owner", owner, "repo", repo)) + return ListAll[types.Activity](ctx, s.client, path, activityFeedQuery(filters...)) +} + +// IterActivityFeeds returns an iterator over the repository's activity feed entries. +func (s *RepoService) IterActivityFeeds(ctx context.Context, owner, repo string, filters ...ActivityFeedListOptions) iter.Seq2[types.Activity, error] { + path := ResolvePath("/api/v1/repos/{owner}/{repo}/activities/feeds", pathParams("owner", owner, "repo", repo)) + return ListIter[types.Activity](ctx, s.client, path, activityFeedQuery(filters...)) +} + // ListTopics returns the topics assigned to a repository. func (s *RepoService) ListTopics(ctx context.Context, owner, repo string) ([]string, error) { path := ResolvePath("/api/v1/repos/{owner}/{repo}/topics", pathParams("owner", owner, "repo", repo)) @@ -673,3 +700,20 @@ func repoKeyQuery(filters ...RepoKeyListOptions) map[string]string { } return query } + +func activityFeedQuery(filters ...ActivityFeedListOptions) map[string]string { + if len(filters) == 0 { + return nil + } + + query := make(map[string]string, 1) + for _, filter := range filters { + if filter.Date != nil { + query["date"] = filter.Date.Format("2006-01-02") + } + } + if len(query) == 0 { + return nil + } + return query +} diff --git a/repos_test.go b/repos_test.go index 4c5ad06..81208bc 100644 --- a/repos_test.go +++ b/repos_test.go @@ -8,10 +8,44 @@ import ( "net/http/httptest" "reflect" "testing" + "time" "dappco.re/go/core/forge/types" ) +func TestRepoService_ListActivityFeeds_Good(t *testing.T) { + date := time.Date(2026, time.April, 2, 15, 4, 5, 0, time.UTC) + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + t.Errorf("expected GET, got %s", r.Method) + } + if r.URL.Path != "/api/v1/repos/core/go-forge/activities/feeds" { + t.Errorf("wrong path: %s", r.URL.Path) + http.NotFound(w, r) + return + } + if got := r.URL.Query().Get("date"); got != "2026-04-02" { + t.Errorf("wrong date: %s", got) + } + w.Header().Set("X-Total-Count", "1") + json.NewEncoder(w).Encode([]types.Activity{{ + ID: 7, + OpType: "create_repo", + Content: "created repository", + }}) + })) + defer srv.Close() + + f := NewForge(srv.URL, "tok") + activities, err := f.Repos.ListActivityFeeds(context.Background(), "core", "go-forge", ActivityFeedListOptions{Date: &date}) + if err != nil { + t.Fatal(err) + } + if len(activities) != 1 || activities[0].ID != 7 || activities[0].OpType != "create_repo" { + t.Fatalf("got %#v", activities) + } +} + func TestRepoService_ListTopics_Good(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet {