Skip to content

Add --draft and --non-draft filters to gh pr list#4316

Merged
samcoe merged 6 commits intocli:trunkfrom
SiarheiFedartsou:sf-pulls-draft
Sep 20, 2021
Merged

Add --draft and --non-draft filters to gh pr list#4316
samcoe merged 6 commits intocli:trunkfrom
SiarheiFedartsou:sf-pulls-draft

Conversation

@SiarheiFedartsou
Copy link
Contributor

Adds --draft and --non-draft filters to gh pr list. I didn't create new ticket for this, but it was previously mentioned in #641
Implementation was done using other options as a reference: seems to work :)

@SiarheiFedartsou SiarheiFedartsou marked this pull request as ready for review September 12, 2021 17:58
defer http.Verify(t)

_, err := runCommand(http, true, `-l one,two -a hubot`)
if err == nil && err.Error() != "multiple labels with --assignee are not supported" {
Copy link
Contributor Author

@SiarheiFedartsou SiarheiFedartsou Sep 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed this test, because it seems to be non-relevant anymore and CLI works perfectly in this case. I tested it with:
gh pr list -a vilmibm -l blocked,enhancement and it gave me this PR #3557 as a result.
It was green just because of logic error in test itself(it should have been if err == nil || err.Error() != "..." instead of if err == nil && err.Error() != "...")

@topofe

This comment was marked as spam.

@topofe

This comment was marked as spam.

@topofe

This comment was marked as spam.

Copy link
Contributor

@samcoe samcoe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code LGTM. My only question is about the UX of having two flags vs a single flag. For single flag options we could also go with something like --draft=true|false or --draft-status={unpublished|published|all}. @mislav @vilmibm any thoughts?

@SiarheiFedartsou
Copy link
Contributor Author

@samcoe
I mainly used --archived & --no-archived flags from gh repo list as a reference, but I don't have any hard opinions here and let me know if we need to refactor it to have different UX.

@samcoe samcoe self-assigned this Sep 13, 2021
@vilmibm
Copy link
Contributor

vilmibm commented Sep 13, 2021

I like --draft={true,false} and would consider updating that similar archive flag to match (in another future PR)

@SiarheiFedartsou
Copy link
Contributor Author

--draft={true,false}

@samcoe @vilmibm
Folks, do we have examples of such boolean-like flag somewhere? Or it should be usual string argument, but I should parse it as boolean(taking into account 0/1/yes/no/true/false options) afterwards on my own?

@samcoe
Copy link
Contributor

samcoe commented Sep 13, 2021

@SiarheiFedartsou Our commander library, Cobra, offers a boolean flag option. An example in our code base can be found here

cmd.Flags().BoolP("web", "w", false, "Add body in browser")
or by searching for other instances of BoolP.

@SiarheiFedartsou
Copy link
Contributor Author

@samcoe
well, IIUC BoolP always stores either true or false in argument. In our case we actually have 3 states: we either want to show drafts only, or non-drafts only or all PRs. So, maybe proposal with --draft-status={unpublished|published|all} would work better here. WDYT?

@samcoe
Copy link
Contributor

samcoe commented Sep 14, 2021

@SiarheiFedartsou I agree, which is why I put forth that alternative suggestion, but I do think the UX is better with --draft=true|false just because remembering the options of published, unpublished, and all adds cognitive overhead for the use of the flag when boolean is simpler. We can accomplish the same things though by doing something like this

type ListOptions struct {
  Draft bool
  DraftChanged bool
}

func NewCmdList ... {
  opts := &ListOptions{}
  cmd := &cobra.Command{
    RunE: func(cmd *cobra.Command, args []string) error {
      if cmd.Flags().Changed("draft") {
         opts.DraftChanged = true
      }
   }
  cmd.Flags().BoolP(&opts.Draft, "draft", ...)
}

Now the ListOptions know if the flag was explicitly set and what value it was set to using two fields. Does that make sense?

@SiarheiFedartsou
Copy link
Contributor Author

@samcoe yeah, I was thinking about something like this, but since I am not very familiar with cobra I didn't know how to accomplish it. Thanks, will give it a try!

@SiarheiFedartsou
Copy link
Contributor Author

@samcoe I applied changes in UX proposed by you, please take a look one more time.

@samcoe
Copy link
Contributor

samcoe commented Sep 20, 2021

@SiarheiFedartsou Thanks for the changes! I made one change which was to convert the draft boolean flag into to a string early on so that it is easier to propagate through to the search code.

@samcoe samcoe merged commit 02ed5a9 into cli:trunk Sep 20, 2021
@billygriffin
Copy link
Contributor

billygriffin commented Sep 20, 2021

@SiarheiFedartsou Thanks for your work! Any chance you could edit the PR body and title to document the final expected behavior just so when people look back on the PR, they know where we landed with the flag structure and what is intended to happen in each case?

@mislav
Copy link
Contributor

mislav commented Sep 21, 2021

I'm late to this party, but I just wanted to state for the record that I would have actually preferred separate --draft and --non-draft flags in this case, and that using a single boolean flag for this filter can be confusing both in the code (as evident by the implementation that saves a boolean flag to a string variable) and to the user.

For example, gh pr create --draft is a boolean flag. Every boolean flag has only 2 states by default, with false being the default state. That means that passing gh pr create --draft=false explicitly is identical to not passing the flag at all.

However, this new pr list --draft flag doesn't work like that. It has three states:

  1. gh pr list - draft filter is inactive
  2. gh pr list --draft or gh pr list --draft=true - list only draft PRs
  3. gh pr list --draft=false - list non-draft PRs

Furthermore, it might not be clear to the user how to use this new flag. Its current documentation is:

  -d, --draft             Filter by draft state

The --draft={true|false} syntax might not be obvious to the user because it's not mentioned in the documentation for this flag.

To summarize, I see two potential problems here: that this boolean flag has 3 states (whereas other boolean flags in gh have only 2 states) and that using this filter to list non-draft PRs requires knowledge of non-obvious flag syntax.

If the goal was to avoid introducing two new flags (--draft & --non-draft) to support a single filter, which I understand, then maybe we could consider other approaches? For example, we can piggyback on the --state filter:

  1. gh pr list --state=draft (implies --state=open)
  2. gh pr list --state=ready (implies --state=open)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants