Obtain GitHub issues in a specific milestone using GraphQL and IssueFilters - graphql

A similar question was previously asked but doesn't use IssueFilters which is what I want to use in this question.
Using GitHub's GraphQL Explorer, I am able to get issues of a repository using this query:
{
repository(owner: "neovim", name: "neovim") {
hasIssuesEnabled
issues(first: 20, orderBy: {field: CREATED_AT, direction: DESC}, filterBy: {milestone:"*"}) {
nodes {
... on Issue {
number
title
milestone {
number
id
url
title
}
}
}
}
}
}
The milestone is an issueFilter which, according to the documentation, allows you to:
List issues by given milestone argument. If a string representation of an integer is passed, it should refer to a milestone by its number field. Pass in null for issues with no milestone, and * for issues that are assigned to any milestone.
However, using a filter that is not a * but let's say filterBy: {milestone:"9"} (9 being a valid milestone number for the repository I am using), the query returns no nodes:
{
"data": {
"repository": {
"hasIssuesEnabled": true,
"issues": {
"nodes": []
}
}
}
}
I do not understand why this does not work from the documentation I read. Am I missing something regarding what means "it should refer to a milestone by its number field"?

Related

What is the recommended schema for paginated GraphQL results

Let's say I have users list to be returned. What would be best schema strategy among following.
Users returned contains only the data of user as follows, separate query is used for pagination details. In this query the downside is we need to pass same filters to both users and usersCount query.
query {
users(skip: 0, limit: 100, filters: someFilter) {
name
},
usersCount(filters: someFilters)
}
Which return following
{
results: {
users: [
{ name: "Foo" },
{ name: "Bar" },
],
usersCount: 1000,
}
}
In this strategy we make pagination details as part of users query, we don't need to pass filters twice. I feel this query is not nice to read.
query {
users(skip: 0, limit: 100, filters: someFilter) {
items: {
name
},
count
}
}
Which returns the following result
{
results: {
users: {
items: [
{ name: "Foo" },
{ name: "Bar" },
],
count: 1000,
}
}
}
I am curious to know which strategy is the recommended way while designing paginated results?
I would recommend to follow the official recommendation on graphql spec,
You need to switch to cursor based pagination.
This type of pagination uses a record or a pointer to a record in the dataset to paginate results. The cursor will refer to a record in the database.
You can follow the example in the link.
GraphQL Cursor Connections Specification
Also checkout how GitHub does it here: https://docs.github.com/en/graphql/reference/interfaces#node

GitHub GraphQL API: only get issues that have over n comments

I'm playing with GitHub GraphQL API in order to get the list of most commented issues (say, comments > 100) across most popular repositories.
Here's the search query that I'm starting from:
search(query: "stars:>10000 fork:false pushed:>2020-01-01 is:public mirror:false archived:false", type: REPOSITORY)
So far so good, except that it looks like this high level GitHub search doesn't provide any filters related to issues and comments: I can't filter out repos that don't have issues at all, nor can I set a threshold for the number of comments.
Then I try to see if there's a filter specific to the list of issues, but it seems that the filterBy for issues doesn't provide any way to filter by comments or related activity:
search(query: "stars:>10000 fork:false pushed:>2020-01-01 is:public mirror:false archived:false", type: REPOSITORY) {
repositoryCount
nodes {
... on Repository {
issues(first: 100, filterBy: { <!-- Nothing useful here--> }, orderBy: {field: CREATED_AT, direction: ASC}) {
totalCount
edges {
node {
title
comments {
totalCount
}
id
number
}
}
}
}
}
}
Am I missing something obvious, or do I really need to get all issues from the API and then process the result locally to strip away issues that have less than 100 comments?

Apollo mixes two different arrays of the same query seemingly at random

With a schema like
schema {
query: QueryRoot
}
scalar MyBigUint
type Order {
id: Int!
data: OrderCommons!
kind: OrderType!
}
type OrderBook {
bids(limit: Int): [Order!]!
asks(limit: Int): [Order!]!
}
type OrderCommons {
quantity: Int!
price: MyBigUint! // where it doesn't matter whether it's MyBigUint or a simple Int - the issue occurs anyways
}
enum OrderType {
BUY
SELL
}
type QueryRoot {
orderbook: OrderBook!
}
And a query query { orderbook { bids { data { price } }, asks { data { price } } } }
In a graphql playground of my graphql API (and on the network level of my Apollo app too) I receive a result like
{
"data": {
"orderbook": {
"bids": [
{
"data": {
"price": "127"
}
},
{
"data": {
"price": "74"
}
},
...
],
"asks": [
{
"data": {
"price": "181"
}
},
{
"data": {
"price": "187"
}
},
...
]
}
}
}
where, for the purpose of this question, the bids are ordered in descending order by price like ["127", "74", "73", "72"], etc, and asks are ordered in ascending order, accordingly.
However, in Apollo, after a query is done, I notice that one of the arrays gets seemingly random data.
For the purpose of the question, useQuery react hook is used, but the same happens when I query imperatively from a freshly initialized ApolloClient.
const { data, subscribeToMore, ...rest } = useQuery<OrderbookResponse>(GET_ORDERBOOK_QUERY);
console.log(data?.orderbook?.bids?.map(r => r.data.price));
console.log(data?.orderbook?.asks?.map(r => r.data.price));
Here, corrupted data of Bids gets printed i.e. ['304', '306', '298', '309', '277', '153', '117', '108', '87', '76'] (notice the order being wrong, at the least), whereas Asks data looks just fine. Inspecting the network, I find that Bids are not only properly ordered there, but also have different (correct, from DB) values!
Therefore, it seems something's getting corrupted on the way while Apollo delivers the data.
What could be the issue here I wonder, and where to start debugging such kind of an issue? There seem to be no warnings from Apollo either, it seems to just silently corrupt the data.
I'm clearly doing something wrong, but what?
The issue seems to stem from how Apollo caches data.
My Bids and Asks could have the same numeric IDs but share the same Order graphql type. Apollo rightfully assumes a Bid and an Ask with the same ID are the same things and the resulting data gets wrecked as a consequence.
An easy fix is to show Apollo that there's a complex key to the Order type on cache initialization:
cache: new InMemoryCache({
typePolicies: {
Order: {
keyFields: ['id', 'kind'],
}
}
})
This way it'll understand that the Order entities Ask and Bid with the same ID are different pieces of data indeed.
Note that the field kind should be also added to the query strings accordingly.

