Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions .github/workflows/lua.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,15 @@ jobs:
with:
neovim: true
version: ${{ matrix.nvim_version }}
- name: Install luajit
uses: leafo/gh-actions-lua@v10
- uses: leafo/gh-actions-lua@v11
with:
luaVersion: "luajit-openresty"
- name: Install luarocks
uses: leafo/gh-actions-luarocks@v4
- uses: hishamhm/gh-actions-luarocks@master
with:
luaRocksVersion: "3.12.0"
- name: build
run: |
luarocks install busted
- name: Run tests
shell: bash
run: |
Expand Down
131 changes: 110 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,40 @@
# gitlab.nvim
gitlab.nvim
===========
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @makbari. Your contribution is appreciated. Just a suggestion: These style changes don't seem to be necessary, they are not mentioned in the PR description, and so they make the review more difficult as the reviewer has to look for the substantial changes which are advertised in the description. So I think you might just as well revert the style changes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi there,
Sorry, i oversee this, it was automatic change via a plugin. a good reminder that i need to check the changes with more open eyes 👀


This Neovim plugin is designed to make it easy to review Gitlab MRs from within the editor. This means you can do things like:

- Create, approve, and merge MRs for the current branch
- Read and edit an MR description
- Add or remove reviewers and assignees
- Resolve, reply to, and unresolve discussion threads
- Create, edit, delete, and reply to comments
- View and manage pipeline Jobs
- Upload files, jump to the browser, and a lot more!
- Create, approve, and merge MRs for the current branch
- Read and edit an MR description
- Add or remove reviewers and assignees
- Resolve, reply to, and unresolve discussion threads
- Create, edit, delete, and reply to comments
- View and manage pipeline Jobs
- Upload files, jump to the browser, and a lot more!

