feat(cmd/release): allow to delete release with its attached tag
This commit is contained in:
parent
4a2ca15350
commit
0b0ae1e673
2 changed files with 80 additions and 2 deletions
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/cli/cli/v2/api"
|
||||
"github.com/cli/cli/v2/internal/ghinstance"
|
||||
"github.com/cli/cli/v2/internal/ghrepo"
|
||||
"github.com/cli/cli/v2/pkg/cmd/release/shared"
|
||||
"github.com/cli/cli/v2/pkg/cmdutil"
|
||||
|
|
@ -21,6 +22,7 @@ type DeleteOptions struct {
|
|||
|
||||
TagName string
|
||||
SkipConfirm bool
|
||||
CleanupTag bool
|
||||
}
|
||||
|
||||
func NewCmdDelete(f *cmdutil.Factory, runF func(*DeleteOptions) error) *cobra.Command {
|
||||
|
|
@ -47,6 +49,7 @@ func NewCmdDelete(f *cmdutil.Factory, runF func(*DeleteOptions) error) *cobra.Co
|
|||
}
|
||||
|
||||
cmd.Flags().BoolVarP(&opts.SkipConfirm, "yes", "y", false, "Skip the confirmation prompt")
|
||||
cmd.Flags().BoolVar(&opts.CleanupTag, "cleanup-tag", false, "Delete the tag attached to the release")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
|
@ -88,13 +91,23 @@ func deleteRun(opts *DeleteOptions) error {
|
|||
return err
|
||||
}
|
||||
|
||||
var cleanupMessage string
|
||||
mustCleanupTag := opts.CleanupTag
|
||||
if mustCleanupTag {
|
||||
err = deleteTag(httpClient, baseRepo, release.TagName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cleanupMessage = " and cleanup the tag"
|
||||
}
|
||||
|
||||
if !opts.IO.IsStdoutTTY() || !opts.IO.IsStderrTTY() {
|
||||
return nil
|
||||
}
|
||||
|
||||
iofmt := opts.IO.ColorScheme()
|
||||
fmt.Fprintf(opts.IO.ErrOut, "%s Deleted release %s\n", iofmt.SuccessIconWithColor(iofmt.Red), release.TagName)
|
||||
if !release.IsDraft {
|
||||
fmt.Fprintf(opts.IO.ErrOut, "%s Deleted release %s%s\n", iofmt.SuccessIconWithColor(iofmt.Red), release.TagName, cleanupMessage)
|
||||
if !release.IsDraft && !mustCleanupTag {
|
||||
fmt.Fprintf(opts.IO.ErrOut, "%s Note that the %s git tag still remains in the repository\n", iofmt.WarningIcon(), release.TagName)
|
||||
}
|
||||
|
||||
|
|
@ -118,3 +131,25 @@ func deleteRelease(httpClient *http.Client, releaseURL string) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteTag(httpClient *http.Client, baseRepo ghrepo.Interface, tagName string) error {
|
||||
path := fmt.Sprintf("repos/%s/%s/git/refs/tags/%s", baseRepo.RepoOwner(), baseRepo.RepoName(), tagName)
|
||||
url := ghinstance.RESTPrefix(baseRepo.RepoHost()) + path
|
||||
|
||||
req, err := http.NewRequest("DELETE", url, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode > 299 {
|
||||
return api.HandleHTTPError(resp)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ func Test_NewCmdDelete(t *testing.T) {
|
|||
want: DeleteOptions{
|
||||
TagName: "v1.2.3",
|
||||
SkipConfirm: false,
|
||||
CleanupTag: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -40,6 +41,17 @@ func Test_NewCmdDelete(t *testing.T) {
|
|||
want: DeleteOptions{
|
||||
TagName: "v1.2.3",
|
||||
SkipConfirm: true,
|
||||
CleanupTag: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "cleanup tag",
|
||||
args: "v1.2.3 --cleanup-tag",
|
||||
isTTY: true,
|
||||
want: DeleteOptions{
|
||||
TagName: "v1.2.3",
|
||||
SkipConfirm: false,
|
||||
CleanupTag: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -83,8 +95,10 @@ func Test_NewCmdDelete(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
|
||||
assert.Equal(t, tt.want.TagName, opts.TagName)
|
||||
assert.Equal(t, tt.want.SkipConfirm, opts.SkipConfirm)
|
||||
assert.Equal(t, tt.want.CleanupTag, opts.CleanupTag)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -104,6 +118,7 @@ func Test_deleteRun(t *testing.T) {
|
|||
opts: DeleteOptions{
|
||||
TagName: "v1.2.3",
|
||||
SkipConfirm: true,
|
||||
CleanupTag: false,
|
||||
},
|
||||
wantStdout: ``,
|
||||
wantStderr: heredoc.Doc(`
|
||||
|
|
@ -117,6 +132,31 @@ func Test_deleteRun(t *testing.T) {
|
|||
opts: DeleteOptions{
|
||||
TagName: "v1.2.3",
|
||||
SkipConfirm: false,
|
||||
CleanupTag: false,
|
||||
},
|
||||
wantStdout: ``,
|
||||
wantStderr: ``,
|
||||
},
|
||||
{
|
||||
name: "cleanup-tag & skipping confirmation",
|
||||
isTTY: true,
|
||||
opts: DeleteOptions{
|
||||
TagName: "v1.2.3",
|
||||
SkipConfirm: true,
|
||||
CleanupTag: true,
|
||||
},
|
||||
wantStdout: ``,
|
||||
wantStderr: heredoc.Doc(`
|
||||
✓ Deleted release v1.2.3 and cleanup the tag
|
||||
`),
|
||||
},
|
||||
{
|
||||
name: "cleanup-tag",
|
||||
isTTY: false,
|
||||
opts: DeleteOptions{
|
||||
TagName: "v1.2.3",
|
||||
SkipConfirm: false,
|
||||
CleanupTag: true,
|
||||
},
|
||||
wantStdout: ``,
|
||||
wantStderr: ``,
|
||||
|
|
@ -135,7 +175,10 @@ func Test_deleteRun(t *testing.T) {
|
|||
"draft": false,
|
||||
"url": "https://api.github.com/repos/OWNER/REPO/releases/23456"
|
||||
}`))
|
||||
|
||||
fakeHTTP.Register(httpmock.REST("DELETE", "repos/OWNER/REPO/releases/23456"), httpmock.StatusStringResponse(204, ""))
|
||||
fakeHTTP.Register(httpmock.REST("DELETE", "repos/OWNER/REPO/git/refs/tags/v1.2.3"), httpmock.StatusStringResponse(204, ""))
|
||||
|
||||
|
||||
tt.opts.IO = ios
|
||||
tt.opts.HttpClient = func() (*http.Client, error) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue