Skip to content

Commit

Permalink
Merge pull request cli#839 from cli/issue-pr-create-metadata-wizard
Browse files Browse the repository at this point in the history
Prompt for additional metadata during `issue/pr create`
  • Loading branch information
mislav authored May 8, 2020
2 parents d0f168f + 8c84d68 commit 4a3588d
Show file tree
Hide file tree
Showing 6 changed files with 290 additions and 69 deletions.
4 changes: 2 additions & 2 deletions api/queries_org.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func OrganizationProjects(client *Client, owner string) ([]RepoProject, error) {
HasNextPage bool
EndCursor string
}
} `graphql:"projects(states: [OPEN], first: 100, after: $endCursor)"`
} `graphql:"projects(states: [OPEN], first: 100, orderBy: {field: NAME, direction: ASC}, after: $endCursor)"`
} `graphql:"organization(login: $owner)"`
}

Expand Down Expand Up @@ -81,7 +81,7 @@ func OrganizationTeams(client *Client, owner string) ([]OrgTeam, error) {
HasNextPage bool
EndCursor string
}
} `graphql:"teams(first: 100, after: $endCursor)"`
} `graphql:"teams(first: 100, orderBy: {field: NAME, direction: ASC}, after: $endCursor)"`
} `graphql:"organization(login: $owner)"`
}

Expand Down
15 changes: 13 additions & 2 deletions api/queries_repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,24 @@ func (r Repository) ViewerCanPush() bool {
}
}

// ViewerCanTriage is true when the requesting user can triage issues and pull requests
func (r Repository) ViewerCanTriage() bool {
switch r.ViewerPermission {
case "ADMIN", "MAINTAIN", "WRITE", "TRIAGE":
return true
default:
return false
}
}

func GitHubRepo(client *Client, repo ghrepo.Interface) (*Repository, error) {
query := `
query($owner: String!, $name: String!) {
repository(owner: $owner, name: $name) {
id
hasIssuesEnabled
description
viewerPermission
}
}`
variables := map[string]interface{}{
Expand Down Expand Up @@ -584,7 +595,7 @@ func RepoProjects(client *Client, repo ghrepo.Interface) ([]RepoProject, error)
HasNextPage bool
EndCursor string
}
} `graphql:"projects(states: [OPEN], first: 100, after: $endCursor)"`
} `graphql:"projects(states: [OPEN], first: 100, orderBy: {field: NAME, direction: ASC}, after: $endCursor)"`
} `graphql:"repository(owner: $owner, name: $name)"`
}

Expand Down Expand Up @@ -672,7 +683,7 @@ func RepoLabels(client *Client, repo ghrepo.Interface) ([]RepoLabel, error) {
HasNextPage bool
EndCursor string
}
} `graphql:"labels(first: 100, after: $endCursor)"`
} `graphql:"labels(first: 100, orderBy: {field: NAME, direction: ASC}, after: $endCursor)"`
} `graphql:"repository(owner: $owner, name: $name)"`
}

Expand Down
36 changes: 22 additions & 14 deletions command/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -386,8 +386,6 @@ func issueCreate(cmd *cobra.Command, args []string) error {
return fmt.Errorf("could not parse milestone: %w", err)
}

hasMetadata := len(assignees) > 0 || len(labelNames) > 0 || len(projectNames) > 0 || milestoneTitle != ""

