Skip to content

Commit 95b1e7f

Browse files
authored
Merge pull request cli#5019 from k-jun/fix/release-discussion-category
fix(release): discussion category with assets
2 parents 6e14426 + 5d36bcc commit 95b1e7f

File tree

3 files changed

+175
-92
lines changed

3 files changed

+175
-92
lines changed

pkg/cmd/release/create/create.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -389,13 +389,6 @@ func createRun(opts *CreateOptions) error {
389389
}
390390
}
391391

392-
if opts.Draft && len(opts.DiscussionCategory) > 0 {
393-
return fmt.Errorf(
394-
"%s Discussions not supported with draft releases",
395-
opts.IO.ColorScheme().FailureIcon(),
396-
)
397-
}
398-
399392
params := map[string]interface{}{
400393
"tag_name": opts.TagName,
401394
"draft": opts.Draft,
@@ -443,7 +436,7 @@ func createRun(opts *CreateOptions) error {
443436
}
444437

445438
if !opts.Draft {
446-
rel, err := publishRelease(httpClient, newRelease.APIURL)
439+
rel, err := publishRelease(httpClient, newRelease.APIURL, opts.DiscussionCategory)
447440
if err != nil {
448441
return err
449442
}

pkg/cmd/release/create/create_test.go

Lines changed: 163 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ func Test_createRun(t *testing.T) {
287287
name string
288288
isTTY bool
289289
opts CreateOptions
290-
wantParams interface{}
290+
httpStubs func(t *testing.T, reg *httpmock.Registry)
291291
wantErr string
292292
wantStdout string
293293
wantStderr string
@@ -302,12 +302,20 @@ func Test_createRun(t *testing.T) {
302302
BodyProvided: true,
303303
Target: "",
304304
},
305-
wantParams: map[string]interface{}{
306-
"tag_name": "v1.2.3",
307-
"name": "The Big 1.2",
308-
"body": "* Fixed bugs",
309-
"draft": false,
310-
"prerelease": false,
305+
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
306+
reg.Register(httpmock.REST("POST", "repos/OWNER/REPO/releases"), httpmock.RESTPayload(201, `{
307+
"url": "https://api.github.com/releases/123",
308+
"upload_url": "https://api.github.com/assets/upload",
309+
"html_url": "https://github.com/OWNER/REPO/releases/tag/v1.2.3"
310+
}`, func(params map[string]interface{}) {
311+
assert.Equal(t, map[string]interface{}{
312+
"tag_name": "v1.2.3",
313+
"name": "The Big 1.2",
314+
"body": "* Fixed bugs",
315+
"draft": false,
316+
"prerelease": false,
317+
}, params)
318+
}))
311319
},
312320
wantStdout: "https://github.com/OWNER/REPO/releases/tag/v1.2.3\n",
313321
wantStderr: ``,
@@ -323,13 +331,21 @@ func Test_createRun(t *testing.T) {
323331
Target: "",
324332
DiscussionCategory: "General",
325333
},
326-
wantParams: map[string]interface{}{
327-
"tag_name": "v1.2.3",
328-
"name": "The Big 1.2",
329-
"body": "* Fixed bugs",
330-
"draft": false,
331-
"prerelease": false,
332-
"discussion_category_name": "General",
334+
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
335+
reg.Register(httpmock.REST("POST", "repos/OWNER/REPO/releases"), httpmock.RESTPayload(201, `{
336+
"url": "https://api.github.com/releases/123",
337+
"upload_url": "https://api.github.com/assets/upload",
338+
"html_url": "https://github.com/OWNER/REPO/releases/tag/v1.2.3"
339+
}`, func(params map[string]interface{}) {
340+
assert.Equal(t, map[string]interface{}{
341+
"tag_name": "v1.2.3",
342+
"name": "The Big 1.2",
343+
"body": "* Fixed bugs",
344+
"draft": false,
345+
"prerelease": false,
346+
"discussion_category_name": "General",
347+
}, params)
348+
}))
333349
},
334350
wantStdout: "https://github.com/OWNER/REPO/releases/tag/v1.2.3\n",
335351
wantStderr: ``,
@@ -344,11 +360,19 @@ func Test_createRun(t *testing.T) {
344360
BodyProvided: true,
345361
Target: "main",
346362
},
347-
wantParams: map[string]interface{}{
348-
"tag_name": "v1.2.3",
349-
"draft": false,
350-
"prerelease": false,
351-
"target_commitish": "main",
363+
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
364+
reg.Register(httpmock.REST("POST", "repos/OWNER/REPO/releases"), httpmock.RESTPayload(201, `{
365+
"url": "https://api.github.com/releases/123",
366+
"upload_url": "https://api.github.com/assets/upload",
367+
"html_url": "https://github.com/OWNER/REPO/releases/tag/v1.2.3"
368+
}`, func(params map[string]interface{}) {
369+
assert.Equal(t, map[string]interface{}{
370+
"tag_name": "v1.2.3",
371+
"draft": false,
372+
"prerelease": false,
373+
"target_commitish": "main",
374+
}, params)
375+
}))
352376
},
353377
wantStdout: "https://github.com/OWNER/REPO/releases/tag/v1.2.3\n",
354378
wantStderr: ``,
@@ -364,35 +388,22 @@ func Test_createRun(t *testing.T) {
364388
Draft: true,
365389
Target: "",
366390
},
367-
wantParams: map[string]interface{}{
368-
"tag_name": "v1.2.3",
369-
"draft": true,
370-
"prerelease": false,
391+
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
392+
reg.Register(httpmock.REST("POST", "repos/OWNER/REPO/releases"), httpmock.RESTPayload(201, `{
393+
"url": "https://api.github.com/releases/123",
394+
"upload_url": "https://api.github.com/assets/upload",
395+
"html_url": "https://github.com/OWNER/REPO/releases/tag/v1.2.3"
396+
}`, func(params map[string]interface{}) {
397+
assert.Equal(t, map[string]interface{}{
398+
"tag_name": "v1.2.3",
399+
"draft": true,
400+
"prerelease": false,
401+
}, params)
402+
}))
371403
},
372404
wantStdout: "https://github.com/OWNER/REPO/releases/tag/v1.2.3\n",
373405
wantStderr: ``,
374406
},
375-
{
376-
name: "discussion category for draft release",
377-
isTTY: true,
378-
opts: CreateOptions{
379-
TagName: "v1.2.3",
380-
Name: "",
381-
Body: "",
382-
BodyProvided: true,
383-
Draft: true,
384-
Target: "",
385-
DiscussionCategory: "general",
386-
},
387-
wantParams: map[string]interface{}{
388-
"tag_name": "v1.2.3",
389-
"draft": true,
390-
"prerelease": false,
391-
"discussion_category_name": "general",
392-
},
393-
wantErr: "X Discussions not supported with draft releases",
394-
wantStdout: "",
395-
},
396407
{
397408
name: "with generate notes",
398409
isTTY: true,
@@ -404,11 +415,19 @@ func Test_createRun(t *testing.T) {
404415
BodyProvided: true,
405416
GenerateNotes: true,
406417
},
407-
wantParams: map[string]interface{}{
408-
"tag_name": "v1.2.3",
409-
"draft": false,
410-
"prerelease": false,
411-
"generate_release_notes": true,
418+
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
419+
reg.Register(httpmock.REST("POST", "repos/OWNER/REPO/releases"), httpmock.RESTPayload(201, `{
420+
"url": "https://api.github.com/releases/123",
421+
"upload_url": "https://api.github.com/assets/upload",
422+
"html_url": "https://github.com/OWNER/REPO/releases/tag/v1.2.3"
423+
}`, func(params map[string]interface{}) {
424+
assert.Equal(t, map[string]interface{}{
425+
"tag_name": "v1.2.3",
426+
"draft": false,
427+
"prerelease": false,
428+
"generate_release_notes": true,
429+
}, params)
430+
}))
412431
},
413432
wantStdout: "https://github.com/OWNER/REPO/releases/tag/v1.2.3\n",
414433
wantErr: "",
@@ -433,10 +452,97 @@ func Test_createRun(t *testing.T) {
433452
},
434453
Concurrency: 1,
435454
},
436-
wantParams: map[string]interface{}{
437-
"tag_name": "v1.2.3",
438-
"draft": true,
439-
"prerelease": false,
455+
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
456+
reg.Register(httpmock.REST("POST", "repos/OWNER/REPO/releases"), httpmock.RESTPayload(201, `{
457+
"url": "https://api.github.com/releases/123",
458+
"upload_url": "https://api.github.com/assets/upload",
459+
"html_url": "https://github.com/OWNER/REPO/releases/tag/v1.2.3"
460+
}`, func(params map[string]interface{}) {
461+
assert.Equal(t, map[string]interface{}{
462+
"tag_name": "v1.2.3",
463+
"draft": true,
464+
"prerelease": false,
465+
}, params)
466+
}))
467+
reg.Register(httpmock.REST("POST", "assets/upload"), func(req *http.Request) (*http.Response, error) {
468+
q := req.URL.Query()
469+
assert.Equal(t, "ball.tgz", q.Get("name"))
470+
assert.Equal(t, "", q.Get("label"))
471+
return &http.Response{
472+
StatusCode: 201,
473+
Request: req,
474+
Body: ioutil.NopCloser(bytes.NewBufferString(`{}`)),
475+
Header: map[string][]string{
476+
"Content-Type": {"application/json"},
477+
},
478+
}, nil
479+
})
480+
reg.Register(httpmock.REST("PATCH", "releases/123"), httpmock.RESTPayload(201, `{
481+
"html_url": "https://github.com/OWNER/REPO/releases/tag/v1.2.3-final"
482+
}`, func(params map[string]interface{}) {
483+
assert.Equal(t, map[string]interface{}{
484+
"draft": false,
485+
}, params)
486+
}))
487+
},
488+
wantStdout: "https://github.com/OWNER/REPO/releases/tag/v1.2.3-final\n",
489+
wantStderr: ``,
490+
},
491+
{
492+
name: "upload files and create discussion",
493+
isTTY: true,
494+
opts: CreateOptions{
495+
TagName: "v1.2.3",
496+
Name: "",
497+
Body: "",
498+
BodyProvided: true,
499+
Draft: false,
500+
Target: "",
501+
Assets: []*shared.AssetForUpload{
502+
{
503+
Name: "ball.tgz",
504+
Open: func() (io.ReadCloser, error) {
505+
return ioutil.NopCloser(bytes.NewBufferString(`TARBALL`)), nil
506+
},
507+
},
508+
},
509+
DiscussionCategory: "general",
510+
Concurrency: 1,
511+
},
512+
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
513+
reg.Register(httpmock.REST("POST", "repos/OWNER/REPO/releases"), httpmock.RESTPayload(201, `{
514+
"url": "https://api.github.com/releases/123",
515+
"upload_url": "https://api.github.com/assets/upload",
516+
"html_url": "https://github.com/OWNER/REPO/releases/tag/v1.2.3"
517+
}`, func(params map[string]interface{}) {
518+
assert.Equal(t, map[string]interface{}{
519+
"tag_name": "v1.2.3",
520+
"draft": true,
521+
"prerelease": false,
522+
"discussion_category_name": "general",
523+
}, params)
524+
}))
525+
reg.Register(httpmock.REST("POST", "assets/upload"), func(req *http.Request) (*http.Response, error) {
526+
q := req.URL.Query()
527+
assert.Equal(t, "ball.tgz", q.Get("name"))
528+
assert.Equal(t, "", q.Get("label"))
529+
return &http.Response{
530+
StatusCode: 201,
531+
Request: req,
532+
Body: ioutil.NopCloser(bytes.NewBufferString(`{}`)),
533+
Header: map[string][]string{
534+
"Content-Type": {"application/json"},
535+
},
536+
}, nil
537+
})
538+
reg.Register(httpmock.REST("PATCH", "releases/123"), httpmock.RESTPayload(201, `{
539+
"html_url": "https://github.com/OWNER/REPO/releases/tag/v1.2.3-final"
540+
}`, func(params map[string]interface{}) {
541+
assert.Equal(t, map[string]interface{}{
542+
"draft": false,
543+
"discussion_category_name": "general",
544+
}, params)
545+
}))
440546
},
441547
wantStdout: "https://github.com/OWNER/REPO/releases/tag/v1.2.3-final\n",
442548
wantStderr: ``,
@@ -450,15 +556,10 @@ func Test_createRun(t *testing.T) {
450556
io.SetStderrTTY(tt.isTTY)
451557

452558
fakeHTTP := &httpmock.Registry{}
453-
fakeHTTP.Register(httpmock.REST("POST", "repos/OWNER/REPO/releases"), httpmock.StatusStringResponse(201, `{
454-
"url": "https://api.github.com/releases/123",
455-
"upload_url": "https://api.github.com/assets/upload",
456-
"html_url": "https://github.com/OWNER/REPO/releases/tag/v1.2.3"
457-
}`))
458-
fakeHTTP.Register(httpmock.REST("POST", "assets/upload"), httpmock.StatusStringResponse(201, `{}`))
459-
fakeHTTP.Register(httpmock.REST("PATCH", "releases/123"), httpmock.StatusStringResponse(201, `{
460-
"html_url": "https://github.com/OWNER/REPO/releases/tag/v1.2.3-final"
461-
}`))
559+
if tt.httpStubs != nil {
560+
tt.httpStubs(t, fakeHTTP)
561+
}
562+
defer fakeHTTP.Verify(t)
462563

463564
tt.opts.IO = io
464565
tt.opts.HttpClient = func() (*http.Client, error) {
@@ -476,26 +577,6 @@ func Test_createRun(t *testing.T) {
476577
require.NoError(t, err)
477578
}
478579

479-
bb, err := ioutil.ReadAll(fakeHTTP.Requests[0].Body)
480-
require.NoError(t, err)
481-
var params interface{}
482-
err = json.Unmarshal(bb, &params)
483-
require.NoError(t, err)
484-
assert.Equal(t, tt.wantParams, params)
485-
486-
if len(tt.opts.Assets) > 0 {
487-
q := fakeHTTP.Requests[1].URL.Query()
488-
assert.Equal(t, tt.opts.Assets[0].Name, q.Get("name"))
489-
assert.Equal(t, tt.opts.Assets[0].Label, q.Get("label"))
490-
491-
bb, err := ioutil.ReadAll(fakeHTTP.Requests[2].Body)
492-
require.NoError(t, err)
493-
var updateParams interface{}
494-
err = json.Unmarshal(bb, &updateParams)
495-
require.NoError(t, err)
496-
assert.Equal(t, map[string]interface{}{"draft": false}, updateParams)
497-
}
498-
499580
assert.Equal(t, tt.wantStdout, stdout.String())
500581
assert.Equal(t, tt.wantStderr, stderr.String())
501582
})

pkg/cmd/release/create/http.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,17 @@ func createRelease(httpClient *http.Client, repo ghrepo.Interface, params map[st
155155
return &newRelease, err
156156
}
157157

158-
func publishRelease(httpClient *http.Client, releaseURL string) (*shared.Release, error) {
159-
req, err := http.NewRequest("PATCH", releaseURL, bytes.NewBufferString(`{"draft":false}`))
158+
func publishRelease(httpClient *http.Client, releaseURL string, discussionCategory string) (*shared.Release, error) {
159+
params := map[string]interface{}{"draft": false}
160+
if discussionCategory != "" {
161+
params["discussion_category_name"] = discussionCategory
162+
}
163+
164+
bodyBytes, err := json.Marshal(params)
165+
if err != nil {
166+
return nil, err
167+
}
168+
req, err := http.NewRequest("PATCH", releaseURL, bytes.NewBuffer(bodyBytes))
160169
if err != nil {
161170
return nil, err
162171
}

0 commit comments

Comments
 (0)