github.com/cli/cli@v1.14.1-0.20210902173923-1af6a669e342/api/query_builder.go (about)

     1  package api
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  )
     7  
     8  func squeeze(r rune) rune {
     9  	switch r {
    10  	case '\n', '\t':
    11  		return -1
    12  	default:
    13  		return r
    14  	}
    15  }
    16  
    17  func shortenQuery(q string) string {
    18  	return strings.Map(squeeze, q)
    19  }
    20  
    21  var issueComments = shortenQuery(`
    22  	comments(first: 100) {
    23  		nodes {
    24  			author{login},
    25  			authorAssociation,
    26  			body,
    27  			createdAt,
    28  			includesCreatedEdit,
    29  			isMinimized,
    30  			minimizedReason,
    31  			reactionGroups{content,users{totalCount}}
    32  		},
    33  		pageInfo{hasNextPage,endCursor},
    34  		totalCount
    35  	}
    36  `)
    37  
    38  var prReviewRequests = shortenQuery(`
    39  	reviewRequests(first: 100) {
    40  		nodes {
    41  			requestedReviewer {
    42  				__typename,
    43  				...on User{login},
    44  				...on Team{
    45  					organization{login}
    46  					name,
    47  					slug
    48  				}
    49  			}
    50  		}
    51  	}
    52  `)
    53  
    54  var prReviews = shortenQuery(`
    55  	reviews(first: 100) {
    56  		nodes {
    57  			author{login},
    58  			authorAssociation,
    59  			submittedAt,
    60  			body,
    61  			state,
    62  			reactionGroups{content,users{totalCount}}
    63  		}
    64  		pageInfo{hasNextPage,endCursor}
    65  	}
    66  `)
    67  
    68  var prFiles = shortenQuery(`
    69  	files(first: 100) {
    70  		nodes {
    71  			additions,
    72  			deletions,
    73  			path
    74  		}
    75  	}
    76  `)
    77  
    78  var prCommits = shortenQuery(`
    79  	commits(first: 100) {
    80  		nodes {
    81  			commit {
    82  				authors(first:100) {
    83  					nodes {
    84  						name,
    85  						email,
    86  						user{id,login}
    87  					}
    88  				},
    89  				messageHeadline,
    90  				messageBody,
    91  				oid,
    92  				committedDate,
    93  				authoredDate
    94  			}
    95  		}
    96  	}
    97  `)
    98  
    99  func StatusCheckRollupGraphQL(after string) string {
   100  	var afterClause string
   101  	if after != "" {
   102  		afterClause = ",after:" + after
   103  	}
   104  	return fmt.Sprintf(shortenQuery(`
   105  	statusCheckRollup: commits(last: 1) {
   106  		nodes {
   107  			commit {
   108  				statusCheckRollup {
   109  					contexts(first:100%s) {
   110  						nodes {
   111  							__typename
   112  							...on StatusContext {
   113  								context,
   114  								state,
   115  								targetUrl
   116  							},
   117  							...on CheckRun {
   118  								name,
   119  								status,
   120  								conclusion,
   121  								startedAt,
   122  								completedAt,
   123  								detailsUrl
   124  							}
   125  						},
   126  						pageInfo{hasNextPage,endCursor}
   127  					}
   128  				}
   129  			}
   130  		}
   131  	}`), afterClause)
   132  }
   133  
   134  var IssueFields = []string{
   135  	"assignees",
   136  	"author",
   137  	"body",
   138  	"closed",
   139  	"comments",
   140  	"createdAt",
   141  	"closedAt",
   142  	"id",
   143  	"labels",
   144  	"milestone",
   145  	"number",
   146  	"projectCards",
   147  	"reactionGroups",
   148  	"state",
   149  	"title",
   150  	"updatedAt",
   151  	"url",
   152  }
   153  
   154  var PullRequestFields = append(IssueFields,
   155  	"additions",
   156  	"baseRefName",
   157  	"changedFiles",
   158  	"commits",
   159  	"deletions",
   160  	"files",
   161  	"headRefName",
   162  	"headRepository",
   163  	"headRepositoryOwner",
   164  	"isCrossRepository",
   165  	"isDraft",
   166  	"maintainerCanModify",
   167  	"mergeable",
   168  	"mergeCommit",
   169  	"mergedAt",
   170  	"mergedBy",
   171  	"mergeStateStatus",
   172  	"potentialMergeCommit",
   173  	"reviewDecision",
   174  	"reviewRequests",
   175  	"reviews",
   176  	"statusCheckRollup",
   177  )
   178  
   179  func PullRequestGraphQL(fields []string) string {
   180  	var q []string
   181  	for _, field := range fields {
   182  		switch field {
   183  		case "author":
   184  			q = append(q, `author{login}`)
   185  		case "mergedBy":
   186  			q = append(q, `mergedBy{login}`)
   187  		case "headRepositoryOwner":
   188  			q = append(q, `headRepositoryOwner{id,login,...on User{name}}`)
   189  		case "headRepository":
   190  			q = append(q, `headRepository{id,name}`)
   191  		case "assignees":
   192  			q = append(q, `assignees(first:100){nodes{id,login,name},totalCount}`)
   193  		case "labels":
   194  			q = append(q, `labels(first:100){nodes{id,name,description,color},totalCount}`)
   195  		case "projectCards":
   196  			q = append(q, `projectCards(first:100){nodes{project{name}column{name}},totalCount}`)
   197  		case "milestone":
   198  			q = append(q, `milestone{number,title,description,dueOn}`)
   199  		case "reactionGroups":
   200  			q = append(q, `reactionGroups{content,users{totalCount}}`)
   201  		case "mergeCommit":
   202  			q = append(q, `mergeCommit{oid}`)
   203  		case "potentialMergeCommit":
   204  			q = append(q, `potentialMergeCommit{oid}`)
   205  		case "comments":
   206  			q = append(q, issueComments)
   207  		case "reviewRequests":
   208  			q = append(q, prReviewRequests)
   209  		case "reviews":
   210  			q = append(q, prReviews)
   211  		case "files":
   212  			q = append(q, prFiles)
   213  		case "commits":
   214  			q = append(q, prCommits)
   215  		case "lastCommit": // pseudo-field
   216  			q = append(q, `commits(last:1){nodes{commit{oid}}}`)
   217  		case "commitsCount": // pseudo-field
   218  			q = append(q, `commits{totalCount}`)
   219  		case "requiresStrictStatusChecks": // pseudo-field
   220  			q = append(q, `baseRef{branchProtectionRule{requiresStrictStatusChecks}}`)
   221  		case "statusCheckRollup":
   222  			q = append(q, StatusCheckRollupGraphQL(""))
   223  		default:
   224  			q = append(q, field)
   225  		}
   226  	}
   227  	return strings.Join(q, ",")
   228  }
   229  
   230  var RepositoryFields = []string{
   231  	"id",
   232  	"name",
   233  	"nameWithOwner",
   234  	"owner",
   235  	"parent",
   236  	"templateRepository",
   237  	"description",
   238  	"homepageUrl",
   239  	"openGraphImageUrl",
   240  	"usesCustomOpenGraphImage",
   241  	"url",
   242  	"sshUrl",
   243  	"mirrorUrl",
   244  	"securityPolicyUrl",
   245  
   246  	"createdAt",
   247  	"pushedAt",
   248  	"updatedAt",
   249  
   250  	"isBlankIssuesEnabled",
   251  	"isSecurityPolicyEnabled",
   252  	"hasIssuesEnabled",
   253  	"hasProjectsEnabled",
   254  	"hasWikiEnabled",
   255  	"mergeCommitAllowed",
   256  	"squashMergeAllowed",
   257  	"rebaseMergeAllowed",
   258  
   259  	"forkCount",
   260  	"stargazerCount",
   261  	"watchers",
   262  	"issues",
   263  	"pullRequests",
   264  
   265  	"codeOfConduct",
   266  	"contactLinks",
   267  	"defaultBranchRef",
   268  	"deleteBranchOnMerge",
   269  	"diskUsage",
   270  	"fundingLinks",
   271  	"isArchived",
   272  	"isEmpty",
   273  	"isFork",
   274  	"isInOrganization",
   275  	"isMirror",
   276  	"isPrivate",
   277  	"isTemplate",
   278  	"isUserConfigurationRepository",
   279  	"licenseInfo",
   280  	"viewerCanAdminister",
   281  	"viewerDefaultCommitEmail",
   282  	"viewerDefaultMergeMethod",
   283  	"viewerHasStarred",
   284  	"viewerPermission",
   285  	"viewerPossibleCommitEmails",
   286  	"viewerSubscription",
   287  
   288  	"repositoryTopics",
   289  	"primaryLanguage",
   290  	"languages",
   291  	"issueTemplates",
   292  	"pullRequestTemplates",
   293  	"labels",
   294  	"milestones",
   295  	"latestRelease",
   296  
   297  	"assignableUsers",
   298  	"mentionableUsers",
   299  	"projects",
   300  
   301  	// "branchProtectionRules", // too complex to expose
   302  	// "collaborators", // does it make sense to expose without affiliation filter?
   303  }
   304  
   305  func RepositoryGraphQL(fields []string) string {
   306  	var q []string
   307  	for _, field := range fields {
   308  		switch field {
   309  		case "codeOfConduct":
   310  			q = append(q, "codeOfConduct{key,name,url}")
   311  		case "contactLinks":
   312  			q = append(q, "contactLinks{about,name,url}")
   313  		case "fundingLinks":
   314  			q = append(q, "fundingLinks{platform,url}")
   315  		case "licenseInfo":
   316  			q = append(q, "licenseInfo{key,name,nickname}")
   317  		case "owner":
   318  			q = append(q, "owner{id,login}")
   319  		case "parent":
   320  			q = append(q, "parent{id,name,owner{id,login}}")
   321  		case "templateRepository":
   322  			q = append(q, "templateRepository{id,name,owner{id,login}}")
   323  		case "repositoryTopics":
   324  			q = append(q, "repositoryTopics(first:100){nodes{topic{name}}}")
   325  		case "issueTemplates":
   326  			q = append(q, "issueTemplates{name,title,body,about}")
   327  		case "pullRequestTemplates":
   328  			q = append(q, "pullRequestTemplates{body,filename}")
   329  		case "labels":
   330  			q = append(q, "labels(first:100){nodes{id,color,name,description}}")
   331  		case "languages":
   332  			q = append(q, "languages(first:100){edges{size,node{name}}}")
   333  		case "primaryLanguage":
   334  			q = append(q, "primaryLanguage{name}")
   335  		case "latestRelease":
   336  			q = append(q, "latestRelease{publishedAt,tagName,name,url}")
   337  		case "milestones":
   338  			q = append(q, "milestones(first:100,states:OPEN){nodes{number,title,description,dueOn}}")
   339  		case "assignableUsers":
   340  			q = append(q, "assignableUsers(first:100){nodes{id,login,name}}")
   341  		case "mentionableUsers":
   342  			q = append(q, "mentionableUsers(first:100){nodes{id,login,name}}")
   343  		case "projects":
   344  			q = append(q, "projects(first:100,states:OPEN){nodes{id,name,number,body,resourcePath}}")
   345  		case "watchers":
   346  			q = append(q, "watchers{totalCount}")
   347  		case "issues":
   348  			q = append(q, "issues(states:OPEN){totalCount}")
   349  		case "pullRequests":
   350  			q = append(q, "pullRequests(states:OPEN){totalCount}")
   351  		case "defaultBranchRef":
   352  			q = append(q, "defaultBranchRef{name}")
   353  		default:
   354  			q = append(q, field)
   355  		}
   356  	}
   357  	return strings.Join(q, ",")
   358  }