Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save 0xdevalias/04ec31b12edaae727cd87d379499c14c to your computer and use it in GitHub Desktop.
Save 0xdevalias/04ec31b12edaae727cd87d379499c14c to your computer and use it in GitHub Desktop.
Some notes on how to read GitHub notifications from the gh CLI.

Reading GitHub Notifications from gh CLI

Some notes on how to read GitHub notifications from the gh CLI.

Table of Contents

Notes

The following are the notes I wrote in a GitHub issue for accessing GitHub notifications from the CLI, including formatting them to have clickable links/etc:

This could be potentially improved further if these issues get resolved positively:

  • cli/cli#10261
    • Allow --jq and --template to be used together in gh api

  • cli/cli#10262
    • Add custom formatting functions to --jq similar to those added to --template

  • cli/cli#10263
    • Allow passing additional arguments through to --jq script, just like we can with jq --arg

I also added a zsh wrapper script version of this to my dotfiles:

Which I then aliased as gh notifications:

Here are my original notes, and the resulting gh api command:

The ideal version would include

  • usernames involved in the update (have to switch the query to GraphQL)
  • the correct web url to click on - needs mangling of API url or url construction from parts for issues, PRs and other objects
  • Handle non repo updates like from projects etc
  • Show the status of the issue(open / closed) / PR(draft,closed, merged, open) color coded like the UI does.
  • Group by repository not just sort by date.

Originally posted by @manquer in #659

Since gh api doesn't allow us to pass both --jq and --template currently:

And because the Go template language doesn't seem to allow us to perform more complex manipulations:

We can seemly manipulate the output from gh with either the --jq or --template flags:

Templates are go templates:

Which according to ChatGPT, doesn't seem to allow more complex string manipulations:

Using Go's text/template or html/template package, you cannot directly perform complex string manipulations like regex or advanced parsing, as the templates focus on simple variable interpolation and basic functions (e.g., split, join, index).

Originally posted by @0xdevalias in #4

We first need to convert the original --template command to an equivalent using only --jq:

We could do this using jq's @tsv + the external column program like this:

gh api notifications \
  --method GET \
  -F participating=true \
  --jq '
    def timeago:
      . | fromdateiso8601 | now - . | . / 60 | floor | # Convert to minutes
      if . < 60 then
        (. | tostring + " minutes ago")
      elif . < 1440 then
        (. / 60 | floor | tostring + " hours ago")
      elif . < 43200 then
        (. / 1440 | floor | tostring + " days ago")
      elif . < 525600 then
        (. / 43200 | floor | tostring + " months ago")
      else
        (. / 525600 | floor | tostring + " years ago")
      end;

    .[] | 
      [
        .repository.full_name, 
        (.subject.title | .[:100]), 
        .subject.type, 
        .reason, 
        (.updated_at | timeago)
      ] | @tsv' \
  --paginate | column -t -s $'\t'

But if we wanted to fully encapsulate the processing within --jq, we could create an extra ljust function and use it like this:

gh api notifications \
  --method GET \
  -F participating=true \
  --jq '
    def timeago:
      . | fromdateiso8601 | now - . | . / 60 | floor | # Convert to minutes
      if . < 60 then
        (. | tostring + " minutes ago")
      elif . < 1440 then
        (. / 60 | floor | tostring + " hours ago")
      elif . < 43200 then
        (. / 1440 | floor | tostring + " days ago")
      elif . < 525600 then
        (. / 43200 | floor | tostring + " months ago")
      else
        (. / 525600 | floor | tostring + " years ago")
      end;
  
    def ljust(width): . + " " * (width - (. | length));
  
    .[] | 
      [
        (.repository.full_name | ljust(25)), 
        (.subject.title | .[:50] | ljust(50)), 
        (.subject.type | ljust(12)), 
        (.reason | ljust(8)), 
        (.updated_at | timeago)
      ] | join("  ")' \
  --paginate

Both of these give output similar to the original:

Original --template:

prisma/prisma           Support for a Union type                                         Issue        manual  45 minutes ago
jekyll/jekyll           Rename `baseurl` to `base_path`                                  Issue        manual  3 months ago

--jq + column:

