From d725875d0f4bf1fe630e8f0df65628cc3b4819da Mon Sep 17 00:00:00 2001 From: Dmitry Makovey Date: Mon, 27 Mar 2023 12:25:17 -0600 Subject: [PATCH 1/6] Add todo listing --- api/todo.go | 33 +++++++++++++ commands/issue/issue.go | 6 +-- commands/root.go | 2 + commands/todo/list/list.go | 96 ++++++++++++++++++++++++++++++++++++++ commands/todo/todo.go | 25 ++++++++++ 5 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 api/todo.go create mode 100644 commands/todo/list/list.go create mode 100644 commands/todo/todo.go diff --git a/api/todo.go b/api/todo.go new file mode 100644 index 000000000..1ca7b8cdb --- /dev/null +++ b/api/todo.go @@ -0,0 +1,33 @@ +package api + +import ( + "github.com/xanzy/go-gitlab" +) + +var ListTodos = func(client *gitlab.Client, opts *gitlab.ListTodosOptions, all bool) ([]*gitlab.Todo, error) { + var todos []*gitlab.Todo + var err error + if client == nil { + client = apiClient.Lab() + } + if opts.PerPage == 0 { + opts.PerPage = DefaultListLimit + } + if all { + todos_part, resp, _ := client.Todos.ListTodos(opts) + todos = append(todos, todos_part...) + var myopt gitlab.ListTodosOptions = *opts + for resp.NextPage != 0 { + myopt.Page = resp.NextPage + todos_part, resp, err = client.Todos.ListTodos(&myopt) + todos = append(todos, todos_part...) + } + } else { + todos, _, err = client.Todos.ListTodos(opts) + } + if err != nil { + return nil, err + } + + return todos, nil +} diff --git a/commands/issue/issue.go b/commands/issue/issue.go index 3ab5002cf..7b79368a7 100644 --- a/commands/issue/issue.go +++ b/commands/issue/issue.go @@ -27,13 +27,13 @@ func NewCmdIssue(f *cmdutils.Factory) *cobra.Command { glab issue list glab issue create --label --confidential glab issue view --web - glab issue note -m "closing because !123 was merged" + glab issue note -m "closing because !124 was merged" `), Annotations: map[string]string{ "help:arguments": heredoc.Doc(` An issue can be supplied as argument in any of the following formats: - - by number, e.g. "123" - - by URL, e.g. "https://gitlab.com/NAMESPACE/REPO/-/issues/123" + - by number, e.g. "124" + - by URL, e.g. "https://gitlab.com/NAMESPACE/REPO/-/issues/124" `), }, } diff --git a/commands/root.go b/commands/root.go index 51a4f6164..bdbf927fe 100644 --- a/commands/root.go +++ b/commands/root.go @@ -23,6 +23,7 @@ import ( scheduleCmd "gitlab.com/gitlab-org/cli/commands/schedule" snippetCmd "gitlab.com/gitlab-org/cli/commands/snippet" sshCmd "gitlab.com/gitlab-org/cli/commands/ssh-key" + todoCmd "gitlab.com/gitlab-org/cli/commands/todo" updateCmd "gitlab.com/gitlab-org/cli/commands/update" userCmd "gitlab.com/gitlab-org/cli/commands/user" variableCmd "gitlab.com/gitlab-org/cli/commands/variable" @@ -120,6 +121,7 @@ func NewCmdRoot(f *cmdutils.Factory, version, buildDate string) *cobra.Command { rootCmd.AddCommand(apiCmd.NewCmdApi(f, nil)) rootCmd.AddCommand(scheduleCmd.NewCmdSchedule(f)) rootCmd.AddCommand(snippetCmd.NewCmdSnippet(f)) + rootCmd.AddCommand(todoCmd.NewCmdTodo(f)) rootCmd.Flags().BoolP("version", "v", false, "show glab version information") return rootCmd diff --git a/commands/todo/list/list.go b/commands/todo/list/list.go new file mode 100644 index 000000000..ca9e805e9 --- /dev/null +++ b/commands/todo/list/list.go @@ -0,0 +1,96 @@ +package list + +import ( + "encoding/json" + "fmt" + + "gitlab.com/gitlab-org/cli/api" + "gitlab.com/gitlab-org/cli/commands/cmdutils" + + "github.com/MakeNowJust/heredoc" + "github.com/spf13/cobra" + "github.com/xanzy/go-gitlab" +) + +func NewCmdList(f *cmdutils.Factory) *cobra.Command { + todoListCmd := &cobra.Command{ + Use: "list [flags]", + Short: `Get the list of TODO items`, + Example: heredoc.Doc(` + glab ci list + glab ci list --format=json + `), + Long: ``, + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + var err error + var all bool + all = true + + apiClient, err := f.HttpClient() + if err != nil { + return err + } + + repo, err := f.BaseRepo() + if err != nil { + return err + } + + project, err := repo.Project(apiClient) + + // l := &gitlab.ListProjectPipelinesOptions{} + l := &gitlab.ListTodosOptions{} + + if m, _ := cmd.Flags().GetString("state"); m != "" { + l.State = gitlab.String(m) + } + if m, _ := cmd.Flags().GetString("type"); m != "" { + l.Type = gitlab.String(m) + } + if m, _ := cmd.Flags().GetBool("global"); m == false { + l.ProjectID = &project.ID + } + if p, _ := cmd.Flags().GetInt("page"); p != 0 { + l.Page = p + all = false + } + if p, _ := cmd.Flags().GetInt("per-page"); p != 0 { + l.PerPage = p + all = false + } + + todos, err := api.ListTodos(apiClient, l, all) + if err != nil { + return err + } + + if m, _ := cmd.Flags().GetString("output-format"); m == "text" { + for _, t := range todos { + var milestone string + if t.Target.Milestone != nil { + milestone = t.Target.Milestone.Title + } else { + milestone = "nil" + } + fmt.Fprintf(f.IO.StdOut, "%s\t%s\t%s\t%s\t%s\n", t.Target.UpdatedAt, milestone, t.TargetType, t.Target.Title, t.Target.WebURL) + } + // fmt.Fprintf(f.IO.StdOut, "%s\n", todos) + + } else { + todoListJSON, _ := json.Marshal(todos) + fmt.Fprintln(f.IO.StdOut, string(todoListJSON)) + } + return nil + }, + } + todoListCmd.Flags().StringP("output-format", "F", "text", "Format output as: text, json") + todoListCmd.Flags().BoolP("global", "g", false, "Global list of TODO") + todoListCmd.Flags().StringP("state", "s", "pending", "State of TODO. One of: pending, done") + todoListCmd.Flags().StringP("type", "t", "", "Type of TODO. One of: MergeRequest, Commit, Epic, DesignManagement::Design or AlertManagement::Alert") + //TODO todoListCmd.Flags().StringP("author", "a", "text", "Author of TODO") + //TODO todoListCmd.Flags().StringP("project", "p", "text", "Project of TODO") + //TODO todoListCmd.Flags().StringP("group", "g", "text", "Group of TODO") + + return todoListCmd +} diff --git a/commands/todo/todo.go b/commands/todo/todo.go new file mode 100644 index 000000000..69aa5657a --- /dev/null +++ b/commands/todo/todo.go @@ -0,0 +1,25 @@ +package todo + +import ( + "github.com/MakeNowJust/heredoc" + "gitlab.com/gitlab-org/cli/commands/cmdutils" + + "github.com/spf13/cobra" + todoListCmd "gitlab.com/gitlab-org/cli/commands/todo/list" +) + +func NewCmdTodo(f *cmdutils.Factory) *cobra.Command { + issueCmd := &cobra.Command{ + Use: "todo [command] [flags]", + Short: `Work with GitLab todo`, + Long: ``, + Example: heredoc.Doc(` + glab todo list + `), + } + + cmdutils.EnableRepoOverride(issueCmd, f) + + issueCmd.AddCommand(todoListCmd.NewCmdList(f)) + return issueCmd +} -- GitLab From 873e53b526698a8ec595fa709c42d26babb5fd10 Mon Sep 17 00:00:00 2001 From: Dmitry Makovey Date: Mon, 27 Mar 2023 12:40:29 -0600 Subject: [PATCH 2/6] revert accidental modification --- commands/issue/issue.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/commands/issue/issue.go b/commands/issue/issue.go index 7b79368a7..3ab5002cf 100644 --- a/commands/issue/issue.go +++ b/commands/issue/issue.go @@ -27,13 +27,13 @@ func NewCmdIssue(f *cmdutils.Factory) *cobra.Command { glab issue list glab issue create --label --confidential glab issue view --web - glab issue note -m "closing because !124 was merged" + glab issue note -m "closing because !123 was merged" `), Annotations: map[string]string{ "help:arguments": heredoc.Doc(` An issue can be supplied as argument in any of the following formats: - - by number, e.g. "124" - - by URL, e.g. "https://gitlab.com/NAMESPACE/REPO/-/issues/124" + - by number, e.g. "123" + - by URL, e.g. "https://gitlab.com/NAMESPACE/REPO/-/issues/123" `), }, } -- GitLab From 28670f09a280859f5eac20a607c0cddd4922d09a Mon Sep 17 00:00:00 2001 From: Dmitry Makovey Date: Mon, 27 Mar 2023 12:43:21 -0600 Subject: [PATCH 3/6] streamline logic --- commands/todo/list/list.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/commands/todo/list/list.go b/commands/todo/list/list.go index ca9e805e9..a0167ab8f 100644 --- a/commands/todo/list/list.go +++ b/commands/todo/list/list.go @@ -37,9 +37,6 @@ func NewCmdList(f *cmdutils.Factory) *cobra.Command { return err } - project, err := repo.Project(apiClient) - - // l := &gitlab.ListProjectPipelinesOptions{} l := &gitlab.ListTodosOptions{} if m, _ := cmd.Flags().GetString("state"); m != "" { @@ -49,6 +46,7 @@ func NewCmdList(f *cmdutils.Factory) *cobra.Command { l.Type = gitlab.String(m) } if m, _ := cmd.Flags().GetBool("global"); m == false { + project, _ := repo.Project(apiClient) l.ProjectID = &project.ID } if p, _ := cmd.Flags().GetInt("page"); p != 0 { @@ -89,7 +87,6 @@ func NewCmdList(f *cmdutils.Factory) *cobra.Command { todoListCmd.Flags().StringP("state", "s", "pending", "State of TODO. One of: pending, done") todoListCmd.Flags().StringP("type", "t", "", "Type of TODO. One of: MergeRequest, Commit, Epic, DesignManagement::Design or AlertManagement::Alert") //TODO todoListCmd.Flags().StringP("author", "a", "text", "Author of TODO") - //TODO todoListCmd.Flags().StringP("project", "p", "text", "Project of TODO") //TODO todoListCmd.Flags().StringP("group", "g", "text", "Group of TODO") return todoListCmd -- GitLab From cebd4c070bb878ba0d00cfe2d44c0bb900b559c4 Mon Sep 17 00:00:00 2001 From: Dmitry Makovey Date: Mon, 27 Mar 2023 12:44:16 -0600 Subject: [PATCH 4/6] Add documentation --- docs/source/todo/help.md | 25 +++++++++++++++++++++++ docs/source/todo/index.md | 37 ++++++++++++++++++++++++++++++++++ docs/source/todo/list.md | 42 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 docs/source/todo/help.md create mode 100755 docs/source/todo/index.md create mode 100644 docs/source/todo/list.md diff --git a/docs/source/todo/help.md b/docs/source/todo/help.md new file mode 100644 index 000000000..2e9ef308d --- /dev/null +++ b/docs/source/todo/help.md @@ -0,0 +1,25 @@ +--- +stage: Create +group: Code Review +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + + + +# `glab todo help` + +Help about any command + +```plaintext +glab todo help [command] [flags] +``` + +## Options inherited from parent commands + +```plaintext + --help Show help for command + -R, --repo OWNER/REPO Select another repository using the OWNER/REPO or `GROUP/NAMESPACE/REPO` format or full URL or git URL +``` diff --git a/docs/source/todo/index.md b/docs/source/todo/index.md new file mode 100755 index 000000000..bdd4ebdd6 --- /dev/null +++ b/docs/source/todo/index.md @@ -0,0 +1,37 @@ +--- +stage: Create +group: Code Review +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + + + +# `glab todo` + +Work with GitLab todo + +## Examples + +```plaintext +glab todo list + +``` + +## Options + +```plaintext + -R, --repo OWNER/REPO Select another repository using the OWNER/REPO or `GROUP/NAMESPACE/REPO` format or full URL or git URL +``` + +## Options inherited from parent commands + +```plaintext + --help Show help for command +``` + +## Subcommands + +- [list](list.md) diff --git a/docs/source/todo/list.md b/docs/source/todo/list.md new file mode 100644 index 000000000..c8f2c9502 --- /dev/null +++ b/docs/source/todo/list.md @@ -0,0 +1,42 @@ +--- +stage: Create +group: Code Review +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + + + +# `glab todo list` + +Get the list of TODO items + +```plaintext +glab todo list [flags] +``` + +## Examples + +```plaintext +glab ci list +glab ci list --format=json + +``` + +## Options + +```plaintext + -g, --global Global list of TODO + -F, --output-format string Format output as: text, json (default "text") + -s, --state string State of TODO. One of: pending, done (default "pending") + -t, --type string Type of TODO. One of: MergeRequest, Commit, Epic, DesignManagement::Design or AlertManagement::Alert +``` + +## Options inherited from parent commands + +```plaintext + --help Show help for command + -R, --repo OWNER/REPO Select another repository using the OWNER/REPO or `GROUP/NAMESPACE/REPO` format or full URL or git URL +``` -- GitLab From edf40f962496229f51c4837ad6cda598b55a55e3 Mon Sep 17 00:00:00 2001 From: Dmitry Makovey Date: Mon, 27 Mar 2023 12:49:25 -0600 Subject: [PATCH 5/6] don't querry repo if we don't have to --- commands/todo/list/list.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/commands/todo/list/list.go b/commands/todo/list/list.go index a0167ab8f..4bcd93d54 100644 --- a/commands/todo/list/list.go +++ b/commands/todo/list/list.go @@ -32,11 +32,6 @@ func NewCmdList(f *cmdutils.Factory) *cobra.Command { return err } - repo, err := f.BaseRepo() - if err != nil { - return err - } - l := &gitlab.ListTodosOptions{} if m, _ := cmd.Flags().GetString("state"); m != "" { @@ -46,6 +41,10 @@ func NewCmdList(f *cmdutils.Factory) *cobra.Command { l.Type = gitlab.String(m) } if m, _ := cmd.Flags().GetBool("global"); m == false { + repo, err := f.BaseRepo() + if err != nil { + return err + } project, _ := repo.Project(apiClient) l.ProjectID = &project.ID } -- GitLab From 241ce1b7cc4f331d6b0605187478a30111a897fc Mon Sep 17 00:00:00 2001 From: Dmitry Makovey Date: Mon, 27 Mar 2023 13:01:37 -0600 Subject: [PATCH 6/6] addess linter issues --- commands/todo/list/list.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/commands/todo/list/list.go b/commands/todo/list/list.go index 4bcd93d54..71401f84b 100644 --- a/commands/todo/list/list.go +++ b/commands/todo/list/list.go @@ -40,7 +40,7 @@ func NewCmdList(f *cmdutils.Factory) *cobra.Command { if m, _ := cmd.Flags().GetString("type"); m != "" { l.Type = gitlab.String(m) } - if m, _ := cmd.Flags().GetBool("global"); m == false { + if m, _ := cmd.Flags().GetBool("global"); !m { repo, err := f.BaseRepo() if err != nil { return err @@ -73,7 +73,6 @@ func NewCmdList(f *cmdutils.Factory) *cobra.Command { fmt.Fprintf(f.IO.StdOut, "%s\t%s\t%s\t%s\t%s\n", t.Target.UpdatedAt, milestone, t.TargetType, t.Target.Title, t.Target.WebURL) } // fmt.Fprintf(f.IO.StdOut, "%s\n", todos) - } else { todoListJSON, _ := json.Marshal(todos) fmt.Fprintln(f.IO.StdOut, string(todoListJSON)) @@ -85,8 +84,8 @@ func NewCmdList(f *cmdutils.Factory) *cobra.Command { todoListCmd.Flags().BoolP("global", "g", false, "Global list of TODO") todoListCmd.Flags().StringP("state", "s", "pending", "State of TODO. One of: pending, done") todoListCmd.Flags().StringP("type", "t", "", "Type of TODO. One of: MergeRequest, Commit, Epic, DesignManagement::Design or AlertManagement::Alert") - //TODO todoListCmd.Flags().StringP("author", "a", "text", "Author of TODO") - //TODO todoListCmd.Flags().StringP("group", "g", "text", "Group of TODO") + // TODO todoListCmd.Flags().StringP("author", "a", "text", "Author of TODO") + // TODO todoListCmd.Flags().StringP("group", "g", "text", "Group of TODO") return todoListCmd } -- GitLab