if isWeb, err := cmd.Flags().GetBool("web"); err == nil && isWeb {
// TODO: move URL generation into GitHubRepository
openURL := fmt.Sprintf("https://github.com/%s/issues/new", ghrepo.FullName(baseRepo))
Expand Down Expand Up @@ -420,11 +418,17 @@ func issueCreate(cmd *cobra.Command, args []string) error {
}

action := SubmitAction
tb := issueMetadataState{
Assignees: assignees,
Labels: labelNames,
Projects: projectNames,
Milestone: milestoneTitle,
}

interactive := !(cmd.Flags().Changed("title") && cmd.Flags().Changed("body"))

if interactive {
tb, err := titleBodySurvey(cmd, title, body, defaults{}, templateFiles, !hasMetadata)
err := titleBodySurvey(cmd, &tb, apiClient, baseRepo, title, body, defaults{}, templateFiles, false, repo.ViewerCanTriage())
if err != nil {
return fmt.Errorf("could not collect title and/or body: %w", err)
}
Expand Down Expand Up @@ -465,19 +469,23 @@ func issueCreate(cmd *cobra.Command, args []string) error {
"body": body,
}

if hasMetadata {
metadataInput := api.RepoMetadataInput{
Assignees: len(assignees) > 0,
Labels: len(labelNames) > 0,
Projects: len(projectNames) > 0,
Milestones: milestoneTitle != "",
if tb.HasMetadata() {
if tb.MetadataResult == nil {
metadataInput := api.RepoMetadataInput{
Assignees: len(tb.Assignees) > 0,
Labels: len(tb.Labels) > 0,
Projects: len(tb.Projects) > 0,
Milestones: tb.Milestone != "",
}

// TODO: for non-interactive mode, only translate given objects to GraphQL IDs
tb.MetadataResult, err = api.RepoMetadata(apiClient, baseRepo, metadataInput)
if err != nil {
return err
}
}

metadata, err := api.RepoMetadata(apiClient, baseRepo, metadataInput)
if err != nil {
return err
}
err = addMetadataToIssueParams(params, metadata, assignees, labelNames, projectNames, milestoneTitle)
err = addMetadataToIssueParams(params, tb.MetadataResult, tb.Assignees, tb.Labels, tb.Projects, tb.Milestone)
if err != nil {
return err
}
Expand Down
51 changes: 31 additions & 20 deletions command/pr_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,6 @@ func prCreate(cmd *cobra.Command, _ []string) error {
return fmt.Errorf("could not parse milestone: %w", err)
}

hasMetadata := len(reviewers) > 0 || len(assignees) > 0 || len(labelNames) > 0 || len(projectNames) > 0 || milestoneTitle != ""

baseTrackingBranch := baseBranch
if baseRemote, err := remotes.FindByRepo(baseRepo.RepoOwner(), baseRepo.RepoName()); err == nil {
baseTrackingBranch = fmt.Sprintf("%s/%s", baseRemote.Name, baseBranch)
Expand Down Expand Up @@ -202,15 +200,24 @@ func prCreate(cmd *cobra.Command, _ []string) error {
}
}

// TODO: only drop into interactive mode if stdin & stdout are a tty
if !isWeb && !autofill && (title == "" || body == "") {
tb := issueMetadataState{
Reviewers: reviewers,
Assignees: assignees,
Labels: labelNames,
Projects: projectNames,
Milestone: milestoneTitle,
}

interactive := !(cmd.Flags().Changed("title") && cmd.Flags().Changed("body"))

if !isWeb && !autofill && interactive {
var templateFiles []string
if rootDir, err := git.ToplevelDir(); err == nil {
// TODO: figure out how to stub this in tests
templateFiles = githubtemplate.Find(rootDir, "PULL_REQUEST_TEMPLATE")
}

tb, err := titleBodySurvey(cmd, title, body, defs, templateFiles, !hasMetadata)
err := titleBodySurvey(cmd, &tb, client, baseRepo, title, body, defs, templateFiles, true, baseRepo.ViewerCanTriage())
if err != nil {
return fmt.Errorf("could not collect title and/or body: %w", err)
}
Expand Down Expand Up @@ -316,41 +323,45 @@ func prCreate(cmd *cobra.Command, _ []string) error {
"headRefName": headBranchLabel,
}

if hasMetadata {
metadataInput := api.RepoMetadataInput{
Reviewers: len(reviewers) > 0,
Assignees: len(assignees) > 0,
Labels: len(labelNames) > 0,
Projects: len(projectNames) > 0,
Milestones: milestoneTitle != "",
}
if tb.HasMetadata() {
if tb.MetadataResult == nil {
metadataInput := api.RepoMetadataInput{
Reviewers: len(tb.Reviewers) > 0,
Assignees: len(tb.Assignees) > 0,
Labels: len(tb.Labels) > 0,
Projects: len(tb.Projects) > 0,
Milestones: tb.Milestone != "",
}

metadata, err := api.RepoMetadata(client, baseRepo, metadataInput)
if err != nil {
return err
// TODO: for non-interactive mode, only translate given objects to GraphQL IDs
tb.MetadataResult, err = api.RepoMetadata(client, baseRepo, metadataInput)
if err != nil {
return err
}
}
err = addMetadataToIssueParams(params, metadata, assignees, labelNames, projectNames, milestoneTitle)

err = addMetadataToIssueParams(params, tb.MetadataResult, tb.Assignees, tb.Labels, tb.Projects, tb.Milestone)
if err != nil {
return err
}

var userReviewers []string
var teamReviewers []string
for _, r := range reviewers {
for _, r := range tb.Reviewers {
if strings.ContainsRune(r, '/') {
teamReviewers = append(teamReviewers, r)
} else {
userReviewers = append(teamReviewers, r)
}
}

userReviewerIDs, err := metadata.MembersToIDs(userReviewers)
userReviewerIDs, err := tb.MetadataResult.MembersToIDs(userReviewers)
if err != nil {
return fmt.Errorf("could not request reviewer: %w", err)
}
params["userReviewerIds"] = userReviewerIDs

teamReviewerIDs, err := metadata.TeamsToIDs(teamReviewers)
teamReviewerIDs, err := tb.MetadataResult.TeamsToIDs(teamReviewers)
if err != nil {
return fmt.Errorf("could not request reviewer: %w", err)
}
Expand Down
6 changes: 3 additions & 3 deletions command/pr_create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ func TestPRCreate_survey_defaults_multicommit(t *testing.T) {
as.Stub([]*QuestionStub{
{
Name: "confirmation",
Value: 1,
Value: 0,
},
})

Expand Down Expand Up @@ -458,7 +458,7 @@ func TestPRCreate_survey_defaults_monocommit(t *testing.T) {
as.Stub([]*QuestionStub{
{
Name: "confirmation",
Value: 1,
Value: 0,
},
})

Expand Down Expand Up @@ -602,7 +602,7 @@ func TestPRCreate_defaults_error_interactive(t *testing.T) {
as.Stub([]*QuestionStub{
{
Name: "confirmation",
Value: 0,
Value: 1,
},
})

Expand Down
Loading

0 comments on commit 4a3588d

Please sign in to comment.