package statusreport import ( "fmt" "net/http" "buf.build/gen/go/openstatus/api/connectrpc/gosimple/openstatus/status_report/v1/status_reportv1connect" status_reportv1 "buf.build/gen/go/openstatus/api/protocolbuffers/go/openstatus/status_report/v1" "connectrpc.com/connect" "github.com/fatih/color" "github.com/urfave/cli/v3" "github.com/openstatusHQ/cli/internal/api" ) func NewStatusReportClient(apiKey string) status_reportv1connect.StatusReportServiceClient { return status_reportv1connect.NewStatusReportServiceClient( api.DefaultHTTPClient, api.ConnectBaseURL, connect.WithInterceptors(api.NewAuthInterceptor(apiKey)), connect.WithProtoJSON(), ) } func NewStatusReportClientWithHTTPClient(httpClient *http.Client, apiKey string) status_reportv1connect.StatusReportServiceClient { return status_reportv1connect.NewStatusReportServiceClient( httpClient, api.ConnectBaseURL, connect.WithInterceptors(api.NewAuthInterceptor(apiKey)), connect.WithProtoJSON(), ) } func statusToSDK(s string) (status_reportv1.StatusReportStatus, error) { switch s { case "investigating": return status_reportv1.StatusReportStatus_STATUS_REPORT_STATUS_INVESTIGATING, nil case "identified": return status_reportv1.StatusReportStatus_STATUS_REPORT_STATUS_IDENTIFIED, nil case "monitoring": return status_reportv1.StatusReportStatus_STATUS_REPORT_STATUS_MONITORING, nil case "resolved": return status_reportv1.StatusReportStatus_STATUS_REPORT_STATUS_RESOLVED, nil default: return status_reportv1.StatusReportStatus_STATUS_REPORT_STATUS_UNSPECIFIED, fmt.Errorf("invalid status %q: must be one of investigating, identified, monitoring, resolved", s) } } func statusToString(s status_reportv1.StatusReportStatus) string { switch s { case status_reportv1.StatusReportStatus_STATUS_REPORT_STATUS_INVESTIGATING: return "investigating" case status_reportv1.StatusReportStatus_STATUS_REPORT_STATUS_IDENTIFIED: return "identified" case status_reportv1.StatusReportStatus_STATUS_REPORT_STATUS_MONITORING: return "monitoring" case status_reportv1.StatusReportStatus_STATUS_REPORT_STATUS_RESOLVED: return "resolved" default: return "unknown" } } func statusColor(s string) string { switch s { case "investigating": return color.RedString(s) case "identified": return color.YellowString(s) case "monitoring": return color.BlueString(s) case "resolved": return color.GreenString(s) default: return s } } func impactToSDK(s string) (status_reportv1.PageComponentImpact, error) { switch s { case "operational": return status_reportv1.PageComponentImpact_PAGE_COMPONENT_IMPACT_OPERATIONAL, nil case "degraded", "degraded_performance": return status_reportv1.PageComponentImpact_PAGE_COMPONENT_IMPACT_DEGRADED_PERFORMANCE, nil case "partial_outage": return status_reportv1.PageComponentImpact_PAGE_COMPONENT_IMPACT_PARTIAL_OUTAGE, nil case "major_outage": return status_reportv1.PageComponentImpact_PAGE_COMPONENT_IMPACT_MAJOR_OUTAGE, nil default: return status_reportv1.PageComponentImpact_PAGE_COMPONENT_IMPACT_UNSPECIFIED, fmt.Errorf("invalid impact %q: must be one of operational, degraded, partial_outage, major_outage", s) } } func impactToString(i status_reportv1.PageComponentImpact) string { switch i { case status_reportv1.PageComponentImpact_PAGE_COMPONENT_IMPACT_OPERATIONAL: return "operational" case status_reportv1.PageComponentImpact_PAGE_COMPONENT_IMPACT_DEGRADED_PERFORMANCE: return "degraded" case status_reportv1.PageComponentImpact_PAGE_COMPONENT_IMPACT_PARTIAL_OUTAGE: return "partial_outage" case status_reportv1.PageComponentImpact_PAGE_COMPONENT_IMPACT_MAJOR_OUTAGE: return "major_outage" default: return "" } } func impactColor(s string) string { switch s { case "operational": return color.GreenString(s) case "degraded": return color.YellowString(s) case "partial_outage": return color.MagentaString(s) case "major_outage": return color.RedString(s) default: return s } } func currentImpacts(updates []*status_reportv1.StatusReportUpdate) map[string]status_reportv1.PageComponentImpact { if len(updates) == 0 { return nil } out := make(map[string]status_reportv1.PageComponentImpact) for _, u := range updates { for _, ci := range u.GetComponentImpacts() { out[ci.GetPageComponentId()] = ci.GetImpact() } } return out } func affectedOrder(report *status_reportv1.StatusReport) []string { if report == nil { return nil } seen := make(map[string]struct{}) out := make([]string, 0, len(report.GetPageComponentIds())) for _, id := range report.GetPageComponentIds() { if _, ok := seen[id]; ok { continue } seen[id] = struct{}{} out = append(out, id) } for _, u := range report.GetUpdates() { for _, ci := range u.GetComponentImpacts() { id := ci.GetPageComponentId() if _, ok := seen[id]; ok { continue } seen[id] = struct{}{} out = append(out, id) } } return out } func StatusReportCmd() *cli.Command { return &cli.Command{ Name: "status-report", Aliases: []string{"sr"}, Usage: "Manage status reports", Commands: []*cli.Command{ GetStatusReportListCmd(), GetStatusReportInfoCmd(), GetStatusReportCreateCmd(), GetStatusReportUpdateCmd(), GetStatusReportDeleteCmd(), GetStatusReportAddUpdateCmd(), }, } }