This MR represents a major refactor of the Go codebase, as well as introducing tests for the handlers. The MR also introduces an endpoint to shutdown or restart the Go server, which may be useful for clients who want to refresh the state of the plugin after checking out branches. Finally, this MR adds a contributing document for users who want to make feature changes.
187 lines
5.2 KiB
Lua
187 lines
5.2 KiB
Lua
-- This module is responsible for the MR pipline
|
|
-- This lets the user see the current status of the pipeline
|
|
-- and retrigger the pipeline from within the editor
|
|
local Popup = require("nui.popup")
|
|
local state = require("gitlab.state")
|
|
local job = require("gitlab.job")
|
|
local u = require("gitlab.utils")
|
|
local M = {
|
|
pipeline_jobs = nil,
|
|
pipeline_popup = nil,
|
|
}
|
|
|
|
local function get_pipeline()
|
|
local pipeline = state.INFO.head_pipeline or state.INFO.pipeline
|
|
|
|
if type(pipeline) ~= "table" or (type(pipeline) == "table" and u.table_size(pipeline) == 0) then
|
|
u.notify("Pipeline not found", vim.log.levels.WARN)
|
|
return
|
|
end
|
|
return pipeline
|
|
end
|
|
|
|
M.get_pipeline_status = function()
|
|
local pipeline = get_pipeline()
|
|
if pipeline == nil then
|
|
return nil
|
|
end
|
|
return string.format("%s (%s)", state.settings.pipeline[pipeline.status], pipeline.status)
|
|
end
|
|
|
|
-- The function will render the Pipeline state in a popup
|
|
M.open = function()
|
|
local pipeline = get_pipeline()
|
|
if not pipeline then
|
|
return
|
|
end
|
|
|
|
job.run_job("/pipeline/" .. pipeline.id, "GET", nil, function(data)
|
|
local pipeline_jobs = u.reverse(type(data.Jobs) == "table" and data.Jobs or {})
|
|
M.pipeline_jobs = pipeline_jobs
|
|
|
|
local width = string.len(pipeline.web_url) + 10
|
|
local height = 6 + #pipeline_jobs + 3
|
|
|
|
local pipeline_popup = Popup(u.create_popup_state("Loading Pipeline...", width, height))
|
|
M.pipeline_popup = pipeline_popup
|
|
pipeline_popup:mount()
|
|
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
|
vim.opt_local.wrap = false
|
|
|
|
local lines = {}
|
|
|
|
u.switch_can_edit_buf(bufnr, true)
|
|
table.insert(lines, "Status: " .. M.get_pipeline_status())
|
|
table.insert(lines, "")
|
|
table.insert(lines, string.format("Last Run: %s", u.time_since(pipeline.created_at)))
|
|
table.insert(lines, string.format("Url: %s", pipeline.web_url))
|
|
table.insert(lines, string.format("Triggered By: %s", pipeline.source))
|
|
|
|
table.insert(lines, "")
|
|
table.insert(lines, "Jobs:")
|
|
for _, pipeline_job in ipairs(pipeline_jobs) do
|
|
table.insert(
|
|
lines,
|
|
string.format(
|
|
"%s (%s) %s",
|
|
state.settings.pipeline[pipeline_job.status],
|
|
pipeline_job.status,
|
|
pipeline_job.name
|
|
)
|
|
)
|
|
end
|
|
|
|
vim.schedule(function()
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
|
|
M.color_status(pipeline.status, bufnr, lines[1], 1)
|
|
|
|
for i, pipeline_job in ipairs(pipeline_jobs) do
|
|
M.color_status(pipeline_job.status, bufnr, lines[7 + i], 7 + i)
|
|
end
|
|
|
|
pipeline_popup.border:set_text("top", "Pipeline Status", "center")
|
|
state.set_popup_keymaps(pipeline_popup, M.retrigger, M.see_logs)
|
|
u.switch_can_edit_buf(bufnr, false)
|
|
end)
|
|
end)
|
|
end
|
|
|
|
M.retrigger = function()
|
|
local pipeline = get_pipeline()
|
|
if not pipeline then
|
|
return
|
|
end
|
|
if pipeline.status ~= "failed" then
|
|
u.notify("Pipeline is not in a failed state!", vim.log.levels.WARN)
|
|
return
|
|
end
|
|
|
|
job.run_job("/pipeline/" .. pipeline.id, "POST", nil, function()
|
|
u.notify("Pipeline re-triggered!", vim.log.levels.INFO)
|
|
end)
|
|
end
|
|
|
|
M.see_logs = function()
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
|
local linnr = vim.api.nvim_win_get_cursor(0)[1]
|
|
local text = u.get_line_content(bufnr, linnr)
|
|
local last_word = u.get_last_word(text)
|
|
if last_word == nil then
|
|
u.notify("Cannot find job name", vim.log.levels.ERROR)
|
|
return
|
|
end
|
|
|
|
local j = nil
|
|
for _, pipeline_job in ipairs(M.pipeline_jobs) do
|
|
if pipeline_job.name == last_word then
|
|
j = pipeline_job
|
|
end
|
|
end
|
|
|
|
if j == nil then
|
|
u.notify("Cannot find job in state", vim.log.levels.ERROR)
|
|
return
|
|
end
|
|
|
|
local body = { job_id = j.id }
|
|
job.run_job("/job", "GET", body, function(data)
|
|
local file = data.file
|
|
if file == "" then
|
|
u.notify("Log trace is empty", vim.log.levels.WARN)
|
|
return
|
|
end
|
|
|
|
local lines = {}
|
|
for line in file:gmatch("[^\n]+") do
|
|
table.insert(lines, line)
|
|
end
|
|
|
|
if #lines == 0 then
|
|
u.notify("Log trace lines could not be parsed", vim.log.levels.ERROR)
|
|
return
|
|
end
|
|
|
|
M.pipeline_popup:unmount()
|
|
vim.cmd.enew()
|
|
|
|
bufnr = vim.api.nvim_get_current_buf()
|
|
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
|
|
|
|
-- TODO: Fix for Windows
|
|
local job_file_path = string.format("/tmp/gitlab.nvim.job-%d", j.id)
|
|
vim.cmd("w! " .. job_file_path)
|
|
vim.cmd.bd()
|
|
|
|
vim.cmd.enew()
|
|
vim.cmd("term cat " .. job_file_path)
|
|
end)
|
|
end
|
|
|
|
M.color_status = function(status, bufnr, status_line, linnr)
|
|
local ns_id = vim.api.nvim_create_namespace("GitlabNamespace")
|
|
vim.cmd(string.format("highlight default StatusHighlight guifg=%s", state.settings.pipeline[status]))
|
|
|
|
local status_to_color_map = {
|
|
created = "DiagnosticWarn",
|
|
pending = "DiagnosticWarn",
|
|
preparing = "DiagnosticWarn",
|
|
scheduled = "DiagnosticWarn",
|
|
running = "DiagnosticWarn",
|
|
canceled = "DiagnosticWarn",
|
|
skipped = "DiagnosticWarn",
|
|
failed = "DiagnosticError",
|
|
success = "DiagnosticOK",
|
|
}
|
|
|
|
vim.api.nvim_buf_set_extmark(
|
|
bufnr,
|
|
ns_id,
|
|
linnr - 1,
|
|
0,
|
|
{ end_row = linnr - 1, end_col = string.len(status_line), hl_group = status_to_color_map[status] }
|
|
)
|
|
end
|
|
|
|
return M
|