Repository: buildtesters/buildtest (language: python)

Issue:
[FEATURE]: buildtest buildspec maintainers
### Please describe your feature request

Currently we have an option `buildtest buildspec --maintainers` and `buildtest buildspec --maintainers-by-buildspecs` that prints output of maintainers and breakdown of buildspecs by maintainers.

We should move this logic to another command let's call it `buildtest buildspec maintainers`. 

The logic if the following command can be equivalent to `buildtest bc maintainers list` which shows all maintainers

```
(buildtest)  ~/Documents/GitHubDesktop/buildtest/ [devel] buildtest bc find -m
List of Maintainers
┏━━━━━━━━━━━━━━━━━━┓
┃ Maintainers      ┃
┡━━━━━━━━━━━━━━━━━━┩
│ @johndoe         │
│ @bobsmith        │
│ @shahzebsiddiqui │
└──────────────────┘
```

Similarly it should have an option `--terse` which will allow one to see a listing of output without table

```
(buildtest)  ~/Documents/GitHubDesktop/buildtest/ [devel] buildtest bc find -m --terse
maintainers
@johndoe
@bobsmith
@shahzebsiddiqui
```

The implementation of `buildtest bc -mb` should be translated to command `buildtest bc maintainers --breakdown` which shows a breakdown of buildspecs by maintainers


### Post question in Slack

- [X] I agree that I posted my question in [slack](https://hpcbuildtest.slack.com/) before creating this issue

### Is there an existing issue

- [X] I confirm there is no existing [issue](https://github.com/buildtesters/buildtest/issues) for this issue
[FEATURE]: buildtest buildspec maintainers find
### Please describe your feature request

Create a new command `buildtest buildspec maintainers find <maintainer>` that will report a listing of buildspecs given a maintainer name. 

In the output below we have the current implementation which shows a breakdown

```
(buildtest)  ~/Documents/GitHubDesktop/buildtest/ [devel] buildtest bc find -mb
                                                                           Breakdown of buildspecs by maintainers
┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Maintainers      ┃ Buildspec                                                                                                                                                             ┃
┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ @johndoe         │ /Users/siddiq90/Documents/GitHubDesktop/buildtest/tutorials/maintainers_example.yml                                                                                   │
│ @bobsmith        │ /Users/siddiq90/Documents/GitHubDesktop/buildtest/tutorials/maintainers_example.yml                                                                                   │
│ @shahzebsiddiqui │ /Users/siddiq90/Documents/GitHubDesktop/buildtest/tutorials/hello_world.yml:/Users/siddiq90/Documents/GitHubDesktop/buildtest/general_tests/configuration/ulimits.yml │
```

With this command we can do `buildtest bc maintainers find @johndoe` which will show a listing of all buildspecs associated with the maintainer `@johndoe` in this case its `/Users/siddiq90/Documents/GitHubDesktop/buildtest/tutorials/maintainers_example.yml`. The default output is a table format however one can use `buildtest bc maintainers --terse find @johndoe` where `--terse` will show as a listing instead of table.

Once this is implementation is complete, a useful command can be to edit all buildspecs given a maintainer name which can be done via `buildtest bc edit-file $(buildtest bc maintainers --terse find @johndoe)`

### Post question in Slack

- [X] I agree that I posted my question in [slack](https://hpcbuildtest.slack.com/) before creating this issue

### Is there an existing issue

- [X] I confirm there is no existing [issue](https://github.com/buildtesters/buildtest/issues) for this issue


Discussion / hints:

Fix patch:
diff --git a/bash_completion.sh b/bash_completion.sh
index 6b7cc3035..351061bee 100644
--- a/bash_completion.sh
+++ b/bash_completion.sh
@@ -75,6 +75,11 @@ _buildspec_cache_test_names()
 {
   buildtest buildspec find --format name --terse -n | sort
 }
+
+_avail_maintainers()
+{
+  buildtest buildspec maintainers --terse -l --no-header | sort
+}
 #  entry point to buildtest bash completion function
 _buildtest ()
 {
@@ -216,7 +221,7 @@ _buildtest ()
       ;;
 
     buildspec|bc)
-      local cmds="-h --help edit-test edit-file find show summary validate"
+      local cmds="-h --help edit-test edit-file find maintainers show summary validate"
       COMPREPLY=( $( compgen -W "${cmds}" -- $cur ) )
 
       # switch based on 2nd word 'buildtest buildspec <subcommand>'
@@ -229,8 +234,8 @@ _buildtest ()
            COMPREPLY=( $( compgen -W "${opts}" -- $cur ) );;
          # completion for rest of arguments
          *)
-           local longopts="--buildspec --executors --filter --format --group-by-executor --group-by-tags --help --helpfilter --helpformat --maintainers --maintainers-by-buildspecs --no-header --pager --paths --rebuild --tags --root --terse"
-           local shortopts="-b -e -h -m -mb -n -p -r -t"
+           local longopts="--buildspec --executors --filter --format --group-by-executor --group-by-tags --help --helpfilter --helpformat --no-header --pager --paths --rebuild --tags --root --terse"
+           local shortopts="-b -e -h -n -p -r -t"
            local subcmds="invalid"
            local allopts="${longopts} ${shortopts} ${subcmds}"
            COMPREPLY=( $( compgen -W "${allopts}" -- $cur ) );;
@@ -238,6 +243,16 @@ _buildtest ()
         ;;
       show|edit-test)
         COMPREPLY=( $( compgen -W "$(_buildspec_cache_test_names)" -- $cur ) );;
+      maintainers)
+        local opts="--breakdown --list --help --terse --no-header -b -h -l -n find"
+        COMPREPLY=( $( compgen -W "${opts}" -- $cur ) )
+
+        case ${COMP_WORDS[3]} in
+        find)
+          COMPREPLY=( $( compgen -W "$(_avail_maintainers)" -- $cur ) );;
+        esac
+        ;;
+
       edit-file)
         COMPREPLY=( $( compgen -W "$(_avail_buildspecs)" -- $cur ) );;
       validate)