prisma/prisma           Support for a Union type                                         Issue        manual  43 minutes ago
jekyll/jekyll           Rename `baseurl` to `base_path`                                  Issue        manual  3 months ago

Only --jq

prisma/prisma              Support for a Union type                            Issue         manual    43 minutes ago
jekyll/jekyll              Rename `baseurl` to `base_path`                     Issue         manual    3 months ago

Now that the logic is all within --jq, we can define extra functions to manipulate and improve the output based on the additional requirements/desires.

For example (not 100% thoroughly tested, may be bugs), the following adds conversions for the web_url, displying the status, and depending which format block you uncomment, grouping by repo:

gh api notifications \
  --method GET \
  -F participating=true \
  --jq '
    def timeago:
      . | fromdateiso8601 | now - . | . / 60 | floor |
      if . < 60 then
        (. | tostring + " minutes ago")
      elif . < 1440 then
        (. / 60 | floor | tostring + " hours ago")
      elif . < 43200 then
        (. / 1440 | floor | tostring + " days ago")
      elif . < 525600 then
        (. / 43200 | floor | tostring + " months ago")
      else
        (. / 525600 | floor | tostring + " years ago")
      end;

    def ljust(width): . + " " * (width - (. | length));
    
    def api_to_web_url:
      if test("^https://api.github.com/repos/[^/]+/[^/]+/(issues|pulls)/[0-9]+$") then
        sub("^https://api.github.com/repos/"; "https://github.com/")
      elif test("^https://api.github.com/repos/[^/]+/[^/]+/issues/comments/[0-9]+$") then
        capture("^https://api.github.com/repos/(?<repo>[^/]+/[^/]+)/issues/comments/(?<comment>[0-9]+)$") |
        "https://github.com/\(.repo)/issues#issuecomment-\(.comment)"
      elif test("^https://api.github.com/repos/") then
        sub("^https://api.github.com/repos/"; "https://github.com/")
      else
        .
      end;

    def get_status:
      if .subject.type == "Issue" then
        if .state == "closed" then "🔴 Closed" else "🟢 Open" end
      elif .subject.type == "PullRequest" then
        if .state == "merged" then "🟣 Merged"
        elif .state == "closed" then "🔴 Closed"
        elif .draft then "⚪ Draft"
        else "🟢 Open" end
      else
        "     -"
      end;

    def format_item:
      [
        (.repository.full_name | ljust(25)),
        (.subject.title | .[:50] | ljust(50)),
        (.subject.type | ljust(12)),
        (get_status | ljust(12)),
        (.reason | ljust(8)),
        (.updated_at | timeago | ljust(15)),
        (.subject.url | api_to_web_url)
      ] | join("  ");

    def format_grouped_item:
      [
        "    ",  # Indent for grouping
        (.subject.title | .[:50] | ljust(50)),
        (.subject.type | ljust(12)),
        (get_status | ljust(12)),
        (.reason | ljust(8)),
        (.updated_at | timeago | ljust(15)),
        (.subject.url | api_to_web_url)
      ] | join("  ");

    def format_repo_header:
      .repository.html_url | 
      sub("^https://github.com/"; "") | 
      "\n\u001b[1m\u001b[36m=== \(.) ===\u001b[0m";

    # GROUPING SWITCH: Comment out one of these two blocks
    
    # Block 1: No grouping - just format and output
    .[] | format_item
    
    # Block 2: With grouping
    #group_by(.repository.full_name) | 
    #map({
    #  group: ., 
    #  max_time: ([.[].updated_at | fromdateiso8601] | max)
    #}) | 
    #sort_by(-.max_time) | 
    #.[].group | 
    #(.[0] | format_repo_header) as $header |
    #($header, (.[] | format_grouped_item))' \
  --paginate

Which gives output like this for non-grouped:

ggerganov/whisper.cpp      MacWhisper, native macOS app for Whisper            Discussion         -        manual    6 minutes ago    https://github.com/ggerganov/whisper.cpp/discussions/420
prisma/prisma              Support for a Union type                            Issue         🟢 Open        manual    1 hours ago      https://github.com/prisma/prisma/issues/2505
jekyll/jekyll              Rename `baseurl` to `base_path`                     Issue         🟢 Open        manual    3 months ago     https://github.com/jekyll/jekyll/issues/4711

