Skip to content

Consistent interface for getting a PR#926

Closed
probablycorey wants to merge 8 commits intotrunkfrom
good-pr
Closed

Consistent interface for getting a PR#926
probablycorey wants to merge 8 commits intotrunkfrom
good-pr

Conversation

@probablycorey
Copy link
Contributor

@probablycorey probablycorey commented May 14, 2020

There are several ways to look up PRs, and we've been repeating that code in a few places. It's now getting more complicated so I wanted to clean that up a bit by having a consistent func that will return a PR in these formats.

  1. If the arg is a string check if it is a url, branch, or number. Look up the PR based on that.
  2. If there is no arg, look up the PR associated with the current branch

This seems simple, but I ran into enough problems that I want to verify the interface before I go any further. I'm proposing this...

func getPr(cmd *cobra.Command, prString string) (*api.PullRequest, error)

pros
A consistent interface for looking up a PR based on an arg

cons
It will almost always do a graphql lookup on the PR because many methods rely on some PR metadata. This will make our tests a little more complicated because we need to stub that out. It will also make pr view a little bit slower because it now makes an api call.

problems
I can't get TestPRCheckout_urlArg_differentBase to run correctly. The code used to change the base branch if a url was passed to checkout but not if a number or branch was. But that seems inconsistent now. I'm having trouble coming up with a situation where you'd need to change the base branch when a url was passed.

@probablycorey probablycorey self-assigned this May 14, 2020
@probablycorey probablycorey requested review from mislav and vilmibm May 14, 2020 22:23
@mislav
Copy link
Contributor

mislav commented May 15, 2020

@probablycorey I love that you're working on this 👏 I feel like the current level of boilerplate is just getting out of hand.

This seems simple, but I ran into enough problems that I want to verify the interface before I go any further. I'm proposing this...

func getPr(cmd *cobra.Command, prString string) (*api.PullRequest, error)

Knowing our specific use-cases, I feel like this interface is too simple. For example, as you said, it always results in an API request, but for some cases we don't necessarily need an API request, e.g. if we parse a PR number from a URL, we can just open that URL directly in pr view --web without the overhead of fetching information about the PR that we are not going to use in the client.

On the other hand, some use-cases require more GraphQL fields to be fetched than others. For instance, pr view (non-web) needs a lot of information about a PR, including metadata such as projects and assignees, while pr checkout basically only needs the name of the head branch and the owner/repo pair of the head repository (in case PR comes from a fork).

Finally, I think any helper function that parses PRs from URLs should also return the reference to the baseRepo in a separate argument, because for some commands such as pr checkout we need use that baseRepo value in subsequent logic.

I don't know what a correct solution should be, but it seems to me that we have different needs in each of the gh pr ... commands and that a one-size-fits-all approach would be tricky to achieve. 🤔

@mislav
Copy link
Contributor

mislav commented May 15, 2020

Oooh I just had an epiphany about requesting variable level of GraphQL information per different invocation.

How about we initialize a model in the caller and pass that to the query function to tell it what level of information we want?

prArg := args[0]
pr := api.PullRequestLight{}
err := pullRequestFromArgument(prArg, &pr)
if err != nil {
  return err
}
// now we can use all `pr.*` fields as defined by PullRequestLight

// alternatively, `pr view` might request a model with more fields
pr := api.PullRequestHeavy{} // this has many extra fields
err := pullRequestFromArgument(prArg, &pr)
// ...
// `pr.*` now has many extra fields we can peruse

This is assuming that the new queries would be backed by the githubv4 library. I'm happy to pair on this if it helps illustrate it further!

@probablycorey
Copy link
Contributor Author

Finally, I think any helper function that parses PRs from URLs should also return the reference to the baseRepo in a separate argument, because for some commands such as pr checkout we need use that baseRepo value in subsequent logic.

One thing I don't get is why we need to get the baseRepo from a PR from a url, but not from a PR that is opened from a fork? Why don't we change the baseRepo in both instances since the baseRepo will be different in both instances?

@mislav mislav changed the base branch from master to trunk May 27, 2020 11:41
@mislav mislav deleted the good-pr branch September 2, 2020 11:21
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.

2 participants