Skip to content

Commit 760d963

Browse files
committed
Refactor status action & github sync logic
1 parent 3897a02 commit 760d963

File tree

7 files changed

+110
-218
lines changed

7 files changed

+110
-218
lines changed

src/actions/status.py

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
from src.webhooks.server import WebhookServer
55
from src.util.logging import Logger
66
from src.actions.result import ActionResult
7+
from src.jobs.base import JobStatus
8+
from src.config.config import Config
9+
import os
710

811

912
class StatusAction(BaseAction):
@@ -13,7 +16,8 @@ class StatusAction(BaseAction):
1316
name="status",
1417
description="Show system status",
1518
help_text="""Show the current status of the system, including:
16-
- Running jobs
19+
- Job statistics
20+
- Installed extensions
1721
- Scheduled actions
1822
- Webhook server status""",
1923
agent_hint="Use this command to check the system status",
@@ -22,29 +26,53 @@ class StatusAction(BaseAction):
2226

2327
def __init__(self):
2428
self.logger = Logger("StatusAction")
29+
self.config = Config()
2530

2631
async def execute(self, *args) -> ActionResult:
2732
"""Execute the status action"""
2833
try:
2934
lines = []
3035

31-
# Add running jobs section
32-
lines.append("🏃 Running Jobs:")
36+
# Add job statistics section
37+
lines.append("📊 Job Statistics:")
3338
try:
34-
# Get job status
3539
job_manager = await JobManager.get_instance()
3640
jobs = await job_manager.list_jobs()
3741

38-
if jobs:
39-
for job in jobs:
40-
lines.append(f"• {job['id']} ({job['type']}, status: {job['status']})")
42+
# Count jobs by status
43+
running = sum(1 for job in jobs if job["status"] == JobStatus.RUNNING.value)
44+
completed = sum(1 for job in jobs if job["status"] == JobStatus.COMPLETED.value)
45+
cancelled = sum(1 for job in jobs if job["status"] == JobStatus.CANCELLED.value)
46+
47+
lines.append(f"• Running: {running}")
48+
lines.append(f"• Completed: {completed}")
49+
lines.append(f"• Cancelled: {cancelled}")
50+
except Exception as e:
51+
lines.append(f"• Error getting job statistics: {str(e)}")
52+
53+
# Add installed extensions section
54+
lines.append("\n🧩 Installed Extensions:")
55+
try:
56+
extensions_dir = self.config.get("extensions_dir", "./extensions")
57+
if os.path.exists(extensions_dir):
58+
# Get list of directories in extensions folder
59+
extension_dirs = [
60+
d
61+
for d in os.listdir(extensions_dir)
62+
if os.path.isdir(os.path.join(extensions_dir, d)) and not d.startswith("_")
63+
]
64+
if extension_dirs:
65+
for ext_dir in sorted(extension_dirs):
66+
lines.append(f"• {ext_dir}")
67+
else:
68+
lines.append("• No extensions installed")
4169
else:
42-
lines.append("• No jobs currently running")
70+
lines.append("• Extensions directory not found")
4371
except Exception as e:
44-
lines.append(f"• Error getting jobs: {str(e)}")
72+
lines.append(f"• Error getting extensions: {str(e)}")
4573

74+
# Add scheduled actions section
4675
try:
47-
# Get scheduled actions status
4876
scheduler = await Scheduler.get_instance()
4977
actions = scheduler.list_actions()
5078

@@ -65,8 +93,8 @@ async def execute(self, *args) -> ActionResult:
6593
except Exception as e:
6694
lines.append(f"• Error getting scheduled actions: {str(e)}")
6795

96+
# Add webhook server status section
6897
try:
69-
# Get webhook status
7098
webhook_server = await WebhookServer.get_instance()
7199
lines.append("\n🌐 Webhook Server:")
72100
if webhook_server and webhook_server.runner:

src/jobs/github_monitor.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from src.handlers.registry import HandlerRegistry
99
import aiohttp
1010
from sqlalchemy import text
11-
from datetime import datetime, timedelta, timezone
11+
from datetime import datetime, timezone
1212
import asyncio
1313
from urllib.parse import urlparse
1414

@@ -207,12 +207,8 @@ async def _check_repo_updates(self, repo: Dict[str, Any]) -> None:
207207
self.logger.info(f"Checking updates for {repo_url}")
208208
self.logger.debug(f"Current state: {repo}")
209209

210-
# Use interval * 2 for the cutoff time
211-
cutoff_time = datetime.now(timezone.utc) - timedelta(seconds=self.interval * 2)
212-
213-
# Ensure cutoff time is timezone-aware
214-
if cutoff_time.tzinfo is None:
215-
cutoff_time = cutoff_time.replace(tzinfo=timezone.utc)
210+
# Use last_check time from repo state (will be set to creation time for new repos)
211+
cutoff_time = repo["last_check"].replace(tzinfo=timezone.utc) if repo["last_check"] else datetime.now(timezone.utc)
216212

217213
# Check commits and PRs in parallel
218214
commits_task = self._get_new_commits(owner, name, cutoff_time)