diff --git a/docs/gettingstarted/buildspecs_interface.rst b/docs/gettingstarted/buildspecs_interface.rst
index 5b92ec144..9bdc60e82 100644
--- a/docs/gettingstarted/buildspecs_interface.rst
+++ b/docs/gettingstarted/buildspecs_interface.rst
@@ -150,26 +150,6 @@ name of test and test description. Shown below is an example output.
 .. command-output:: buildtest buildspec find --group-by-executor
     :ellipsis: 31
 
-
-.. _buildspec_maintainers:
-
-Query Maintainers
-~~~~~~~~~~~~~~~~~
-
-When you are writing your buildspecs, you can specify the ``maintainers`` field to assign
-authors to buildspecs. buildtest can query the maintainers from the cache
-once buildspecs are loaded. You can retrieve all maintainers using ``--maintainers`` option or ``-m``
-short option. In this example, we show all maintainers for buildspecs in buildspec
-cache
-
-.. command-output:: buildtest buildspec find --maintainers
-
-If you want to see a breakdown of maintainers by buildspec file you can use ``--maintainers-by-buildspecs``
-or ``-mb`` short option. This can be useful to get correlation between maintainers and the buildspec file.
-
-.. command-output:: buildtest buildspec find -mb
-
-
 Terse Output
 ~~~~~~~~~~~~~
 
@@ -195,6 +175,38 @@ each buildspec followed by error message.
 
 .. command-output:: buildtest buildspec find invalid -e
 
