From c7157c6f4d3f512e653dd593440a0e4ef2c541ac Mon Sep 17 00:00:00 2001 From: Tobias Wackenhut Date: Wed, 24 Apr 2024 23:08:19 +0200 Subject: [PATCH] Add GitHub Enterprise support * fixes #4 --- lua/gh-actions/github.lua | 49 ++++++++++++++++++++++++++++----------- lua/gh-actions/init.lua | 14 ++++++----- lua/gh-actions/utils.lua | 2 +- 3 files changed, 44 insertions(+), 21 deletions(-) diff --git a/lua/gh-actions/github.lua b/lua/gh-actions/github.lua index 07f20e0..c053e81 100644 --- a/lua/gh-actions/github.lua +++ b/lua/gh-actions/github.lua @@ -5,7 +5,7 @@ local utils = require('gh-actions.utils') local M = {} ---@param str string ----@return string +---@return table local function strip_git_suffix(str) if str:sub(-4) == '.git' then return str:sub(1, -5) @@ -28,12 +28,13 @@ function M.get_current_repository() local origin_url = table.concat(origin_url_job:result(), '') - return strip_git_suffix(origin_url):match('github.com[:/](.+)$') + return strip_git_suffix(origin_url):match('([^@/:]+)[:/](.+)$') end ---@param cmd? string +---@param server? string ---@return string|nil -local function get_token_from_gh_cli(cmd) +local function get_token_from_gh_cli(cmd, server) local has_gh_installed = vim.fn.executable('gh') == 1 if not has_gh_installed and not cmd then return nil @@ -43,7 +44,11 @@ local function get_token_from_gh_cli(cmd) if cmd then res = vim.fn.system(cmd) else - res = vim.fn.system('gh auth token') + local gh_enterprise_flag = "" + if server ~= nil and server ~= "" then + gh_enterprise_flag = " --hostname " .. server + end + res = vim.fn.system('gh auth token' .. gh_enterprise_flag) end local token = string.gsub(res or '', '\n', '') @@ -57,24 +62,30 @@ end ---@param cmd? string ---@return string -function M.get_github_token(cmd) +function M.get_github_token(cmd, server) return vim.env.GITHUB_TOKEN - or get_token_from_gh_cli(cmd) + or get_token_from_gh_cli(cmd, server) -- TODO: We could also ask for the token here via nui or assert(nil, 'No GITHUB_TOKEN found in env and no gh cli config found') end +---@param server string ---@param path string ---@param opts? table -function M.fetch(path, opts) +function M.fetch(server, path, opts) opts = opts or {} opts.callback = opts.callback and vim.schedule_wrap(opts.callback) + local url = string.format('https://api.github.com%s', path) + if server ~= "github.com" then + url = string.format('https://%s/api/v3%s', server, path) + end + return curl[opts.method or 'get']( - string.format('https://api.github.com%s', path), + url, vim.tbl_deep_extend('force', opts, { headers = { - Authorization = string.format('Bearer %s', M.get_github_token()), + Authorization = string.format('Bearer %s', M.get_github_token(nil, server)), }, }) ) @@ -96,12 +107,14 @@ end ---@field total_count number ---@field workflows GhWorkflow[] +---@param server string ---@param repo string ---@param opts? { callback?: fun(workflows: GhWorkflow[]): any } -function M.get_workflows(repo, opts) +function M.get_workflows(server, repo, opts) opts = opts or {} return M.fetch( + server, string.format('/repos/%s/actions/workflows', repo), vim.tbl_deep_extend('force', opts, { callback = function(response) @@ -166,13 +179,15 @@ local function process_workflow_runs_response(opts) end end +---@param server string ---@param repo string ---@param per_page? integer ---@param opts? { callback?: fun(workflow_runs: GhWorkflowRun[]): any } -function M.get_repository_workflow_runs(repo, per_page, opts) +function M.get_repository_workflow_runs(server, repo, per_page, opts) opts = opts or {} return M.fetch( + server, string.format('/repos/%s/actions/runs', repo), vim.tbl_deep_extend('force', { query = { per_page = per_page } }, opts, { callback = process_workflow_runs_response(opts), @@ -180,14 +195,16 @@ function M.get_repository_workflow_runs(repo, per_page, opts) ) end +---@param server string ---@param repo string ---@param workflow_id integer ---@param per_page? integer ---@param opts? { callback?: fun(workflow_runs: GhWorkflowRun[]): any } -function M.get_workflow_runs(repo, workflow_id, per_page, opts) +function M.get_workflow_runs(server, repo, workflow_id, per_page, opts) opts = opts or {} return M.fetch( + server, string.format('/repos/%s/actions/workflows/%d/runs', repo, workflow_id), vim.tbl_deep_extend('force', { query = { per_page = per_page } }, opts, { callback = process_workflow_runs_response(opts), @@ -195,14 +212,16 @@ function M.get_workflow_runs(repo, workflow_id, per_page, opts) ) end +---@param server string ---@param repo string ---@param workflow_id integer ---@param ref string ---@param opts? table -function M.dispatch_workflow(repo, workflow_id, ref, opts) +function M.dispatch_workflow(server, repo, workflow_id, ref, opts) opts = opts or {} return M.fetch( + server, string.format( '/repos/%s/actions/workflows/%d/dispatches', repo, @@ -237,14 +256,16 @@ end ---@field total_count number ---@field jobs GhWorkflowRunJob[] +---@param server string ---@param repo string ---@param workflow_run_id integer ---@param per_page? integer ---@param opts? { callback?: fun(workflow_runs: GhWorkflowRunJob[]): any } -function M.get_workflow_run_jobs(repo, workflow_run_id, per_page, opts) +function M.get_workflow_run_jobs(server, repo, workflow_run_id, per_page, opts) opts = opts or {} return M.fetch( + server, string.format('/repos/%s/actions/runs/%d/jobs', repo, workflow_run_id), vim.tbl_deep_extend('force', { query = { per_page = per_page } }, opts, { callback = function(response) diff --git a/lua/gh-actions/init.lua b/lua/gh-actions/init.lua index c0c7514..f428db0 100644 --- a/lua/gh-actions/init.lua +++ b/lua/gh-actions/init.lua @@ -36,13 +36,14 @@ end --TODO Maybe send lsp progress events when fetching, to interact -- with fidget.nvim local function fetch_data() - local repo = gh.get_current_repository() + local server, repo = gh.get_current_repository() store.update_state(function(state) state.repo = repo + state.server = server end) - gh.get_workflows(repo, { + gh.get_workflows(server, repo, { callback = function(workflows) store.update_state(function(state) state.workflows = workflows @@ -50,7 +51,7 @@ local function fetch_data() end, }) - gh.get_repository_workflow_runs(repo, 100, { + gh.get_repository_workflow_runs(server, repo, 100, { callback = function(workflow_runs) local old_workflow_runs = store.get_state().workflow_runs @@ -68,7 +69,7 @@ local function fetch_data() ) for _, run in ipairs(running_workflows) do - gh.get_workflow_run_jobs(repo, run.id, 20, { + gh.get_workflow_run_jobs(server, repo, run.id, 20, { callback = function(jobs) store.update_state(function(state) state.workflow_jobs[run.id] = jobs @@ -195,6 +196,7 @@ function M.open() local workflow = ui.get_workflow() if workflow then + local server = store.get_state().server local repo = store.get_state().repo -- TODO should we get current ref instead or show an input with the @@ -224,11 +226,11 @@ function M.open() if #questions > 0 and i <= #questions then questions[i]:mount() else - gh.dispatch_workflow(repo, workflow.id, default_branch, { + gh.dispatch_workflow(server, repo, workflow.id, default_branch, { body = { inputs = input_values or {} }, callback = function(_res) utils.delay(2000, function() - gh.get_workflow_runs(repo, workflow.id, 5, { + gh.get_workflow_runs(server, repo, workflow.id, 5, { callback = function(workflow_runs) store.update_state(function(state) state.workflow_runs = utils.uniq(function(run) diff --git a/lua/gh-actions/utils.lua b/lua/gh-actions/utils.lua index 8838f55..fa3c800 100644 --- a/lua/gh-actions/utils.lua +++ b/lua/gh-actions/utils.lua @@ -57,7 +57,7 @@ function M.parse_yaml(yamlstr) if has_rust_module then return rust.parse_yaml(yamlstr or '') else - return vim.json.decode(vim.fn.system('yq', yamlstr) or '') + return vim.json.decode(vim.fn.system({'yq', '-o', 'json'}, yamlstr) or '') end end