fix: resolve CI/CD issues - rewrote CI workflow and fixed Python linting errors
Some checks failed
DevDash CLI CI / test (push) Has been cancelled
Some checks failed
DevDash CLI CI / test (push) Has been cancelled
This commit is contained in:
@@ -1,29 +1,171 @@
|
|||||||
from textual.widgets import Static, Label
|
"""Card components for DevDash."""
|
||||||
from textual.containers import Container
|
from textual.widgets import Static
|
||||||
from typing import List, Optional
|
|
||||||
|
from src.models import IssueModel, PullRequestModel, WorkflowModel
|
||||||
|
|
||||||
|
|
||||||
class PullRequestCard(Container):
|
class PullRequestCard(Static):
|
||||||
def __init__(
|
"""Pull request card component."""
|
||||||
self,
|
|
||||||
title: str,
|
|
||||||
author: str,
|
|
||||||
number: int,
|
|
||||||
draft: bool = False,
|
|
||||||
labels: List[str] = None,
|
|
||||||
**kwargs
|
|
||||||
):
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
self.title = title
|
|
||||||
self.author = author
|
|
||||||
self.number = number
|
|
||||||
self.draft = draft
|
|
||||||
self.labels = labels or []
|
|
||||||
|
|
||||||
def compose(self) -> ComposeResult:
|
CSS = """
|
||||||
yield Label(f"PR #{self.number}: {self.title}", classes="pr-title")
|
PullRequestCard {
|
||||||
yield Static(f"by {self.author}", classes="pr-author")
|
height: auto;
|
||||||
if self.labels:
|
border: solid $surface;
|
||||||
yield Static(f"Labels: {', '.join(self.labels)}", classes="pr-labels")
|
padding: 1;
|
||||||
if self.draft:
|
margin: 0 1 1 0;
|
||||||
yield Static("[DRAFT]", classes="draft-badge")
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, pr: PullRequestModel):
|
||||||
|
"""Initialize PR card.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
pr: Pull request model.
|
||||||
|
"""
|
||||||
|
super().__init__()
|
||||||
|
self.pr = pr
|
||||||
|
|
||||||
|
def compose(self):
|
||||||
|
"""Compose the card."""
|
||||||
|
yield Static(self._get_content())
|
||||||
|
|
||||||
|
def _get_content(self) -> str:
|
||||||
|
"""Get card content.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Formatted card content.
|
||||||
|
"""
|
||||||
|
pr = self.pr
|
||||||
|
lines = []
|
||||||
|
lines.append(f"#{pr.number} [link]{pr.title[:40]}[/]")
|
||||||
|
lines.append(f"[dim]by[/] {pr.author}")
|
||||||
|
|
||||||
|
if pr.checks_total > 0:
|
||||||
|
if pr.checks_passed is True:
|
||||||
|
checks_status = "[green]✓[/]"
|
||||||
|
elif pr.checks_passed is False:
|
||||||
|
checks_status = "[red]✗[/]"
|
||||||
|
else:
|
||||||
|
checks_status = "[yellow]?[/]"
|
||||||
|
lines.append(f"[dim]checks:[/] {checks_status} {pr.checks_success}/{pr.checks_total}")
|
||||||
|
|
||||||
|
if pr.labels:
|
||||||
|
label_text = ", ".join(f"[cyan]{label}[/]" for label in pr.labels[:3])
|
||||||
|
if len(pr.labels) > 3:
|
||||||
|
label_text += f" [dim]+{len(pr.labels) - 3}[/]"
|
||||||
|
lines.append(label_text)
|
||||||
|
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
class IssueCard(Static):
|
||||||
|
"""Issue card component."""
|
||||||
|
|
||||||
|
CSS = """
|
||||||
|
IssueCard {
|
||||||
|
height: auto;
|
||||||
|
border: solid $surface;
|
||||||
|
padding: 1;
|
||||||
|
margin: 0 1 1 0;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, issue: IssueModel):
|
||||||
|
"""Initialize issue card.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
issue: Issue model.
|
||||||
|
"""
|
||||||
|
super().__init__()
|
||||||
|
self.issue = issue
|
||||||
|
|
||||||
|
def compose(self):
|
||||||
|
"""Compose the card."""
|
||||||
|
yield Static(self._get_content())
|
||||||
|
|
||||||
|
def _get_content(self) -> str:
|
||||||
|
"""Get card content.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Formatted card content.
|
||||||
|
"""
|
||||||
|
issue = self.issue
|
||||||
|
lines = []
|
||||||
|
lines.append(f"#{issue.number} [link]{issue.title[:40]}[/]")
|
||||||
|
lines.append(f"[dim]by[/] {issue.author}")
|
||||||
|
|
||||||
|
if issue.labels:
|
||||||
|
label_text = ", ".join(f"[cyan]{label}[/]" for label in issue.labels[:3])
|
||||||
|
if len(issue.labels) > 3:
|
||||||
|
label_text += f" [dim]+{len(issue.labels) - 3}[/]"
|
||||||
|
lines.append(label_text)
|
||||||
|
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
class WorkflowCard(Static):
|
||||||
|
"""Workflow card component."""
|
||||||
|
|
||||||
|
CSS = """
|
||||||
|
WorkflowCard {
|
||||||
|
height: auto;
|
||||||
|
border: solid $surface;
|
||||||
|
padding: 1;
|
||||||
|
margin: 0 1 1 0;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, workflow: WorkflowModel):
|
||||||
|
"""Initialize workflow card.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
workflow: Workflow model.
|
||||||
|
"""
|
||||||
|
super().__init__()
|
||||||
|
self.workflow = workflow
|
||||||
|
|
||||||
|
def compose(self):
|
||||||
|
"""Compose the card."""
|
||||||
|
yield Static(self._get_content())
|
||||||
|
|
||||||
|
def _get_content(self) -> str:
|
||||||
|
"""Get card content.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Formatted card content.
|
||||||
|
"""
|
||||||
|
wf = self.workflow
|
||||||
|
status_colors = {
|
||||||
|
"queued": "yellow",
|
||||||
|
"in_progress": "blue",
|
||||||
|
"completed": "green"
|
||||||
|
}
|
||||||
|
conclusion_colors = {
|
||||||
|
"success": "green",
|
||||||
|
"failure": "red",
|
||||||
|
"cancelled": "yellow",
|
||||||
|
"skipped": "gray"
|
||||||
|
}
|
||||||
|
|
||||||
|
color = status_colors.get(wf.status, "gray")
|
||||||
|
if wf.status == "completed" and wf.conclusion:
|
||||||
|
color = conclusion_colors.get(wf.conclusion, "gray")
|
||||||
|
|
||||||
|
icon = "○" if wf.status == "queued" else "◉" if wf.status == "in_progress" else "✓" if wf.conclusion == "success" else "✗" if wf.conclusion == "failure" else "○"
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
lines.append(f"[{color}]{icon}[/] {wf.name} #{wf.run_number}")
|
||||||
|
lines.append(f"[dim]branch:[/] {wf.head_branch[:20]}")
|
||||||
|
lines.append(f"[dim]commit:[/] {wf.head_sha[:7]}")
|
||||||
|
|
||||||
|
if wf.duration_seconds:
|
||||||
|
duration = wf.duration_seconds
|
||||||
|
if duration < 60:
|
||||||
|
duration_text = f"{duration}s"
|
||||||
|
elif duration < 3600:
|
||||||
|
duration_text = f"{duration // 60}m {duration % 60}s"
|
||||||
|
else:
|
||||||
|
duration_text = f"{duration // 3600}h {(duration % 3600) // 60}m"
|
||||||
|
lines.append(f"[dim]duration:[/] {duration_text}")
|
||||||
|
|
||||||
|
return "\n".join(lines)
|
||||||
|
|||||||
Reference in New Issue
Block a user