src/models/github.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class GitHubRepoState(Base):
1515
repo_url = Column(String, primary_key=True) # Normalized repo URL
1616
last_commit_sha = Column(String) # Last processed commit SHA
1717
last_pr_number = Column(Integer) # Last processed PR number
18-
last_check = Column(DateTime) # Last time we checked this repo
18+
last_check = Column(DateTime, default=datetime.utcnow) # Last time we checked this repo
1919
created_at = Column(DateTime, default=datetime.utcnow)
2020
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
2121

src/util/db_schema.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from src.backend.database import db
33

44
# Define allowed tables
5-
ALLOWED_TABLES = {"projects", "assets", "event_logs"}
5+
ALLOWED_TABLES = {"projects", "assets"}
66

77

88
def get_table_schema() -> str:
@@ -64,8 +64,6 @@ def get_db_query_hint() -> str:
6464

6565
examples = """
6666
- List projects: db_query '{"from": "projects", "order_by": [{"field": "id", "direction": "desc"}], "limit": 10}'
67-
- Search events: db_query '{"from": "event_logs", "order_by": [{"field": "created_at", "direction": "desc"}], "limit": 10}'
68-
- Filter by multiple conditions: db_query '{"from": "event_logs", "where": [{"field": "handler_name", "op": "=", "value": "ProjectEventHandler"},{"field": "created_at", "op": ">", "value": "2024-01-01"}], "limit": 10}'
6967
"""
7068

7169
return f"""Database Schema:

tests/actions/test_status.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,10 @@ async def test_status_running_jobs(mock_job_manager, mock_scheduler, mock_webhoo
8989
result = await action.execute()
9090

9191
result_str = str(result)
92-
assert "🏃 Running Jobs:" in result_str
93-
assert "test-job-1" in result_str
94-
assert "test" in result_str
95-
assert "running" in result_str
92+
assert "📊 Job Statistics:" in result_str
93+
assert "• Running: 1" in result_str
94+
assert "• Completed: 1" in result_str
95+
assert "• Cancelled: 0" in result_str
9696

9797

9898
@pytest.mark.asyncio
@@ -110,8 +110,10 @@ async def test_status_no_running_jobs(mock_job_manager, mock_scheduler, mock_web
110110
result = await action.execute()
111111

112112
result_str = str(result)
113-
assert "🏃 Running Jobs:" in result_str
114-
assert "No jobs currently running" in result_str
113+
assert "📊 Job Statistics:" in result_str
114+
assert "• Running: 0" in result_str
115+
assert "• Completed: 0" in result_str
116+
assert "• Cancelled: 0" in result_str
115117

116118

117119
@pytest.mark.asyncio
@@ -126,9 +128,9 @@ async def test_status_scheduled_actions(mock_job_manager, mock_scheduler, mock_w
126128
result = await action.execute()
127129

128130
assert "📅 Scheduled Actions:" in result
129-
assert "test_action" in result
130-
assert "test_command" in result
131-
assert "60 minutes" in result
131+
assert "test_action" in result
132+
assert "• Command: test_command" in result
133+
assert "• Interval: 60 minutes" in result
132134

133135

134136
@pytest.mark.asyncio
@@ -143,7 +145,7 @@ async def test_status_no_scheduled_actions(mock_job_manager, mock_scheduler, moc
143145
action = StatusAction()
144146
result = await action.execute()
145147

146-
assert "No scheduled actions configured" in result
148+
assert "No scheduled actions configured" in result
147149

148150

149151
@pytest.mark.asyncio
@@ -158,7 +160,7 @@ async def test_status_webhook_server(mock_job_manager, mock_scheduler, mock_webh
158160
result = await action.execute()
159161

160162
assert "🌐 Webhook Server:" in result
161-
assert "Running on port 8080" in result
163+
assert "Running on port 8080" in result
162164

163165

164166
@pytest.mark.asyncio
@@ -173,7 +175,7 @@ async def test_status_webhook_server_not_running(mock_job_manager, mock_schedule
173175
action = StatusAction()
174176
result = await action.execute()
175177

176-
assert "Not running" in result
178+
assert "Not running" in result
177179

178180

179181
@pytest.mark.asyncio
@@ -191,5 +193,5 @@ async def test_status_error_handling(mock_job_manager, mock_scheduler, mock_webh
191193
result = await action.execute()
192194

193195
result_str = str(result)
194-
assert "🏃 Running Jobs:" in result_str
195-
assert "Error getting jobs: Test error" in result_str
196+
assert "📊 Job Statistics:" in result_str
197+
assert "Error getting job statistics: Test error" in result_str

tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858

5959
# Mock engine inspection results
6060
mock_inspector = Mock()
61-
mock_inspector.get_table_names.return_value = ["projects", "assets", "event_logs"]
61+
mock_inspector.get_table_names.return_value = ["projects", "assets"]
6262
mock_inspector.get_columns.return_value = [
6363
{"name": "id", "type": "INTEGER", "nullable": False},
6464
{"name": "name", "type": "VARCHAR", "nullable": True},

0 commit comments

Comments
 (0)