Skip to content

Commit

Permalink
Restrict request params of CreateRelease and EditRelease to known sub…
Browse files Browse the repository at this point in the history
…set (#997)

Fixes #992.
  • Loading branch information
gmlewis authored Sep 12, 2018
1 parent 6a06666 commit c3e9de6
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 28 deletions.
81 changes: 61 additions & 20 deletions github/repos_releases.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,26 @@ import (

// RepositoryRelease represents a GitHub release in a repository.
type RepositoryRelease struct {
ID *int64 `json:"id,omitempty"`
TagName *string `json:"tag_name,omitempty"`
TargetCommitish *string `json:"target_commitish,omitempty"`
Name *string `json:"name,omitempty"`
Body *string `json:"body,omitempty"`
Draft *bool `json:"draft,omitempty"`
Prerelease *bool `json:"prerelease,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
PublishedAt *Timestamp `json:"published_at,omitempty"`
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
AssetsURL *string `json:"assets_url,omitempty"`
Assets []ReleaseAsset `json:"assets,omitempty"`
UploadURL *string `json:"upload_url,omitempty"`
ZipballURL *string `json:"zipball_url,omitempty"`
TarballURL *string `json:"tarball_url,omitempty"`
Author *User `json:"author,omitempty"`
NodeID *string `json:"node_id,omitempty"`
TagName *string `json:"tag_name,omitempty"`
TargetCommitish *string `json:"target_commitish,omitempty"`
Name *string `json:"name,omitempty"`
Body *string `json:"body,omitempty"`
Draft *bool `json:"draft,omitempty"`
Prerelease *bool `json:"prerelease,omitempty"`

// The following fields are not used in CreateRelease or EditRelease:
ID *int64 `json:"id,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
PublishedAt *Timestamp `json:"published_at,omitempty"`
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
AssetsURL *string `json:"assets_url,omitempty"`
Assets []ReleaseAsset `json:"assets,omitempty"`
UploadURL *string `json:"upload_url,omitempty"`
ZipballURL *string `json:"zipball_url,omitempty"`
TarballURL *string `json:"tarball_url,omitempty"`
Author *User `json:"author,omitempty"`
NodeID *string `json:"node_id,omitempty"`
}

func (r RepositoryRelease) String() string {
Expand Down Expand Up @@ -125,13 +127,40 @@ func (s *RepositoriesService) getSingleRelease(ctx context.Context, url string)
return release, resp, nil
}

// repositoryReleaseRequest is a subset of RepositoryRelease and
// is used internally by CreateRelease and EditRelease to pass
// only the known fields for these endpoints.
//
// See https://github.com/google/go-github/issues/992 for more
// information.
type repositoryReleaseRequest struct {
TagName *string `json:"tag_name,omitempty"`
TargetCommitish *string `json:"target_commitish,omitempty"`
Name *string `json:"name,omitempty"`
Body *string `json:"body,omitempty"`
Draft *bool `json:"draft,omitempty"`
Prerelease *bool `json:"prerelease,omitempty"`
}

// CreateRelease adds a new release for a repository.
//
// Note that only a subset of the release fields are used.
// See RepositoryRelease for more information.
//
// GitHub API docs: https://developer.github.com/v3/repos/releases/#create-a-release
func (s *RepositoriesService) CreateRelease(ctx context.Context, owner, repo string, release *RepositoryRelease) (*RepositoryRelease, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/releases", owner, repo)

req, err := s.client.NewRequest("POST", u, release)
releaseReq := &repositoryReleaseRequest{
TagName: release.TagName,
TargetCommitish: release.TargetCommitish,
Name: release.Name,
Body: release.Body,
Draft: release.Draft,
Prerelease: release.Prerelease,
}

req, err := s.client.NewRequest("POST", u, releaseReq)
if err != nil {
return nil, nil, err
}
Expand All @@ -146,11 +175,23 @@ func (s *RepositoriesService) CreateRelease(ctx context.Context, owner, repo str

// EditRelease edits a repository release.
//
// Note that only a subset of the release fields are used.
// See RepositoryRelease for more information.
//
// GitHub API docs: https://developer.github.com/v3/repos/releases/#edit-a-release
func (s *RepositoriesService) EditRelease(ctx context.Context, owner, repo string, id int64, release *RepositoryRelease) (*RepositoryRelease, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id)

req, err := s.client.NewRequest("PATCH", u, release)
releaseReq := &repositoryReleaseRequest{
TagName: release.TagName,
TargetCommitish: release.TargetCommitish,
Name: release.Name,
Body: release.Body,
Draft: release.Draft,
Prerelease: release.Prerelease,
}

req, err := s.client.NewRequest("PATCH", u, releaseReq)
if err != nil {
return nil, nil, err
}
Expand Down
48 changes: 40 additions & 8 deletions github/repos_releases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,31 @@ func TestRepositoriesService_CreateRelease(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

input := &RepositoryRelease{Name: String("v1.0")}
input := &RepositoryRelease{
Name: String("v1.0"),
// Fields to be removed:
ID: Int64(2),
CreatedAt: &Timestamp{referenceTime},
PublishedAt: &Timestamp{referenceTime},
URL: String("http://url/"),
HTMLURL: String("http://htmlurl/"),
AssetsURL: String("http://assetsurl/"),
Assets: []ReleaseAsset{{ID: Int64(5)}},
UploadURL: String("http://uploadurl/"),
ZipballURL: String("http://zipballurl/"),
TarballURL: String("http://tarballurl/"),
Author: &User{Name: String("octocat")},
NodeID: String("nodeid"),
}

mux.HandleFunc("/repos/o/r/releases", func(w http.ResponseWriter, r *http.Request) {
v := new(RepositoryRelease)
v := new(repositoryReleaseRequest)
json.NewDecoder(r.Body).Decode(v)

testMethod(t, r, "POST")
if !reflect.DeepEqual(v, input) {
t.Errorf("Request body = %+v, want %+v", v, input)
want := &repositoryReleaseRequest{Name: String("v1.0")}
if !reflect.DeepEqual(v, want) {
t.Errorf("Request body = %+v, want %+v", v, want)
}
fmt.Fprint(w, `{"id":1}`)
})
Expand All @@ -131,15 +147,31 @@ func TestRepositoriesService_EditRelease(t *testing.T) {
client, mux, _, teardown := setup()
defer teardown()

input := &RepositoryRelease{Name: String("n")}
input := &RepositoryRelease{
Name: String("n"),
// Fields to be removed:
ID: Int64(2),
CreatedAt: &Timestamp{referenceTime},
PublishedAt: &Timestamp{referenceTime},
URL: String("http://url/"),
HTMLURL: String("http://htmlurl/"),
AssetsURL: String("http://assetsurl/"),
Assets: []ReleaseAsset{{ID: Int64(5)}},
UploadURL: String("http://uploadurl/"),
ZipballURL: String("http://zipballurl/"),
TarballURL: String("http://tarballurl/"),
Author: &User{Name: String("octocat")},
NodeID: String("nodeid"),
}

mux.HandleFunc("/repos/o/r/releases/1", func(w http.ResponseWriter, r *http.Request) {
v := new(RepositoryRelease)
v := new(repositoryReleaseRequest)
json.NewDecoder(r.Body).Decode(v)

testMethod(t, r, "PATCH")
if !reflect.DeepEqual(v, input) {
t.Errorf("Request body = %+v, want %+v", v, input)
want := &repositoryReleaseRequest{Name: String("n")}
if !reflect.DeepEqual(v, want) {
t.Errorf("Request body = %+v, want %+v", v, want)
}
fmt.Fprint(w, `{"id":1}`)
})
Expand Down

0 comments on commit c3e9de6

Please sign in to comment.