And this for grouped:

=== ggerganov/whisper.cpp ===
      MacWhisper, native macOS app for Whisper            Discussion         -        manual    7 minutes ago    https://github.com/ggerganov/whisper.cpp/discussions/420

=== prisma/prisma ===
      Support for a Union type                            Issue         🟢 Open        manual    1 hours ago      https://github.com/prisma/prisma/issues/2505

=== jekyll/jekyll ===
      Rename `baseurl` to `base_path`                     Issue         🟢 Open        manual    3 months ago     https://github.com/jekyll/jekyll/issues/4711

This could be potentially improved further if either of these issues get resolved positively:

Originally posted by @0xdevalias in cli/cli#659 (comment)

GitHub iOS GraphQL Query

RE: cli/cli#659 (comment)

Seems like the Mobile app is using some graphQL API endpoints behind a feature flag

Interesting.. willing to share the details for them? That way we might just be able to use them directly in a gh extension to add support for it?

POST Request Details

POST /graphql HTTP/2
Host: api.github.com
Content-Type: application/json
Graphql-Features: merge_queue,private_profile_setting,project_next_field_configuration,issues_close_state,project_next_recent_connection,file_level_commenting,issue_types,sub_issues
Accept: application/vnd.github.merge-info-preview+json,application/vnd.github.shadow-cat-preview+json,application/vnd.github.echo-preview+json,application/vnd.github.starfox-preview+json,application/vnd.github.doctor-strange-preview+json
Apollographql-Client-Version: 1.192.0-152022212
Authorization: Bearer REDACTED
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB;q=1.0, en-AU;q=0.9, ja-AU;q=0.8, fa-AU;q=0.7
Content-Length: 4030
User-Agent: GitHub/1.192.0 (com.github.stormbreaker.prod; build:152022212; iOS 18.2.1; iPhone15,3)
X-Apollo-Operation-Type: query
Apollographql-Client-Name: com.github.stormbreaker.prod-apollo-ios
X-Apollo-Operation-Name: Inbox

