zyv4yk opened a new pull request, #9086:
URL: https://github.com/apache/devlake/pull/9086

   <!--
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at
   
       http://www.apache.org/licenses/LICENSE-2.0
   
   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
   
   ### ⚠️ Pre Checklist
   
   - [x] I have read through the [Contributing 
Documentation](https://devlake.apache.org/community/).
   - [x] I have added relevant tests.
   - [ ] I have added relevant documentation.
   - [x] I will add labels to the PR, such as `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 no `pull_requests.author_id` in the domain layer.
   
   `author`, `mergedBy` and review authors are typed `Actor` in the GitHub 
schema, and `Actor` is implemented by `User`, `Bot`, `Organization`, 
`Mannequin` and `EnterpriseUserAccount`. `GraphqlInlineAccountQuery` spread 
only `... on User`, so a `Bot` author came back as an empty selection set and 
the `Id == 0` guard in `extractGraphqlPreAccount` then 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.** 
`GraphqlInlineAccountQuery` is reused for fields the schema types as `User` — 
PR and issue assignees, and `commit.author.user` — and GitHub rejects the 
*entire* query when `... on Bot` is spread there:
   
   ```
   Fragment on Bot can't be spread inside User
   ```
   
   So this PR splits the two cases:
   
   - `GraphqlInlineAccountQuery` — unchanged shape, for `User`-typed fields 
(assignees, commit authors).
   - `GraphqlInlineActorQuery` — `... on User` + `... on Bot`, for 
`Actor`-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 `!= nil` checks at the call sites.
   
   Two details in the normalization:
   
   1. **`Bot.login` has no `[bot]` suffix.** GraphQL returns `dependabot`, REST 
returns `dependabot[bot]`, both with `databaseId` `49699333`. The suffix is 
appended so one actor does not end up with two logins depending on the 
collector. This also keeps the `is_bot` flag from #9000 working: its fallback 
is `strings.HasSuffix(login, "[bot]")`, and `_tool_github_accounts.type` is 
never populated on the GraphQL path.
   2. **`Bot` exposes a narrower field set** than `User` — no `name`, `company` 
or `email` — hence a separate `GithubBotEdge`. `Name`, `Company` and `Email` 
are left empty, which is exactly what the REST collector stores for a bot (`GET 
/users/dependabot[bot]` returns `null` for all three).
   
   One follow-on: `Collect Users` looks bot logins up through `user(login:)`, 
which resolves Users only and answers `Could 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_accounts` that would be one guaranteed 
`NOT_FOUND` per bot on every sync, so the cursor skips them. Bots still become 
accounts — `ConvertAccounts` reads `_tool_github_repo_accounts` and only 
enriches from `_tool_github_accounts` when 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 } }` on `grafana/grafana`:
   
   | | before | after |
   |---|---|---|
   | `#131864` | `""` / `0` | `cursor` / `206951365` |
   | `#131868` review authors | `""`, `""` | `github-actions`, `cursor` |
   | `#131851` review authors | `""`, `""`, `""` | 
`copilot-pull-request-reviewer`, `cursor`, `PranshulSoni` |
   
   The single-field version of the same check, which needs nothing but a token:
   
   ```
   gh api graphql -f query='
   {
     search(query: "repo:grafana/grafana is:pr author:app/dependabot", type: 
ISSUE, first: 1) {
       nodes { ... on PullRequest {
         number
         userFragmentOnly: author { ... on User { login databaseId } }
         withBotFragment:  author { __typename ... on User { login databaseId } 
... on Bot { login databaseId } }
       } }
     }
   }'
   
   {"number":131544,
    "userFragmentOnly":{},
    
"withBotFragment":{"__typename":"Bot","login":"dependabot","databaseId":49699333}}
   ```
   
   ### Other Information
   
   **Tests.** `account_graphql_pre_extractor_test.go` covers 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.ConstructQuery` output, asserting `... on Bot` reaches the actor 
fields and never the `User`-typed ones. `go build`, `go vet` and `golangci-lint 
run ./plugins/github_graphql/...` are clean. The `e2e` package needs 
`E2E_DB_URL` and was not run locally; the only `github_graphql` e2e 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`.
   


-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to