Skip to content

Commit c3e9de6

Browse files
authored
Restrict request params of CreateRelease and EditRelease to known subset (#997)
Fixes #992.
1 parent 6a06666 commit c3e9de6

File tree

2 files changed

+101
-28
lines changed

2 files changed

+101
-28
lines changed

github/repos_releases.go

Lines changed: 61 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,26 @@ import (
1919

2020
// RepositoryRelease represents a GitHub release in a repository.
2121
type RepositoryRelease struct {
22-
ID *int64 `json:"id,omitempty"`
23-
TagName *string `json:"tag_name,omitempty"`
24-
TargetCommitish *string `json:"target_commitish,omitempty"`
25-
Name *string `json:"name,omitempty"`
26-
Body *string `json:"body,omitempty"`
27-
Draft *bool `json:"draft,omitempty"`
28-
Prerelease *bool `json:"prerelease,omitempty"`
29-
CreatedAt *Timestamp `json:"created_at,omitempty"`
30-
PublishedAt *Timestamp `json:"published_at,omitempty"`
31-
URL *string `json:"url,omitempty"`
32-
HTMLURL *string `json:"html_url,omitempty"`
33-
AssetsURL *string `json:"assets_url,omitempty"`
34-
Assets []ReleaseAsset `json:"assets,omitempty"`
35-
UploadURL *string `json:"upload_url,omitempty"`
36-
ZipballURL *string `json:"zipball_url,omitempty"`
37-
TarballURL *string `json:"tarball_url,omitempty"`
38-
Author *User `json:"author,omitempty"`
39-
NodeID *string `json:"node_id,omitempty"`
22+
TagName *string `json:"tag_name,omitempty"`
23+
TargetCommitish *string `json:"target_commitish,omitempty"`
24+
Name *string `json:"name,omitempty"`
25+
Body *string `json:"body,omitempty"`
26+
Draft *bool `json:"draft,omitempty"`
27+
Prerelease *bool `json:"prerelease,omitempty"`
28+
29+
// The following fields are not used in CreateRelease or EditRelease:
30+
ID *int64 `json:"id,omitempty"`
31+
CreatedAt *Timestamp `json:"created_at,omitempty"`
32+
PublishedAt *Timestamp `json:"published_at,omitempty"`
33+
URL *string `json:"url,omitempty"`
34+
HTMLURL *string `json:"html_url,omitempty"`
35+
AssetsURL *string `json:"assets_url,omitempty"`
36+
Assets []ReleaseAsset `json:"assets,omitempty"`
37+
UploadURL *string `json:"upload_url,omitempty"`
38+
ZipballURL *string `json:"zipball_url,omitempty"`
39+
TarballURL *string `json:"tarball_url,omitempty"`
40+
Author *User `json:"author,omitempty"`
41+
NodeID *string `json:"node_id,omitempty"`
4042
}
4143

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

130+
// repositoryReleaseRequest is a subset of RepositoryRelease and
131+
// is used internally by CreateRelease and EditRelease to pass
132+
// only the known fields for these endpoints.
133+
//
134+
// See https://github.com/google/go-github/issues/992 for more
135+
// information.
136+
type repositoryReleaseRequest struct {
137+
TagName *string `json:"tag_name,omitempty"`
138+
TargetCommitish *string `json:"target_commitish,omitempty"`
139+
Name *string `json:"name,omitempty"`
140+
Body *string `json:"body,omitempty"`
141+
Draft *bool `json:"draft,omitempty"`
142+
Prerelease *bool `json:"prerelease,omitempty"`
143+
}
144+
128145
// CreateRelease adds a new release for a repository.
129146
//
147+
// Note that only a subset of the release fields are used.
148+
// See RepositoryRelease for more information.
149+
//
130150
// GitHub API docs: https://developer.github.com/v3/repos/releases/#create-a-release
131151
func (s *RepositoriesService) CreateRelease(ctx context.Context, owner, repo string, release *RepositoryRelease) (*RepositoryRelease, *Response, error) {
132152
u := fmt.Sprintf("repos/%s/%s/releases", owner, repo)
133153

134-
req, err := s.client.NewRequest("POST", u, release)
154+
releaseReq := &repositoryReleaseRequest{
155+
TagName: release.TagName,
156+
TargetCommitish: release.TargetCommitish,
157+
Name: release.Name,
158+
Body: release.Body,
159+
Draft: release.Draft,
160+
Prerelease: release.Prerelease,
161+
}
162+
163+
req, err := s.client.NewRequest("POST", u, releaseReq)
135164
if err != nil {
136165
return nil, nil, err
137166
}
@@ -146,11 +175,23 @@ func (s *RepositoriesService) CreateRelease(ctx context.Context, owner, repo str
146175

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

153-
req, err := s.client.NewRequest("PATCH", u, release)
185+
releaseReq := &repositoryReleaseRequest{
186+
TagName: release.TagName,
187+
TargetCommitish: release.TargetCommitish,
188+
Name: release.Name,
189+
Body: release.Body,
190+
Draft: release.Draft,
191+
Prerelease: release.Prerelease,
192+
}
193+
194+
req, err := s.client.NewRequest("PATCH", u, releaseReq)
154195
if err != nil {
155196
return nil, nil, err
156197
}

github/repos_releases_test.go

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,31 @@ func TestRepositoriesService_CreateRelease(t *testing.T) {
103103
client, mux, _, teardown := setup()
104104
defer teardown()
105105

106-
input := &RepositoryRelease{Name: String("v1.0")}
106+
input := &RepositoryRelease{
107+
Name: String("v1.0"),
108+
// Fields to be removed:
109+
ID: Int64(2),
110+
CreatedAt: &Timestamp{referenceTime},
111+
PublishedAt: &Timestamp{referenceTime},
112+
URL: String("http://url/"),
113+
HTMLURL: String("http://htmlurl/"),
114+
AssetsURL: String("http://assetsurl/"),
115+
Assets: []ReleaseAsset{{ID: Int64(5)}},
116+
UploadURL: String("http://uploadurl/"),
117+
ZipballURL: String("http://zipballurl/"),
118+
TarballURL: String("http://tarballurl/"),
119+
Author: &User{Name: String("octocat")},
120+
NodeID: String("nodeid"),
121+
}
107122

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

112127
testMethod(t, r, "POST")
113-
if !reflect.DeepEqual(v, input) {
114-
t.Errorf("Request body = %+v, want %+v", v, input)
128+
want := &repositoryReleaseRequest{Name: String("v1.0")}
129+
if !reflect.DeepEqual(v, want) {
130+
t.Errorf("Request body = %+v, want %+v", v, want)
115131
}
116132
fmt.Fprint(w, `{"id":1}`)
117133
})
@@ -131,15 +147,31 @@ func TestRepositoriesService_EditRelease(t *testing.T) {
131147
client, mux, _, teardown := setup()
132148
defer teardown()
133149

134-
input := &RepositoryRelease{Name: String("n")}
150+
input := &RepositoryRelease{
151+
Name: String("n"),
152+
// Fields to be removed:
153+
ID: Int64(2),
154+
CreatedAt: &Timestamp{referenceTime},
155+
PublishedAt: &Timestamp{referenceTime},
156+
URL: String("http://url/"),
157+
HTMLURL: String("http://htmlurl/"),
158+
AssetsURL: String("http://assetsurl/"),
159+
Assets: []ReleaseAsset{{ID: Int64(5)}},
160+
UploadURL: String("http://uploadurl/"),
161+
ZipballURL: String("http://zipballurl/"),
162+
TarballURL: String("http://tarballurl/"),
163+
Author: &User{Name: String("octocat")},
164+
NodeID: String("nodeid"),
165+
}
135166

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

140171
testMethod(t, r, "PATCH")
141-
if !reflect.DeepEqual(v, input) {
142-
t.Errorf("Request body = %+v, want %+v", v, input)
172+
want := &repositoryReleaseRequest{Name: String("n")}
173+
if !reflect.DeepEqual(v, want) {
174+
t.Errorf("Request body = %+v, want %+v", v, want)
143175
}
144176
fmt.Fprint(w, `{"id":1}`)
145177
})

0 commit comments

Comments
 (0)