{
    "operationName": "Inbox",
    "query": "query Inbox($first: Int!, $after: String, $filterBy: NotificationThreadFilters, $query: String, $avatarSize: Int!) { viewer { __typename id ...WebNotificationsEnabledFragment notificationThreads( first: $first after: $after filterBy: $filterBy query: $query ) { __typename pageInfo { __typename hasNextPage endCursor } totalCount nodes { __typename ...NotificationThreadCommonFieldsFragment url subject { __typename ... on CheckSuite { ...InboxSubjectCheckSuiteFieldsFragment } ... on WorkflowRun { ...InboxSubjectWorkflowRunFieldsFragment } ... on Commit { ...InboxSubjectCommitFieldsFragment } ... on Gist { ...InboxSubjectGistFieldsFragment } ... on TeamDiscussion { ...InboxSubjectTeamDiscussionFieldsFragment } ... on Issue { ...InboxSubjectIssueFieldsFragment } ... on PullRequest { ...InboxSubjectPullRequestFieldsFragment } ... on Release { ...InboxSubjectReleaseFieldsFragment } ... on RepositoryVulnerabilityAlert { ...InboxSubjectRepositoryVulnerabilityAlertFieldsFragment } ... on RepositoryAdvisory { ...InboxSubjectRepositoryAdvisoryFieldsFragment } ...InboxSubjectDiscussionFieldsFragment ... on RepositoryDependabotAlertsThread { ...InboxSubjectRepositoryDependabotAlertsThreadFieldsFragment } ... on SecurityAdvisory { ...InboxSubjectSecurityAdvisoryFieldsFragment } } } } } }\nfragment AvatarFragment on Actor { __typename avatarUrl(size: $avatarSize) }\nfragment InboxSubjectCheckSuiteFieldsFragment on CheckSuite { __typename id url conclusion status }\nfragment InboxSubjectCommitFieldsFragment on Commit { __typename id abbreviatedOid url repository { __typename id owner { __typename id login } name } }\nfragment InboxSubjectDiscussionFieldsFragment on Discussion { __typename id url number discussionStateReason: stateReason answer { __typename id } category { __typename id isAnswerable } repository { __typename id isOrganizationDiscussionRepository } }\nfragment InboxSubjectGistFieldsFragment on Gist { __typename url id }\nfragment InboxSubjectIssueFieldsFragment on Issue { __typename id number issueState: state stateReason issueHtmlTitle: titleHTML url }\nfragment InboxSubjectPullRequestFieldsFragment on PullRequest { __typename id number pullRequestHtmlTitle: titleHTML url ...PullRequestStateIcon }\nfragment InboxSubjectReleaseFieldsFragment on Release { __typename id tagName url }\nfragment InboxSubjectRepositoryAdvisoryFieldsFragment on RepositoryAdvisory { __typename id url }\nfragment InboxSubjectRepositoryDependabotAlertsThreadFieldsFragment on RepositoryDependabotAlertsThread { __typename id notificationsPermalink }\nfragment InboxSubjectRepositoryVulnerabilityAlertFieldsFragment on RepositoryVulnerabilityAlert { __typename id permalink }\nfragment InboxSubjectSecurityAdvisoryFieldsFragment on SecurityAdvisory { __typename id ghsaId notificationsPermalink }\nfragment InboxSubjectTeamDiscussionFieldsFragment on TeamDiscussion { __typename url id }\nfragment InboxSubjectWorkflowRunFieldsFragment on WorkflowRun { __typename id url runNumber workflow { __typename id name } checkSuite { __typename id } }\nfragment ListSubscribableFragment on Subscribable { __typename id viewerSubscription viewerCanSubscribe }\nfragment NotificationThreadCommonFieldsFragment on NotificationThread { __typename id threadType title isUnread unreadItemsCount lastUpdatedAt subscriptionStatus summaryItemAuthor { __typename id ...AvatarFragment } summaryItemBody isArchived isSaved reason list { __typename ...ListSubscribableFragment ... on Repository { id owner { __typename id login } name } ... on User { id login userName: name } ... on Team { id organization { __typename id login } slug } ... on Organization { id login } } }\nfragment PullRequestStateIcon on PullRequest { __typename pullRequestState: state isDraft mergeQueueEntry { __typename id position } }\nfragment WebNotificationsEnabledFragment on User { __typename notificationSettings { __typename getsParticipatingWeb getsWatchingWeb } }",
    "variables":
    {
        "avatarSize": 48,
        "first": 30,
        "query": ""
    }
}

Pretty-Printed GraphQL Query

