diff --git a/README.md b/README.md index f000c72..ba388d4 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,9 @@ 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, edit, and delete comments on an MR -- Reply to exisiting comments -- Read MR summaries -- Approve an MR -- Revoke approval for an MR +- Create, edit, delete, and reply to comments on an MR +- Read and Edit an MR description +- Approve/Revoke Approval for an MR https://github.com/harrisoncramer/gitlab.nvim/assets/32515581/dfd3aa8a-6fc4-4e43-8d2f-489df0745822 @@ -58,7 +56,7 @@ This plugin requires a `.gitlab.nvim` file in the root of the local Gitlab direc ``` project_id=112415 auth_token=your_gitlab_token -gitlab_url=https://my-personal-gitlab-instance.com +gitlab_url=https://my-personal-gitlab-instance.com/ ``` If you don't want to write your authentication token into a dotfile, you may provide it as a shell variable. For instance in your `.bashrc` or `.zshrc` file: @@ -72,7 +70,7 @@ By default, the plugin will interact with MRs against a "main" branch. You can c ``` project_id=112415 auth_token=your_gitlab_token -gitlab_url=https://my-personal-gitlab-instance.com +gitlab_url=https://my-personal-gitlab-instance.com/ base_branch=master ``` @@ -88,7 +86,7 @@ require("gitlab").setup({ keymaps = { popup = { -- The popup for comment creation, editing, and replying exit = "", - perform_action = "s", -- Once in normal mode, does action + perform_action = "s", -- Once in normal mode, does action (like saving comment or editing description, etc) }, discussion_tree = { -- The discussion tree that holds all comments jump_to_location = "o", @@ -118,12 +116,15 @@ First, check out the branch that you want to review locally. git checkout feature-branch ``` -Then open Neovim and the reviewer will be initialized. The `project_id` you specify in your configuration file must match the project_id of the Gitlab project your terminal is inside of. The `summary` command will pull down the MR description into a buffer so that you can read it: +Then open Neovim and the reviewer will be initialized. The `project_id` you specify in your configuration file must match the project_id of the Gitlab project your terminal is inside of. + +The `summary` command will pull down the MR description into a buffer so that you can read it. To edit the description, edit the buffer and press the `perform_action` keybinding when in normal mode (it's `s` by default): ```lua require("gitlab").summary() ``` + The `approve` command will approve the merge request for the current branch: ```lua diff --git a/cmd/main.go b/cmd/main.go index 1d8a368..cf25c1a 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -29,6 +29,7 @@ func main() { } m := http.NewServeMux() + m.Handle("/mr", withGitlabContext(http.HandlerFunc(UpdateHandler), c)) m.Handle("/approve", withGitlabContext(http.HandlerFunc(ApproveHandler), c)) m.Handle("/revoke", withGitlabContext(http.HandlerFunc(RevokeHandler), c)) m.Handle("/info", withGitlabContext(http.HandlerFunc(InfoHandler), c)) diff --git a/cmd/update.go b/cmd/update.go new file mode 100644 index 0000000..dd7c61d --- /dev/null +++ b/cmd/update.go @@ -0,0 +1,74 @@ +package main + +import ( + "encoding/json" + "errors" + "io" + "log" + "net/http" + + "github.com/xanzy/go-gitlab" +) + +type UpdateRequest struct { + Description string `json:"description"` +} + +type UpdateResponse struct { + SuccessResponse + MergeRequest *gitlab.MergeRequest `json:"mr"` +} + +func UpdateHandler(w http.ResponseWriter, r *http.Request) { + c := r.Context().Value("client").(Client) + w.Header().Set("Content-Type", "application/json") + if r.Method != http.MethodPut { + c.handleError(w, errors.New("Invalid request type"), "That request type is not allowed", http.StatusMethodNotAllowed) + return + } + + body, err := io.ReadAll(r.Body) + if err != nil { + c.handleError(w, err, "Could not read request body", http.StatusBadRequest) + return + } + + defer r.Body.Close() + var updateRequest UpdateRequest + err = json.Unmarshal(body, &updateRequest) + + if err != nil { + c.handleError(w, err, "Could not read JSON from request", http.StatusBadRequest) + return + } + + git, err := gitlab.NewClient(c.authToken) + if err != nil { + log.Fatalf("Failed to create client: %v", err) + } + + mr, res, err := git.MergeRequests.UpdateMergeRequest(c.projectId, c.mergeId, &gitlab.UpdateMergeRequestOptions{Description: &updateRequest.Description}) + + if err != nil { + c.handleError(w, err, "Could not edit merge request", http.StatusBadRequest) + return + } + + if res.StatusCode != http.StatusOK { + c.handleError(w, err, "Could not edit merge request", http.StatusBadRequest) + return + } + + w.WriteHeader(http.StatusOK) + + response := UpdateResponse{ + SuccessResponse: SuccessResponse{ + Message: "Merge request updated", + Status: http.StatusOK, + }, + MergeRequest: mr, + } + + json.NewEncoder(w).Encode(response) + +} diff --git a/lua/gitlab/init.lua b/lua/gitlab/init.lua index 2e2e901..5838821 100644 --- a/lua/gitlab/init.lua +++ b/lua/gitlab/init.lua @@ -45,6 +45,7 @@ M.setup = function(args) if not M.setPluginConfiguration(args) then return end -- Return if not a valid gitlab project + local command = state.BIN .. " " .. state.PROJECT_ID diff --git a/lua/gitlab/summary.lua b/lua/gitlab/summary.lua index 735af24..59cddfc 100644 --- a/lua/gitlab/summary.lua +++ b/lua/gitlab/summary.lua @@ -1,13 +1,14 @@ -local state = require("gitlab.state") -local Popup = require("nui.popup") -local u = require("gitlab.utils") -local keymaps = require("gitlab.keymaps") -local summaryPopup = Popup(u.create_popup_state("Loading Summary...", "80%", "80%")) -local M = {} +local job = require("gitlab.job") +local state = require("gitlab.state") +local Popup = require("nui.popup") +local u = require("gitlab.utils") +local keymaps = require("gitlab.keymaps") +local descriptionPopup = Popup(u.create_popup_state("Loading Description...", "80%", "80%")) +local M = {} -M.summary = function() +M.summary = function() if u.base_invalid() then return end - summaryPopup:mount() + descriptionPopup:mount() local currentBuffer = vim.api.nvim_get_current_buf() local title = state.INFO.title local description = state.INFO.description @@ -18,9 +19,17 @@ M.summary = function() end vim.schedule(function() vim.api.nvim_buf_set_lines(currentBuffer, 0, -1, false, lines) - vim.api.nvim_buf_set_option(currentBuffer, "modifiable", false) - summaryPopup.border:set_text("top", title, "center") - keymaps.set_popup_keymaps(summaryPopup) + descriptionPopup.border:set_text("top", title, "center") + keymaps.set_popup_keymaps(descriptionPopup, M.edit_description) + end) +end + +M.edit_description = function(text) + local jsonTable = { description = text } + local json = vim.json.encode(jsonTable) + job.run_job("mr", "PUT", json, function(data) + vim.notify(data.message, vim.log.levels.INFO) + state.INFO.description = data.mr.description end) end diff --git a/lua/gitlab/utils/init.lua b/lua/gitlab/utils/init.lua index 059fa21..004c375 100644 --- a/lua/gitlab/utils/init.lua +++ b/lua/gitlab/utils/init.lua @@ -187,6 +187,7 @@ local create_popup_state = function(title, width, height) buf_options = { filetype = 'markdown' }, + relative = "editor", enter = true, focusable = true, border = {