githubgraphqlgithub-apigithub-graphqlgithub-api-v4

Pull Request Review Comment wrong position from the diff?


I have a webhook that listen to all code reviews, then I fetch the comments of this PR review in order to get the position of the comment in the diff. I'm using the GitHub REST API, but the issue I have is the same with the GraphQL API.

So the workflow is:

  1. Get the review ID from the webhook
  2. Fetch the comment list of that review
  3. For each comment, get the diff hunk and the position to find the edited line

All of that works fine 99% of the time. Sometimes I get null in the position, I ignore these comments.

But this time, I get another weird issue. Usually, the position refers to the index of the line in the diff.

For example, in:

@@ -1 +1,3 @@
-# sedy-test
\\ No newline at end of file
+# sedy-test
+
+This repository is used to test [sedy](https://github.com/marmelab/sedy).

If the position is 3, the edited line is +# sedy-test.

The issue is that for some comments, I get a position that can't be inside the diff. As an example, see this PR.

When I try to fetch the comment position of the review with the following request:

{
  repository(owner: "Kmaschta", name: "comfygure") {
    pullRequest(number: 1) {
      reviews(last: 1) {
        edges {
          node {
            state
            comments(first: 1) {
              edges {
                node {
                  bodyText
                  authorAssociation
                  position
                  originalPosition
                  diffHunk
                }
              }
            }
          }
        }
      }
    }
  }
}

The response is the following:

{
  "data": {
    "repository": {
      "pullRequest": {
        "reviews": {
          "edges": [
            {
              "node": {
                "state": "COMMENTED",
                "comments": {
                  "edges": [
                    {
                      "node": {
                        "bodyText": "s/fot/for/",
                        "authorAssociation": "OWNER",
                        "position": 71,
                        "originalPosition": 71,
                        "diffHunk": "@@ -24,31 +34,39 @@ const ls = (ui, modules) => function* () {\n };\n \n const add = (ui, modules, options) => function* () {\n-    const { red, bold } = ui.colors;\n+    const { red, bold, green } = ui.colors;\n \n     if (!options.length) {\n         ui.error(`${red('No environment specified.')}`);\n-        help(ui, 1);\n     }\n \n     if (options.length > 1) {\n         ui.error(`${red('Invalid environment format. The environment name should be one word.')}`);\n-        help(ui, 1);\n+    }\n+\n+    if (options.length !== 1) {\n+        ui.print(`${bold('SYNOPSIS')}\n+        ${bold('comfy')} env add <environment>\n+\n+Type ${green('comfy env --help')} for details`);\n+\n+        return ui.exit(0);\n     }\n \n     const project = yield modules.project.retrieveFromConfig();\n     const environment = yield modules.environment.add(project, options[0]);\n-    const addCommand = `comfy add ${environment.name}`;\n+    const addCommand = `comfy setall ${environment.name}`;\n \n-    ui.print(`${bold('Cool!')} Your new environment \"${bold(environment.name)}\" was successfully saved.`);\n-    ui.print(`You can now add a configuration, try ${bold(addCommand)}`);\n+    ui.print(`${bold(green('Environment successfully created'))}`);\n+    ui.print(`You can now set a configuration fot this environment using ${bold(addCommand)}`);"
                      }
                    }
                  ]
                }
              }
            }
          ]
        }
      }
    }
  }
}

The position is 71, but the diff doesn't contain more than 40 lines.

So is it a bug if the GitHub API, or I didn't understand the point of the position field?

Note: I posted the same question on the GitHub forum.


Solution

  • From Github API comment doc :

    The position value equals the number of lines down from the first "@@" hunk header in the file you want to add a comment. The line just below the "@@" line is position 1, the next line is position 2, and so on. The position in the diff continues to increase through lines of whitespace and additional hunks until the beginning of a new file.

    Here diffHunk gives you the current diff hunk which is not necessary the first in the file

    If you get the full diff file it's more clear :

    curl "https://api.github.com/repos/Kmaschta/comfygure/pulls/1" \
         -H "Accept: application/vnd.github.v3.diff"
    

    The comment is in env.js whose first hunk starts at line 77, your comment is in line 148 while the diffHunk in your request starts at line 114

    I don't think it's possible to request the full PR diff using GraphQL at the moment but you can use Rest v3 as above