query Inbox(
  $first: Int!
  $after: String
  $filterBy: NotificationThreadFilters
  $query: String
  $avatarSize: Int!
) {
  viewer {
    __typename
    id
    ...WebNotificationsEnabledFragment
    notificationThreads(
      first: $first
      after: $after
      filterBy: $filterBy
      query: $query
    ) {
      __typename
      pageInfo {
        __typename
        hasNextPage
        endCursor
      }
      totalCount
      nodes {
        __typename
        ...NotificationThreadCommonFieldsFragment
        url
        subject {
          __typename
          ... on CheckSuite {
            ...InboxSubjectCheckSuiteFieldsFragment
          }
          ... on WorkflowRun {
            ...InboxSubjectWorkflowRunFieldsFragment
          }
          ... on Commit {
            ...InboxSubjectCommitFieldsFragment
          }
          ... on Gist {
            ...InboxSubjectGistFieldsFragment
          }
          ... on TeamDiscussion {
            ...InboxSubjectTeamDiscussionFieldsFragment
          }
          ... on Issue {
            ...InboxSubjectIssueFieldsFragment
          }
          ... on PullRequest {
            ...InboxSubjectPullRequestFieldsFragment
          }
          ... on Release {
            ...InboxSubjectReleaseFieldsFragment
          }
          ... on RepositoryVulnerabilityAlert {
            ...InboxSubjectRepositoryVulnerabilityAlertFieldsFragment
          }
          ... on RepositoryAdvisory {
            ...InboxSubjectRepositoryAdvisoryFieldsFragment
          }
          ...InboxSubjectDiscussionFieldsFragment
          ... on RepositoryDependabotAlertsThread {
            ...InboxSubjectRepositoryDependabotAlertsThreadFieldsFragment
          }
          ... on SecurityAdvisory {
            ...InboxSubjectSecurityAdvisoryFieldsFragment
          }
        }
      }
    }
  }
}
fragment AvatarFragment on Actor {
  __typename
  avatarUrl(size: $avatarSize)
}
fragment InboxSubjectCheckSuiteFieldsFragment on CheckSuite {
  __typename
  id
  url
  conclusion
  status
}
fragment InboxSubjectCommitFieldsFragment on Commit {
  __typename
  id
  abbreviatedOid
  url
  repository {
    __typename
    id
    owner {
      __typename
      id
      login
    }
    name
  }
}
fragment InboxSubjectDiscussionFieldsFragment on Discussion {
  __typename
  id
  url
  number
  discussionStateReason: stateReason
  answer {
    __typename
    id
  }
  category {
    __typename
    id
    isAnswerable
  }
  repository {
    __typename
    id
    isOrganizationDiscussionRepository
  }
}
fragment InboxSubjectGistFieldsFragment on Gist {
  __typename
  url
  id
}
fragment InboxSubjectIssueFieldsFragment on Issue {
  __typename
  id
  number
  issueState: state
  stateReason
  issueHtmlTitle: titleHTML
  url
}
fragment InboxSubjectPullRequestFieldsFragment on PullRequest {
  __typename
  id
  number
  pullRequestHtmlTitle: titleHTML
  url
  ...PullRequestStateIcon
}
fragment InboxSubjectReleaseFieldsFragment on Release {
  __typename
  id
  tagName
  url
}
fragment InboxSubjectRepositoryAdvisoryFieldsFragment on RepositoryAdvisory {
  __typename
  id
  url
}
fragment InboxSubjectRepositoryDependabotAlertsThreadFieldsFragment on RepositoryDependabotAlertsThread {
  __typename
  id
  notificationsPermalink
}
fragment InboxSubjectRepositoryVulnerabilityAlertFieldsFragment on RepositoryVulnerabilityAlert {
  __typename
  id
  permalink
}
fragment InboxSubjectSecurityAdvisoryFieldsFragment on SecurityAdvisory {
  __typename
  id
  ghsaId
  notificationsPermalink
}
fragment InboxSubjectTeamDiscussionFieldsFragment on TeamDiscussion {
  __typename
  url
  id
}
fragment InboxSubjectWorkflowRunFieldsFragment on WorkflowRun {
  __typename
  id
  url
  runNumber
  workflow {
    __typename
    id
    name
  }
  checkSuite {
    __typename
    id
  }
}
fragment ListSubscribableFragment on Subscribable {
  __typename
  id
  viewerSubscription
  viewerCanSubscribe
}
fragment NotificationThreadCommonFieldsFragment on NotificationThread {
  __typename
  id
  threadType
  title
  isUnread
  unreadItemsCount
  lastUpdatedAt
  subscriptionStatus
  summaryItemAuthor {
    __typename
    id
    ...AvatarFragment
  }
  summaryItemBody
  isArchived
  isSaved
  reason
  list {
    __typename
    ...ListSubscribableFragment
    ... on Repository {
      id
      owner {
        __typename
        id
        login
      }
      name
    }
    ... on User {
      id
      login
      userName: name
    }
    ... on Team {
      id
      organization {
        __typename
        id
        login
      }
      slug
    }
    ... on Organization {
      id
      login
    }
  }
}
fragment PullRequestStateIcon on PullRequest {
  __typename
  pullRequestState: state
  isDraft
  mergeQueueEntry {
    __typename
    id
    position
  }
}
fragment WebNotificationsEnabledFragment on User {
  __typename
  notificationSettings {
    __typename
    getsParticipatingWeb
    getsWatchingWeb
  }
}

Attempted gh api graphql command

