pipeline dag visualization + Dashboard command center upgrade + command palette wiring. fixed repo pipeline page.
This commit is contained in:
@@ -61,12 +61,27 @@ type dashRepo struct {
|
||||
OpenIssueCount int `json:"openIssueCount"`
|
||||
}
|
||||
|
||||
type dashRun struct {
|
||||
ID int64 `json:"id"`
|
||||
RepoID int64 `json:"repoId"`
|
||||
RepoName string `json:"repoName"`
|
||||
OwnerName string `json:"ownerName"`
|
||||
TriggerRef string `json:"triggerRef"`
|
||||
TriggerSHA string `json:"triggerSha"`
|
||||
TriggeredBy string `json:"triggeredBy"`
|
||||
Status string `json:"status"`
|
||||
StartedAt *string `json:"startedAt"`
|
||||
FinishedAt *string `json:"finishedAt"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
}
|
||||
|
||||
type dashboardResponse struct {
|
||||
Stats dashStats `json:"stats"`
|
||||
ReviewQueue []dashPR `json:"reviewQueue"`
|
||||
MyOpenPRs []dashPR `json:"myOpenPRs"`
|
||||
MyOpenIssues []dashIssue `json:"myOpenIssues"`
|
||||
Repos []dashRepo `json:"repos"`
|
||||
RecentRuns []dashRun `json:"recentRuns"`
|
||||
}
|
||||
|
||||
// ── Handler ───────────────────────────────────────────────────────────────────
|
||||
@@ -211,6 +226,36 @@ func (h *DashboardHandler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
// 7. Recent CI runs across user repos.
|
||||
var recentRuns []models.PipelineRun
|
||||
if len(repoIDs) > 0 {
|
||||
h.db.In("repo_id", repoIDs).Desc("id").Limit(5).Find(&recentRuns)
|
||||
}
|
||||
runsDash := make([]dashRun, 0, len(recentRuns))
|
||||
for _, run := range recentRuns {
|
||||
rp := repoByID[run.RepoID]
|
||||
dr := dashRun{
|
||||
ID: run.ID,
|
||||
RepoID: run.RepoID,
|
||||
RepoName: rp.Name,
|
||||
OwnerName: owner.Username,
|
||||
TriggerRef: run.TriggerRef,
|
||||
TriggerSHA: run.TriggerSHA,
|
||||
TriggeredBy: run.TriggeredBy,
|
||||
Status: run.Status,
|
||||
CreatedAt: run.CreatedAt.Format("2006-01-02T15:04:05Z"),
|
||||
}
|
||||
if run.StartedAt != nil {
|
||||
s := run.StartedAt.Format("2006-01-02T15:04:05Z")
|
||||
dr.StartedAt = &s
|
||||
}
|
||||
if run.FinishedAt != nil {
|
||||
f := run.FinishedAt.Format("2006-01-02T15:04:05Z")
|
||||
dr.FinishedAt = &f
|
||||
}
|
||||
runsDash = append(runsDash, dr)
|
||||
}
|
||||
|
||||
resp := dashboardResponse{
|
||||
Stats: dashStats{
|
||||
RepoCount: len(repos),
|
||||
@@ -222,6 +267,7 @@ func (h *DashboardHandler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
MyOpenPRs: myPRDash,
|
||||
MyOpenIssues: issueDash,
|
||||
Repos: dashRepos,
|
||||
RecentRuns: runsDash,
|
||||
}
|
||||
jsonOK(w, resp)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
"xorm.io/xorm"
|
||||
|
||||
"github.com/forgeo/forgebucket/internal/api/middleware"
|
||||
"github.com/forgeo/forgebucket/internal/models"
|
||||
)
|
||||
|
||||
@@ -19,6 +20,59 @@ func NewPipelineHandler(db *xorm.Engine) *PipelineHandler {
|
||||
return &PipelineHandler{db: db}
|
||||
}
|
||||
|
||||
// recentRunResponse extends PipelineRun with repo context for the global feed.
|
||||
type recentRunResponse struct {
|
||||
models.PipelineRun
|
||||
RepoName string `json:"repoName"`
|
||||
OwnerName string `json:"ownerName"`
|
||||
}
|
||||
|
||||
// ListRecentRuns returns recent runs across all repos owned by the current user.
|
||||
// GET /api/v1/pipelines/runs
|
||||
func (h *PipelineHandler) ListRecentRuns(w http.ResponseWriter, r *http.Request) {
|
||||
userID, _ := middleware.UserIDFromContext(r.Context())
|
||||
|
||||
limit := 30
|
||||
if l, err := strconv.Atoi(r.URL.Query().Get("limit")); err == nil && l > 0 && l <= 100 {
|
||||
limit = l
|
||||
}
|
||||
|
||||
// Repos owned by this user.
|
||||
var repos []models.Repository
|
||||
h.db.Where("owner_id = ?", userID).Cols("id", "name").Find(&repos)
|
||||
if len(repos) == 0 {
|
||||
jsonOK(w, []recentRunResponse{})
|
||||
return
|
||||
}
|
||||
|
||||
repoIDs := make([]int64, len(repos))
|
||||
repoNameByID := make(map[int64]string, len(repos))
|
||||
for i, rp := range repos {
|
||||
repoIDs[i] = rp.ID
|
||||
repoNameByID[rp.ID] = rp.Name
|
||||
}
|
||||
|
||||
// Owner username.
|
||||
var owner models.User
|
||||
h.db.ID(userID).Cols("username").Get(&owner)
|
||||
|
||||
var runs []models.PipelineRun
|
||||
h.db.In("repo_id", repoIDs).Desc("id").Limit(limit).Find(&runs)
|
||||
if runs == nil {
|
||||
runs = []models.PipelineRun{}
|
||||
}
|
||||
|
||||
result := make([]recentRunResponse, len(runs))
|
||||
for i, run := range runs {
|
||||
result[i] = recentRunResponse{
|
||||
PipelineRun: run,
|
||||
RepoName: repoNameByID[run.RepoID],
|
||||
OwnerName: owner.Username,
|
||||
}
|
||||
}
|
||||
jsonOK(w, result)
|
||||
}
|
||||
|
||||
// ListPipelines returns all pipeline definitions for a repository.
|
||||
func (h *PipelineHandler) ListPipelines(w http.ResponseWriter, r *http.Request) {
|
||||
repoID, ok := h.repoID(w, r)
|
||||
|
||||
Reference in New Issue
Block a user