rickub/clipublic Fork 0
main
Commits
Clone
git clone https://git.rickub.com/rickub/cli.git
git clone ssh://git@rickub.com/rickub/cli.git
milestone.go · 163 lines · 4.1 KBGo Blame HistoryRaw
Initial import of the rickub CLI as a standalone public project 1a1d430 Olivier Girardot 9h ago1package cmd
2
3import (
4 "fmt"
5 "strings"
6
7 "github.com/spf13/cobra"
8)
9
10var (
11 milestoneRepo string
12 milestoneState string
13 milestoneTitle string
14 milestoneDue string
15 milestoneDescription string
16)
17
18func init() {
19 msCmd := &cobra.Command{
20 Use: "milestone",
21 Aliases: []string{"milestones"},
22 Short: "Work with milestones",
23 }
24 msCmd.PersistentFlags().StringVarP(&milestoneRepo, "repo", "R", "", "target repo as owner/repo (default: current git remote)")
25
26 listCmd := &cobra.Command{
27 Use: "list",
28 Short: "List milestones",
29 Args: cobra.NoArgs,
30 RunE: runMilestoneList,
31 }
32 listCmd.Flags().StringVar(&milestoneState, "state", "open", "open | closed | all")
33
34 createCmd := &cobra.Command{
35 Use: "create",
36 Short: "Create a milestone",
37 Args: cobra.NoArgs,
38 RunE: runMilestoneCreate,
39 }
40 createCmd.Flags().StringVarP(&milestoneTitle, "title", "t", "", "title (required)")
41 createCmd.Flags().StringVarP(&milestoneDescription, "description", "d", "", "description")
42 createCmd.Flags().StringVar(&milestoneDue, "due", "", "due date, YYYY-MM-DD")
43
44 closeCmd := &cobra.Command{
45 Use: "close <id>",
46 Short: "Close a milestone (by id; see `milestone list`)",
47 Args: cobra.ExactArgs(1),
48 RunE: func(cmd *cobra.Command, args []string) error { return runMilestoneSetState(cmd, args, "closed") },
49 }
50
51 reopenCmd := &cobra.Command{
52 Use: "reopen <id>",
53 Short: "Reopen a closed milestone",
54 Args: cobra.ExactArgs(1),
55 RunE: func(cmd *cobra.Command, args []string) error { return runMilestoneSetState(cmd, args, "open") },
56 }
57
58 deleteCmd := &cobra.Command{
59 Use: "delete <id>",
60 Short: "Delete a milestone (issues keep going, milestone cleared)",
61 Args: cobra.ExactArgs(1),
62 RunE: runMilestoneDelete,
63 }
64
65 msCmd.AddCommand(listCmd, createCmd, closeCmd, reopenCmd, deleteCmd)
66 rootCmd.AddCommand(msCmd)
67}
68
69func runMilestoneList(cmd *cobra.Command, _ []string) error {
70 client, err := newClient()
71 if err != nil {
72 return err
73 }
74 owner, repo, err := resolveRepo(milestoneRepo)
75 if err != nil {
76 return err
77 }
78 mses, err := client.ListMilestones(cmd.Context(), owner, repo, milestoneState)
79 if err != nil {
80 return err
81 }
82 if flagJSON {
83 return printJSON(cmd.OutOrStdout(), mses)
84 }
85 if len(mses) == 0 {
86 fmt.Fprintln(cmd.OutOrStdout(), "No milestones.")
87 return nil
88 }
89 tw := newTabw(cmd.OutOrStdout())
90 fmt.Fprintln(tw, "ID\tSTATE\tDUE\tPROGRESS\tTITLE")
91 for _, m := range mses {
92 progress := fmt.Sprintf("%d/%d", m.ClosedCount, m.OpenCount+m.ClosedCount)
93 fmt.Fprintf(tw, "%s\t%s\t%s\t%s\t%s\n", m.ID, m.State, dash(deref(m.DueOn)), progress, m.Title)
94 }
95 tw.Flush()
96 return nil
97}
98
99func deref(s *string) string {
100 if s == nil {
101 return ""
102 }
103 return *s
104}
105
106func runMilestoneCreate(cmd *cobra.Command, _ []string) error {
107 if strings.TrimSpace(milestoneTitle) == "" {
108 return fmt.Errorf("--title is required")
109 }
110 client, err := newClient()
111 if err != nil {
112 return err
113 }
114 owner, repo, err := resolveRepo(milestoneRepo)
115 if err != nil {
116 return err
117 }
118 m, err := client.CreateMilestone(cmd.Context(), owner, repo, milestoneTitle, milestoneDescription, milestoneDue)
119 if err != nil {
120 return err
121 }
122 if flagJSON {
123 return printJSON(cmd.OutOrStdout(), m)
124 }
125 fmt.Fprintf(cmd.OutOrStdout(), "Created milestone %s (%s)\n", m.Title, m.ID)
126 return nil
127}
128
129func runMilestoneSetState(cmd *cobra.Command, args []string, state string) error {
130 client, err := newClient()
131 if err != nil {
132 return err
133 }
134 owner, repo, err := resolveRepo(milestoneRepo)
135 if err != nil {
136 return err
137 }
138 m, err := client.UpdateMilestone(cmd.Context(), owner, repo, args[0], map[string]any{"state": state})
139 if err != nil {
140 return err
141 }
142 if flagJSON {
143 return printJSON(cmd.OutOrStdout(), m)
144 }
145 fmt.Fprintf(cmd.OutOrStdout(), "Milestone %s is now %s.\n", m.Title, m.State)
146 return nil
147}
148
149func runMilestoneDelete(cmd *cobra.Command, args []string) error {
150 client, err := newClient()
151 if err != nil {
152 return err
153 }
154 owner, repo, err := resolveRepo(milestoneRepo)
155 if err != nil {
156 return err
157 }
158 if err := client.DeleteMilestone(cmd.Context(), owner, repo, args[0]); err != nil {
159 return err
160 }
161 fmt.Fprintf(cmd.OutOrStdout(), "Deleted milestone %s.\n", args[0])
162 return nil
163}