+.. _buildspec_maintainers:
+
+Query Maintainers (``buildtest buildspec maintainers``)
+----------------------------------------------------------
+
+buildtest keeps track of maintainers (i.e authors) for a given buildspec provided that you
+specify the ``maintainers`` property. This is stored in the buildspec cache which can be used
+to query some interesting details.
+
+Shown below is the help for ``buildtest buildspec maintainers --help``
+
+.. command-output:: buildtest buildspec maintainers --help
+
+If you want to see a listing of all maintainers you can use the ``--list`` as shown below
+
+.. command-output:: buildtest buildspec maintainers --list
+
+If you prefer a machine readable format, then you can use ``--terse`` and ``--no-header``.
+
+.. command-output:: buildtest buildspec maintainers --list --terse --no-header
+
+If you want to see a breakdown of all buildspecs by maintainers you can use `--breakdown` which will
+display the following information
+
+.. command-output:: buildtest buildspec maintainers --breakdown
+
+The ``buildtest buildspec maintainers find`` command can be used to report buildspec given a maintainer
+name which works similar to `--breakdown` but doesn't report information for all maintainers. Shown
+below, we query all buildspecs by maintainer **@shahzebsiddiqui**
+
+.. command-output:: buildtest buildspec maintainers find @shahzebsiddiqui
+
 
 Cache Summary - ``buildtest buildspec summary``
 ------------------------------------------------
@@ -362,7 +374,7 @@ with two commands to edit your buildspecs ``buildtest buildspec edit-test`` and
 discuss below.
 
 Editing by Test ``buildtest buildspec edit-test``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 The ``buildtest buildspec edit-test`` allows one to specify a list of test as positional
 arguments to edit-test in your preferred editor. buildtest will provide tab completion for this


Test patch:
diff --git a/buildtest/cli/__init__.py b/buildtest/cli/__init__.py
index 4843da870..e0cbc5fd2 100644
--- a/buildtest/cli/__init__.py
+++ b/buildtest/cli/__init__.py
@@ -504,35 +504,17 @@ def buildspec_menu(subparsers):
         metavar="",
     )
 
