Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 56 additions & 2 deletions github/gists.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,19 @@ type Gist struct {
NodeID *string `json:"node_id,omitempty"`
}

// CreateGistRequest represents the input for creating a gist.
type CreateGistRequest struct {
Description *string `json:"description,omitempty"`
Public *bool `json:"public,omitempty"`
Files map[GistFilename]GistFile `json:"files,omitempty"`
}

// UpdateGistRequest represents the input for updating a gist.
type UpdateGistRequest struct {
Description *string `json:"description,omitempty"`
Files map[GistFilename]GistFile `json:"files,omitempty"`
}

func (g Gist) String() string {
return Stringify(g)
}
Expand Down Expand Up @@ -224,7 +237,7 @@ func (s *GistsService) GetRevision(ctx context.Context, id, sha string) (*Gist,
// GitHub API docs: https://docs.github.com/rest/gists/gists#create-a-gist
//
//meta:operation POST /gists
func (s *GistsService) Create(ctx context.Context, gist *Gist) (*Gist, *Response, error) {
func (s *GistsService) Create(ctx context.Context, gist CreateGistRequest) (*Gist, *Response, error) {
u := "gists"
req, err := s.client.NewRequest("POST", u, gist)
if err != nil {
Expand All @@ -240,12 +253,33 @@ func (s *GistsService) Create(ctx context.Context, gist *Gist) (*Gist, *Response
return g, resp, nil
}

// CreateFromGist creates a gist for the authenticated user using a Gist struct.
//
// Deprecated: Use Create with CreateGistRequest instead.
//
// GitHub API docs: https://docs.github.com/rest/gists/gists#create-a-gist
//
//meta:operation POST /gists
func (s *GistsService) CreateFromGist(ctx context.Context, gist *Gist) (*Gist, *Response, error) {
var req CreateGistRequest

if gist != nil {
req = CreateGistRequest{
Description: gist.Description,
Public: gist.Public,
Files: gist.Files,
}
}

return s.Create(ctx, req)
}
Comment on lines +263 to +275
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this wrapper?

In this PR #3654 we didn't introduce any wrappers, but it breaks API in a similar way.

Copy link
Collaborator

@gmlewis gmlewis Aug 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that we don't need the wrappers. I was trying to decide, but I think you are correct, @alexandear.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it.
Since wrappers aren’t needed, I’ll go ahead and remove the four deprecated methods (CreateFromGist, EditFromGist, CreateCommentFromGistComment, and EditCommentFromGistComment)


// Edit a gist.
//
// GitHub API docs: https://docs.github.com/rest/gists/gists#update-a-gist
//
//meta:operation PATCH /gists/{gist_id}
func (s *GistsService) Edit(ctx context.Context, id string, gist *Gist) (*Gist, *Response, error) {
func (s *GistsService) Edit(ctx context.Context, id string, gist UpdateGistRequest) (*Gist, *Response, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func (s *GistsService) Edit(ctx context.Context, id string, gist UpdateGistRequest) (*Gist, *Response, error) {
func (s *GistsService) Update(ctx context.Context, id string, gist UpdateGistRequest) (*Gist, *Response, error) {

I think the API consistency would be improved if we replaced Edit with Update and if we're changing the method signature that seems like a good time to make this change? @gmlewis what do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I agree. Thank you, @stevehipwell.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ll go ahead and replace Edit → Update and EditComment → UpdateComment to keep things consistent

u := fmt.Sprintf("gists/%v", id)
req, err := s.client.NewRequest("PATCH", u, gist)
if err != nil {
Expand All @@ -261,6 +295,26 @@ func (s *GistsService) Edit(ctx context.Context, id string, gist *Gist) (*Gist,
return g, resp, nil
}

// EditFromGist updates a gist using a Gist struct.
//
// Deprecated: Use Edit with UpdateGistRequest instead.
//
// GitHub API docs: https://docs.github.com/rest/gists/gists#update-a-gist
//
//meta:operation PATCH /gists/{gist_id}
func (s *GistsService) EditFromGist(ctx context.Context, id string, gist *Gist) (*Gist, *Response, error) {
var req UpdateGistRequest

if gist != nil {
req = UpdateGistRequest{
Description: gist.Description,
Files: gist.Files,
}
}

return s.Edit(ctx, id, req)
}

// ListCommits lists commits of a gist.
//
// GitHub API docs: https://docs.github.com/rest/gists/gists#list-gist-commits
Expand Down
52 changes: 50 additions & 2 deletions github/gists_comments.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ type GistComment struct {
CreatedAt *Timestamp `json:"created_at,omitempty"`
}

// CreateGistCommentRequest represents the input for creating a gist comment.
type CreateGistCommentRequest struct {
Body *string `json:"body,omitempty"`
}

// UpdateGistCommentRequest represents the input for updating a gist comment.
type UpdateGistCommentRequest struct {
Body *string `json:"body,omitempty"`
}

func (g GistComment) String() string {
return Stringify(g)
}
Expand Down Expand Up @@ -75,7 +85,7 @@ func (s *GistsService) GetComment(ctx context.Context, gistID string, commentID
// GitHub API docs: https://docs.github.com/rest/gists/comments#create-a-gist-comment
//
//meta:operation POST /gists/{gist_id}/comments
func (s *GistsService) CreateComment(ctx context.Context, gistID string, comment *GistComment) (*GistComment, *Response, error) {
func (s *GistsService) CreateComment(ctx context.Context, gistID string, comment CreateGistCommentRequest) (*GistComment, *Response, error) {
u := fmt.Sprintf("gists/%v/comments", gistID)
req, err := s.client.NewRequest("POST", u, comment)
if err != nil {
Expand All @@ -91,12 +101,31 @@ func (s *GistsService) CreateComment(ctx context.Context, gistID string, comment
return c, resp, nil
}

// CreateCommentFromGistComment creates a comment for a gist using a GistComment struct.
//
// Deprecated: Use CreateComment with CreateGistCommentRequest instead.
//
// GitHub API docs: https://docs.github.com/rest/gists/comments#create-a-gist-comment
//
//meta:operation POST /gists/{gist_id}/comments
func (s *GistsService) CreateCommentFromGistComment(ctx context.Context, gistID string, comment *GistComment) (*GistComment, *Response, error) {
var req CreateGistCommentRequest

if comment != nil {
req = CreateGistCommentRequest{
Body: comment.Body,
}
}

return s.CreateComment(ctx, gistID, req)
}

// EditComment edits an existing gist comment.
//
// GitHub API docs: https://docs.github.com/rest/gists/comments#update-a-gist-comment
//
//meta:operation PATCH /gists/{gist_id}/comments/{comment_id}
func (s *GistsService) EditComment(ctx context.Context, gistID string, commentID int64, comment *GistComment) (*GistComment, *Response, error) {
func (s *GistsService) EditComment(ctx context.Context, gistID string, commentID int64, comment UpdateGistCommentRequest) (*GistComment, *Response, error) {
u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID)
req, err := s.client.NewRequest("PATCH", u, comment)
if err != nil {
Expand All @@ -112,6 +141,25 @@ func (s *GistsService) EditComment(ctx context.Context, gistID string, commentID
return c, resp, nil
}

// EditCommentFromGistComment edits an existing gist comment using a GistComment struct.
//
// Deprecated: Use EditComment with UpdateGistCommentRequest instead.
//
// GitHub API docs: https://docs.github.com/rest/gists/comments#update-a-gist-comment
//
//meta:operation PATCH /gists/{gist_id}/comments/{comment_id}
func (s *GistsService) EditCommentFromGistComment(ctx context.Context, gistID string, commentID int64, comment *GistComment) (*GistComment, *Response, error) {
var req UpdateGistCommentRequest

if comment != nil {
req = UpdateGistCommentRequest{
Body: comment.Body,
}
}

return s.EditComment(ctx, gistID, commentID, req)
}

// DeleteComment deletes a gist comment.
//
// GitHub API docs: https://docs.github.com/rest/gists/comments#delete-a-gist-comment
Expand Down
106 changes: 86 additions & 20 deletions github/gists_comments_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,36 +170,37 @@ func TestGistsService_CreateComment(t *testing.T) {
input := &GistComment{ID: Ptr(int64(1)), Body: Ptr("b")}

mux.HandleFunc("/gists/1/comments", func(w http.ResponseWriter, r *http.Request) {
v := new(GistComment)
v := new(CreateGistCommentRequest)
assertNilError(t, json.NewDecoder(r.Body).Decode(v))

testMethod(t, r, "POST")
if !cmp.Equal(v, input) {
t.Errorf("Request body = %+v, want %+v", v, input)
want := &CreateGistCommentRequest{Body: Ptr("b")}
if !cmp.Equal(v, want) {
t.Errorf("Request body = %+v, want %+v", v, want)
}

fmt.Fprint(w, `{"id":1}`)
})

ctx := context.Background()
comment, _, err := client.Gists.CreateComment(ctx, "1", input)
comment, _, err := client.Gists.CreateCommentFromGistComment(ctx, "1", input)
if err != nil {
t.Errorf("Gists.CreateComment returned error: %v", err)
t.Errorf("Gists.CreateCommentFromGistComment returned error: %v", err)
}

want := &GistComment{ID: Ptr(int64(1))}
if !cmp.Equal(comment, want) {
t.Errorf("Gists.CreateComment returned %+v, want %+v", comment, want)
t.Errorf("Gists.CreateCommentFromGistComment returned %+v, want %+v", comment, want)
}

const methodName = "CreateComment"
const methodName = "CreateCommentFromGistComment"
testBadOptions(t, methodName, func() (err error) {
_, _, err = client.Gists.CreateComment(ctx, "\n", input)
_, _, err = client.Gists.CreateCommentFromGistComment(ctx, "\n", input)
return err
})

testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
got, resp, err := client.Gists.CreateComment(ctx, "1", input)
got, resp, err := client.Gists.CreateCommentFromGistComment(ctx, "1", input)
if got != nil {
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
}
Expand All @@ -212,47 +213,80 @@ func TestGistsService_CreateComment_invalidID(t *testing.T) {
client, _, _ := setup(t)

ctx := context.Background()
_, _, err := client.Gists.CreateComment(ctx, "%", nil)
_, _, err := client.Gists.CreateCommentFromGistComment(ctx, "%", nil)
testURLParseError(t, err)
}

func TestGistsService_CreateComment_ValueParameter(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)

input := CreateGistCommentRequest{
Body: Ptr("Test comment body"),
}

mux.HandleFunc("/gists/1/comments", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "POST")
v := new(CreateGistCommentRequest)
assertNilError(t, json.NewDecoder(r.Body).Decode(v))

if !cmp.Equal(v, &input) {
t.Errorf("Request body = %+v, want %+v", v, &input)
}

fmt.Fprint(w, `{"id": 1}`)
})

ctx := context.Background()
comment, _, err := client.Gists.CreateComment(ctx, "1", input)
if err != nil {
t.Errorf("Gists.CreateComment returned error: %v", err)
}

want := &GistComment{ID: Ptr(int64(1))}
if !cmp.Equal(comment, want) {
t.Errorf("Gists.CreateComment returned %+v, want %+v", comment, want)
}
}

func TestGistsService_EditComment(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)

input := &GistComment{ID: Ptr(int64(1)), Body: Ptr("b")}

mux.HandleFunc("/gists/1/comments/2", func(w http.ResponseWriter, r *http.Request) {
v := new(GistComment)
v := new(UpdateGistCommentRequest)
assertNilError(t, json.NewDecoder(r.Body).Decode(v))

testMethod(t, r, "PATCH")
if !cmp.Equal(v, input) {
t.Errorf("Request body = %+v, want %+v", v, input)
want := &UpdateGistCommentRequest{Body: Ptr("b")}
if !cmp.Equal(v, want) {
t.Errorf("Request body = %+v, want %+v", v, want)
}

fmt.Fprint(w, `{"id":1}`)
})

ctx := context.Background()
comment, _, err := client.Gists.EditComment(ctx, "1", 2, input)
comment, _, err := client.Gists.EditCommentFromGistComment(ctx, "1", 2, input)
if err != nil {
t.Errorf("Gists.EditComment returned error: %v", err)
t.Errorf("Gists.EditCommentFromGistComment returned error: %v", err)
}

want := &GistComment{ID: Ptr(int64(1))}
if !cmp.Equal(comment, want) {
t.Errorf("Gists.EditComment returned %+v, want %+v", comment, want)
t.Errorf("Gists.EditCommentFromGistComment returned %+v, want %+v", comment, want)
}

const methodName = "EditComment"
const methodName = "EditCommentFromGistComment"
testBadOptions(t, methodName, func() (err error) {
_, _, err = client.Gists.EditComment(ctx, "\n", -2, input)
_, _, err = client.Gists.EditCommentFromGistComment(ctx, "\n", -2, input)
return err
})

testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
got, resp, err := client.Gists.EditComment(ctx, "1", 2, input)
got, resp, err := client.Gists.EditCommentFromGistComment(ctx, "1", 2, input)
if got != nil {
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
}
Expand All @@ -265,10 +299,42 @@ func TestGistsService_EditComment_invalidID(t *testing.T) {
client, _, _ := setup(t)

ctx := context.Background()
_, _, err := client.Gists.EditComment(ctx, "%", 1, nil)
_, _, err := client.Gists.EditCommentFromGistComment(ctx, "%", 1, nil)
testURLParseError(t, err)
}

func TestGistsService_EditComment_ValueParameter(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)

input := UpdateGistCommentRequest{
Body: Ptr("Updated comment body"),
}

mux.HandleFunc("/gists/1/comments/2", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "PATCH")
v := new(UpdateGistCommentRequest)
assertNilError(t, json.NewDecoder(r.Body).Decode(v))

if !cmp.Equal(v, &input) {
t.Errorf("Request body = %+v, want %+v", v, &input)
}

fmt.Fprint(w, `{"id": 1}`)
})

ctx := context.Background()
comment, _, err := client.Gists.EditComment(ctx, "1", 2, input)
if err != nil {
t.Errorf("Gists.EditComment returned error: %v", err)
}

want := &GistComment{ID: Ptr(int64(1))}
if !cmp.Equal(comment, want) {
t.Errorf("Gists.EditComment returned %+v, want %+v", comment, want)
}
}

func TestGistsService_DeleteComment(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)
Expand Down
Loading
Loading