gitlink-cli/shortcuts/workflow/repo_report_fetch.go

137 lines
3.5 KiB
Go

package workflow
import (
"fmt"
"strings"
"github.com/gitlink-org/gitlink-cli/shortcuts/common"
)
type RepoReportFetchOptions struct {
Owner string
Repo string
IssueLimit int
PRLimit int
StaleDays int
IncludeIssues bool
IncludePRs bool
IncludeHealth bool
}
func FetchRepoReportInput(ctx *common.RuntimeContext, opts RepoReportFetchOptions) (RepoReportInput, []ScoringNote, error) {
owner, repo, err := resolveFetchRepo(ctx, opts.Owner, opts.Repo)
if err != nil {
return RepoReportInput{}, nil, fmt.Errorf("workflow +repo-report remote mode requires --owner and --repo or a Git remote: %w", err)
}
if opts.IssueLimit <= 0 {
opts.IssueLimit = 20
}
if opts.PRLimit <= 0 {
opts.PRLimit = 10
}
if opts.StaleDays <= 0 {
opts.StaleDays = 30
}
input := RepoReportInput{
Repository: fmt.Sprintf("%s/%s", owner, repo),
Source: "remote-read-only-fetch",
}
notes := []ScoringNote{}
successes := 0
if opts.IncludeHealth {
health, healthNotes, err := FetchHealthInput(ctx, HealthFetchOptions{
Owner: owner,
Repo: repo,
StaleDays: opts.StaleDays,
IncludeCI: true,
IncludeRelease: true,
IncludeDocs: true,
})
notes = append(notes, healthNotes...)
if err != nil {
notes = append(notes, ScoringNote{Metric: "repo_report_health", Note: fmt.Sprintf("health fetch failed: %v", err)})
} else {
input.Health = &health
successes++
}
}
if opts.IncludeIssues {
issues, err := FetchIssuesForTriage(ctx, TriageFetchOptions{
Owner: owner,
Repo: repo,
State: "open",
Limit: opts.IssueLimit,
Page: 1,
})
if err != nil {
notes = append(notes, ScoringNote{Metric: "repo_report_issues", Note: fmt.Sprintf("issue fetch failed: %v", err)})
} else {
input.Issues = issues
successes++
}
}
if opts.IncludePRs {
prs, err := fetchPRListForReport(ctx, owner, repo, opts.PRLimit)
if err != nil {
notes = append(notes, ScoringNote{Metric: "repo_report_prs", Note: fmt.Sprintf("pull request list fetch failed: %v", err)})
} else {
input.PullRequests = prs
successes++
if len(prs) > 0 {
notes = append(notes, ScoringNote{
Metric: "repo_report_prs",
Note: "PR report uses list metadata only; changed files and commits require workflow +pr-summary with a PR number.",
})
}
}
}
if successes == 0 {
if len(notes) == 0 {
notes = append(notes, ScoringNote{Metric: "repo_report", Note: "no report sections were enabled or fetched"})
}
return RepoReportInput{}, uniqueScoringNotes(notes), fmt.Errorf("fetch repo report: all enabled sections failed")
}
return input, uniqueScoringNotes(notes), nil
}
func fetchPRListForReport(ctx *common.RuntimeContext, owner, repo string, limit int) ([]PRSummaryInput, error) {
if limit <= 0 {
limit = 10
}
query := pullListQuery("open")
query.Set("page", "1")
query.Set("limit", fmt.Sprintf("%d", limit))
env, err := ctx.CallAPIWithQuery("GET", workflowRepoPath(owner, repo)+"/pulls", query)
if err != nil {
return nil, err
}
items := apiList(env.Data)
inputs := make([]PRSummaryInput, 0, len(items))
for _, raw := range items {
item, ok := raw.(map[string]interface{})
if !ok {
continue
}
input, ok := normalizePRSummaryItem(item)
if !ok {
continue
}
input.Repository = fmt.Sprintf("%s/%s", owner, repo)
input.Source = "remote-read-only-fetch:list-metadata"
if strings.TrimSpace(input.State) == "" {
input.State = "open"
}
inputs = append(inputs, input)
if len(inputs) >= limit {
break
}
}
return inputs, nil
}