Add --verify-tag to release edit command (#7646)

This commit is contained in:
Raj Hawaldar 2023-07-07 19:53:39 +05:30 committed by GitHub
parent 3dd3fb0319
commit 0d8c34bf59
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 71 additions and 12 deletions

View file

@ -157,6 +157,7 @@ func Test_deleteAssetRun(t *testing.T) {
ios.SetStderrTTY(tt.isTTY)
fakeHTTP := &httpmock.Registry{}
defer fakeHTTP.Verify(t)
shared.StubFetchRelease(t, fakeHTTP, "OWNER", "REPO", tt.opts.TagName, `{
"tag_name": "v1.2.3",
"draft": false,

View file

@ -516,7 +516,7 @@ func Test_downloadRun_cloberAndSkip(t *testing.T) {
tt.opts.IO = ios
reg := &httpmock.Registry{}
// defer reg.Verify(t) // FIXME: intermittetly fails due to StubFetchRelease internals
defer reg.Verify(t)
shared.StubFetchRelease(t, reg, "OWNER", "REPO", "v1.2.3", `{
"assets": [
{ "name": "windows-64bit.zip", "size": 34,

View file

@ -26,6 +26,7 @@ type EditOptions struct {
Draft *bool
Prerelease *bool
IsLatest *bool
VerifyTag bool
}
func NewCmdEdit(f *cmdutil.Factory, runF func(*EditOptions) error) *cobra.Command {
@ -81,6 +82,7 @@ func NewCmdEdit(f *cmdutil.Factory, runF func(*EditOptions) error) *cobra.Comman
cmd.Flags().StringVar(&opts.Target, "target", "", "Target `branch` or full commit SHA (default: main branch)")
cmd.Flags().StringVar(&opts.TagName, "tag", "", "The name of the tag")
cmd.Flags().StringVarP(&notesFile, "notes-file", "F", "", "Read release notes from `file` (use \"-\" to read from standard input)")
cmd.Flags().BoolVar(&opts.VerifyTag, "verify-tag", false, "Abort in case the git tag doesn't already exist in the remote repository")
_ = cmdutil.RegisterBranchCompletionFlags(f.GitClient, cmd, "target")
@ -110,6 +112,17 @@ func editRun(tag string, opts *EditOptions) error {
params["tag_name"] = release.TagName
}
if opts.VerifyTag && opts.TagName != "" {
remoteTagPresent, err := remoteTagExists(httpClient, baseRepo, opts.TagName)
if err != nil {
return err
}
if !remoteTagPresent {
return fmt.Errorf("tag %s doesn't exist in the repo %s, aborting due to --verify-tag flag",
opts.TagName, ghrepo.FullName(baseRepo))
}
}
editedRelease, err := editRelease(httpClient, baseRepo, release.DatabaseID, params)
if err != nil {
return err

View file

@ -140,6 +140,15 @@ func Test_NewCmdEdit(t *testing.T) {
Body: stringPtr("MY NOTES"),
},
},
{
name: "verify-tag",
args: "v1.2.0 --tag=v1.1.0 --verify-tag",
isTTY: false,
want: EditOptions{
TagName: "v1.1.0",
VerifyTag: true,
},
},
}
for _, tt := range tests {
@ -189,6 +198,7 @@ func Test_NewCmdEdit(t *testing.T) {
assert.Equal(t, tt.want.Draft, opts.Draft)
assert.Equal(t, tt.want.Prerelease, opts.Prerelease)
assert.Equal(t, tt.want.IsLatest, opts.IsLatest)
assert.Equal(t, tt.want.VerifyTag, opts.VerifyTag)
})
}
}
@ -406,6 +416,21 @@ func Test_editRun(t *testing.T) {
wantStdout: "https://github.com/OWNER/REPO/releases/tag/v1.2.3\n",
wantStderr: "",
},
{
name: "error when remote tag does not exist and verify-tag flag is set",
isTTY: true,
opts: EditOptions{
TagName: "v1.2.4",
VerifyTag: true,
},
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
reg.Register(httpmock.GraphQL("RepositoryFindRef"),
httpmock.StringResponse(`{"data":{"repository":{"ref": {"id": ""}}}}`))
},
wantErr: "tag v1.2.4 doesn't exist in the repo OWNER/REPO, aborting due to --verify-tag flag",
wantStdout: "",
wantStderr: "",
},
}
for _, tt := range tests {
@ -416,7 +441,7 @@ func Test_editRun(t *testing.T) {
ios.SetStderrTTY(tt.isTTY)
fakeHTTP := &httpmock.Registry{}
// defer reg.Verify(t) // FIXME: intermittetly fails due to StubFetchRelease internals
defer fakeHTTP.Verify(t)
shared.StubFetchRelease(t, fakeHTTP, "OWNER", "REPO", "v1.2.3", `{
"id": 12345,
"tag_name": "v1.2.3"

View file

@ -11,6 +11,7 @@ import (
"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/shurcooL/githubv4"
)
func editRelease(httpClient *http.Client, repo ghrepo.Interface, releaseID int64, params map[string]interface{}) (*shared.Release, error) {
@ -48,3 +49,22 @@ func editRelease(httpClient *http.Client, repo ghrepo.Interface, releaseID int64
err = json.Unmarshal(b, &newRelease)
return &newRelease, err
}
func remoteTagExists(httpClient *http.Client, repo ghrepo.Interface, tagName string) (bool, error) {
gql := api.NewClientFromHTTP(httpClient)
qualifiedTagName := fmt.Sprintf("refs/tags/%s", tagName)
var query struct {
Repository struct {
Ref struct {
ID string
} `graphql:"ref(qualifiedName: $tagName)"`
} `graphql:"repository(owner: $owner, name: $name)"`
}
variables := map[string]interface{}{
"owner": githubv4.String(repo.RepoOwner()),
"name": githubv4.String(repo.RepoName()),
"tagName": githubv4.String(qualifiedTagName),
}
err := gql.Query(repo.RepoHost(), "RepositoryFindRef", &query, variables)
return query.Repository.Ref.ID != "", err
}

View file

@ -9,6 +9,7 @@ import (
"net/http"
"reflect"
"strings"
"testing"
"time"
"github.com/cli/cli/v2/api"
@ -224,11 +225,7 @@ func fetchReleasePath(ctx context.Context, httpClient *http.Client, host string,
return &release, nil
}
type testingT interface {
Errorf(format string, args ...interface{})
}
func StubFetchRelease(t testingT, reg *httpmock.Registry, owner, repoName, tagName, responseBody string) {
func StubFetchRelease(t *testing.T, reg *httpmock.Registry, owner, repoName, tagName, responseBody string) {
path := "repos/OWNER/REPO/releases/tags/v1.2.3"
if tagName == "" {
path = "repos/OWNER/REPO/releases/latest"
@ -239,10 +236,12 @@ func StubFetchRelease(t testingT, reg *httpmock.Registry, owner, repoName, tagNa
if tagName != "" {
reg.Register(
httpmock.GraphQL(`query RepositoryReleaseByTag\b`),
httpmock.GraphQLQuery(`{ "data": { "repository": { "release": null }}}`, func(q string, vars map[string]interface{}) {
assert.Equal(t, owner, vars["owner"])
assert.Equal(t, repoName, vars["name"])
assert.Equal(t, tagName, vars["tagName"])
}))
httpmock.GraphQLQuery(`{ "data": { "repository": { "release": null }}}`,
func(q string, vars map[string]interface{}) {
assert.Equal(t, owner, vars["owner"])
assert.Equal(t, repoName, vars["name"])
assert.Equal(t, tagName, vars["tagName"])
}),
)
}
}

View file

@ -215,6 +215,7 @@ func Test_viewRun(t *testing.T) {
ios.SetStderrTTY(tt.isTTY)
fakeHTTP := &httpmock.Registry{}
defer fakeHTTP.Verify(t)
shared.StubFetchRelease(t, fakeHTTP, "OWNER", "REPO", tt.opts.TagName, fmt.Sprintf(`{
"tag_name": "v1.2.3",
"draft": false,