173 lines
4.5 KiB
Go
173 lines
4.5 KiB
Go
package edit
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"github.com/MakeNowJust/heredoc"
|
|
"github.com/cli/cli/v2/internal/ghrepo"
|
|
"github.com/cli/cli/v2/pkg/cmd/release/shared"
|
|
"github.com/cli/cli/v2/pkg/cmdutil"
|
|
"github.com/cli/cli/v2/pkg/iostreams"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
type EditOptions struct {
|
|
IO *iostreams.IOStreams
|
|
HttpClient func() (*http.Client, error)
|
|
BaseRepo func() (ghrepo.Interface, error)
|
|
|
|
TagName string
|
|
Target string
|
|
Name *string
|
|
Body *string
|
|
DiscussionCategory *string
|
|
Draft *bool
|
|
Prerelease *bool
|
|
IsLatest *bool
|
|
VerifyTag bool
|
|
}
|
|
|
|
func NewCmdEdit(f *cmdutil.Factory, runF func(*EditOptions) error) *cobra.Command {
|
|
opts := &EditOptions{
|
|
IO: f.IOStreams,
|
|
HttpClient: f.HttpClient,
|
|
}
|
|
|
|
var notesFile string
|
|
|
|
cmd := &cobra.Command{
|
|
DisableFlagsInUseLine: true,
|
|
|
|
Use: "edit <tag>",
|
|
Short: "Edit a release",
|
|
Example: heredoc.Doc(`
|
|
# Publish a release that was previously a draft
|
|
$ gh release edit v1.0 --draft=false
|
|
|
|
# Update the release notes from the content of a file
|
|
$ gh release edit v1.0 --notes-file /path/to/release_notes.md
|
|
`),
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
opts.BaseRepo = f.BaseRepo
|
|
|
|
if cmd.Flags().NFlag() == 0 {
|
|
return cmdutil.FlagErrorf("use flags to specify properties to edit")
|
|
}
|
|
|
|
if notesFile != "" {
|
|
b, err := cmdutil.ReadFile(notesFile, opts.IO.In)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
body := string(b)
|
|
opts.Body = &body
|
|
}
|
|
|
|
if runF != nil {
|
|
return runF(opts)
|
|
}
|
|
return editRun(args[0], opts)
|
|
},
|
|
}
|
|
|
|
cmdutil.NilBoolFlag(cmd, &opts.Draft, "draft", "", "Save the release as a draft instead of publishing it")
|
|
cmdutil.NilBoolFlag(cmd, &opts.Prerelease, "prerelease", "", "Mark the release as a prerelease")
|
|
cmdutil.NilBoolFlag(cmd, &opts.IsLatest, "latest", "", "Explicitly mark the release as \"Latest\"")
|
|
cmdutil.NilStringFlag(cmd, &opts.Body, "notes", "n", "Release notes")
|
|
cmdutil.NilStringFlag(cmd, &opts.Name, "title", "t", "Release title")
|
|
cmdutil.NilStringFlag(cmd, &opts.DiscussionCategory, "discussion-category", "", "Start a discussion in the specified category when publishing a draft")
|
|
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(¬esFile, "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")
|
|
|
|
return cmd
|
|
}
|
|
|
|
func editRun(tag string, opts *EditOptions) error {
|
|
httpClient, err := opts.HttpClient()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
baseRepo, err := opts.BaseRepo()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
release, err := shared.FetchRelease(context.Background(), httpClient, baseRepo, tag)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
params := getParams(opts)
|
|
|
|
// If we don't provide any tag name, the API will remove the current tag from the release
|
|
if _, ok := params["tag_name"]; !ok {
|
|
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
|
|
}
|
|
|
|
fmt.Fprintf(opts.IO.Out, "%s\n", editedRelease.URL)
|
|
|
|
return nil
|
|
}
|
|
|
|
func getParams(opts *EditOptions) map[string]interface{} {
|
|
params := map[string]interface{}{}
|
|
|
|
if opts.Body != nil {
|
|
params["body"] = opts.Body
|
|
}
|
|
|
|
if opts.DiscussionCategory != nil {
|
|
params["discussion_category_name"] = *opts.DiscussionCategory
|
|
}
|
|
|
|
if opts.Draft != nil {
|
|
params["draft"] = *opts.Draft
|
|
}
|
|
|
|
if opts.Name != nil {
|
|
params["name"] = opts.Name
|
|
}
|
|
|
|
if opts.Prerelease != nil {
|
|
params["prerelease"] = *opts.Prerelease
|
|
}
|
|
|
|
if opts.TagName != "" {
|
|
params["tag_name"] = opts.TagName
|
|
}
|
|
|
|
if opts.Target != "" {
|
|
params["target_commitish"] = opts.Target
|
|
}
|
|
|
|
if opts.IsLatest != nil {
|
|
// valid values: true/false/legacy
|
|
params["make_latest"] = fmt.Sprintf("%v", *opts.IsLatest)
|
|
}
|
|
|
|
return params
|
|
}
|