![Screenshot 2024-12-08 at 5 43 53 PM](https://github.com/user-attachments/assets/cb9e94e3-3817-4846-ba44-16ec06ea7654)

https://github.com/harrisoncramer/gitlab.nvim/assets/32515581/dc5c07de-4ae6-4335-afe1-d554e3804372

To view these help docs and to get more detailed help information, please run `:h gitlab.nvim`

## Requirements
Requirements
------------

- <a href="https://go.dev/">Go</a> >= v1.19
- <a href="https://go.dev/">Go</a> >= v1.19

## Quick Start
Quick Start
-----------

1. Install Go
2. Add configuration (see Installation section)
3. Run `:lua require("gitlab").choose_merge_request()` or `:lua require("gitlab").review()` if already in review branch/worktree.
1. Install Go
2. Add configuration (see Installation section)
3. Run `:lua require("gitlab").choose_merge_request()` or `:lua require("gitlab").review()` if already in review branch/worktree.

This will checkout the branch locally, and open the plugin's reviewer pane.

For more detailed information about the Lua APIs please run `:h gitlab.nvim.api`

## Installation
Installation
------------

With <a href="https://github.com/folke/lazy.nvim">Lazy</a>:

Expand Down Expand Up @@ -73,11 +77,13 @@ And with <a href="https://github.com/lewis6991/pckr.nvim">pckr.nvim</a>:

Add `branch = "develop",` to your configuration if you want to use the (possibly unstable) development version of `gitlab.nvim`.

## Contributing
Contributing
------------

Contributions to the plugin are welcome. Please read [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md) before you start working on a pull request.

## Connecting to Gitlab
Connecting to Gitlab
--------------------

This plugin requires an <a href="https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token">auth token</a> to connect to Gitlab. The token can be set in the root directory of the project in a `.gitlab.nvim` environment file, or can be set via a shell environment variable called `GITLAB_TOKEN` instead. If both are present, the `.gitlab.nvim` file will take precedence.

Expand All @@ -97,10 +103,10 @@ gitlab_url=https://my-personal-gitlab-instance.com/

The plugin will look for the `.gitlab.nvim` file in the root of the current project by default. However, you may provide a custom path to the configuration file via the `config_path` option. This must be an absolute path to the directory that holds your `.gitlab.nvim` file.

In case even more control over the auth config is needed, there is the possibility to override the `auth_provider` settings field. It should be
a function that returns the `token` as well as the `gitlab_url` value, and a nilable error. If the `gitlab_url` is `nil`, `https://gitlab.com` is used as default.
In case even more control over the auth config is needed, there is the possibility to override the `auth_provider` settings field. It should be a function that returns the `token` as well as the `gitlab_url` value, and a nilable error. If the `gitlab_url` is `nil`, `https://gitlab.com` is used as default.

Here an example how to use a custom `auth_provider`:

```lua
require("gitlab").setup({
auth_provider = function()
Expand All @@ -111,13 +117,96 @@ require("gitlab").setup({

For more settings, please see `:h gitlab.nvim.connecting-to-gitlab`

## Configuring the Plugin
Configuring the Plugin
----------------------

The plugin expects you to call `setup()` and pass in a table of options. All of these values are optional, and if you call this function with no values the defaults will be used.

For a list of all these settings please run `:h gitlab.nvim.configuring-the-plugin` which will show you the help stored in [doc/gitlab.nvim.txt](doc/gitlab.nvim.txt).

## Keybindings
Keybindings
-----------

`gitlab.nvim` comes with a set of default `keymaps` for different contexts. You can override any of these in your configuration.

### Global Keymaps

These keymaps are available globally (i.e., in any buffer).

```
g? Open a help popup for local keymaps
glaa Add assignee
glad Delete assignee
glla Add label
glld Delete label
glra Add reviewer
glrd Delete reviewer
glA Approve MR
glR Revoke MR approval
glM Merge the feature branch to the target branch and close MR
glC Create a new MR for currently checked-out feature branch
glc Chose MR for review
glS Start review for the currently checked-out branch
gls Show the editable summary of the MR
glu Copy the URL of the MR to the system clipboard
glo Open the URL of the MR in the default Internet browser
gln Create a note (comment not linked to a specific line)
glp Show the pipeline status
gld Toggle the discussions window
glD Toggle between draft mode and live mode
glP Publish all draft comments/notes
```

#### Popup Keymaps

These `keymaps` are active in the popup windows (e.g., for creating comments, editing the summary, etc.).

```
<Tab> Cycle to the next field
<S-Tab> Cycle to the previous field
ZZ Perform action (e.g., save comment)
ZA Perform linewise action
ZQ Discard changes and quit the popup
```

#### Discussion Tree Keymaps

These `keymaps` are active in the discussion tree window.

```
Ea Add an emoji to the note/comment
Ed Remove an emoji from a note/comment
dd Delete comment
e Edit comment
r Reply to comment
- Toggle the resolved status of the whole discussion
o Jump to comment location in file
a Jump to the comment location in the reviewer window
b Jump to the URL of the current note/discussion
u Copy the URL of the current node to clipboard
c Toggle between the notes and discussions views
i Toggle type of discussion tree
P Publish the currently focused note/comment
dt Toggle between date formats
D Toggle between draft mode and live mode
st Toggle whether discussions are sorted by the "latest_reply", or by "original_comment"
t Open or close the discussion
T Open or close separately both resolved and unresolved discussions
R Open or close all resolved discussions
U Open or close all unresolved discussions
<C-R> Refresh the data in the view
<leader>p Print the current node (for debugging)
```

#### Reviewer Keymaps

These `keymaps` are active in the reviewer window (the diff view).

```
c Create a comment for the lines that the following {motion} moves over
s Create a suggestion for the lines that the following {motion} moves over
a Jump to the comment in the discussion tree
```

The plugin sets up a number of useful keybindings in the special buffers it creates, and some global keybindings as well. Refer to the relevant section of the manual `:h gitlab.nvim.keybindings` for more details.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should merge this line with the information under the Keybindings heading.


Expand Down
5 changes: 3 additions & 2 deletions after/syntax/gitlab.vim
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ endif
let expanders = '^\s*\%(' . g:gitlab_discussion_tree_expander_open . '\|' . g:gitlab_discussion_tree_expander_closed . '\)'
let username = '@[a-zA-Z0-9.]\+'

" Covers times like '14 days ago', 'just now', as well as 'October 3, 2024'
" Covers times like '14 days ago', 'just now', as well as 'October 3, 2024', and '02/28/2025 at 00:50'
let time_ago = '\d\+ \w\+ ago'
let formatted_date = '\w\+ \{1,2}\d\{1,2}, \d\{4}'
let date = '\%(' . time_ago . '\|' . formatted_date . '\|just now\)'
let absolute_time = '\d\{2}/\d\{2}/\d\{4} at \d\{2}:\d\{2}'
let date = '\%(' . time_ago . '\|' . formatted_date . '\|' . absolute_time . '\|just now\)'

let published = date . ' \%(' . g:gitlab_discussion_tree_resolved . '\|' . g:gitlab_discussion_tree_unresolved . '\|' . g:gitlab_discussion_tree_unlinked . '\)\?'
let state = ' \%(' . published . '\|' . g:gitlab_discussion_tree_draft . '\)'
Expand Down
15 changes: 12 additions & 3 deletions cmd/app/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"net/http"
"net/url"

"github.com/harrisoncramer/gitlab.nvim/cmd/app/git"
"github.com/hashicorp/go-retryablehttp"
Expand Down Expand Up @@ -66,10 +67,18 @@ func NewClient() (*Client, error) {
},
}

if proxy := pluginOptions.ConnectionSettings.Proxy; proxy != "" {
u, err := url.Parse(proxy)
if err != nil {
return nil, fmt.Errorf("parse proxy url: %w", err)
}
tr.Proxy = http.ProxyURL(u)
}

retryClient := retryablehttp.NewClient()
retryClient.HTTPClient.Transport = tr
retryClient.RetryMax = 0
gitlabOptions = append(gitlabOptions, gitlab.WithHTTPClient(retryClient.HTTPClient))
gitlabOptions = append(gitlabOptions, gitlab.WithoutRetries())

client, err := gitlab.NewClient(pluginOptions.AuthToken, gitlabOptions...)

Expand Down Expand Up @@ -99,11 +108,11 @@ func InitProjectSettings(c *Client, gitInfo git.GitData) (*ProjectInfo, error) {
project, _, err := c.GetProject(gitInfo.ProjectPath(), &opt)

if err != nil {
return nil, fmt.Errorf(fmt.Sprintf("Error getting project at %s", gitInfo.RemoteUrl), err)
return nil, fmt.Errorf("error getting project at %s: %w", gitInfo.RemoteUrl, err)
}

if project == nil {
return nil, fmt.Errorf(fmt.Sprintf("Could not find project at %s", gitInfo.RemoteUrl), err)
return nil, fmt.Errorf("could not find project at %s", gitInfo.RemoteUrl)
}

projectId := fmt.Sprint(project.ID)
Expand Down
8 changes: 7 additions & 1 deletion cmd/app/comment_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,19 @@ type RequestWithPosition interface {
func buildCommentPosition(commentWithPositionData RequestWithPosition) *gitlab.PositionOptions {
positionData := commentWithPositionData.GetPositionData()

// If the file has been renamed, then this is a relevant part of the payload
oldFileName := positionData.OldFileName
if oldFileName == "" {
oldFileName = positionData.FileName
}

opt := &gitlab.PositionOptions{
PositionType: &positionData.Type,
StartSHA: &positionData.StartCommitSHA,
HeadSHA: &positionData.HeadCommitSHA,
BaseSHA: &positionData.BaseCommitSHA,
NewPath: &positionData.FileName,
OldPath: &positionData.OldFileName,
OldPath: &oldFileName,
NewLine: positionData.NewLine,
OldLine: positionData.OldLine,
}
Expand Down
1 change: 1 addition & 0 deletions cmd/app/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type PluginOptions struct {
} `json:"debug"`
ChosenMrIID int `json:"chosen_mr_iid"`
ConnectionSettings struct {
Proxy string `json:"proxy"`
Insecure bool `json:"insecure"`
Remote string `json:"remote"`
} `json:"connection_settings"`
Expand Down
3 changes: 3 additions & 0 deletions doc/gitlab.nvim.txt
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ you call this function with no values the defaults will be used:
},
},
connection_settings = {
proxy = "", -- Configure a proxy URL to use when connecting to GitLab. Supports URL schemes: http, https, socks5
insecure = false, -- Like curl's --insecure option, ignore bad x509 certificates on connection
remote = "origin", -- The default remote that your MRs target
},
Expand Down Expand Up @@ -213,6 +214,7 @@ you call this function with no values the defaults will be used:
switch_view = "c", -- Toggle between the notes and discussions views
toggle_tree_type = "i", -- Toggle type of discussion tree - "simple", or "by_file_name"
publish_draft = "P", -- Publish the currently focused note/comment
toggle_date_format = "dt", -- Toggle between date formats: relative (e.g., "5 days ago", "just now", "October 13, 2024" for dates more than a month ago) and absolute (e.g., "03/01/2024 at 11:43")
toggle_draft_mode = "D", -- Toggle between draft mode (comments posted as drafts) and live mode (comments are posted immediately)
toggle_sort_method = "st", -- Toggle whether discussions are sorted by the "latest_reply", or by "original_comment", see `:h gitlab.nvim.toggle_sort_method`
toggle_node = "t", -- Open or close the discussion
Expand Down Expand Up @@ -267,6 +269,7 @@ you call this function with no values the defaults will be used:
draft = "✎", -- Symbol to show next to draft comments/notes
tree_type = "simple", -- Type of discussion tree - "simple" means just list of discussions, "by_file_name" means file tree with discussions under file
draft_mode = false, -- Whether comments are posted as drafts as part of a review
relative_date = true, -- Whether to show relative time like "5 days ago" or absolute time like "03/01/2025 at 01:43"
winbar = nil, -- Custom function to return winbar title, should return a string. Provided with WinbarTable (defined in annotations.lua)
-- If using lualine, please add "gitlab" to disabled file types, otherwise you will not see the winbar.
},
Expand Down
65 changes: 25 additions & 40 deletions lua-test.sh
Original file line number Diff line number Diff line change
@@ -1,59 +1,44 @@
#!/usr/bin/env bash
#
# Setup and run tests for lua part of gitlab.nvim.
#
# In order to run tests you need to have `luarocks` and `git` installed. This script will check if
# environment is already setup, if not it will initialize current directory with `luarocks`,
# install `busted` framework and download plugin dependencies.
#
# Requires `luarocks`, `git`, and `nvim` installed.
#
set -e

LUA_VERSION="5.1"
set -euo pipefail

PLUGINS_FOLDER="tests/plugins"
PLUGINS=(
"https://github.com/MunifTanjim/nui.nvim"
"https://github.com/nvim-lua/plenary.nvim"
"https://github.com/sindrets/diffview.nvim"
"https://github.com/MunifTanjim/nui.nvim"
"https://github.com/nvim-lua/plenary.nvim"
"https://github.com/sindrets/diffview.nvim"
)

if ! command -v luarocks > /dev/null 2>&1; then
echo "You need to have luarocks installed in order to run tests."
exit 1
fi

if ! command -v git > /dev/null 2>&1; then
echo "You need to have git installed in order to run tests."
exit 1
if ! command -v luarocks >/dev/null 2>&1; then
echo "Error: luarocks not found. Please install LuaRocks." >&2
exit 1
fi

if ! luarocks --lua-version=$LUA_VERSION which busted > /dev/null 2>&1; then
echo "Installing busted."
luarocks init
luarocks config --scope project lua_version "$LUA_VERSION"
luarocks install --lua-version="$LUA_VERSION" busted
if ! command -v git >/dev/null 2>&1; then
echo "Error: git not found. Please install Git." >&2
exit 1
fi

for arg in "$@"; do
if [[ $arg =~ "--coverage" ]] && ! luarocks --lua-version=$LUA_VERSION which luacov > /dev/null 2>&1; then
luarocks install --lua-version="$LUA_VERSION" luacov
# lcov reporter for luacov - lcov format is supported by `nvim-coverage`
luarocks install --lua-version="$LUA_VERSION" luacov-reporter-lcov
if ! command -v nvim >/dev/null 2>&1; then
echo "Error: nvim not found. Please install Neovim." >&2
exit 1
fi
done

# Clone test plugin dependencies
mkdir -p "$PLUGINS_FOLDER"
for plugin in "${PLUGINS[@]}"; do
plugin_name=${plugin##*/}
plugin_folder="$PLUGINS_FOLDER/$plugin_name"

# Check if plugin was already downloaded
if [[ -d "$plugin_folder/.git" ]]; then
# We could also try to pull here but I am not sure if that wouldn't slow down tests too much.
continue
fi

plugin_name="${plugin##*/}"
plugin_folder="$PLUGINS_FOLDER/$plugin_name"
if [[ ! -d "$plugin_folder/.git" ]]; then
echo "Cloning $plugin..."
git clone --depth 1 "$plugin" "$plugin_folder"

fi
done

nvim -u NONE -U NONE -N -i NONE -l tests/init.lua "$@"
# Run tests
echo "Running tests with Neovim..."
nvim -u NONE -U NONE -N -i NONE -l tests/init.lua "$@"
Loading