Create POC for MR review feature

### Problem to solve

Before we implement #53, we'd like to validate certain assumptions like:

- GitLab API provides us with the MR diff file content and comments in an easy-to-consume format
- VS Code Extension API allows for easy integration of the GitLab API results with the diff view

### Proposal

Implement POC that can:

1. Show files that have been changed in the MR
1. For each one of those files shows a diff view between merge-base and the MR branch
1. Display comments from the MR diff
1. Allow creating comments on the diff

# Report from POC implementation

This report is a summary of the POC work. It will try to explain what uncertainties we've removed and discovered.

![_Extension_Development_Host__-_test_js__MR____test-project_and_mr_item_js___gitlab-vscode-extension_and_zsh](https://gitlab.com/gitlab-org/gitlab-vscode-extension/uploads/e641142e889443c1118f8a5ab49a0f92/_Extension_Development_Host__-_test_js__MR____test-project_and_mr_item_js___gitlab-vscode-extension_and_zsh.png)

## Try it yourself

Straight to the fun bit, try it yourself by installing the [packaged extension with POC](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/raw/mr-review-poc/gitlab-workflow-3.6.0.vsix?inline=false) ([how to install](https://stackoverflow.com/questions/37071388/how-can-i-install-visual-studio-code-extensions-offline))

**Caveat: All MR refs (commits) need to be available locally (run `git pull` before trying the POC)**

I've tested the POC on `gitlab-org/gitlab` project and it seemed to work for most of the MR's.

The messy code is available in [`mr-review-poc` branch](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/tree/mr-review-poc).

## Features:

### File tree:

![_Extension_Development_Host__-_index_md___gitlab](https://gitlab.com/gitlab-org/gitlab-vscode-extension/uploads/7dc75673aba70492f162abc2f095bf00/_Extension_Development_Host__-_index_md___gitlab.png)

#### Certainty overview

- Dependencies available and working: **4/5**
  - REST API ✅, GraphQL ❌
- VS Code API suits our needs: **4.5/5**
  - Only the Git Changed status indicator is unavailable to us.
- The codebase is ready for implementation: **3/5**
  - Tree view cleanup necessary before starting

#### Details

There is no custom UI involved; we are going to utilise the VS Code API.

We can get necessary information about the changed files from the REST API ([MR version](https://docs.gitlab.com/ee/api/merge_requests.html#get-a-single-mr-diff-version)). The GraphQL API can't provide us with the necessary information (https://gitlab.com/gitlab-org/gitlab/-/issues/280803).

Creating the file tree seems straight forward, the only thing I wasn't able to achieve vas to show the Git Changed status indicator:

![_Extension_Development_Host__-_snippet_blob_actions_edit_vue___gitlab](https://gitlab.com/gitlab-org/gitlab-vscode-extension/uploads/3637bb847c89d94b70cc4157bdf9c3b7/_Extension_Development_Host__-_snippet_blob_actions_edit_vue___gitlab.png)

The API seems not to be officially exposed.

When talking about the design, we'll have to decide between two ways of showing the changes:

| Tree | Path in the item detail |
| ------ | ------ |
| ![constants_ts___gitlab-vscode-extension](https://gitlab.com/gitlab-org/gitlab-vscode-extension/uploads/bc8cbe08ad4bc90054dca50a6ce9a525/constants_ts___gitlab-vscode-extension.png) | ![constants_ts___gitlab-vscode-extension](https://gitlab.com/gitlab-org/gitlab-vscode-extension/uploads/436d38db17c1a2d0d980c53a9eaabc43/constants_ts___gitlab-vscode-extension.png) |

#### Known issues and uncertainty

- The current code ([issuable.js](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/src/data_providers/issuable.js) and [sidebar\_tree\_item.js](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/src/data_providers/sidebar_tree_item.js) will need a cleanup before we can start build on topo of it.
- We'll probably always work with the last MR version and will ignore the intermediate versions.
- We might want to start showing Merge Requests differently from issues in the Tree View. Also we might want to choose icons for all tree items.

### File Diff View

![_Extension_Development_Host__-_terraform_list_vue__MR____gitlab_and_Add__Ability_to_chec______gitlab-vscode-extension_and_zsh](https://gitlab.com/gitlab-org/gitlab-vscode-extension/uploads/8731b1c3adb85de00977d0a4edbfdeb5/_Extension_Development_Host__-_terraform_list_vue__MR____gitlab_and_Add__Ability_to_chec______gitlab-vscode-extension_and_zsh.png)

#### Certainty overview

- Dependencies available and working: **3/5**
  - fetching remote content has not been tested
- VS Code API suits our needs: **5/5**
- The codebase is ready for implementation: **2/5**
  - It would be best to slowly shift Git related responsibility to VS Code (instead of running shell command)

#### Details

VS Code provides us with the diff functionality, the only thing we do is defining a custom document URI and then implement content providers for that URI.

Uri:

```
"gl-review://authority/app/assets/javascripts/terraform/graphql/queries/get_states.query.graphql?commit%3D5fa9332d0cedb98b0095b34d01470e419d3a98ba%26workspace%3D%2FUsers%2Ftomas%2Fworkspace%2Fgitlab%2Fgitlab-development-kit%2Fgitlab%26version%3Dbase"
```

When VS Code tries to open our URI, it will invoke our content provider, which returns a `string` content of the file. The POC implements only the local git content provider, which means that the file version (correct commit) needs to be in the local git repository. The proper implementation is going to implement a fallback provider which will fetch the content from the API.

```mermaid
graph LR
A[VS Code] -- "gl-review: URI" --> B[LocalGitContentProvider]
B --> C[RemoteApiContentProvider]
```

The future-proof way to interact with `git` is to use the VS Code core extension for Git (originally suggested in !54). It is how most of git-related extensions work. The added benefit is that everything git related (VS Code VCS view, other extensions, our extension) is going to be in sync. This will require a bit of plumbing implementation, potentially overlapping with [Consistent handling of remotes, instances and branches](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues/260).

#### Known issues and uncertainty

- I haven't implemented the API file content provider and so we don't have 100% certainty that we can retrieve the content.
- I'm not sure how are we going to react to remote changes. For example, when the user refreshes the file tree and all of a sudden the displayed diff doesn't correspond with the latest version.
- I'm not sure if there is a difference in how we'll use API to fetch file content from forked projects
- **Images** - VS Code can show images in tabs, but the POC haven't done any exploration of how that works.

### Showing existing comments

![_Extension_Development_Host__-_test_js__MR____test-project](https://gitlab.com/gitlab-org/gitlab-vscode-extension/uploads/53a54bf961c2845edf5d527771348e5a/_Extension_Development_Host__-_test_js__MR____test-project.png)

#### Certainty overview

- Dependencies available and working: **5/5**
- VS Code API suits our needs: **4/5**
  - GitLab-specific highlighting like #243, !54 and @viktomas is not going to work
  - images and advanced Markdown syntax (mermaidjs) is not working out of the box and maybe not at all
- The codebase is ready for implementation: **5/5**
  - This is going to be a greenfield development.

#### Details

This feature is going to use GraphQL, so far it seems to be the only endpoint that's going to work out of the box.

<details>
<summary>See the full GrapQL query</summary>

```graphql
 query GetDiscussions($projectPath: ID!, $iid: String!) {
    project(fullPath: $projectPath) {
      mergeRequest(iid: $iid) {
        discussions {
          nodes {
            notes {
              nodes {
                body
                author {
                  name
                  avatarUrl
                }
                position {
                  diffRefs {
                    baseSha
                    headSha
                  }
                  filePath
                  positionType
                  newLine
                  oldLine
                  newPath
                  oldPath
                }
              }
            }
          }
        }
      }
    }
  }
```

</details>

The VS Code API allows us to add comments for our custom URI. This seems to work really well (and potentially handles automatically comments on outdated diffs). Each comment has a `body` (markdown string) and Author information. We create the commits as follows:

```js
commentController.createCommentThread(
  getReviewUri({
    path,
    commit,
    workspace: this.projectUri,
    version: old ? 'base' : 'head',
  }),
  new vscode.Range(vsPosition, vsPosition),
  comments,
);
```

#### Known issues and uncertainty

- **I assumed the following about the GrapQL response**
  - Each GitLab comment has a `diffRefs` and I assume they always point to the latest MR version (even if the comment was made on the previous version).
- The POC didn't validate editing or deleting existing comments. 
- Reactions to the comments are possible but weren't part of the POC.
- As mentioned in the "Certainty overview", some markdown might be not rendering correctly
- The comments can range over multiple files (according to the API) but it hasn't been tested

### ⚠️Creating new review comments⚠️

![pullRequestNode_ts__Pull_Request____vscode-pull-request-github](https://gitlab.com/gitlab-org/gitlab-vscode-extension/uploads/d9dcfad2c415cfd1e651592733fbd400/pullRequestNode_ts__Pull_Request____vscode-pull-request-github.png)

#### Certainty overview

- Dependencies available and working: **1/5**
  - I wasn't able to reliably create a comment (note) on GitLab MR through our API.
- VS Code API suits our needs: **3/5**
  - It should because other extensions work, but parts of the API are not officially documented.
- The codebase is ready for implementation: **5/5**
  - This is going to be a greenfield development.

#### Details

First, we tell the VS Code where in the file can we create comments. VS Code provides an API for that: [CommentingRangeProvider](https://code.visualstudio.com/api/references/vscode-api#CommentingRangeProvider). This provider gets a URI and returns ranges of lines where it is possible to comment.

My understanding is that on an MR Diff, we can comment on any (even not changed) line in the left-hand side of the diff and only on changed lines in the right-hand side:

![Update_test_js_take_2___2____Merge_Requests___Tomas_Vik___test_project___GitLab](https://gitlab.com/gitlab-org/gitlab-vscode-extension/uploads/5872be9dc8cd3e79bfa6b32adc34ffc7/Update_test_js_take_2___2____Merge_Requests___Tomas_Vik___test_project___GitLab.png)

When we have the commenting ranges, the user can click on the commenting gutter and start a comment:

![_Extension_Development_Host__-_test_js__MR____test-project](https://gitlab.com/gitlab-org/gitlab-vscode-extension/uploads/3cb38bd8a5b1a7ac572c22b4a562d38d/_Extension_Development_Host__-_test_js__MR____test-project.png)

The buttons on the comment are custom defined and can have arbitrary functionality (Comment now, Add to review). This configuration is done in [package.json](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/mr-review-poc/package.json#L142) and **it is not officially documented**.

#### GitLab API problem

We are not dogfooding our REST or GraphQL APIs for our code review on GitLab website. I wasn't able to create a new comment through our API in two days. Partly because I'm unfamiliar with the domain and partly because the documentation is quite brief. I faced several bugs (https://gitlab.com/gitlab-org/gitlab/-/issues/281143 and one similar to https://gitlab.com/gitlab-org/gitlab/-/issues/37066) that I need to debug further before I can report them.

Without further investigation, I can't tell whether there is a way of implementing creating comments from VS Code or whether we need to implement/update/fix API endpoints first.

#### Known issues and uncertainty

- The POC didn't implement adding comments and so there is large uncertainty.
- I'm also not familiar with the MR Review workflows to be able to foresee any edge cases.
- Large part of the comment functionality is undocumented and we might result in using [vscode-pull-request-github](https://github.com/microsoft/vscode-pull-request-github) as documentation (it's good that it is under MIT license).

### Local git manipulation (e.g. Check out MR branch)

I wasn't able to include this in POC.
<!-- triage-serverless v3 PLEASE DO NOT REMOVE THIS SECTION -->
*This page may contain information related to upcoming products, features and functionality.
It is important to note that the information presented is for informational purposes only, so please do not rely on the information for purchasing or planning purposes.
Just like with all projects, the items mentioned on the page are subject to change or delay, and the development, release, and timing of any products, features, or functionality remain at the sole discretion of GitLab Inc.*
<!-- triage-serverless v3 PLEASE DO NOT REMOVE THIS SECTION -->

Story points: 3.0