Merge Request Thread via API

I’d like to use the Merge Request Discussions API to add a comment referencing a specific line of code on the branched side of the diff.

I’m using the python wrapper for the API, and my code looks something like:

file_to_comment = 'foo.py'
line_to_comment = 42

merge_request.discussions.create({
  'body': 'a comment',
  'position': {
    'base_sha': merge_request.diff_refs['base_sha'],
    'start_sha': merge_request.diff_refs['start_sha'],
    'head_sha': merge_request.diff_refs['head_sha'],
    'position': text,
    'new_path': file_to_comment,
    'new_line': line_to_comment,
    'old_path': file_to_comment,
    'old_line': line_to_comment,
  }
})

Depending on the situation, I’ll get an error response of:

line_code can’t be blank, must be a valid line code.

My understanding is that the old_path / old_line must match what gitlab computed as the values of that line on the left hand side of the diff. However, it’s unclear how I could even compute this given the APIs available in the Gitlab API.

Has anyone solved this or have ideas on how to approach it?

In my case, line_code and type are only necessary.

curl --request POST \
--header "PRIVATE-TOKEN: xxx" \
--header "Content-Type: application/json" \
--data '{
  "body": "multi-line comment",
  "position": {
    "base_sha": "base_sha",
    "start_sha": "start_sha",
    "head_sha": "head_sha",
    "old_path": "PathSame",
    "new_path": "PathSame",
    "position_type": "text",
    "old_line": null,
    "new_line": 4,
    "line_range": {
      "start": {
        "line_code": "sha1HasedPathSame_null_4",
        "type": "new",
      },
      "end": {
        "line_code": "sha1HasedPathSame_null_4",
        "type": "new",
      }
    }
  }
}' \
--url "https://gitlab.com/api/v4/projects/xxx/merge_requests/xxx/discussions"


curl --request POST \
--header "PRIVATE-TOKEN: xxxx" \
--header "Content-Type: application/json" \
--data '{
  "body": "multi-line comment",
  "position": {
    "base_sha": "base_sha",
    "start_sha": "start_sha",
    "head_sha": "head_sha",
    "old_path": "PathSame",
    "new_path": "PathSame",
    "position_type": "text",
    "old_line": null,
    "new_line": 44,
    "line_range": {
      "start": {
        "line_code": "sha1HasedPathSame_39_40",
        "type": "old",
      },
      "end": {
        "line_code": "sha1HasedPathSame_42_44",
        "type": "new",
      }
    }
  }
}' \
--url "https://gitlab.com/api/v4/projects/xxx/merge_requests/xxx/discussions"

@ggrothau
The document show the following structure.
After commenting on the differences in GitLab’s GUI, you can check the responses to the discussion in the developer tool for a clearer understanding.

{
  "old_line": 54, // Line number on the before-change side of the line where the comment is added
  "new_line": 60, // Line number on the after-change side of the line where the comment is added
  "line_range": {
    "start": {
      "line_code": "{file_path_fash}_51_58", // SHA1 hash of changed file path_start line number on before-change side of diff that comment targets (regardless of whether there are changes)_start line number on after-change side of diff that comment targets (regardless of whether there are changes)
      "type": "old", // "old" if the start line of the change diff that the comment targets is a deleted line, "new" if it's an added line, null if it's an unchanged line
      "old_line": 51, // Start line number on the before-change side of the diff that the comment targets. Null if the line has no changes
      "new_line": null // Start line number on the after-change side of the diff that the comment targets. Null if the line has no changes
    },
    "end": {
      "line_code": "{file_path_fash}_54_60", // SHA1 hash of changed file path_end line number on before-change side of diff that comment targets (regardless of whether there are changes)_end line number on after-change side of diff that comment targets (regardless of whether there are changes)
      "type": "old", // "old" if the end line of the change diff that the comment targets is a deleted line, "new" if it's an added line, null if it's an unchanged line
      "old_line": 54, // End line number on the before-change side of the diff that the comment targets. Null if the line has no changes
      "new_line": 60 // End line number on the after-change side of the diff that the comment targets. Null if the line has no changes
    }
  }
}