package create
import (
"fmt"
"net/http"
"time"
"github.com/MakeNowJust/heredoc/v2"
"github.com/spf13/cobra"
"gitcode.com/gitcode-cli/cli/api"
cmdutil "gitcode.com/gitcode-cli/cli/pkg/cmdutil"
"gitcode.com/gitcode-cli/cli/pkg/iostreams"
)
type CreateOptions struct {
IO *iostreams.IOStreams
HttpClient func() (*http.Client, error)
BaseRepo func() (string, error)
Repository string
Title string
Description string
DueDate string
JSON bool
}
func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Command {
opts := &CreateOptions{
IO: f.IOStreams,
HttpClient: f.HttpClient,
BaseRepo: f.BaseRepo,
}
cmd := &cobra.Command{
Use: "create <title>",
Short: "Create a milestone",
Long: heredoc.Doc(`
Create a new milestone in a GitCode repository.
`),
Example: heredoc.Doc(`
# Create a milestone (due date defaults to 30 days from now)
$ gc milestone create "v1.0" -R owner/repo
# Create with specific due date
$ gc milestone create "v1.0" --due-date "2024-12-31" -R owner/repo
# Create with description
$ gc milestone create "v2.0" --description "Next release" --due-date "2025-01-31" -R owner/repo
# Output as JSON
$ gc milestone create "v1.0" -R owner/repo --json
`),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
opts.Title = args[0]
if runF != nil {
return runF(opts)
}
return createRun(opts)
},
}
cmd.Flags().StringVarP(&opts.Repository, "repo", "R", "", "Repository (owner/repo)")
cmd.Flags().StringVarP(&opts.Description, "description", "d", "", "Description")
cmd.Flags().StringVarP(&opts.DueDate, "due-date", "D", "", "Due date (YYYY-MM-DD)")
cmd.Flags().BoolVar(&opts.JSON, "json", false, "Output as JSON")
return cmd
}
func createRun(opts *CreateOptions) error {
if opts.Description != "" {
if err := cmdutil.ScanContentForSecrets(opts.Description); err != nil {
return err
}
}
cs := opts.IO.ColorScheme()
httpClient, err := opts.HttpClient()
if err != nil {
return fmt.Errorf("failed to create HTTP client: %w", err)
}
client, err := cmdutil.AuthenticatedClient(httpClient)
if err != nil {
return err
}
repository, err := cmdutil.ResolveRepo(opts.Repository, opts.BaseRepo)
if err != nil {
return err
}
owner, repo, err := parseRepo(repository)
if err != nil {
return err
}
var dueOn string
if opts.DueDate != "" {
_, err := time.Parse("2006-01-02", opts.DueDate)
if err != nil {
return cmdutil.NewUsageError("invalid due date format, use YYYY-MM-DD")
}
dueOn = opts.DueDate
} else {
dueOn = time.Now().AddDate(0, 0, 30).Format("2006-01-02")
}
ms, err := api.CreateMilestone(client, owner, repo, &api.CreateMilestoneOptions{
Title: opts.Title,
Description: opts.Description,
DueOn: dueOn,
})
if err != nil {
return fmt.Errorf("failed to create milestone: %w", err)
}
if opts.JSON {
return cmdutil.WriteJSON(opts.IO.Out, ms)
}
fmt.Fprintf(opts.IO.Out, "%s Created milestone #%d %s in %s/%s\n", cs.Green("✓"), ms.Number, cs.Bold(ms.Title), owner, repo)
return nil
}
func parseRepo(repo string) (string, string, error) {
return cmdutil.ParseRepo(repo)
}