fix(github_graphql): resolve Bot actors so bot-authored PRs keep their author - #9086
Open
zyv4yk wants to merge 1 commit into
Open
fix(github_graphql): resolve Bot actors so bot-authored PRs keep their author#9086zyv4yk wants to merge 1 commit into
zyv4yk wants to merge 1 commit into
Conversation
…r author `author`, `mergedBy` and review authors are typed `Actor` in the GitHub schema, which `Bot` implements alongside `User`. The inline query spread only `... on User`, so every pull request, issue and review opened by a GitHub App, Dependabot or Renovate came back with an empty selection set and was stored with no author at all. `... on Bot` cannot simply be added to the existing query: GitHub rejects the whole request with "Fragment on Bot can't be spread inside User" when it is spread on a `User`-typed field such as assignees or a commit author. Actor fields therefore get their own GraphqlInlineActorQuery, and both types resolve through an Account() accessor. Bot logins are normalized to the `[bot]` suffix the REST collector stores, so an account keeps one identity across collectors, and the accounts lookup skips bot logins because `user(login:)` never resolves them. Fixes apache#9085 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
pr-type/bug-fix,pr-type/feature-development, etc.Summary
When the GitHub connection runs on GraphQL, every pull request, issue and review opened by an actor of type
Bot— GitHub Apps, Dependabot, Renovate, GitHub Actions — is stored with no author:author_name = '',author_id = 0, and nopull_requests.author_idin the domain layer.author,mergedByand review authors are typedActorin the GitHub schema, andActoris implemented byUser,Bot,Organization,MannequinandEnterpriseUserAccount.GraphqlInlineAccountQueryspread only... on User, so aBotauthor came back as an empty selection set and theId == 0guard inextractGraphqlPreAccountthen dropped the account. The REST collector is unaffected, which is why the same repo shows bot PRs on REST and none on GraphQL.The fragment cannot just be added to the existing struct.
GraphqlInlineAccountQueryis reused for fields the schema types asUser— PR and issue assignees, andcommit.author.user— and GitHub rejects the entire query when... on Botis spread there:So this PR splits the two cases:
GraphqlInlineAccountQuery— unchanged shape, forUser-typed fields (assignees, commit authors).GraphqlInlineActorQuery—... on User+... on Bot, forActor-typed fields (PullRequest.author,PullRequest.mergedBy,PullRequestReview.author,Issue.author).Both expose
Account() GithubAccountEdge, so the extractors read one normalized account and stop caring which type the actor resolved to. The accessor is nil-safe, which also removes the!= nilchecks at the call sites.Two details in the normalization:
Bot.loginhas no[bot]suffix. GraphQL returnsdependabot, REST returnsdependabot[bot], both withdatabaseId49699333. The suffix is appended so one actor does not end up with two logins depending on the collector. This also keeps theis_botflag from feat(dora): exclude bot/automation accounts from PR Pickup Time calcu… #9000 working: its fallback isstrings.HasSuffix(login, "[bot]"), and_tool_github_accounts.typeis never populated on the GraphQL path.Botexposes a narrower field set thanUser— noname,companyoremail— hence a separateGithubBotEdge.Name,CompanyandEmailare left empty, which is exactly what the REST collector stores for a bot (GET /users/dependabot[bot]returnsnullfor all three).One follow-on:
Collect Userslooks bot logins up throughuser(login:), which resolves Users only and answersCould not resolve to a User with the login of 'dependabot[bot]'. Errors there are already ignored, but now that bot logins reach_tool_github_repo_accountsthat would be one guaranteedNOT_FOUNDper bot on every sync, so the cursor skips them. Bots still become accounts —ConvertAccountsreads_tool_github_repo_accountsand only enriches from_tool_github_accountswhen a row exists.Does this close any open issues?
Closes #9085
Screenshots
Running the query this PR generates against the live API,
nodes { author { login databaseId } }ongrafana/grafana:#131864""/0cursor/206951365#131868review authors"",""github-actions,cursor#131851review authors"","",""copilot-pull-request-reviewer,cursor,PranshulSoniThe single-field version of the same check, which needs nothing but a token:
Other Information
Tests.
account_graphql_pre_extractor_test.gocovers the accessor for both query types (user, bot, bot login that already carries the suffix, unresolved actor, nil), the raw-layer JSON round trip in both the new and the pre-fix shape, and — the part that actually guards the regression —graphql.ConstructQueryoutput, asserting... on Botreaches the actor fields and never theUser-typed ones.go build,go vetandgolangci-lint run ./plugins/github_graphql/...are clean. Thee2epackage needsE2E_DB_URLand was not run locally; the onlygithub_graphqle2e fixture covers deployments, which this PR does not touch.Existing data. The author is already empty in
_raw_github_graphql_prs, so rows collected before this fix are not repaired by re-running extract or convert — they need a re-collect in Full Refresh mode.Labels. I do not have permission to set them; this is
pr-type/bug-fix.