feat(forge): add missing collection wrappers
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
597f4e0bb8
commit
49daff2cb6
16 changed files with 611 additions and 3 deletions
21
branches.go
21
branches.go
|
|
@ -25,6 +25,27 @@ func newBranchService(c *Client) *BranchService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListBranches returns all branches for a repository.
|
||||||
|
func (s *BranchService) ListBranches(ctx context.Context, owner, repo string) ([]types.Branch, error) {
|
||||||
|
path := ResolvePath("/api/v1/repos/{owner}/{repo}/branches", pathParams("owner", owner, "repo", repo))
|
||||||
|
return ListAll[types.Branch](ctx, s.client, path, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IterBranches returns an iterator over all branches for a repository.
|
||||||
|
func (s *BranchService) IterBranches(ctx context.Context, owner, repo string) iter.Seq2[types.Branch, error] {
|
||||||
|
path := ResolvePath("/api/v1/repos/{owner}/{repo}/branches", pathParams("owner", owner, "repo", repo))
|
||||||
|
return ListIter[types.Branch](ctx, s.client, path, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateBranch creates a new branch in a repository.
|
||||||
|
func (s *BranchService) CreateBranch(ctx context.Context, owner, repo string, opts *types.CreateBranchRepoOption) (*types.Branch, error) {
|
||||||
|
var out types.Branch
|
||||||
|
if err := s.client.Post(ctx, ResolvePath("/api/v1/repos/{owner}/{repo}/branches", pathParams("owner", owner, "repo", repo)), opts, &out); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ListBranchProtections returns all branch protections for a repository.
|
// ListBranchProtections returns all branch protections for a repository.
|
||||||
func (s *BranchService) ListBranchProtections(ctx context.Context, owner, repo string) ([]types.BranchProtection, error) {
|
func (s *BranchService) ListBranchProtections(ctx context.Context, owner, repo string) ([]types.BranchProtection, error) {
|
||||||
path := ResolvePath("/api/v1/repos/{owner}/{repo}/branch_protections", pathParams("owner", owner, "repo", repo))
|
path := ResolvePath("/api/v1/repos/{owner}/{repo}/branch_protections", pathParams("owner", owner, "repo", repo))
|
||||||
|
|
|
||||||
66
branches_extra_test.go
Normal file
66
branches_extra_test.go
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
package forge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
json "github.com/goccy/go-json"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"dappco.re/go/core/forge/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBranchService_ListBranches_Good(t *testing.T) {
|
||||||
|
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/branches" {
|
||||||
|
t.Errorf("wrong path: %s", r.URL.Path)
|
||||||
|
}
|
||||||
|
w.Header().Set("X-Total-Count", "1")
|
||||||
|
json.NewEncoder(w).Encode([]types.Branch{{Name: "main"}})
|
||||||
|
}))
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
f := NewForge(srv.URL, "tok")
|
||||||
|
branches, err := f.Branches.ListBranches(context.Background(), "core", "go-forge")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(branches) != 1 || branches[0].Name != "main" {
|
||||||
|
t.Fatalf("got %#v", branches)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBranchService_CreateBranch_Good(t *testing.T) {
|
||||||
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
t.Errorf("expected POST, got %s", r.Method)
|
||||||
|
}
|
||||||
|
if r.URL.Path != "/api/v1/repos/core/go-forge/branches" {
|
||||||
|
t.Errorf("wrong path: %s", r.URL.Path)
|
||||||
|
}
|
||||||
|
var body types.CreateBranchRepoOption
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if body.BranchName != "release/v1" {
|
||||||
|
t.Fatalf("unexpected body: %+v", body)
|
||||||
|
}
|
||||||
|
json.NewEncoder(w).Encode(types.Branch{Name: body.BranchName})
|
||||||
|
}))
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
f := NewForge(srv.URL, "tok")
|
||||||
|
branch, err := f.Branches.CreateBranch(context.Background(), "core", "go-forge", &types.CreateBranchRepoOption{
|
||||||
|
BranchName: "release/v1",
|
||||||
|
OldRefName: "main",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if branch.Name != "release/v1" {
|
||||||
|
t.Fatalf("got name=%q", branch.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
10
commits.go
10
commits.go
|
|
@ -84,6 +84,16 @@ func (s *CommitService) GetCombinedStatus(ctx context.Context, owner, repo, ref
|
||||||
return &out, nil
|
return &out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCombinedStatusByRef returns the combined status for a given commit reference.
|
||||||
|
func (s *CommitService) GetCombinedStatusByRef(ctx context.Context, owner, repo, ref string) (*types.CombinedStatus, error) {
|
||||||
|
path := ResolvePath("/api/v1/repos/{owner}/{repo}/commits/{ref}/status", pathParams("owner", owner, "repo", repo, "ref", ref))
|
||||||
|
var out types.CombinedStatus
|
||||||
|
if err := s.client.Get(ctx, path, &out); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ListStatuses returns all commit statuses for a given ref.
|
// ListStatuses returns all commit statuses for a given ref.
|
||||||
func (s *CommitService) ListStatuses(ctx context.Context, owner, repo, ref string) ([]types.CommitStatus, error) {
|
func (s *CommitService) ListStatuses(ctx context.Context, owner, repo, ref string) ([]types.CommitStatus, error) {
|
||||||
path := ResolvePath("/api/v1/repos/{owner}/{repo}/commits/{ref}/statuses", pathParams("owner", owner, "repo", repo, "ref", ref))
|
path := ResolvePath("/api/v1/repos/{owner}/{repo}/commits/{ref}/statuses", pathParams("owner", owner, "repo", repo, "ref", ref))
|
||||||
|
|
|
||||||
36
commits_extra_test.go
Normal file
36
commits_extra_test.go
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
package forge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
json "github.com/goccy/go-json"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"dappco.re/go/core/forge/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCommitService_GetCombinedStatusByRef_Good(t *testing.T) {
|
||||||
|
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/commits/main/status" {
|
||||||
|
t.Errorf("wrong path: %s", r.URL.Path)
|
||||||
|
}
|
||||||
|
json.NewEncoder(w).Encode(types.CombinedStatus{
|
||||||
|
SHA: "main",
|
||||||
|
TotalCount: 3,
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
f := NewForge(srv.URL, "tok")
|
||||||
|
status, err := f.Commits.GetCombinedStatusByRef(context.Background(), "core", "go-forge", "main")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if status.SHA != "main" || status.TotalCount != 3 {
|
||||||
|
t.Fatalf("got %#v", status)
|
||||||
|
}
|
||||||
|
}
|
||||||
21
issues.go
21
issues.go
|
|
@ -142,6 +142,27 @@ func (s *IssueService) IterSearchIssues(ctx context.Context, opts SearchIssuesOp
|
||||||
return ListIter[types.Issue](ctx, s.client, "/api/v1/repos/issues/search", opts.queryParams())
|
return ListIter[types.Issue](ctx, s.client, "/api/v1/repos/issues/search", opts.queryParams())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListIssues returns all issues in a repository.
|
||||||
|
func (s *IssueService) ListIssues(ctx context.Context, owner, repo string) ([]types.Issue, error) {
|
||||||
|
path := ResolvePath("/api/v1/repos/{owner}/{repo}/issues", pathParams("owner", owner, "repo", repo))
|
||||||
|
return ListAll[types.Issue](ctx, s.client, path, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IterIssues returns an iterator over all issues in a repository.
|
||||||
|
func (s *IssueService) IterIssues(ctx context.Context, owner, repo string) iter.Seq2[types.Issue, error] {
|
||||||
|
path := ResolvePath("/api/v1/repos/{owner}/{repo}/issues", pathParams("owner", owner, "repo", repo))
|
||||||
|
return ListIter[types.Issue](ctx, s.client, path, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateIssue creates a new issue in a repository.
|
||||||
|
func (s *IssueService) CreateIssue(ctx context.Context, owner, repo string, opts *types.CreateIssueOption) (*types.Issue, error) {
|
||||||
|
var out types.Issue
|
||||||
|
if err := s.client.Post(ctx, ResolvePath("/api/v1/repos/{owner}/{repo}/issues", pathParams("owner", owner, "repo", repo)), opts, &out); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Pin pins an issue.
|
// Pin pins an issue.
|
||||||
func (s *IssueService) Pin(ctx context.Context, owner, repo string, index int64) error {
|
func (s *IssueService) Pin(ctx context.Context, owner, repo string, index int64) error {
|
||||||
path := ResolvePath("/api/v1/repos/{owner}/{repo}/issues/{index}/pin", pathParams("owner", owner, "repo", repo, "index", int64String(index)))
|
path := ResolvePath("/api/v1/repos/{owner}/{repo}/issues/{index}/pin", pathParams("owner", owner, "repo", repo, "index", int64String(index)))
|
||||||
|
|
|
||||||
63
issues_extra_test.go
Normal file
63
issues_extra_test.go
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
package forge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
json "github.com/goccy/go-json"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"dappco.re/go/core/forge/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIssueService_ListIssues_Good(t *testing.T) {
|
||||||
|
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/issues" {
|
||||||
|
t.Errorf("wrong path: %s", r.URL.Path)
|
||||||
|
}
|
||||||
|
w.Header().Set("X-Total-Count", "1")
|
||||||
|
json.NewEncoder(w).Encode([]types.Issue{{ID: 1, Title: "bug"}})
|
||||||
|
}))
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
f := NewForge(srv.URL, "tok")
|
||||||
|
issues, err := f.Issues.ListIssues(context.Background(), "core", "go-forge")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(issues) != 1 || issues[0].Title != "bug" {
|
||||||
|
t.Fatalf("got %#v", issues)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIssueService_CreateIssue_Good(t *testing.T) {
|
||||||
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
t.Errorf("expected POST, got %s", r.Method)
|
||||||
|
}
|
||||||
|
if r.URL.Path != "/api/v1/repos/core/go-forge/issues" {
|
||||||
|
t.Errorf("wrong path: %s", r.URL.Path)
|
||||||
|
}
|
||||||
|
var body types.CreateIssueOption
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if body.Title != "new issue" {
|
||||||
|
t.Fatalf("unexpected body: %+v", body)
|
||||||
|
}
|
||||||
|
json.NewEncoder(w).Encode(types.Issue{ID: 1, Index: 1, Title: body.Title})
|
||||||
|
}))
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
f := NewForge(srv.URL, "tok")
|
||||||
|
issue, err := f.Issues.CreateIssue(context.Background(), "core", "go-forge", &types.CreateIssueOption{Title: "new issue"})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if issue.Title != "new issue" {
|
||||||
|
t.Fatalf("got title=%q", issue.Title)
|
||||||
|
}
|
||||||
|
}
|
||||||
19
orgs.go
19
orgs.go
|
|
@ -41,6 +41,25 @@ func newOrgService(c *Client) *OrgService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListOrgs returns all organisations.
|
||||||
|
func (s *OrgService) ListOrgs(ctx context.Context) ([]types.Organization, error) {
|
||||||
|
return ListAll[types.Organization](ctx, s.client, "/api/v1/orgs", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IterOrgs returns an iterator over all organisations.
|
||||||
|
func (s *OrgService) IterOrgs(ctx context.Context) iter.Seq2[types.Organization, error] {
|
||||||
|
return ListIter[types.Organization](ctx, s.client, "/api/v1/orgs", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateOrg creates a new organisation.
|
||||||
|
func (s *OrgService) CreateOrg(ctx context.Context, opts *types.CreateOrgOption) (*types.Organization, error) {
|
||||||
|
var out types.Organization
|
||||||
|
if err := s.client.Post(ctx, "/api/v1/orgs", opts, &out); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ListMembers returns all members of an organisation.
|
// ListMembers returns all members of an organisation.
|
||||||
func (s *OrgService) ListMembers(ctx context.Context, org string) ([]types.User, error) {
|
func (s *OrgService) ListMembers(ctx context.Context, org string) ([]types.User, error) {
|
||||||
path := ResolvePath("/api/v1/orgs/{org}/members", pathParams("org", org))
|
path := ResolvePath("/api/v1/orgs/{org}/members", pathParams("org", org))
|
||||||
|
|
|
||||||
63
orgs_extra_test.go
Normal file
63
orgs_extra_test.go
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
package forge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
json "github.com/goccy/go-json"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"dappco.re/go/core/forge/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestOrgService_ListOrgs_Good(t *testing.T) {
|
||||||
|
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/orgs" {
|
||||||
|
t.Errorf("wrong path: %s", r.URL.Path)
|
||||||
|
}
|
||||||
|
w.Header().Set("X-Total-Count", "1")
|
||||||
|
json.NewEncoder(w).Encode([]types.Organization{{ID: 1, Name: "core"}})
|
||||||
|
}))
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
f := NewForge(srv.URL, "tok")
|
||||||
|
orgs, err := f.Orgs.ListOrgs(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(orgs) != 1 || orgs[0].Name != "core" {
|
||||||
|
t.Fatalf("got %#v", orgs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOrgService_CreateOrg_Good(t *testing.T) {
|
||||||
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
t.Errorf("expected POST, got %s", r.Method)
|
||||||
|
}
|
||||||
|
if r.URL.Path != "/api/v1/orgs" {
|
||||||
|
t.Errorf("wrong path: %s", r.URL.Path)
|
||||||
|
}
|
||||||
|
var body types.CreateOrgOption
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if body.UserName != "core" {
|
||||||
|
t.Fatalf("unexpected body: %+v", body)
|
||||||
|
}
|
||||||
|
json.NewEncoder(w).Encode(types.Organization{ID: 1, Name: body.UserName})
|
||||||
|
}))
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
f := NewForge(srv.URL, "tok")
|
||||||
|
org, err := f.Orgs.CreateOrg(context.Background(), &types.CreateOrgOption{UserName: "core"})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if org.Name != "core" {
|
||||||
|
t.Fatalf("got name=%q", org.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
21
pulls.go
21
pulls.go
|
|
@ -25,6 +25,27 @@ func newPullService(c *Client) *PullService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListPullRequests returns all pull requests in a repository.
|
||||||
|
func (s *PullService) ListPullRequests(ctx context.Context, owner, repo string) ([]types.PullRequest, error) {
|
||||||
|
path := ResolvePath("/api/v1/repos/{owner}/{repo}/pulls", pathParams("owner", owner, "repo", repo))
|
||||||
|
return ListAll[types.PullRequest](ctx, s.client, path, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IterPullRequests returns an iterator over all pull requests in a repository.
|
||||||
|
func (s *PullService) IterPullRequests(ctx context.Context, owner, repo string) iter.Seq2[types.PullRequest, error] {
|
||||||
|
path := ResolvePath("/api/v1/repos/{owner}/{repo}/pulls", pathParams("owner", owner, "repo", repo))
|
||||||
|
return ListIter[types.PullRequest](ctx, s.client, path, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatePullRequest creates a pull request in a repository.
|
||||||
|
func (s *PullService) CreatePullRequest(ctx context.Context, owner, repo string, opts *types.CreatePullRequestOption) (*types.PullRequest, error) {
|
||||||
|
var out types.PullRequest
|
||||||
|
if err := s.client.Post(ctx, ResolvePath("/api/v1/repos/{owner}/{repo}/pulls", pathParams("owner", owner, "repo", repo)), opts, &out); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Merge merges a pull request. Method is one of "merge", "rebase", "rebase-merge", "squash", "fast-forward-only", "manually-merged".
|
// Merge merges a pull request. Method is one of "merge", "rebase", "rebase-merge", "squash", "fast-forward-only", "manually-merged".
|
||||||
func (s *PullService) Merge(ctx context.Context, owner, repo string, index int64, method string) error {
|
func (s *PullService) Merge(ctx context.Context, owner, repo string, index int64, method string) error {
|
||||||
path := ResolvePath("/api/v1/repos/{owner}/{repo}/pulls/{index}/merge", pathParams("owner", owner, "repo", repo, "index", int64String(index)))
|
path := ResolvePath("/api/v1/repos/{owner}/{repo}/pulls/{index}/merge", pathParams("owner", owner, "repo", repo, "index", int64String(index)))
|
||||||
|
|
|
||||||
67
pulls_extra_test.go
Normal file
67
pulls_extra_test.go
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
package forge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
json "github.com/goccy/go-json"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"dappco.re/go/core/forge/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPullService_ListPullRequests_Good(t *testing.T) {
|
||||||
|
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/pulls" {
|
||||||
|
t.Errorf("wrong path: %s", r.URL.Path)
|
||||||
|
}
|
||||||
|
w.Header().Set("X-Total-Count", "1")
|
||||||
|
json.NewEncoder(w).Encode([]types.PullRequest{{ID: 1, Title: "add feature"}})
|
||||||
|
}))
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
f := NewForge(srv.URL, "tok")
|
||||||
|
prs, err := f.Pulls.ListPullRequests(context.Background(), "core", "go-forge")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(prs) != 1 || prs[0].Title != "add feature" {
|
||||||
|
t.Fatalf("got %#v", prs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPullService_CreatePullRequest_Good(t *testing.T) {
|
||||||
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
t.Errorf("expected POST, got %s", r.Method)
|
||||||
|
}
|
||||||
|
if r.URL.Path != "/api/v1/repos/core/go-forge/pulls" {
|
||||||
|
t.Errorf("wrong path: %s", r.URL.Path)
|
||||||
|
}
|
||||||
|
var body types.CreatePullRequestOption
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if body.Title != "add feature" {
|
||||||
|
t.Fatalf("unexpected body: %+v", body)
|
||||||
|
}
|
||||||
|
json.NewEncoder(w).Encode(types.PullRequest{ID: 1, Title: body.Title, Index: 1})
|
||||||
|
}))
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
f := NewForge(srv.URL, "tok")
|
||||||
|
pr, err := f.Pulls.CreatePullRequest(context.Background(), "core", "go-forge", &types.CreatePullRequestOption{
|
||||||
|
Title: "add feature",
|
||||||
|
Base: "main",
|
||||||
|
Head: "feature",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if pr.Title != "add feature" {
|
||||||
|
t.Fatalf("got title=%q", pr.Title)
|
||||||
|
}
|
||||||
|
}
|
||||||
27
releases.go
27
releases.go
|
|
@ -44,6 +44,27 @@ func newReleaseService(c *Client) *ReleaseService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListReleases returns all releases in a repository.
|
||||||
|
func (s *ReleaseService) ListReleases(ctx context.Context, owner, repo string) ([]types.Release, error) {
|
||||||
|
path := ResolvePath("/api/v1/repos/{owner}/{repo}/releases", pathParams("owner", owner, "repo", repo))
|
||||||
|
return ListAll[types.Release](ctx, s.client, path, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IterReleases returns an iterator over all releases in a repository.
|
||||||
|
func (s *ReleaseService) IterReleases(ctx context.Context, owner, repo string) iter.Seq2[types.Release, error] {
|
||||||
|
path := ResolvePath("/api/v1/repos/{owner}/{repo}/releases", pathParams("owner", owner, "repo", repo))
|
||||||
|
return ListIter[types.Release](ctx, s.client, path, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateRelease creates a release in a repository.
|
||||||
|
func (s *ReleaseService) CreateRelease(ctx context.Context, owner, repo string, opts *types.CreateReleaseOption) (*types.Release, error) {
|
||||||
|
var out types.Release
|
||||||
|
if err := s.client.Post(ctx, ResolvePath("/api/v1/repos/{owner}/{repo}/releases", pathParams("owner", owner, "repo", repo)), opts, &out); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetByTag returns a release by its tag name.
|
// GetByTag returns a release by its tag name.
|
||||||
func (s *ReleaseService) GetByTag(ctx context.Context, owner, repo, tag string) (*types.Release, error) {
|
func (s *ReleaseService) GetByTag(ctx context.Context, owner, repo, tag string) (*types.Release, error) {
|
||||||
path := ResolvePath("/api/v1/repos/{owner}/{repo}/releases/tags/{tag}", pathParams("owner", owner, "repo", repo, "tag", tag))
|
path := ResolvePath("/api/v1/repos/{owner}/{repo}/releases/tags/{tag}", pathParams("owner", owner, "repo", repo, "tag", tag))
|
||||||
|
|
@ -72,7 +93,7 @@ func (s *ReleaseService) DeleteByTag(ctx context.Context, owner, repo, tag strin
|
||||||
|
|
||||||
// ListAssets returns all assets for a release.
|
// ListAssets returns all assets for a release.
|
||||||
func (s *ReleaseService) ListAssets(ctx context.Context, owner, repo string, releaseID int64) ([]types.Attachment, error) {
|
func (s *ReleaseService) ListAssets(ctx context.Context, owner, repo string, releaseID int64) ([]types.Attachment, error) {
|
||||||
path := ResolvePath("/api/v1/repos/{owner}/{repo}/releases/{releaseID}/assets", pathParams("owner", owner, "repo", repo, "releaseID", int64String(releaseID)))
|
path := ResolvePath("/api/v1/repos/{owner}/{repo}/releases/{id}/assets", pathParams("owner", owner, "repo", repo, "id", int64String(releaseID)))
|
||||||
return ListAll[types.Attachment](ctx, s.client, path, nil)
|
return ListAll[types.Attachment](ctx, s.client, path, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,7 +102,7 @@ func (s *ReleaseService) ListAssets(ctx context.Context, owner, repo string, rel
|
||||||
// If opts.ExternalURL is set, the upload uses the external_url form field and
|
// If opts.ExternalURL is set, the upload uses the external_url form field and
|
||||||
// ignores filename/content.
|
// ignores filename/content.
|
||||||
func (s *ReleaseService) CreateAttachment(ctx context.Context, owner, repo string, releaseID int64, opts *ReleaseAttachmentUploadOptions, filename string, content goio.Reader) (*types.Attachment, error) {
|
func (s *ReleaseService) CreateAttachment(ctx context.Context, owner, repo string, releaseID int64, opts *ReleaseAttachmentUploadOptions, filename string, content goio.Reader) (*types.Attachment, error) {
|
||||||
path := ResolvePath("/api/v1/repos/{owner}/{repo}/releases/{releaseID}/assets", pathParams("owner", owner, "repo", repo, "releaseID", int64String(releaseID)))
|
path := ResolvePath("/api/v1/repos/{owner}/{repo}/releases/{id}/assets", pathParams("owner", owner, "repo", repo, "id", int64String(releaseID)))
|
||||||
fields := make(map[string]string, 1)
|
fields := make(map[string]string, 1)
|
||||||
fieldName := "attachment"
|
fieldName := "attachment"
|
||||||
if opts != nil && opts.ExternalURL != "" {
|
if opts != nil && opts.ExternalURL != "" {
|
||||||
|
|
@ -119,7 +140,7 @@ func (s *ReleaseService) EditAsset(ctx context.Context, owner, repo string, rele
|
||||||
|
|
||||||
// IterAssets returns an iterator over all assets for a release.
|
// IterAssets returns an iterator over all assets for a release.
|
||||||
func (s *ReleaseService) IterAssets(ctx context.Context, owner, repo string, releaseID int64) iter.Seq2[types.Attachment, error] {
|
func (s *ReleaseService) IterAssets(ctx context.Context, owner, repo string, releaseID int64) iter.Seq2[types.Attachment, error] {
|
||||||
path := ResolvePath("/api/v1/repos/{owner}/{repo}/releases/{releaseID}/assets", pathParams("owner", owner, "repo", repo, "releaseID", int64String(releaseID)))
|
path := ResolvePath("/api/v1/repos/{owner}/{repo}/releases/{id}/assets", pathParams("owner", owner, "repo", repo, "id", int64String(releaseID)))
|
||||||
return ListIter[types.Attachment](ctx, s.client, path, nil)
|
return ListIter[types.Attachment](ctx, s.client, path, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
66
releases_extra_test.go
Normal file
66
releases_extra_test.go
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
package forge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
json "github.com/goccy/go-json"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"dappco.re/go/core/forge/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestReleaseService_ListReleases_Good(t *testing.T) {
|
||||||
|
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/releases" {
|
||||||
|
t.Errorf("wrong path: %s", r.URL.Path)
|
||||||
|
}
|
||||||
|
w.Header().Set("X-Total-Count", "1")
|
||||||
|
json.NewEncoder(w).Encode([]types.Release{{ID: 1, TagName: "v1.0.0"}})
|
||||||
|
}))
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
f := NewForge(srv.URL, "tok")
|
||||||
|
releases, err := f.Releases.ListReleases(context.Background(), "core", "go-forge")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(releases) != 1 || releases[0].TagName != "v1.0.0" {
|
||||||
|
t.Fatalf("got %#v", releases)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReleaseService_CreateRelease_Good(t *testing.T) {
|
||||||
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
t.Errorf("expected POST, got %s", r.Method)
|
||||||
|
}
|
||||||
|
if r.URL.Path != "/api/v1/repos/core/go-forge/releases" {
|
||||||
|
t.Errorf("wrong path: %s", r.URL.Path)
|
||||||
|
}
|
||||||
|
var body types.CreateReleaseOption
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if body.TagName != "v1.0.0" {
|
||||||
|
t.Fatalf("unexpected body: %+v", body)
|
||||||
|
}
|
||||||
|
json.NewEncoder(w).Encode(types.Release{ID: 1, TagName: body.TagName})
|
||||||
|
}))
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
f := NewForge(srv.URL, "tok")
|
||||||
|
release, err := f.Releases.CreateRelease(context.Background(), "core", "go-forge", &types.CreateReleaseOption{
|
||||||
|
TagName: "v1.0.0",
|
||||||
|
Title: "Release 1.0",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if release.TagName != "v1.0.0" {
|
||||||
|
t.Fatalf("got tag=%q", release.TagName)
|
||||||
|
}
|
||||||
|
}
|
||||||
10
users.go
10
users.go
|
|
@ -535,6 +535,16 @@ func (s *UserService) IterMyFollowers(ctx context.Context) iter.Seq2[types.User,
|
||||||
return ListIter[types.User](ctx, s.client, "/api/v1/user/followers", nil)
|
return ListIter[types.User](ctx, s.client, "/api/v1/user/followers", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListMyFollowing returns all users followed by the authenticated user.
|
||||||
|
func (s *UserService) ListMyFollowing(ctx context.Context) ([]types.User, error) {
|
||||||
|
return ListAll[types.User](ctx, s.client, "/api/v1/user/following", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IterMyFollowing returns an iterator over all users followed by the authenticated user.
|
||||||
|
func (s *UserService) IterMyFollowing(ctx context.Context) iter.Seq2[types.User, error] {
|
||||||
|
return ListIter[types.User](ctx, s.client, "/api/v1/user/following", nil)
|
||||||
|
}
|
||||||
|
|
||||||
// ListMyTeams returns all teams the authenticated user belongs to.
|
// ListMyTeams returns all teams the authenticated user belongs to.
|
||||||
func (s *UserService) ListMyTeams(ctx context.Context) ([]types.Team, error) {
|
func (s *UserService) ListMyTeams(ctx context.Context) ([]types.Team, error) {
|
||||||
return ListAll[types.Team](ctx, s.client, "/api/v1/user/teams", nil)
|
return ListAll[types.Team](ctx, s.client, "/api/v1/user/teams", nil)
|
||||||
|
|
|
||||||
34
users_extra_test.go
Normal file
34
users_extra_test.go
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
package forge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
json "github.com/goccy/go-json"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"dappco.re/go/core/forge/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestUserService_ListMyFollowing_Good(t *testing.T) {
|
||||||
|
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/user/following" {
|
||||||
|
t.Errorf("wrong path: %s", r.URL.Path)
|
||||||
|
}
|
||||||
|
w.Header().Set("X-Total-Count", "1")
|
||||||
|
json.NewEncoder(w).Encode([]types.User{{ID: 1, UserName: "alice"}})
|
||||||
|
}))
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
f := NewForge(srv.URL, "tok")
|
||||||
|
users, err := f.Users.ListMyFollowing(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(users) != 1 || users[0].UserName != "alice" {
|
||||||
|
t.Fatalf("got %#v", users)
|
||||||
|
}
|
||||||
|
}
|
||||||
21
webhooks.go
21
webhooks.go
|
|
@ -26,6 +26,27 @@ func newWebhookService(c *Client) *WebhookService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListHooks returns all webhooks for a repository.
|
||||||
|
func (s *WebhookService) ListHooks(ctx context.Context, owner, repo string) ([]types.Hook, error) {
|
||||||
|
path := ResolvePath("/api/v1/repos/{owner}/{repo}/hooks", pathParams("owner", owner, "repo", repo))
|
||||||
|
return ListAll[types.Hook](ctx, s.client, path, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IterHooks returns an iterator over all webhooks for a repository.
|
||||||
|
func (s *WebhookService) IterHooks(ctx context.Context, owner, repo string) iter.Seq2[types.Hook, error] {
|
||||||
|
path := ResolvePath("/api/v1/repos/{owner}/{repo}/hooks", pathParams("owner", owner, "repo", repo))
|
||||||
|
return ListIter[types.Hook](ctx, s.client, path, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateHook creates a webhook for a repository.
|
||||||
|
func (s *WebhookService) CreateHook(ctx context.Context, owner, repo string, opts *types.CreateHookOption) (*types.Hook, error) {
|
||||||
|
var out types.Hook
|
||||||
|
if err := s.client.Post(ctx, ResolvePath("/api/v1/repos/{owner}/{repo}/hooks", pathParams("owner", owner, "repo", repo)), opts, &out); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// TestHook triggers a test delivery for a webhook.
|
// TestHook triggers a test delivery for a webhook.
|
||||||
func (s *WebhookService) TestHook(ctx context.Context, owner, repo string, id int64) error {
|
func (s *WebhookService) TestHook(ctx context.Context, owner, repo string, id int64) error {
|
||||||
path := ResolvePath("/api/v1/repos/{owner}/{repo}/hooks/{id}/tests", pathParams("owner", owner, "repo", repo, "id", int64String(id)))
|
path := ResolvePath("/api/v1/repos/{owner}/{repo}/hooks/{id}/tests", pathParams("owner", owner, "repo", repo, "id", int64String(id)))
|
||||||
|
|
|
||||||
69
webhooks_extra_test.go
Normal file
69
webhooks_extra_test.go
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
package forge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
json "github.com/goccy/go-json"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"dappco.re/go/core/forge/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestWebhookService_ListHooks_Good(t *testing.T) {
|
||||||
|
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/hooks" {
|
||||||
|
t.Errorf("wrong path: %s", r.URL.Path)
|
||||||
|
}
|
||||||
|
w.Header().Set("X-Total-Count", "1")
|
||||||
|
json.NewEncoder(w).Encode([]types.Hook{{ID: 1, Type: "forgejo"}})
|
||||||
|
}))
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
f := NewForge(srv.URL, "tok")
|
||||||
|
hooks, err := f.Webhooks.ListHooks(context.Background(), "core", "go-forge")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(hooks) != 1 || hooks[0].ID != 1 {
|
||||||
|
t.Fatalf("got %#v", hooks)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWebhookService_CreateHook_Good(t *testing.T) {
|
||||||
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
t.Errorf("expected POST, got %s", r.Method)
|
||||||
|
}
|
||||||
|
if r.URL.Path != "/api/v1/repos/core/go-forge/hooks" {
|
||||||
|
t.Errorf("wrong path: %s", r.URL.Path)
|
||||||
|
}
|
||||||
|
var body types.CreateHookOption
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if body.Type != "forgejo" {
|
||||||
|
t.Fatalf("unexpected body: %+v", body)
|
||||||
|
}
|
||||||
|
json.NewEncoder(w).Encode(types.Hook{ID: 1, Type: body.Type})
|
||||||
|
}))
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
f := NewForge(srv.URL, "tok")
|
||||||
|
hook, err := f.Webhooks.CreateHook(context.Background(), "core", "go-forge", &types.CreateHookOption{
|
||||||
|
Type: "forgejo",
|
||||||
|
Config: &types.CreateHookOptionConfig{
|
||||||
|
"content_type": "json",
|
||||||
|
"url": "https://example.com/hook",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if hook.Type != "forgejo" {
|
||||||
|
t.Fatalf("got type=%q", hook.Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue