You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@devlake.apache.org by "zyv4yk (via GitHub)" <gi...@apache.org> on 2026/08/31 17:35:22 UTC

[I] [Bug][github_graphql] PR/issue author is empty for Bot actors (GitHub Apps, Dependabot) — GraphQL query only spreads "... on User" [devlake]

zyv4yk opened a new issue, #9085:
URL: https://github.com/apache/devlake/issues/9085

   ### Search before asking
   
   - [x] I had searched in the issues and found no similar issues.
   
   ### What happened
   
   When the GitHub connection has `Use GraphQL APIs` enabled, every pull request, issue and review opened by an actor of GraphQL type `Bot` (GitHub Apps, Dependabot, Renovate, GitHub Actions, any AI code-review or automation app) is stored with an **empty author**: `author_name = ''` and `author_id = 0` in `_tool_github_pull_requests`, and no `pull_requests.author_id` in the domain layer.
   
   The data is already empty in the raw layer, so it cannot be recovered by re-running the extractor:
   
   ```json
   "Author": {"Login": "", "Id": 0, "Name": "", "Company": "", "Email": "", ...}
   ```
   
   Root cause is in `backend/plugins/github_graphql/tasks/account_graphql_pre_extractor.go`:
   
   ```go
   type GraphqlInlineAccountQuery struct {
   	GithubAccountEdge `graphql:"... on User"`
   }
   
   func extractGraphqlPreAccount(result *[]interface{}, res *GraphqlInlineAccountQuery, repoId int, connId uint64) {
   	if res == nil || res.Id == 0 {
   		return
   	}
   ```
   
   `author`, `mergedBy`, `assignees` and review authors are all typed as `Actor` in the GitHub schema. `Actor` is implemented by `User`, **`Bot`**, `Organization`, `Mannequin` and `EnterpriseUserAccount`. The query spreads only `... on User`, so for any non-`User` actor GitHub returns an empty selection set, and the `res.Id == 0` guard then drops the account entirely.
   
   The REST collector is not affected — it resolves bot authors correctly — which is why a connection using GraphQL shows almost no bot-authored PRs while a REST one does.
   
   ### What do you expect to happen
   
   PRs, issues and reviews opened by GitHub Apps / bots should carry their author, with the same identity the REST collector produces (`dependabot[bot]`, id `49699333`), so that `accounts` rows, `pull_requests.author_id` and any bot-aware metric work the same regardless of which collector is used.
   
   ### How to reproduce
   
   The behaviour can be shown against the GitHub API directly, no DevLake instance needed. This query mirrors what the plugin sends today (`userFragmentOnly`) next to what it should send (`withBotFragment`):
   
   ```bash
   gh api graphql -f query='
   {
     search(query: "repo:grafana/grafana is:pr author:app/dependabot", type: ISSUE, first: 2) {
       nodes {
         ... on PullRequest {
           number
           userFragmentOnly: author { ... on User { login databaseId } }
           withBotFragment:  author { __typename ... on User { login databaseId } ... on Bot { login databaseId } }
         }
       }
     }
   }'
   ```
   
   Result:
   
   ```json
   {"number":131544,
    "userFragmentOnly":{},
    "withBotFragment":{"__typename":"Bot","login":"dependabot","databaseId":49699333}}
   ```
   
   End to end:
   
   1. Create a GitHub connection with `Use GraphQL APIs` enabled, scoped to a repo that receives Dependabot/Renovate/GitHub App PRs.
   2. Run the blueprint.
   3. `SELECT number, author_name, author_id FROM _tool_github_pull_requests WHERE author_name = '';` — every bot-authored PR is listed.
   4. Repeat with `Use GraphQL APIs` disabled: the same PRs come back with `dependabot[bot]` / `49699333`.
   
   ### Anything else
   
   Happens every time, for every bot-authored PR, on every repo. In our deployment roughly 1,000 PRs opened by our own GitHub App over the last eight months are unattributed, and all 18 bot accounts in `_tool_github_accounts` (collected from comments and reviews) have zero PRs linked to them.
   
   Two details worth knowing before writing the fix:
   
   **1. `Bot` has a different field set than `User`.** It exposes `login`, `databaseId`, `avatarUrl`, `url`, `createdAt`, `updatedAt` — but no `name`, `company` or `email`. `GithubAccountEdge` cannot be reused as-is; a separate struct plus a small normalisation step is needed:
   
   ```go
   type GithubBotEdge struct {
   	Login     string
   	Id        int `graphql:"databaseId"`
   	AvatarUrl string
   	HtmlUrl   string `graphql:"url"`
   }
   
   type GraphqlInlineAccountQuery struct {
   	GithubAccountEdge `graphql:"... on User"`
   	Bot               GithubBotEdge `graphql:"... on Bot"`
   }
   ```
   
   The named-field-with-inline-fragment-tag pattern is already used in this codebase for `RequestedReviewer` (#7716), so the client handles it.
   
   **2. `Bot.login` omits the `[bot]` suffix.** GraphQL returns `dependabot`, REST returns `dependabot[bot]`; the `databaseId` is the same `49699333` in both, so there is no risk of duplicate accounts, but the logins would diverge between collectors.
   
   This matters for the `is_bot` flag added in #9000: the fallback is `strings.HasSuffix(githubUser.Login, "[bot]")`, and `_tool_github_accounts.type` is never populated on the GraphQL path (`GithubAccountEdge` has no `Type` field, and `extractGraphqlPreAccount` only writes `GithubRepoAccount`). So a naive fix would produce bot accounts that `is_bot` cannot detect. The normalisation should append `[bot]` to match REST, and ideally set `Type: "Bot"` on the `GithubAccount` row.
   
   It also interacts with #8886 / #8894: `pr_convertor.go` now guards `if pr.AuthorId != 0` before generating the account id, so as long as the author stays empty these PRs will keep having no `author_id` by design — the fix has to happen at collection time.
   
   Existing data cannot be repaired by re-running extract or convert; a **Full Refresh** re-collect is required, since the author is already empty in `_raw_github_graphql_prs`.
   
   Same fix applies to `mergedBy`, which is currently empty for merges performed by a bot.
   
   ### Version
   
   Verified on `main` @ `79ef9f4f`; the code is unchanged since #8583 (2025-09-24) and is present in `v1.0.3-beta16`.
   
   ### Are you willing to submit PR?
   
   - [x] Yes I am willing to submit a PR!
   
   ### Code of Conduct
   
   - [x] I agree to follow this project's [Code of Conduct](https://www.apache.org/foundation/policies/conduct)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@devlake.apache.org.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [I] [Bug][github_graphql] PR/issue author is empty for Bot actors (GitHub Apps, Dependabot) — GraphQL query only spreads "... on User" [devlake]

Posted by "klesh (via GitHub)" <gi...@apache.org>.
klesh closed issue #9085: [Bug][github_graphql] PR/issue author is empty for Bot actors (GitHub Apps, Dependabot) — GraphQL query only spreads "... on User"
URL: https://github.com/apache/devlake/issues/9085


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@devlake.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [I] [Bug][github_graphql] PR/issue author is empty for Bot actors (GitHub Apps, Dependabot) — GraphQL query only spreads "... on User" [devlake]

Posted by "zyv4yk (via GitHub)" <gi...@apache.org>.
zyv4yk commented on issue #9085:
URL: https://github.com/apache/devlake/issues/9085#issuecomment-5482335515

   Correction to the fix sketch above: the struct shape I proposed does not work, and the PR takes a different route.
   
   `GraphqlInlineAccountQuery` is not used only for `Actor` fields. It is also used where the schema says `User` — PR and issue assignees, and `commit.author.user`. Spreading `... on Bot` on those makes GitHub reject the entire query:
   
   ```
   gh api graphql -f query='
   { repository(owner:"grafana", name:"grafana") { pullRequest(number:131544) {
     assignees(first:1){ nodes { ... on User { login } ... on Bot { login } } } } } }'
   
   {"errors":[{"extensions":{"code":"cannotSpreadFragment","typeName":"Bot","parentName":"User"},
     "message":"Fragment on Bot can't be spread inside User"}]}
   ```
   
   Same error on `commits.nodes.commit.author.user`. So adding the fragment to the existing type would not just miss the fix, it would break PR and issue collection outright.
   
   #9086 splits it in two instead: `GraphqlInlineAccountQuery` keeps its current `User`-only shape, and a new `GraphqlInlineActorQuery` carries `... on User` + `... on Bot` for the four genuinely `Actor`-typed fields (`PullRequest.author`, `PullRequest.mergedBy`, `PullRequestReview.author`, `Issue.author`). Both expose an `Account()` accessor so the extractors read one normalized account.
   
   The rest of the report stands, including the `[bot]` suffix difference between `Bot.login` and the REST login.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@devlake.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org