How to query data from GitHub Discussions using GitHub's GraphQL API

I want to query the data from https://github.com/prisma/prisma/discussions via GitHub's GraphQL API but I don't know how to access it.
GitHub Discussions are a beta feature that's currently available only on a few repos, prisma/prisma being one of them. I would have expected that I can query the data in a similar fashion to querying issues and pull requests of a repo:
{
repository(
owner: "prisma"
name: "prisma"
) {
pullRequests(first: 5 orderBy: {
field: CREATED_AT,
direction: DESC
}) {
edges {
node {
title
}
}
}
issues(first: 5 orderBy: {
field: CREATED_AT,
direction: DESC
}) {
edges {
node {
title
}
}
}
}
}
I'm basically looking for a query that would allow me to do this:
{
repository(
owner: "prisma"
name: "prisma"
) {
# this doesn't work
discussions(first: 5 orderBy: {
field: CREATED_AT,
direction: DESC
}) {
edges {
node {
title
}
}
}
}
}
But such a discussions property doesn't exist on the Repository type in the GitHub API.
EDIT (Dec 8, 2020): I learned from the GitHub team that the data is not yet available via the public GraphQL API but they're working on releasing it soon. I'll leave the question open until it's available.

GraphQL query based on a specific value of a field

I want to be able to retrieve the latest release from GitHub for a specific repo using their GraphQL API. To do that, I need to get the latest release where isDraft and isPrerelease are false. I have managed to get the first part, but cant figure out how to do the "where" part of the query.
Here is the basic query I have gotten (https://developer.github.com/v4/explorer/):
{
repository(owner: "paolosalvatori", name: "ServiceBusExplorer") {
releases(first: 1, orderBy: {field: CREATED_AT, direction: DESC}) {
nodes {
name
tagName
resourcePath
isDraft
isPrerelease
}
}
}
}
Which returns:
{
"data": {
"repository": {
"releases": {
"nodes": [
{
"name": "3.0.4",
"tagName": "3.0.4",
"resourcePath": "/paolosalvatori/ServiceBusExplorer/releases/tag/3.0.4",
"isDraft": false,
"isPrerelease": false
}
]
}
}
}
}
I cant seem to find a way to do this. Part of the reason is that I am new to GraphQL (first time trying to do a query) and I am not sure how to frame my question.
Can one only "query" based on those types that support arguments (like repository and releases below)? Seems like there should be a way to specify a filter on the field values.
Repository: https://developer.github.com/v4/object/repository/
Releases: https://developer.github.com/v4/object/releaseconnection/
Node: https://developer.github.com/v4/object/release/
Can one only "query" based on those types that support arguments
Yes: GraphQL doesn't define a generic query language in the same way, say, SQL does. You can't sort or filter a field result in ways that aren't provided by the server and the application schema.
I want to be able to retrieve the latest [non-draft, non-prerelease] release from GitHub for a specific repo using their GraphQl API.
As you've already found, the releases field on the Repository type doesn't have an option to sort or filter on these fields. Instead, you can iterate through the releases one at a time with multiple GraphQL calls. These would individually look like
query NextRelease($owner: String!, $name: String!, $after: String) {
repository(owner: $owner, name: $name) {
releases(first: 1,
orderBy: {field: CREATED_AT, direction: DESC},
after: $after) {
pageInfo { lastCursor }
nodes { ... ReleaseData } # from the question
}
}
}
Run this in the same way you're running it now (I've split out the information identifying the repository into separate GraphQL variables). You can leave off the after variable for the first call. If (as in your example) it returns "isDraft": false, "isPrerelease": false, you're set. If not, you need to try again: take the value from the lastCursor in the response, and run the same query, passing that cursor value as the after variable value.
{
repository(owner: "paolosalvatori", name: "ServiceBusExplorer") {
releases(first: 1, orderBy: {field: CREATED_AT, direction: DESC}) {
nodes(isDraft :false , isPrerelease :false ) {
name
tagName
resourcePath
isDraft
isPrerelease
}
}
}
}
Alternatively please have look at GraphQL directives, as sometimes it's required to skip or include the fields on the basis of the values
#skip or #include.
The skip directive, when used on fields or fragments, allows us to exclude fields based on some condition.
The include directive, allows us to include fields based on some condition
GraphQL Directives

Resources