github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/pkg/cmd/release/edit/edit.go (about)

     1  package edit
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  
     7  	"github.com/MakeNowJust/heredoc"
     8  	"github.com/ungtb10d/cli/v2/internal/ghrepo"
     9  	"github.com/ungtb10d/cli/v2/pkg/cmd/release/shared"
    10  	"github.com/ungtb10d/cli/v2/pkg/cmdutil"
    11  	"github.com/ungtb10d/cli/v2/pkg/iostreams"
    12  	"github.com/spf13/cobra"
    13  )
    14  
    15  type EditOptions struct {
    16  	IO         *iostreams.IOStreams
    17  	HttpClient func() (*http.Client, error)
    18  	BaseRepo   func() (ghrepo.Interface, error)
    19  
    20  	TagName            string
    21  	Target             string
    22  	Name               *string
    23  	Body               *string
    24  	DiscussionCategory *string
    25  	Draft              *bool
    26  	Prerelease         *bool
    27  	IsLatest           *bool
    28  }
    29  
    30  func NewCmdEdit(f *cmdutil.Factory, runF func(*EditOptions) error) *cobra.Command {
    31  	opts := &EditOptions{
    32  		IO:         f.IOStreams,
    33  		HttpClient: f.HttpClient,
    34  	}
    35  
    36  	var notesFile string
    37  
    38  	cmd := &cobra.Command{
    39  		DisableFlagsInUseLine: true,
    40  
    41  		Use:   "edit <tag>",
    42  		Short: "Edit a release",
    43  		Example: heredoc.Doc(`
    44  			Publish a release that was previously a draft
    45  			$ gh release edit v1.0 --draft=false
    46  
    47  			Update the release notes from the content of a file
    48  			$ gh release edit v1.0 --notes-file /path/to/release_notes.md
    49  		`),
    50  		Args: cobra.ExactArgs(1),
    51  		RunE: func(cmd *cobra.Command, args []string) error {
    52  			opts.BaseRepo = f.BaseRepo
    53  
    54  			if cmd.Flags().NFlag() == 0 {
    55  				return cmdutil.FlagErrorf("use flags to specify properties to edit")
    56  			}
    57  
    58  			if notesFile != "" {
    59  				b, err := cmdutil.ReadFile(notesFile, opts.IO.In)
    60  				if err != nil {
    61  					return err
    62  				}
    63  				body := string(b)
    64  				opts.Body = &body
    65  			}
    66  
    67  			if runF != nil {
    68  				return runF(opts)
    69  			}
    70  			return editRun(args[0], opts)
    71  		},
    72  	}
    73  
    74  	cmdutil.NilBoolFlag(cmd, &opts.Draft, "draft", "", "Save the release as a draft instead of publishing it")
    75  	cmdutil.NilBoolFlag(cmd, &opts.Prerelease, "prerelease", "", "Mark the release as a prerelease")
    76  	cmdutil.NilBoolFlag(cmd, &opts.IsLatest, "latest", "", "Explicitly mark the release as \"Latest\"")
    77  	cmdutil.NilStringFlag(cmd, &opts.Body, "notes", "n", "Release notes")
    78  	cmdutil.NilStringFlag(cmd, &opts.Name, "title", "t", "Release title")
    79  	cmdutil.NilStringFlag(cmd, &opts.DiscussionCategory, "discussion-category", "", "Start a discussion in the specified category when publishing a draft")
    80  	cmd.Flags().StringVar(&opts.Target, "target", "", "Target `branch` or full commit SHA (default: main branch)")
    81  	cmd.Flags().StringVar(&opts.TagName, "tag", "", "The name of the tag")
    82  	cmd.Flags().StringVarP(&notesFile, "notes-file", "F", "", "Read release notes from `file` (use \"-\" to read from standard input)")
    83  
    84  	return cmd
    85  }
    86  
    87  func editRun(tag string, opts *EditOptions) error {
    88  	httpClient, err := opts.HttpClient()
    89  	if err != nil {
    90  		return err
    91  	}
    92  
    93  	baseRepo, err := opts.BaseRepo()
    94  	if err != nil {
    95  		return err
    96  	}
    97  
    98  	release, err := shared.FetchRelease(httpClient, baseRepo, tag)
    99  	if err != nil {
   100  		return err
   101  	}
   102  
   103  	params := getParams(opts)
   104  
   105  	// If we don't provide any tag name, the API will remove the current tag from the release
   106  	if _, ok := params["tag_name"]; !ok {
   107  		params["tag_name"] = release.TagName
   108  	}
   109  
   110  	editedRelease, err := editRelease(httpClient, baseRepo, release.DatabaseID, params)
   111  	if err != nil {
   112  		return err
   113  	}
   114  
   115  	fmt.Fprintf(opts.IO.Out, "%s\n", editedRelease.URL)
   116  
   117  	return nil
   118  }
   119  
   120  func getParams(opts *EditOptions) map[string]interface{} {
   121  	params := map[string]interface{}{}
   122  
   123  	if opts.Body != nil {
   124  		params["body"] = opts.Body
   125  	}
   126  
   127  	if opts.DiscussionCategory != nil {
   128  		params["discussion_category_name"] = *opts.DiscussionCategory
   129  	}
   130  
   131  	if opts.Draft != nil {
   132  		params["draft"] = *opts.Draft
   133  	}
   134  
   135  	if opts.Name != nil {
   136  		params["name"] = opts.Name
   137  	}
   138  
   139  	if opts.Prerelease != nil {
   140  		params["prerelease"] = *opts.Prerelease
   141  	}
   142  
   143  	if opts.TagName != "" {
   144  		params["tag_name"] = opts.TagName
   145  	}
   146  
   147  	if opts.Target != "" {
   148  		params["target_commitish"] = opts.Target
   149  	}
   150  
   151  	if opts.IsLatest != nil {
   152  		// valid values: true/false/legacy
   153  		params["make_latest"] = fmt.Sprintf("%v", *opts.IsLatest)
   154  	}
   155  
   156  	return params
   157  }