gh api graphql \
  --header 'Graphql-Features: merge_queue,private_profile_setting,project_next_field_configuration,issues_close_state,project_next_recent_connection,file_level_commenting,issue_types,sub_issues' \
  --preview 'merge-info' \
  --preview 'shadow-cat' \
  --preview 'echo' \
  --preview 'starfox' \
  --preview 'doctor-strange' \
  -F avatarSize='48' \
  -F first='30' \
  -F searchQuery='' \
  -F operationName='Inbox' \
  --raw-field query='
    query Inbox(
      $first: Int!
      $after: String
      $filterBy: NotificationThreadFilters
      $searchQuery: String
      $avatarSize: Int!
    ) {
      viewer {
        __typename
        id
        ...WebNotificationsEnabledFragment
        notificationThreads(
          first: $first
          after: $after
          filterBy: $filterBy
          query: $searchQuery
        ) {
          __typename
          pageInfo {
            __typename
            hasNextPage
            endCursor
          }
          totalCount
          nodes {
            __typename
            ...NotificationThreadCommonFieldsFragment
            url
            subject {
              __typename
              ... on CheckSuite {
                ...InboxSubjectCheckSuiteFieldsFragment
              }
              ... on WorkflowRun {
                ...InboxSubjectWorkflowRunFieldsFragment
              }
              ... on Commit {
                ...InboxSubjectCommitFieldsFragment
              }
              ... on Gist {
                ...InboxSubjectGistFieldsFragment
              }
              ... on TeamDiscussion {
                ...InboxSubjectTeamDiscussionFieldsFragment
              }
              ... on Issue {
                ...InboxSubjectIssueFieldsFragment
              }
              ... on PullRequest {
                ...InboxSubjectPullRequestFieldsFragment
              }
              ... on Release {
                ...InboxSubjectReleaseFieldsFragment
              }
              ... on RepositoryVulnerabilityAlert {
                ...InboxSubjectRepositoryVulnerabilityAlertFieldsFragment
              }
              ... on RepositoryAdvisory {
                ...InboxSubjectRepositoryAdvisoryFieldsFragment
              }
              ...InboxSubjectDiscussionFieldsFragment
              ... on RepositoryDependabotAlertsThread {
                ...InboxSubjectRepositoryDependabotAlertsThreadFieldsFragment
              }
              ... on SecurityAdvisory {
                ...InboxSubjectSecurityAdvisoryFieldsFragment
              }
            }
          }
        }
      }
    }
    fragment AvatarFragment on Actor {
      __typename
      avatarUrl(size: $avatarSize)
    }
    fragment InboxSubjectCheckSuiteFieldsFragment on CheckSuite {
      __typename
      id
      url
      conclusion
      status
    }
    fragment InboxSubjectCommitFieldsFragment on Commit {
      __typename
      id
      abbreviatedOid
      url
      repository {
        __typename
        id
        owner {
          __typename
          id
          login
        }
        name
      }
    }
    fragment InboxSubjectDiscussionFieldsFragment on Discussion {
      __typename
      id
      url
      number
      discussionStateReason: stateReason
      answer {
        __typename
        id
      }
      category {
        __typename
        id
        isAnswerable
      }
      repository {
        __typename
        id
        isOrganizationDiscussionRepository
      }
    }
    fragment InboxSubjectGistFieldsFragment on Gist {
      __typename
      url
      id
    }
    fragment InboxSubjectIssueFieldsFragment on Issue {
      __typename
      id
      number
      issueState: state
      stateReason
      issueHtmlTitle: titleHTML
      url
    }
    fragment InboxSubjectPullRequestFieldsFragment on PullRequest {
      __typename
      id
      number
      pullRequestHtmlTitle: titleHTML
      url
      ...PullRequestStateIcon
    }
    fragment InboxSubjectReleaseFieldsFragment on Release {
      __typename
      id
      tagName
      url
    }
    fragment InboxSubjectRepositoryAdvisoryFieldsFragment on RepositoryAdvisory {
      __typename
      id
      url
    }
    fragment InboxSubjectRepositoryDependabotAlertsThreadFieldsFragment on RepositoryDependabotAlertsThread {
      __typename
      id
      notificationsPermalink
    }
    fragment InboxSubjectRepositoryVulnerabilityAlertFieldsFragment on RepositoryVulnerabilityAlert {
      __typename
      id
      permalink
    }
    fragment InboxSubjectSecurityAdvisoryFieldsFragment on SecurityAdvisory {
      __typename
      id
      ghsaId
      notificationsPermalink
    }
    fragment InboxSubjectTeamDiscussionFieldsFragment on TeamDiscussion {
      __typename
      url
      id
    }
    fragment InboxSubjectWorkflowRunFieldsFragment on WorkflowRun {
      __typename
      id
      url
      runNumber
      workflow {
        __typename
        id
        name
      }
      checkSuite {
        __typename
        id
      }
    }
    fragment ListSubscribableFragment on Subscribable {
      __typename
      id
      viewerSubscription
      viewerCanSubscribe
    }
    fragment NotificationThreadCommonFieldsFragment on NotificationThread {
      __typename
      id
      threadType
      title
      isUnread
      unreadItemsCount
      lastUpdatedAt
      subscriptionStatus
      summaryItemAuthor {
        __typename
        id
        ...AvatarFragment
      }
      summaryItemBody
      isArchived
      isSaved
      reason
      list {
        __typename
        ...ListSubscribableFragment
        ... on Repository {
          id
          owner {
            __typename
            id
            login
          }
          name
        }
        ... on User {
          id
          login
          userName: name
        }
        ... on Team {
          id
          organization {
            __typename
            id
            login
          }
          slug
        }
        ... on Organization {
          id
          login
        }
      }
    }
    fragment PullRequestStateIcon on PullRequest {
      __typename
      pullRequestState: state
      isDraft
      mergeQueueEntry {
        __typename
        id
        position
      }
    }
    fragment WebNotificationsEnabledFragment on User {
      __typename
      notificationSettings {
        __typename
        getsParticipatingWeb
        getsWatchingWeb
      }
    }
  '
{
    "errors":
    [
        {
            "path":
            [
                "query Inbox",
                "viewer",
                "notificationThreads",
                "nodes",
                "subject",
                "... on RepositoryAdvisory"
            ],
            "extensions":
            {
                "code": "undefinedType",
                "typeName": "RepositoryAdvisory"
            },
            "locations":
            [
                {
                    "line": 59,
                    "column": 15
                }
            ],
            "message": "No such type RepositoryAdvisory, so it can't be a fragment condition"
        },
        {
            "path":
            [
                "fragment InboxSubjectDiscussionFieldsFragment",
                "repository",
                "isOrganizationDiscussionRepository"
            ],
            "extensions":
            {
                "code": "undefinedField",
                "typeName": "Repository",
                "fieldName": "isOrganizationDiscussionRepository"
            },
            "locations":
            [
                {
                    "line": 119,
                    "column": 9
                }
            ],
            "message": "Field 'isOrganizationDiscussionRepository' doesn't exist on type 'Repository'"
        },
        {
            "path":
            [
                "fragment InboxSubjectRepositoryAdvisoryFieldsFragment"
            ],
            "extensions":
            {
                "code": "undefinedType",
                "typeName": "RepositoryAdvisory"
            },
            "locations":
            [
                {
                    "line": 150,
                    "column": 5
                }
            ],
            "message": "No such type RepositoryAdvisory, so it can't be a fragment condition"
        },
        {
            "path":
            [
                "fragment InboxSubjectRepositoryVulnerabilityAlertFieldsFragment",
                "permalink"
            ],
            "extensions":
            {
                "code": "undefinedField",
                "typeName": "RepositoryVulnerabilityAlert",
                "fieldName": "permalink"
            },
            "locations":
            [
                {
                    "line": 163,
                    "column": 7
                }
            ],
            "message": "Field 'permalink' doesn't exist on type 'RepositoryVulnerabilityAlert'"
        },
        {
            "path":
            [
                "fragment WebNotificationsEnabledFragment",
                "notificationSettings"
            ],
            "extensions":
            {
                "code": "undefinedField",
                "typeName": "User",
                "fieldName": "notificationSettings"
            },
            "locations":
            [
                {
                    "line": 259,
                    "column": 7
                }
            ],
            "message": "Field 'notificationSettings' doesn't exist on type 'User'"
        }
    ]
}
gh: No such type RepositoryAdvisory, so it can't be a fragment condition
Field 'isOrganizationDiscussionRepository' doesn't exist on type 'Repository'
No such type RepositoryAdvisory, so it can't be a fragment condition
Field 'permalink' doesn't exist on type 'RepositoryVulnerabilityAlert'
Field 'notificationSettings' doesn't exist on type 'User'

See Also

My Other Related Deepdive Gist's and Projects

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