-    buildspec_find = subparsers_buildspec.add_parser(
-        "find", help="Query information from buildspecs cache"
-    )
-    filter_group = buildspec_find.add_argument_group(
-        "filter and format", "filter and format options"
-    )
-    terse_group = buildspec_find.add_argument_group("terse", "terse options")
-    query_group = buildspec_find.add_argument_group(
-        "query", "query options to retrieve from buildspec cache"
-    )
-
-    subparsers_invalid = buildspec_find.add_subparsers(
-        metavar="", dest="buildspec_find_subcommand"
-    )
-    invalid_buildspecs = subparsers_invalid.add_parser(
-        "invalid", help="Show invalid buildspecs"
-    )
-
-    subparsers_buildspec.add_parser("summary", help="Print summary of buildspec cache")
-
-    show_buildspecs = subparsers_buildspec.add_parser(
-        "show", help="Show content of buildspec file"
+    # buildtest buildspec edit-file
+    edit_via_filename = subparsers_buildspec.add_parser(
+        "edit-file", help="Edit buildspec file based on filename"
     )
-    show_buildspecs.add_argument(
-        "name",
-        help="Show content of buildspec based on test name",
+    edit_via_filename.add_argument(
+        "file",
+        help="Edit buildspec file in editor",
         nargs="*",
     )
 
+    # buildtest buildspec edit-test
     edit_via_testname = subparsers_buildspec.add_parser(
         "edit-test", help="Edit buildspec file based on test name"
     )
@@ -542,53 +524,64 @@ def buildspec_menu(subparsers):
         nargs="*",
     )
 
-    edit_via_filename = subparsers_buildspec.add_parser(
-        "edit-file", help="Edit buildspec file based on filename"
+    # buildtest buildspec find
+
+    buildspec_find = subparsers_buildspec.add_parser(
+        "find", help="Query information from buildspecs cache"
     )
-    edit_via_filename.add_argument(
-        "file",
-        help="Edit buildspec file in editor",
-        nargs="*",
+
+    # buildtest buildspec maintainers
+    buildspec_maintainers = subparsers_buildspec.add_parser(
+        "maintainers", help="Query maintainers from buildspecs cache"
     )
 
-    buildspec_validate = subparsers_buildspec.add_parser(
-        "validate", help="Validate buildspecs with JSON Schema"
+    subparsers_maintainers = buildspec_maintainers.add_subparsers()
+    maintainers_find = subparsers_maintainers.add_parser(
+        "find", help="Find buildspecs based on maintainer name"
     )
-    # buildtest buildspec invalid options
-    invalid_buildspecs.add_argument(
-        "-e", "--error", action="store_true", help="Show error messages"
+
+    maintainers_find.add_argument(
+        "name", help="Find buildspec based on maintainer name"
     )
 
-    # buildtest buildspec validate options
-    buildspec_validate.add_argument(
+    buildspec_maintainers.add_argument(
+        "-l", "--list", action="store_true", help="List all maintainers"
+    )
+    buildspec_maintainers.add_argument(
         "-b",
-        "--buildspec",
-        type=str,
-        help="Specify path to buildspec (file, or directory) to validate",
-        action="append",
+        "--breakdown",
+        action="store_true",
+        help="Breakdown of buildspecs by maintainers",
+    )
+    buildspec_maintainers.add_argument(
+        "--terse", help="Print output in machine readable format", action="store_true"
+    )
+    buildspec_maintainers.add_argument(
+        "-n",
+        "--no-header",
+        action="store_true",
+        help="Print output without header in terse output",
     )
 
-    buildspec_validate.add_argument(
-        "-x",
-        "--exclude",
-        type=str,
-        help="Specify path to buildspec to exclude (file or directory) during validation",
-        action="append",
+    filter_group = buildspec_find.add_argument_group(
+        "filter and format", "filter and format options"
+    )
+    terse_group = buildspec_find.add_argument_group("terse", "terse options")
+    query_group = buildspec_find.add_argument_group(
+        "query", "query options to retrieve from buildspec cache"
     )
 
-    buildspec_validate.add_argument(
-        "-e",
-        "--executor",
-        type=str,
-        action="append",
-        help="Specify buildspecs by executor name to validate",
+    # buildtest buildspec find invalid
+    subparsers_invalid = buildspec_find.add_subparsers(
+        metavar="", dest="buildspec_find_subcommand"
     )
-    buildspec_validate.add_argument(
-        "-t",
-        "--tag",
-        type=str,
-        action="append",
-        help="Specify buildspecs by tag name to validate",
+    invalid_buildspecs = subparsers_invalid.add_parser(
+        "invalid", help="Show invalid buildspecs"
+    )
+
+    # buildtest buildspec find invalid options
+    invalid_buildspecs.add_argument(
+        "-e", "--error", action="store_true", help="Show error messages"
     )
 
     # buildtest buildspec find options
@@ -614,19 +607,6 @@ def buildspec_menu(subparsers):
         action="store_true",
         help="Group tests by executor name",
     )
-
-    query_group.add_argument(
-        "-m",
-        "--maintainers",
-        help="Get all maintainers for all buildspecs",
-        action="store_true",
-    )
-    query_group.add_argument(
-        "-mb",
-        "--maintainers-by-buildspecs",
-        help="Show maintainers breakdown by buildspecs",
-        action="store_true",
-    )
     query_group.add_argument(
         "-p", "--paths", help="print all root buildspec paths", action="store_true"
     )
@@ -679,6 +659,55 @@ def buildspec_menu(subparsers):
         action="append",
     )
 
+    # buildtest buildspec show
+    show_buildspecs = subparsers_buildspec.add_parser(
+        "show", help="Show content of buildspec file"
+    )
+    show_buildspecs.add_argument(
+        "name",
+        help="Show content of buildspec based on test name",
+        nargs="*",
+    )
+
+    # buildtest buildspec summary
+    subparsers_buildspec.add_parser("summary", help="Print summary of buildspec cache")
+
+    # buildtest buildspec validate
+    buildspec_validate = subparsers_buildspec.add_parser(
+        "validate", help="Validate buildspecs with JSON Schema"
+    )
+    # buildtest buildspec validate options
+    buildspec_validate.add_argument(
+        "-b",
+        "--buildspec",
+        type=str,
+        help="Specify path to buildspec (file, or directory) to validate",
+        action="append",
+    )
+
+    buildspec_validate.add_argument(
+        "-x",
+        "--exclude",
+        type=str,
+        help="Specify path to buildspec to exclude (file or directory) during validation",
+        action="append",
+    )
+
+    buildspec_validate.add_argument(
+        "-e",
+        "--executor",
+        type=str,
+        action="append",
+        help="Specify buildspecs by executor name to validate",
+    )
+    buildspec_validate.add_argument(
+        "-t",
+        "--tag",
+        type=str,
+        action="append",
+        help="Specify buildspecs by tag name to validate",
+    )
+
 
 def config_menu(subparsers):
     """This method adds argparse argument for ``buildtest config``"""
diff --git a/buildtest/cli/buildspec.py b/buildtest/cli/buildspec.py
index be8f7bbb7..e8a4a494b 100644
--- a/buildtest/cli/buildspec.py
+++ b/buildtest/cli/buildspec.py
@@ -794,7 +794,6 @@ def print_maintainer(self):
 
         table = Table(
             "Maintainers",
-            title="List of Maintainers",
             header_style="blue",
             title_style="red",
             row_styles=["green"],
@@ -810,7 +809,21 @@ def print_maintainer(self):
 
         console.print(table)
 
+    def print_maintainers_find(self, name):
+        """Display a list of buildspec files associated to a given maintainer. This command is used when running
+        ``buildtest buildspec maintainers find``
+
+        Args:
+            name (str): Name of maintainer specified via ``buildtest buildspec maintainers find <name>``
+        """
+
+        maintainers = list(self.cache["maintainers"].keys())
+        if name in maintainers:
+            for file in self.cache["maintainers"][name]:
+                console.print(file)
+
     def print_maintainers_by_buildspecs(self):
+
         """This method prints maintainers breakdown by buildspecs. This method implements ``buildtest buildspec find --maintainers-by-buildspecs``"""
         if self.terse:
             if not self.header:
@@ -1120,6 +1133,31 @@ def summarize_buildspec_cache(configuration):
     console.print(buildspec_table)
 
 
+def buildspec_maintainers(
+    configuration, list=None, breakdown=None, terse=None, header=None, name=None
+):
+    """Entry point for ``buildtest buildspec maintainers`` command.
+
+    Args:
+        configuration (buildtest.config.SiteConfiguration): instance of type SiteConfiguration
+        list (bool, optional): List all maintainers
+        terse (bool, optional): Print in terse mode
+        header (bool, optional): If True disable printing of headers
+        name (str, optional): List all buildspecs corresponding to maintainer name. This command is specified via ``buildtest buildspec maintainers find <name>``
+    """
+
+    cache = BuildspecCache(configuration=configuration, terse=terse, header=header)
+
+    if list:
+        cache.print_maintainer()
+
+    if breakdown:
+        cache.print_maintainers_by_buildspecs()
+
+    if name:
+        cache.print_maintainers_find(name=name)
+
+
 def buildspec_find(args, configuration):
     """Entry point for ``buildtest buildspec find`` command
 
@@ -1173,16 +1211,6 @@ def buildspec_find(args, configuration):
         cache.print_by_tags()
         return
 
-    # buildtest buildspec find --maintainers
-    if args.maintainers:
-        cache.print_maintainer()
-        return
-
-    #  buildtest buildspec find --maintainers-by-buildspecs
-    if args.maintainers_by_buildspecs:
-        cache.print_maintainers_by_buildspecs()
-        return
-
     # buildtest buildspec find --helpfilter
     if args.helpfilter:
         cache.print_filter_fields()
diff --git a/buildtest/cli/help.py b/buildtest/cli/help.py
index e1d847df0..7362c64d2 100644
--- a/buildtest/cli/help.py
+++ b/buildtest/cli/help.py
@@ -55,12 +55,33 @@ def print_build_help():
     )
     table.add_row("buildtest build -b <file> --rebuild 5", "Rebuild a test 5 times")
     table.add_row("buildtest build -b <file> --testdir /tmp", "Write tests in /tmp")
+
+    table.add_row(
+        "buildtest build --rerun", "Run last successful 'buildtest build' command"
+    )
+    table.add_row(
+        "buildtest -r $HOME/python.json build -t python",
+        "Write test to report file $HOME/python.json for all test run via 'python' tag",
+    )
+    table.add_row(
+        "buildtest build -b <file> --module-purge --modules gcc,python",
+        "For every test run 'module purge' and then load 'gcc' and 'python' module",
+    )
+    table.add_row(
+        "buildtest build -b <file> --unload-modules gcc/9.3.0 --modules gcc/10.3.0",
+        "For every test run 'module unload gcc/9.3.0' and then load 'gcc/10.3.0'",
+    )
     table.add_row(
         "buildtest build -b /tmp/hostname.yml --maxpendtime 120 --pollinterval 10",
-        "Set Poll Interval to 10sec and Max Pend Time to 120 sec when submitting batch job.",
+        "Poll jobs every 10 seconds and maximum pending time for jobs to 120 sec when submitting batch job. Job will be cancelled after 120sec if job is pending",
     )
     table.add_row(
-        "buildtest build --rerun", "Run last successful 'buildtest build' command"
+        "buildtest build -b <file> --account dev",
+        "Use project 'dev' when submitting batch jobs",
+    )
+    table.add_row(
+        "buildtest build -b <file> --timeout 60",
+        "Test will run till it reaches timeout of 60sec and then it will be cancelled if it exceeds the limit.",
     )
 
     console.print(table)
@@ -92,13 +113,6 @@ def print_buildspec_help():
     table.add_row(
         "buildtest buildspec find --executors", "List all unique executors from cache"
     )
-    table.add_row(
-        "buildtest buildspec find --maintainers", "List all maintainers from cache"
-    )
-    table.add_row(
-        "buildtest buildspec find --maintainers-by-buildspecs",
-        "Show breakdown of all buildspecs by maintainer names",
-    )
     table.add_row(
         "buildtest buildspec find --filter type=script,tags=pass",
         "Filter buildspec cache based on type=script and  tags='pass'",
@@ -158,7 +172,7 @@ def print_buildspec_help():
         "Show content of buildspec based on test name 'python_hello'",
     )
     table.add_row(
-        "buildtest buildspec edit python_hello",
+        "buildtest buildspec edit-test python_hello",
         "Open test 'python_hello' in editor and validate file upon closing",
     )
     table.add_row(
@@ -166,6 +180,22 @@ def print_buildspec_help():
         "Open file $BUILDTEST_ROOT/tutorials/sleep.yml in editor and validate file upon closing",
     )
 
+    table.add_row(
+        "buildtest buildspec maintainers find johndoe",
+        "Find buildspec with maintainer name 'johndoe'",
+    )
+    table.add_row(
+        "buildtest buildspec maintainers --list",
+        "List all maintainers from buildspec cache",
+    )
+    table.add_row(
+        "buildtest buildspec maintainers --list --terse --no-header",
+        "List all maintainers in machine readable format without header",
+    )
+    table.add_row(
+        "buildtest buildspec maintainers --breakdown",
+        "Show breakdown of maintainers by buildspecs",
+    )
     console.print(table)
 
 
@@ -242,19 +272,19 @@ def print_inspect_help():
         "Fetch latest runs for all tests in buildspec file 'tutorials/vars.yml'",
     )
     table.add_row(
-        "buildtest inspect query -o hello",
-        "Display content of output file for test name 'hello'",
+        "buildtest inspect query -o exit1_fail",
+        "Display content of output file for latest run for test name 'exit1_fail'",
     )
     table.add_row(
         "buildtest inspect query -e hello",
         "Display content of error file for test name 'hello'",
     )
     table.add_row(
-        "buildtest inspect query -d first -o -e foo bar",
-        "Display first record of tests 'foo', 'bar', and show output and error file",
+        "buildtest inspect query exit1_fail/", "Display all runs for tests 'exit1_fail'"
     )
     table.add_row(
-        "buildtest inspect query -o hello", "Display all runs for tests 'foo'"
+        "buildtest inspect query 'exit1_fail/(24|52)'",
+        "Use regular expression when searching for test via 'buildtest inspect query'",
     )
     console.print(table)
 
@@ -289,6 +319,11 @@ def print_report_help():
         "buildtest -r /tmp/result.json report",
         "Read report file /tmp/result.json and display result",
     )
+    table.add_row("buildtest report --failure", "Show all test failures")
+    table.add_row(
+        "buildtest report --start 2022-01-01 --end 2022-01-05",
+        "Show all test records in the date range from [2022-01-01, 2022-01-05]",
+    )
     table.add_row("buildtest report --terse", "Print report in terse format")
     table.add_row("buildtest report list", "List all report files")
     table.add_row("buildtest report clear", "Remove content of default report file")
@@ -326,6 +361,10 @@ def print_cdash_help():
         "buildtest cdash upload DEMO",
         "Upload all tests to cdash with build name 'DEMO'",
     )
+    table.add_row(
+        "buildtest cdash upload DEMO --open",
+        "Upload test results to CDASH and open results in web browser",
+    )
     table.add_row(
         "buildtest --report /tmp/result.json cdash upload DAILY_CHECK ",
         "Upload all tests from report file '/tmp/result.json' with build name DAILY_CHECK",
diff --git a/buildtest/main.py b/buildtest/main.py
index 0ddb507c4..5a71c4fe8 100644
--- a/buildtest/main.py
+++ b/buildtest/main.py
@@ -9,6 +9,7 @@
 from buildtest.cli.buildspec import (
     BuildspecCache,
     buildspec_find,
+    buildspec_maintainers,
     buildspec_validate,
     edit_buildspec_file,
     edit_buildspec_test,
@@ -176,6 +177,19 @@ def main():
                 configuration=configuration,
                 editor=buildtest_editor,
             )
+        elif args.buildspecs_subcommand == "maintainers":
+            name = None
+            if hasattr(args, "name"):
+                name = args.name
+            buildspec_maintainers(
+                configuration=configuration,
+                list=args.list,
+                breakdown=args.breakdown,
+                terse=args.terse,
+                header=args.no_header,
+                name=name,
+            )
+
         elif args.buildspecs_subcommand == "validate":
             buildspec_validate(
                 buildspecs=args.buildspec,
diff --git a/tests/cli/test_buildspec.py b/tests/cli/test_buildspec.py
index f094af5b5..55a966a41 100644
--- a/tests/cli/test_buildspec.py
+++ b/tests/cli/test_buildspec.py
@@ -6,6 +6,7 @@
 import pytest
 from buildtest.cli.buildspec import (
     BuildspecCache,
+    buildspec_maintainers,
     buildspec_validate,
     show_buildspecs,
     summarize_buildspec_cache,
@@ -90,12 +91,6 @@ def test_func_buildspec_find():
     # buildtest buildspec find --group-by-tags
     cache.print_by_tags()
 
-    # buildtest buildspec find --maintainers
-    cache.print_maintainer()
-
-    # implements buildtest buildspec find --maintainers-by-buildspecs
-    cache.print_maintainers_by_buildspecs()
-
     # implements buildtest buildspec find --helpfilter
     cache.print_filter_fields()
 
@@ -128,6 +123,17 @@ def test_buildspec_find_terse():
     cache.print_maintainers_by_buildspecs()
 
 
+@pytest.mark.cli
+def test_buildspec_maintainers():
+    buildspec_maintainers(
+        configuration=configuration, list=True, terse=True, header=True
+    )
+    buildspec_maintainers(
+        configuration=configuration, breakdown=True, terse=True, header=True
+    )
+    buildspec_maintainers(configuration=configuration, name="@shahzebsiddiqui")
+
+
 @pytest.mark.cli
 def test_buildspec_find_invalid():