Feat: View + Manage Pipeline (#53)

This MR adds the `.pipeline()` command which opens up the pipeline popup. This popup shows information about the current pipeline and it's jobs, and gives users the ability to re-trigger failed jobs.
This commit is contained in:
Harrison (Harry) Cramer
2023-09-03 18:01:54 -04:00
committed by GitHub
parent 4c6dcacfcd
commit e6e0bf4093
15 changed files with 267 additions and 8 deletions

View File

@@ -290,10 +290,8 @@ M.rebuild_unlinked_discussion_tree = function()
end
M.switch_can_edit_bufs = function(bool)
vim.api.nvim_buf_set_option(M.unlinked_section_bufnr, 'modifiable', bool)
vim.api.nvim_buf_set_option(M.unlinked_section_bufnr, "readonly", not bool)
vim.api.nvim_buf_set_option(M.linked_section_bufnr, 'modifiable', bool)
vim.api.nvim_buf_set_option(M.linked_section_bufnr, "readonly", not bool)
u.switch_can_edit_buf(M.unlinked_section_bufnr, bool)
u.switch_can_edit_buf(M.linked_section_bufnr, bool)
end
M.add_discussion = function(arg)

View File

@@ -0,0 +1,96 @@
-- 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 = {}
-- The function will render the Pipeline state in a popup
M.open = function()
local pipeline = state.INFO.pipeline
if type(pipeline) ~= "table" or (type(pipeline) == "table" and u.table_size(pipeline) == 0) then
vim.notify("Pipeline not found", vim.log.levels.WARN)
return
end
local body = { pipeline_id = state.INFO.pipeline.id }
job.run_job("/pipeline", "GET", body, function(data)
local pipeline_jobs = u.reverse(type(data.Jobs) == "table" and data.Jobs or {})
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))
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, string.format("Status: %s (%s)", state.settings.pipeline[pipeline.status], pipeline.status))
table.insert(lines, "")
table.insert(lines, string.format("Last Run: %s", u.format_date(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)
u.switch_can_edit_buf(bufnr, false)
end)
end)
end
M.retrigger = function()
local body = { pipeline_id = state.INFO.pipeline.id }
if state.INFO.pipeline.status ~= 'failed' then
vim.notify("Pipeline is not in a failed state!", vim.log.levels.WARN)
return
end
job.run_job("/pipeline", "POST", body, function(data)
vim.notify("Pipeline re-triggered!", vim.log.levels.INFO)
state.INFO.pipeline = data.Pipeline
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

View File

@@ -7,6 +7,7 @@ local discussions = require("gitlab.actions.discussions")
local summary = require("gitlab.actions.summary")
local assignees_and_reviewers = require("gitlab.actions.assignees_and_reviewers")
local comment = require("gitlab.actions.comment")
local pipeline = require("gitlab.actions.pipeline")
local approvals = require("gitlab.actions.approvals")
local info = state.dependencies.info
@@ -31,6 +32,7 @@ return {
create_comment = async.sequence({ info, revisions }, comment.create_comment),
create_note = async.sequence({ info }, comment.create_note),
review = async.sequence({ u.merge(info, { refresh = true }) }, function() reviewer.open() end),
pipeline = async.sequence({ info }, pipeline.open),
-- Discussion Tree Actions 🌴
toggle_discussions = async.sequence({ info }, discussions.toggle),
edit_comment = async.sequence({ info }, discussions.edit_comment),

View File

@@ -37,6 +37,17 @@ M.settings = {
removed_file = "",
}
},
pipeline = {
created = "",
pending = "",
preparing = "",
scheduled = "",
running = "",
canceled = "",
skipped = "",
success = "",
failed = "",
},
dialogue = {
focus_next = { "j", "<Down>", "<Tab>" },
focus_prev = { "k", "<Up>", "<S-Tab>" },

View File

@@ -49,14 +49,18 @@ M.format_date = function(date_string)
local time_diff = current_date - date
local function pluralize(num, word)
return num .. string.format(" %s", word) .. (num > 1 and "s" or '') .. " ago"
end
if time_diff < 60 then
return time_diff .. " seconds ago"
return pluralize(time_diff, "second")
elseif time_diff < 3600 then
return math.floor(time_diff / 60) .. " minutes ago"
return pluralize(math.floor(time_diff / 60), "minute")
elseif time_diff < 86400 then
return math.floor(time_diff / 3600) .. " hours ago"
return pluralize(math.floor(time_diff / 3600), "hour")
elseif time_diff < 2592000 then
return math.floor(time_diff / 86400) .. " days ago"
return pluralize(math.floor(time_diff / 86400), "day")
else
local formatted_date = os.date("%A, %B %e", date)
return formatted_date
@@ -254,4 +258,17 @@ M.get_win_from_buf = function(bufnr)
end
end
M.switch_can_edit_buf = function(buf, bool)
vim.api.nvim_buf_set_option(buf, 'modifiable', bool)
vim.api.nvim_buf_set_option(buf, "readonly", not bool)
end
M.reverse = function(list)
local rev = {}
for i = #list, 1, -1 do
rev[#rev + 1] = list[i]
end
return rev
end
return M