Some notes on how to read GitHub notifications from the gh CLI.
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 ingh 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 withjq --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
orhtml/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 externalcolumn
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 extraljust
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(" ")' \ --paginateBoth 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))' \ --paginateWhich 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)
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 /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": ""
}
}
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
}
}
- https://github.com/cli/cli/blob/fe74349fe460cd80c21116eabd2753c0ba746f63/pkg/cmd/api/api.go#L277-L277
- https://github.com/cli/cli/blob/fe74349fe460cd80c21116eabd2753c0ba746f63/pkg/cmd/api/api.go#L683-L689
- https://github.com/cli/cli/blob/fe74349fe460cd80c21116eabd2753c0ba746f63/api/client.go#L17-L24
- https://github.com/cli/cli/blob/fe74349fe460cd80c21116eabd2753c0ba746f63/api/client.go#L54-L64
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'