feat: add mergeability checks to summary view

This commit is contained in:
Jakub F. Bortlík
2026-02-26 10:14:57 +01:00
parent 3d2828a950
commit 250ba35a49
10 changed files with 349 additions and 11 deletions

View File

@@ -6,6 +6,7 @@ local M = {}
local user = state.dependencies.user
local info = state.dependencies.info
local labels = state.dependencies.labels
local mergeability = state.dependencies.mergeability
local project_members = state.dependencies.project_members
local revisions = state.dependencies.revisions
local latest_pipeline = state.dependencies.latest_pipeline
@@ -21,6 +22,7 @@ M.data = function(resources, cb)
info = info,
user = user,
labels = labels,
mergeability = mergeability,
project_members = project_members,
revisions = revisions,
pipeline = latest_pipeline,

View File

@@ -8,7 +8,6 @@ local job = require("gitlab.job")
local common = require("gitlab.actions.common")
local u = require("gitlab.utils")
local popup = require("gitlab.popup")
local List = require("gitlab.utils.list")
local state = require("gitlab.state")
local miscellaneous = require("gitlab.actions.miscellaneous")
@@ -108,6 +107,28 @@ M.update_details_popup = function(bufnr, info_lines)
M.color_details(bufnr) -- Color values in details popup
end
---Return the mergeability checks statuses and descriptions
---@return string[]
local make_mergeability_checks = function()
local lines = {}
for _, check in ipairs(state.MERGEABILITY.mergeability_checks) do
local status = state.settings.mergeability_checks.statuses[check.status]
if status == nil then
u.notify(string.format("Unknown mergeability check status: %s", check.status), vim.log.levels.ERROR)
end
if status then
local description = state.settings.mergeability_checks.checks[check.identifier]
if description == nil then
u.notify(string.format("Unknown mergeability check identifier: %s", check.identifier), vim.log.levels.ERROR)
end
if description then
table.insert(lines, status .. " " .. description)
end
end
end
return lines
end
-- Builds a lua list of strings that contain metadata about the current MR. Only builds the
-- lines that users include in their state.settings.info.fields list.
M.build_info_lines = function()
@@ -140,6 +161,7 @@ M.build_info_lines = function()
end,
},
web_url = { title = "MR URL", content = info.web_url },
mergeability_checks = { title = "Mergeability checks", content = make_mergeability_checks },
}
local longest_used = ""
@@ -158,22 +180,26 @@ M.build_info_lines = function()
return string.rep(" ", offset + 3)
end
return List.new(state.settings.info.fields):map(function(v)
local result = {}
for _, v in ipairs(state.settings.info.fields) do
if v == "merge_status" then
v = "detailed_merge_status"
end
local row = options[v]
local line = "* " .. row.title .. row_offset(row.title)
if type(row.content) == "function" then
local content = row.content()
if content ~= nil then
line = line .. row.content()
local title_prefix = "* " .. row.title .. row_offset(row.title)
local content = type(row.content) == "function" and row.content() or row.content
if type(content) == "table" then
-- Multi-line content
local padding = string.rep(" ", #title_prefix)
for i, line in ipairs(#content > 0 and content or { "" }) do
table.insert(result, (i == 1 and title_prefix or padding) .. line)
end
else
line = line .. row.content
-- Single-line content
table.insert(result, title_prefix .. (content or ""))
end
return line
end)
end
return result
end
-- This function will PUT the new description to the Go server

View File

@@ -159,6 +159,7 @@
---@field discussion_tree? DiscussionSettings -- Settings for the popup windows
---@field choose_merge_request? ChooseMergeRequestSettings -- Default settings when choosing a merge request
---@field info? InfoSettings -- Settings for the "info" or "summary" view
---@field mergeability_checks? MergeabilityChecksSettings -- Settings for the mergeability checks in the "summary" view
---@field discussion_signs? DiscussionSigns -- The settings for discussion signs/diagnostics
---@field pipeline? PipelineSettings -- The settings for the pipeline popup
---@field create_mr? CreateMrSettings -- The settings when creating an MR
@@ -252,7 +253,37 @@
---@class InfoSettings
---@field horizontal? boolean -- Display metadata to the left of the summary rather than underneath
---@field fields? ("author" | "created_at" | "updated_at" | "merge_status" | "draft" | "conflicts" | "assignees" | "reviewers" | "pipeline" | "branch" | "target_branch" | "delete_branch" | "squash" | "labels")[]
---@field fields? ("author" | "created_at" | "updated_at" | "merge_status" | "draft" | "conflicts" | "assignees" | "reviewers" | "pipeline" | "branch" | "target_branch" | "delete_branch" | "squash" | "labels" | "mergeability_checks")[]
---@class MergeabilityChecksSettings
---@field statuses MergeabilityStatuses
---@field checks MergeabilityChecks
---@class MergeabilityStatuses
---@field SUCCESS string|false
---@field CHECKING string|false
---@field FAILED string|false
---@field WARNING string|false
---@field INACTIVE string|false
---@class MergeabilityChecks
---@field CI_MUST_PASS string|false
---@field COMMITS_STATUS string|false
---@field CONFLICT string|false
---@field DISCUSSIONS_NOT_RESOLVED string|false
---@field DRAFT_STATUS string|false
---@field JIRA_ASSOCIATION_MISSING string|false
---@field LOCKED_LFS_FILES string|false
---@field LOCKED_PATHS string|false
---@field MERGE_REQUEST_BLOCKED string|false
---@field MERGE_TIME string|false
---@field NEED_REBASE string|false
---@field NOT_APPROVED string|false
---@field NOT_OPEN string|false
---@field REQUESTED_CHANGES string|false
---@field SECURITY_POLICY_VIOLATIONS string|false
---@field STATUS_CHECKS_MUST_PASS string|false
---@field TITLE_REGEX string|false
---@class DiscussionSettings: table
---@field expanders? ExpanderOpts -- Customize the expander icons in the discussion tree

View File

@@ -22,6 +22,7 @@ local health = require("gitlab.health")
local user = state.dependencies.user
local info = state.dependencies.info
local mergeability = state.dependencies.mergeability
local labels_dep = state.dependencies.labels
local project_members = state.dependencies.project_members
local latest_pipeline = state.dependencies.latest_pipeline
@@ -62,6 +63,7 @@ return {
setup = setup,
summary = async.sequence({
u.merge(info, { refresh = true }),
u.merge(mergeability, { refresh = true }),
labels_dep,
}, summary.summary),
approve = async.sequence({ info }, approvals.approve),

View File

@@ -218,6 +218,35 @@ M.settings = {
"squash",
"labels",
"web_url",
"mergeability_checks",
},
},
mergeability_checks = {
statuses = {
SUCCESS = "",
CHECKING = "🔁",
FAILED = "",
WARNING = "⚠️",
INACTIVE = "💤",
},
checks = {
CI_MUST_PASS = "Pipeline must succeed",
COMMITS_STATUS = "Source branch exists and contains commits",
CONFLICT = "Merge conflicts must be resolved",
DISCUSSIONS_NOT_RESOLVED = "Open threads must be resolved",
DRAFT_STATUS = "Merge request must not be draft",
JIRA_ASSOCIATION_MISSING = "Title or description references a Jira issue",
LOCKED_LFS_FILES = "All LFS files must be unlocked",
LOCKED_PATHS = "All paths must be unlocked",
MERGE_REQUEST_BLOCKED = "Merge request is not blocked",
MERGE_TIME = "Merge is not blocked due to a scheduled merge time",
NEED_REBASE = "Merge request must be rebased, fast-forward merge is not possible",
NOT_APPROVED = "All required approvals must be given",
NOT_OPEN = "Merge request must be open",
REQUESTED_CHANGES = "Change requests must be approved by the requesting user",
SECURITY_POLICY_VIOLATIONS = "Security policies are satisfied",
STATUS_CHECKS_MUST_PASS = "External status checks pass",
TITLE_REGEX = "Title matches the expected regex",
},
},
discussion_signs = {
@@ -467,6 +496,12 @@ M.dependencies = {
state = "INFO",
refresh = false,
},
mergeability = {
endpoint = "/mr/info/mergeability",
key = "MergeabilityChecks",
state = "MERGEABILITY",
refresh = false,
},
latest_pipeline = {
endpoint = "/pipeline",
key = "latest_pipeline",