mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 06:14:59 +00:00
docs: tools,github,packages (8 files)
This commit is contained in:
@@ -81,11 +81,26 @@ Phase 6: Cleanup (Week 8+) ⏳ Pending
|
||||
- moderation.cases.json with test data
|
||||
- **Total fakemui icons now: 80+** (up from 70+)
|
||||
|
||||
**✅ Additional Progress (Session 3 - 2025-12-31):**
|
||||
- **@mui/icons-material completely eliminated from source code!**
|
||||
- Migrated 40+ component files to fakemui icons
|
||||
- Created 50+ new fakemui icons including:
|
||||
- Component icons: Article, Checkbox, CropFree, CropPortrait, GridView, etc.
|
||||
- Navigation: FirstPage, LastPage, ViewColumn, ViewStream
|
||||
- Interaction: ToggleOn, TouchApp, FormatAlignLeft
|
||||
- Display: AccountCircle, Verified, LocalOffer, LooksOne, TextFields, TableChart, Minus
|
||||
- Updated atoms/display/Icon.tsx to use fakemui icons dynamically
|
||||
- Migrated get-component-icon.tsx to fakemui
|
||||
- Updated all test files (NavLink.test.tsx, NavItem.test.tsx, NavGroup.test.tsx)
|
||||
- **Total fakemui icons now: 130+** (up from 80+)
|
||||
- Icon mappings complete for all common MUI icon names
|
||||
|
||||
**📋 Ready to Execute:**
|
||||
- ✅ Icon strategy: Full fakemui custom icons (no Phosphor) - 80+ icons!
|
||||
- ✅ Icon strategy: Full fakemui custom icons (no Phosphor) - 130+ icons!
|
||||
- ✅ Phase 1: Complete - all foundation components ready
|
||||
- ✅ Phase 2: ButtonGroup, FormControl, RadioGroup, NativeSelect added
|
||||
- Phase 3: Continue icon expansion as needed
|
||||
- ✅ @mui/icons-material: ELIMINATED from source code
|
||||
- Phase 3: Continue MUI core component elimination
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,100 +1,100 @@
|
||||
-- Analyze workflow run statistics
|
||||
|
||||
---@class AnalyzeModule
|
||||
local M = {}
|
||||
|
||||
---Calculate statistics from a list of runs
|
||||
---@param runs WorkflowRun[] Array of workflow runs
|
||||
---@return RunStats
|
||||
function M.calculateStats(runs)
|
||||
local total = #runs
|
||||
local success = 0
|
||||
local failure = 0
|
||||
local pending = 0
|
||||
local total_duration = 0
|
||||
local completed_runs = 0
|
||||
|
||||
for _, run in ipairs(runs) do
|
||||
if run.conclusion == "success" then
|
||||
success = success + 1
|
||||
elseif run.conclusion == "failure" then
|
||||
failure = failure + 1
|
||||
elseif run.status == "pending" or run.status == "in_progress" then
|
||||
pending = pending + 1
|
||||
end
|
||||
|
||||
-- Calculate duration if completed
|
||||
if run.created_at and run.updated_at then
|
||||
-- Duration calculation would parse ISO dates
|
||||
-- Placeholder for now
|
||||
completed_runs = completed_runs + 1
|
||||
end
|
||||
end
|
||||
|
||||
local success_rate = 0
|
||||
if total > 0 then
|
||||
success_rate = (success / total) * 100
|
||||
end
|
||||
|
||||
local avg_duration = 0
|
||||
if completed_runs > 0 then
|
||||
avg_duration = total_duration / completed_runs
|
||||
end
|
||||
|
||||
return {
|
||||
total = total,
|
||||
success = success,
|
||||
failure = failure,
|
||||
pending = pending,
|
||||
success_rate = math.floor(success_rate * 10) / 10,
|
||||
avg_duration = avg_duration
|
||||
}
|
||||
end
|
||||
|
||||
---Get trend data for success rate over time
|
||||
---@param runs WorkflowRun[] Array of workflow runs
|
||||
---@param buckets number Number of time buckets (default 7)
|
||||
---@return table[] Array of {date, success_rate} pairs
|
||||
function M.getSuccessTrend(runs, buckets)
|
||||
buckets = buckets or 7
|
||||
local trend = {}
|
||||
|
||||
-- Group runs by date and calculate daily success rate
|
||||
-- Placeholder implementation
|
||||
for i = 1, buckets do
|
||||
table.insert(trend, {
|
||||
date = "Day " .. i,
|
||||
success_rate = 0
|
||||
})
|
||||
end
|
||||
|
||||
return trend
|
||||
end
|
||||
|
||||
---Get failure breakdown by type
|
||||
---@param runs WorkflowRun[] Array of workflow runs
|
||||
---@return table<string, number> Map of failure type to count
|
||||
function M.getFailureBreakdown(runs)
|
||||
local breakdown = {
|
||||
build_failure = 0,
|
||||
test_failure = 0,
|
||||
timeout = 0,
|
||||
cancelled = 0,
|
||||
other = 0
|
||||
}
|
||||
|
||||
for _, run in ipairs(runs) do
|
||||
if run.conclusion == "failure" then
|
||||
-- Would analyze job names to categorize
|
||||
breakdown.other = breakdown.other + 1
|
||||
elseif run.conclusion == "timed_out" then
|
||||
breakdown.timeout = breakdown.timeout + 1
|
||||
elseif run.conclusion == "cancelled" then
|
||||
breakdown.cancelled = breakdown.cancelled + 1
|
||||
end
|
||||
end
|
||||
|
||||
return breakdown
|
||||
end
|
||||
|
||||
return M
|
||||
-- Analyze workflow run statistics
|
||||
|
||||
---@class AnalyzeModule
|
||||
local M = {}
|
||||
|
||||
---Calculate statistics from a list of runs
|
||||
---@param runs WorkflowRun[] Array of workflow runs
|
||||
---@return RunStats
|
||||
function M.calculateStats(runs)
|
||||
local total = #runs
|
||||
local success = 0
|
||||
local failure = 0
|
||||
local pending = 0
|
||||
local total_duration = 0
|
||||
local completed_runs = 0
|
||||
|
||||
for _, run in ipairs(runs) do
|
||||
if run.conclusion == "success" then
|
||||
success = success + 1
|
||||
elseif run.conclusion == "failure" then
|
||||
failure = failure + 1
|
||||
elseif run.status == "pending" or run.status == "in_progress" then
|
||||
pending = pending + 1
|
||||
end
|
||||
|
||||
-- Calculate duration if completed
|
||||
if run.created_at and run.updated_at then
|
||||
-- Duration calculation would parse ISO dates
|
||||
-- Placeholder for now
|
||||
completed_runs = completed_runs + 1
|
||||
end
|
||||
end
|
||||
|
||||
local success_rate = 0
|
||||
if total > 0 then
|
||||
success_rate = (success / total) * 100
|
||||
end
|
||||
|
||||
local avg_duration = 0
|
||||
if completed_runs > 0 then
|
||||
avg_duration = total_duration / completed_runs
|
||||
end
|
||||
|
||||
return {
|
||||
total = total,
|
||||
success = success,
|
||||
failure = failure,
|
||||
pending = pending,
|
||||
success_rate = math.floor(success_rate * 10) / 10,
|
||||
avg_duration = avg_duration
|
||||
}
|
||||
end
|
||||
|
||||
---Get trend data for success rate over time
|
||||
---@param runs WorkflowRun[] Array of workflow runs
|
||||
---@param buckets number Number of time buckets (default 7)
|
||||
---@return table[] Array of {date, success_rate} pairs
|
||||
function M.getSuccessTrend(runs, buckets)
|
||||
buckets = buckets or 7
|
||||
local trend = {}
|
||||
|
||||
-- Group runs by date and calculate daily success rate
|
||||
-- Placeholder implementation
|
||||
for i = 1, buckets do
|
||||
table.insert(trend, {
|
||||
date = "Day " .. i,
|
||||
success_rate = 0
|
||||
})
|
||||
end
|
||||
|
||||
return trend
|
||||
end
|
||||
|
||||
---Get failure breakdown by type
|
||||
---@param runs WorkflowRun[] Array of workflow runs
|
||||
---@return table<string, number> Map of failure type to count
|
||||
function M.getFailureBreakdown(runs)
|
||||
local breakdown = {
|
||||
build_failure = 0,
|
||||
test_failure = 0,
|
||||
timeout = 0,
|
||||
cancelled = 0,
|
||||
other = 0
|
||||
}
|
||||
|
||||
for _, run in ipairs(runs) do
|
||||
if run.conclusion == "failure" then
|
||||
-- Would analyze job names to categorize
|
||||
breakdown.other = breakdown.other + 1
|
||||
elseif run.conclusion == "timed_out" then
|
||||
breakdown.timeout = breakdown.timeout + 1
|
||||
elseif run.conclusion == "cancelled" then
|
||||
breakdown.cancelled = breakdown.cancelled + 1
|
||||
end
|
||||
end
|
||||
|
||||
return breakdown
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
@@ -1,96 +1,96 @@
|
||||
-- Fetch workflow runs from GitHub API
|
||||
|
||||
---@class FetchRunsModule
|
||||
local M = {}
|
||||
|
||||
---@class FetchOptions
|
||||
---@field owner string Repository owner
|
||||
---@field repo string Repository name
|
||||
---@field workflow? string Workflow file name
|
||||
---@field branch? string Filter by branch
|
||||
---@field status? RunStatus Filter by status
|
||||
---@field per_page? number Results per page (default 30)
|
||||
---@field page? number Page number (default 1)
|
||||
|
||||
---@class FetchResult
|
||||
---@field runs WorkflowRun[] Array of workflow runs
|
||||
---@field total_count number Total number of runs
|
||||
---@field page number Current page
|
||||
---@field has_more boolean Whether more pages exist
|
||||
|
||||
---Build API URL for workflow runs
|
||||
---@param opts FetchOptions
|
||||
---@return string
|
||||
local function buildUrl(opts)
|
||||
local base = "https://api.github.com/repos/" .. opts.owner .. "/" .. opts.repo
|
||||
|
||||
if opts.workflow then
|
||||
base = base .. "/actions/workflows/" .. opts.workflow .. "/runs"
|
||||
else
|
||||
base = base .. "/actions/runs"
|
||||
end
|
||||
|
||||
local params = {}
|
||||
if opts.branch then
|
||||
table.insert(params, "branch=" .. opts.branch)
|
||||
end
|
||||
if opts.status then
|
||||
table.insert(params, "status=" .. opts.status)
|
||||
end
|
||||
table.insert(params, "per_page=" .. (opts.per_page or 30))
|
||||
table.insert(params, "page=" .. (opts.page or 1))
|
||||
|
||||
if #params > 0 then
|
||||
base = base .. "?" .. table.concat(params, "&")
|
||||
end
|
||||
|
||||
return base
|
||||
end
|
||||
|
||||
---Fetch workflow runs from GitHub
|
||||
---@param opts FetchOptions Fetch options
|
||||
---@return FetchResult
|
||||
function M.fetchRuns(opts)
|
||||
local url = buildUrl(opts)
|
||||
|
||||
-- In production, this would make HTTP request
|
||||
-- For now, return placeholder structure
|
||||
log("Fetching runs from: " .. url)
|
||||
|
||||
return {
|
||||
runs = {},
|
||||
total_count = 0,
|
||||
page = opts.page or 1,
|
||||
has_more = false
|
||||
}
|
||||
end
|
||||
|
||||
---Fetch jobs for a specific run
|
||||
---@param owner string Repository owner
|
||||
---@param repo string Repository name
|
||||
---@param run_id number Run ID
|
||||
---@return WorkflowJob[]
|
||||
function M.fetchJobs(owner, repo, run_id)
|
||||
local url = "https://api.github.com/repos/" .. owner .. "/" .. repo
|
||||
url = url .. "/actions/runs/" .. tostring(run_id) .. "/jobs"
|
||||
|
||||
log("Fetching jobs from: " .. url)
|
||||
|
||||
return {}
|
||||
end
|
||||
|
||||
---Fetch logs for a job
|
||||
---@param owner string Repository owner
|
||||
---@param repo string Repository name
|
||||
---@param job_id number Job ID
|
||||
---@return string Log content
|
||||
function M.fetchLogs(owner, repo, job_id)
|
||||
local url = "https://api.github.com/repos/" .. owner .. "/" .. repo
|
||||
url = url .. "/actions/jobs/" .. tostring(job_id) .. "/logs"
|
||||
|
||||
log("Fetching logs from: " .. url)
|
||||
|
||||
return ""
|
||||
end
|
||||
|
||||
return M
|
||||
-- Fetch workflow runs from GitHub API
|
||||
|
||||
---@class FetchRunsModule
|
||||
local M = {}
|
||||
|
||||
---@class FetchOptions
|
||||
---@field owner string Repository owner
|
||||
---@field repo string Repository name
|
||||
---@field workflow? string Workflow file name
|
||||
---@field branch? string Filter by branch
|
||||
---@field status? RunStatus Filter by status
|
||||
---@field per_page? number Results per page (default 30)
|
||||
---@field page? number Page number (default 1)
|
||||
|
||||
---@class FetchResult
|
||||
---@field runs WorkflowRun[] Array of workflow runs
|
||||
---@field total_count number Total number of runs
|
||||
---@field page number Current page
|
||||
---@field has_more boolean Whether more pages exist
|
||||
|
||||
---Build API URL for workflow runs
|
||||
---@param opts FetchOptions
|
||||
---@return string
|
||||
local function buildUrl(opts)
|
||||
local base = "https://api.github.com/repos/" .. opts.owner .. "/" .. opts.repo
|
||||
|
||||
if opts.workflow then
|
||||
base = base .. "/actions/workflows/" .. opts.workflow .. "/runs"
|
||||
else
|
||||
base = base .. "/actions/runs"
|
||||
end
|
||||
|
||||
local params = {}
|
||||
if opts.branch then
|
||||
table.insert(params, "branch=" .. opts.branch)
|
||||
end
|
||||
if opts.status then
|
||||
table.insert(params, "status=" .. opts.status)
|
||||
end
|
||||
table.insert(params, "per_page=" .. (opts.per_page or 30))
|
||||
table.insert(params, "page=" .. (opts.page or 1))
|
||||
|
||||
if #params > 0 then
|
||||
base = base .. "?" .. table.concat(params, "&")
|
||||
end
|
||||
|
||||
return base
|
||||
end
|
||||
|
||||
---Fetch workflow runs from GitHub
|
||||
---@param opts FetchOptions Fetch options
|
||||
---@return FetchResult
|
||||
function M.fetchRuns(opts)
|
||||
local url = buildUrl(opts)
|
||||
|
||||
-- In production, this would make HTTP request
|
||||
-- For now, return placeholder structure
|
||||
log("Fetching runs from: " .. url)
|
||||
|
||||
return {
|
||||
runs = {},
|
||||
total_count = 0,
|
||||
page = opts.page or 1,
|
||||
has_more = false
|
||||
}
|
||||
end
|
||||
|
||||
---Fetch jobs for a specific run
|
||||
---@param owner string Repository owner
|
||||
---@param repo string Repository name
|
||||
---@param run_id number Run ID
|
||||
---@return WorkflowJob[]
|
||||
function M.fetchJobs(owner, repo, run_id)
|
||||
local url = "https://api.github.com/repos/" .. owner .. "/" .. repo
|
||||
url = url .. "/actions/runs/" .. tostring(run_id) .. "/jobs"
|
||||
|
||||
log("Fetching jobs from: " .. url)
|
||||
|
||||
return {}
|
||||
end
|
||||
|
||||
---Fetch logs for a job
|
||||
---@param owner string Repository owner
|
||||
---@param repo string Repository name
|
||||
---@param job_id number Job ID
|
||||
---@return string Log content
|
||||
function M.fetchLogs(owner, repo, job_id)
|
||||
local url = "https://api.github.com/repos/" .. owner .. "/" .. repo
|
||||
url = url .. "/actions/jobs/" .. tostring(job_id) .. "/logs"
|
||||
|
||||
log("Fetching logs from: " .. url)
|
||||
|
||||
return ""
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
@@ -1,109 +1,109 @@
|
||||
-- Filter workflow runs
|
||||
|
||||
---@class FilterModule
|
||||
local M = {}
|
||||
|
||||
---Apply filters to a list of runs
|
||||
---@param runs WorkflowRun[] Array of workflow runs
|
||||
---@param filters RunFilters Filter criteria
|
||||
---@return WorkflowRun[] Filtered runs
|
||||
function M.filterRuns(runs, filters)
|
||||
local result = {}
|
||||
|
||||
for _, run in ipairs(runs) do
|
||||
local include = true
|
||||
|
||||
-- Filter by status
|
||||
if filters.status and filters.status ~= "all" then
|
||||
if run.status ~= filters.status and run.conclusion ~= filters.status then
|
||||
include = false
|
||||
end
|
||||
end
|
||||
|
||||
-- Filter by branch
|
||||
if include and filters.branch and filters.branch ~= "" then
|
||||
if run.head_branch ~= filters.branch then
|
||||
include = false
|
||||
end
|
||||
end
|
||||
|
||||
-- Filter by date range
|
||||
if include and filters.dateRange then
|
||||
local cutoff = M.getDateCutoff(filters.dateRange)
|
||||
if cutoff and run.created_at < cutoff then
|
||||
include = false
|
||||
end
|
||||
end
|
||||
|
||||
if include then
|
||||
table.insert(result, run)
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
---Get date cutoff for time range filter
|
||||
---@param range string Time range (1d, 7d, 30d)
|
||||
---@return string? ISO date string for cutoff
|
||||
function M.getDateCutoff(range)
|
||||
local days = 0
|
||||
|
||||
if range == "1d" then
|
||||
days = 1
|
||||
elseif range == "7d" then
|
||||
days = 7
|
||||
elseif range == "30d" then
|
||||
days = 30
|
||||
else
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Calculate cutoff date (placeholder)
|
||||
-- Would return ISO date string
|
||||
return nil
|
||||
end
|
||||
|
||||
---Apply filters from form data
|
||||
---@param runs WorkflowRun[] Array of workflow runs
|
||||
---@param formData table Form data with filter values
|
||||
---@return WorkflowRun[]
|
||||
function M.applyFilters(runs, formData)
|
||||
local filters = {
|
||||
status = formData.status,
|
||||
branch = formData.branch,
|
||||
dateRange = formData.dateRange
|
||||
}
|
||||
|
||||
return M.filterRuns(runs, filters)
|
||||
end
|
||||
|
||||
---Sort runs by field
|
||||
---@param runs WorkflowRun[] Array of workflow runs
|
||||
---@param field string Field to sort by
|
||||
---@param ascending boolean Sort ascending if true
|
||||
---@return WorkflowRun[] Sorted runs
|
||||
function M.sortRuns(runs, field, ascending)
|
||||
local sorted = {}
|
||||
for _, run in ipairs(runs) do
|
||||
table.insert(sorted, run)
|
||||
end
|
||||
|
||||
table.sort(sorted, function(a, b)
|
||||
local va = a[field]
|
||||
local vb = b[field]
|
||||
|
||||
if va == nil then return false end
|
||||
if vb == nil then return true end
|
||||
|
||||
if ascending then
|
||||
return va < vb
|
||||
else
|
||||
return va > vb
|
||||
end
|
||||
end)
|
||||
|
||||
return sorted
|
||||
end
|
||||
|
||||
return M
|
||||
-- Filter workflow runs
|
||||
|
||||
---@class FilterModule
|
||||
local M = {}
|
||||
|
||||
---Apply filters to a list of runs
|
||||
---@param runs WorkflowRun[] Array of workflow runs
|
||||
---@param filters RunFilters Filter criteria
|
||||
---@return WorkflowRun[] Filtered runs
|
||||
function M.filterRuns(runs, filters)
|
||||
local result = {}
|
||||
|
||||
for _, run in ipairs(runs) do
|
||||
local include = true
|
||||
|
||||
-- Filter by status
|
||||
if filters.status and filters.status ~= "all" then
|
||||
if run.status ~= filters.status and run.conclusion ~= filters.status then
|
||||
include = false
|
||||
end
|
||||
end
|
||||
|
||||
-- Filter by branch
|
||||
if include and filters.branch and filters.branch ~= "" then
|
||||
if run.head_branch ~= filters.branch then
|
||||
include = false
|
||||
end
|
||||
end
|
||||
|
||||
-- Filter by date range
|
||||
if include and filters.dateRange then
|
||||
local cutoff = M.getDateCutoff(filters.dateRange)
|
||||
if cutoff and run.created_at < cutoff then
|
||||
include = false
|
||||
end
|
||||
end
|
||||
|
||||
if include then
|
||||
table.insert(result, run)
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
---Get date cutoff for time range filter
|
||||
---@param range string Time range (1d, 7d, 30d)
|
||||
---@return string? ISO date string for cutoff
|
||||
function M.getDateCutoff(range)
|
||||
local days = 0
|
||||
|
||||
if range == "1d" then
|
||||
days = 1
|
||||
elseif range == "7d" then
|
||||
days = 7
|
||||
elseif range == "30d" then
|
||||
days = 30
|
||||
else
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Calculate cutoff date (placeholder)
|
||||
-- Would return ISO date string
|
||||
return nil
|
||||
end
|
||||
|
||||
---Apply filters from form data
|
||||
---@param runs WorkflowRun[] Array of workflow runs
|
||||
---@param formData table Form data with filter values
|
||||
---@return WorkflowRun[]
|
||||
function M.applyFilters(runs, formData)
|
||||
local filters = {
|
||||
status = formData.status,
|
||||
branch = formData.branch,
|
||||
dateRange = formData.dateRange
|
||||
}
|
||||
|
||||
return M.filterRuns(runs, filters)
|
||||
end
|
||||
|
||||
---Sort runs by field
|
||||
---@param runs WorkflowRun[] Array of workflow runs
|
||||
---@param field string Field to sort by
|
||||
---@param ascending boolean Sort ascending if true
|
||||
---@return WorkflowRun[] Sorted runs
|
||||
function M.sortRuns(runs, field, ascending)
|
||||
local sorted = {}
|
||||
for _, run in ipairs(runs) do
|
||||
table.insert(sorted, run)
|
||||
end
|
||||
|
||||
table.sort(sorted, function(a, b)
|
||||
local va = a[field]
|
||||
local vb = b[field]
|
||||
|
||||
if va == nil then return false end
|
||||
if vb == nil then return true end
|
||||
|
||||
if ascending then
|
||||
return va < vb
|
||||
else
|
||||
return va > vb
|
||||
end
|
||||
end)
|
||||
|
||||
return sorted
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
@@ -1,47 +1,47 @@
|
||||
-- GitHub Tools initialization
|
||||
-- Entry point for package setup
|
||||
|
||||
---@class InitModule
|
||||
local M = {}
|
||||
|
||||
---@class InitContext
|
||||
---@field config GitHubConfig GitHub configuration
|
||||
---@field user table Current user info
|
||||
|
||||
---@class InitResult
|
||||
---@field success boolean
|
||||
---@field message string
|
||||
---@field config GitHubConfig
|
||||
|
||||
---Initialize the GitHub Tools package
|
||||
---@param ctx InitContext Initialization context
|
||||
---@return InitResult
|
||||
function M.initialize(ctx)
|
||||
local config = ctx.config or {}
|
||||
|
||||
if not config.owner or config.owner == "" then
|
||||
return {
|
||||
success = false,
|
||||
message = "Repository owner is required",
|
||||
config = config
|
||||
}
|
||||
end
|
||||
|
||||
if not config.repo or config.repo == "" then
|
||||
return {
|
||||
success = false,
|
||||
message = "Repository name is required",
|
||||
config = config
|
||||
}
|
||||
end
|
||||
|
||||
log("GitHub Tools initialized for " .. config.owner .. "/" .. config.repo)
|
||||
|
||||
return {
|
||||
success = true,
|
||||
message = "GitHub Tools ready",
|
||||
config = config
|
||||
}
|
||||
end
|
||||
|
||||
return M
|
||||
-- GitHub Tools initialization
|
||||
-- Entry point for package setup
|
||||
|
||||
---@class InitModule
|
||||
local M = {}
|
||||
|
||||
---@class InitContext
|
||||
---@field config GitHubConfig GitHub configuration
|
||||
---@field user table Current user info
|
||||
|
||||
---@class InitResult
|
||||
---@field success boolean
|
||||
---@field message string
|
||||
---@field config GitHubConfig
|
||||
|
||||
---Initialize the GitHub Tools package
|
||||
---@param ctx InitContext Initialization context
|
||||
---@return InitResult
|
||||
function M.initialize(ctx)
|
||||
local config = ctx.config or {}
|
||||
|
||||
if not config.owner or config.owner == "" then
|
||||
return {
|
||||
success = false,
|
||||
message = "Repository owner is required",
|
||||
config = config
|
||||
}
|
||||
end
|
||||
|
||||
if not config.repo or config.repo == "" then
|
||||
return {
|
||||
success = false,
|
||||
message = "Repository name is required",
|
||||
config = config
|
||||
}
|
||||
end
|
||||
|
||||
log("GitHub Tools initialized for " .. config.owner .. "/" .. config.repo)
|
||||
|
||||
return {
|
||||
success = true,
|
||||
message = "GitHub Tools ready",
|
||||
config = config
|
||||
}
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
@@ -1,102 +1,102 @@
|
||||
-- Status utilities for workflow runs
|
||||
|
||||
---@class StatusModule
|
||||
local M = {}
|
||||
|
||||
---@alias StatusColor "success" | "error" | "warning" | "info" | "default"
|
||||
|
||||
---Get color for run status
|
||||
---@param status RunStatus
|
||||
---@return StatusColor
|
||||
function M.getStatusColor(status)
|
||||
if status == "success" then
|
||||
return "success"
|
||||
elseif status == "failure" then
|
||||
return "error"
|
||||
elseif status == "pending" or status == "in_progress" then
|
||||
return "warning"
|
||||
elseif status == "cancelled" or status == "skipped" then
|
||||
return "default"
|
||||
else
|
||||
return "info"
|
||||
end
|
||||
end
|
||||
|
||||
---Get icon name for run status
|
||||
---@param status RunStatus
|
||||
---@return string Icon name from fakemui/icons
|
||||
function M.getStatusIcon(status)
|
||||
if status == "success" then
|
||||
return "CheckCircle"
|
||||
elseif status == "failure" then
|
||||
return "XCircle"
|
||||
elseif status == "pending" then
|
||||
return "Clock"
|
||||
elseif status == "in_progress" then
|
||||
return "Loader"
|
||||
elseif status == "cancelled" then
|
||||
return "Cancel"
|
||||
elseif status == "skipped" then
|
||||
return "ArrowRight"
|
||||
else
|
||||
return "Info"
|
||||
end
|
||||
end
|
||||
|
||||
---Get human-readable status label
|
||||
---@param status RunStatus
|
||||
---@return string
|
||||
function M.getStatusLabel(status)
|
||||
local labels = {
|
||||
success = "Success",
|
||||
failure = "Failed",
|
||||
pending = "Pending",
|
||||
in_progress = "Running",
|
||||
cancelled = "Cancelled",
|
||||
skipped = "Skipped"
|
||||
}
|
||||
|
||||
return labels[status] or status
|
||||
end
|
||||
|
||||
---Render status badge component
|
||||
---@param status RunStatus
|
||||
---@return table UIComponent
|
||||
function M.renderBadge(status)
|
||||
return {
|
||||
type = "Chip",
|
||||
props = {
|
||||
label = M.getStatusLabel(status),
|
||||
color = M.getStatusColor(status),
|
||||
size = "small",
|
||||
icon = M.getStatusIcon(status)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
---Format duration in human-readable form
|
||||
---@param seconds number Duration in seconds
|
||||
---@return string Formatted duration
|
||||
function M.formatDuration(seconds)
|
||||
if seconds < 60 then
|
||||
return math.floor(seconds) .. "s"
|
||||
elseif seconds < 3600 then
|
||||
local mins = math.floor(seconds / 60)
|
||||
local secs = math.floor(seconds % 60)
|
||||
return mins .. "m " .. secs .. "s"
|
||||
else
|
||||
local hours = math.floor(seconds / 3600)
|
||||
local mins = math.floor((seconds % 3600) / 60)
|
||||
return hours .. "h " .. mins .. "m"
|
||||
end
|
||||
end
|
||||
|
||||
---Format timestamp as relative time
|
||||
---@param timestamp string ISO timestamp
|
||||
---@return string Relative time string
|
||||
function M.formatRelativeTime(timestamp)
|
||||
-- Placeholder - would calculate relative time
|
||||
return timestamp
|
||||
end
|
||||
|
||||
return M
|
||||
-- Status utilities for workflow runs
|
||||
|
||||
---@class StatusModule
|
||||
local M = {}
|
||||
|
||||
---@alias StatusColor "success" | "error" | "warning" | "info" | "default"
|
||||
|
||||
---Get color for run status
|
||||
---@param status RunStatus
|
||||
---@return StatusColor
|
||||
function M.getStatusColor(status)
|
||||
if status == "success" then
|
||||
return "success"
|
||||
elseif status == "failure" then
|
||||
return "error"
|
||||
elseif status == "pending" or status == "in_progress" then
|
||||
return "warning"
|
||||
elseif status == "cancelled" or status == "skipped" then
|
||||
return "default"
|
||||
else
|
||||
return "info"
|
||||
end
|
||||
end
|
||||
|
||||
---Get icon name for run status
|
||||
---@param status RunStatus
|
||||
---@return string Icon name from fakemui/icons
|
||||
function M.getStatusIcon(status)
|
||||
if status == "success" then
|
||||
return "CheckCircle"
|
||||
elseif status == "failure" then
|
||||
return "XCircle"
|
||||
elseif status == "pending" then
|
||||
return "Clock"
|
||||
elseif status == "in_progress" then
|
||||
return "Loader"
|
||||
elseif status == "cancelled" then
|
||||
return "Cancel"
|
||||
elseif status == "skipped" then
|
||||
return "ArrowRight"
|
||||
else
|
||||
return "Info"
|
||||
end
|
||||
end
|
||||
|
||||
---Get human-readable status label
|
||||
---@param status RunStatus
|
||||
---@return string
|
||||
function M.getStatusLabel(status)
|
||||
local labels = {
|
||||
success = "Success",
|
||||
failure = "Failed",
|
||||
pending = "Pending",
|
||||
in_progress = "Running",
|
||||
cancelled = "Cancelled",
|
||||
skipped = "Skipped"
|
||||
}
|
||||
|
||||
return labels[status] or status
|
||||
end
|
||||
|
||||
---Render status badge component
|
||||
---@param status RunStatus
|
||||
---@return table UIComponent
|
||||
function M.renderBadge(status)
|
||||
return {
|
||||
type = "Chip",
|
||||
props = {
|
||||
label = M.getStatusLabel(status),
|
||||
color = M.getStatusColor(status),
|
||||
size = "small",
|
||||
icon = M.getStatusIcon(status)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
---Format duration in human-readable form
|
||||
---@param seconds number Duration in seconds
|
||||
---@return string Formatted duration
|
||||
function M.formatDuration(seconds)
|
||||
if seconds < 60 then
|
||||
return math.floor(seconds) .. "s"
|
||||
elseif seconds < 3600 then
|
||||
local mins = math.floor(seconds / 60)
|
||||
local secs = math.floor(seconds % 60)
|
||||
return mins .. "m " .. secs .. "s"
|
||||
else
|
||||
local hours = math.floor(seconds / 3600)
|
||||
local mins = math.floor((seconds % 3600) / 60)
|
||||
return hours .. "h " .. mins .. "m"
|
||||
end
|
||||
end
|
||||
|
||||
---Format timestamp as relative time
|
||||
---@param timestamp string ISO timestamp
|
||||
---@return string Relative time string
|
||||
function M.formatRelativeTime(timestamp)
|
||||
-- Placeholder - would calculate relative time
|
||||
return timestamp
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"status": {
|
||||
"colors": [
|
||||
{ "status": "success", "expected_color": "success", "desc": "Success is green" },
|
||||
{ "status": "failure", "expected_color": "error", "desc": "Failure is red" },
|
||||
{ "status": "pending", "expected_color": "warning", "desc": "Pending is yellow" },
|
||||
{ "status": "in_progress", "expected_color": "warning", "desc": "In progress is yellow" },
|
||||
{ "status": "cancelled", "expected_color": "default", "desc": "Cancelled is gray" },
|
||||
{ "status": "skipped", "expected_color": "default", "desc": "Skipped is gray" }
|
||||
],
|
||||
"icons": [
|
||||
{ "status": "success", "expected_icon": "CheckCircle", "desc": "Success shows check" },
|
||||
{ "status": "failure", "expected_icon": "XCircle", "desc": "Failure shows X" },
|
||||
{ "status": "pending", "expected_icon": "Clock", "desc": "Pending shows clock" },
|
||||
{ "status": "in_progress", "expected_icon": "Loader", "desc": "Running shows loader" }
|
||||
],
|
||||
"durations": [
|
||||
{ "seconds": 30, "expected": "30s", "desc": "30 seconds" },
|
||||
{ "seconds": 90, "expected": "1m 30s", "desc": "90 seconds to minutes" },
|
||||
{ "seconds": 3660, "expected": "1h 1m", "desc": "3660 seconds to hours" },
|
||||
{ "seconds": 7200, "expected": "2h 0m", "desc": "2 hours exact" }
|
||||
]
|
||||
},
|
||||
"filter": {
|
||||
"status_filters": [
|
||||
{ "filter": "success", "runs": 10, "expected_count": 5, "desc": "Filter success only" },
|
||||
{ "filter": "failure", "runs": 10, "expected_count": 3, "desc": "Filter failures only" },
|
||||
{ "filter": "all", "runs": 10, "expected_count": 10, "desc": "No filter returns all" }
|
||||
],
|
||||
"date_ranges": [
|
||||
{ "range": "1d", "expected_days": 1, "desc": "Last 24 hours" },
|
||||
{ "range": "7d", "expected_days": 7, "desc": "Last 7 days" },
|
||||
{ "range": "30d", "expected_days": 30, "desc": "Last 30 days" }
|
||||
]
|
||||
},
|
||||
"analyze": {
|
||||
"success_rates": [
|
||||
{ "success": 8, "total": 10, "expected_rate": 80.0, "desc": "80% success rate" },
|
||||
{ "success": 0, "total": 10, "expected_rate": 0.0, "desc": "0% success rate" },
|
||||
{ "success": 10, "total": 10, "expected_rate": 100.0, "desc": "100% success rate" },
|
||||
{ "success": 0, "total": 0, "expected_rate": 0.0, "desc": "Empty list" }
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,53 +1,53 @@
|
||||
-- GitHub Tools package types
|
||||
---@meta
|
||||
|
||||
---@alias RunStatus "success" | "failure" | "pending" | "cancelled" | "skipped"
|
||||
---@alias RunConclusion "success" | "failure" | "cancelled" | "skipped" | "timed_out" | "action_required"
|
||||
|
||||
---@class WorkflowRun
|
||||
---@field id number Run ID
|
||||
---@field name string Workflow name
|
||||
---@field head_branch string Branch name
|
||||
---@field head_sha string Commit SHA
|
||||
---@field status RunStatus Run status
|
||||
---@field conclusion? RunConclusion Run conclusion
|
||||
---@field created_at string ISO timestamp
|
||||
---@field updated_at string ISO timestamp
|
||||
---@field run_number number Run number
|
||||
---@field html_url string GitHub URL
|
||||
|
||||
---@class WorkflowJob
|
||||
---@field id number Job ID
|
||||
---@field name string Job name
|
||||
---@field status RunStatus Job status
|
||||
---@field conclusion? RunConclusion Job conclusion
|
||||
---@field started_at? string ISO timestamp
|
||||
---@field completed_at? string ISO timestamp
|
||||
---@field steps JobStep[] Job steps
|
||||
|
||||
---@class JobStep
|
||||
---@field name string Step name
|
||||
---@field status RunStatus Step status
|
||||
---@field conclusion? RunConclusion Step conclusion
|
||||
---@field number number Step number
|
||||
|
||||
---@class RunFilters
|
||||
---@field status? RunStatus Filter by status
|
||||
---@field branch? string Filter by branch
|
||||
---@field dateRange? string Time range (1d, 7d, 30d)
|
||||
|
||||
---@class RunStats
|
||||
---@field total number Total runs
|
||||
---@field success number Successful runs
|
||||
---@field failure number Failed runs
|
||||
---@field pending number Pending runs
|
||||
---@field success_rate number Success percentage
|
||||
---@field avg_duration number Average duration in seconds
|
||||
|
||||
---@class GitHubConfig
|
||||
---@field owner string Repository owner
|
||||
---@field repo string Repository name
|
||||
---@field token? string GitHub token
|
||||
---@field workflow? string Workflow file name
|
||||
|
||||
return {}
|
||||
-- GitHub Tools package types
|
||||
---@meta
|
||||
|
||||
---@alias RunStatus "success" | "failure" | "pending" | "cancelled" | "skipped"
|
||||
---@alias RunConclusion "success" | "failure" | "cancelled" | "skipped" | "timed_out" | "action_required"
|
||||
|
||||
---@class WorkflowRun
|
||||
---@field id number Run ID
|
||||
---@field name string Workflow name
|
||||
---@field head_branch string Branch name
|
||||
---@field head_sha string Commit SHA
|
||||
---@field status RunStatus Run status
|
||||
---@field conclusion? RunConclusion Run conclusion
|
||||
---@field created_at string ISO timestamp
|
||||
---@field updated_at string ISO timestamp
|
||||
---@field run_number number Run number
|
||||
---@field html_url string GitHub URL
|
||||
|
||||
---@class WorkflowJob
|
||||
---@field id number Job ID
|
||||
---@field name string Job name
|
||||
---@field status RunStatus Job status
|
||||
---@field conclusion? RunConclusion Job conclusion
|
||||
---@field started_at? string ISO timestamp
|
||||
---@field completed_at? string ISO timestamp
|
||||
---@field steps JobStep[] Job steps
|
||||
|
||||
---@class JobStep
|
||||
---@field name string Step name
|
||||
---@field status RunStatus Step status
|
||||
---@field conclusion? RunConclusion Step conclusion
|
||||
---@field number number Step number
|
||||
|
||||
---@class RunFilters
|
||||
---@field status? RunStatus Filter by status
|
||||
---@field branch? string Filter by branch
|
||||
---@field dateRange? string Time range (1d, 7d, 30d)
|
||||
|
||||
---@class RunStats
|
||||
---@field total number Total runs
|
||||
---@field success number Successful runs
|
||||
---@field failure number Failed runs
|
||||
---@field pending number Pending runs
|
||||
---@field success_rate number Success percentage
|
||||
---@field avg_duration number Average duration in seconds
|
||||
|
||||
---@class GitHubConfig
|
||||
---@field owner string Repository owner
|
||||
---@field repo string Repository name
|
||||
---@field token? string GitHub token
|
||||
---@field workflow? string Workflow file name
|
||||
|
||||
return {}
|
||||
|
||||
Reference in New Issue
Block a user