Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add /api/v1 routes to openapi spec #637

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ build-backend = "poetry.core.masonry.api"

[tool.poetry.scripts]
codegate = "codegate.cli:main"
generate-openapi = "src.codegate.dashboard.dashboard:generate_openapi"
generate-openapi = "src.codegate.server:generate_openapi"

[tool.black]
line-length = 100
Expand Down
39 changes: 12 additions & 27 deletions src/codegate/dashboard/dashboard.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import asyncio
import json
from typing import AsyncGenerator, List, Optional

import requests
import structlog
from fastapi import APIRouter, Depends, FastAPI
from fastapi import APIRouter, Depends
from fastapi.responses import StreamingResponse
from codegate import __version__

from codegate import __version__
from codegate.dashboard.post_processing import (
parse_get_alert_conversation,
parse_messages_in_conversations,
Expand All @@ -20,23 +19,23 @@
dashboard_router = APIRouter(tags=["Dashboard"])
db_reader = None


def get_db_reader():
global db_reader
if db_reader is None:
db_reader = DbReader()
return db_reader


def fetch_latest_version() -> str:
url = "https://api.github.com/repos/stacklok/codegate/releases/latest"
headers = {
"Accept": "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28"
}
headers = {"Accept": "application/vnd.github+json", "X-GitHub-Api-Version": "2022-11-28"}
response = requests.get(url, headers=headers, timeout=5)
response.raise_for_status()
data = response.json()
return data.get("tag_name", "unknown")


@dashboard_router.get("/dashboard/messages")
def get_messages(db_reader: DbReader = Depends(get_db_reader)) -> List[Conversation]:
"""
Expand Down Expand Up @@ -72,17 +71,18 @@ async def stream_sse():
"""
return StreamingResponse(generate_sse_events(), media_type="text/event-stream")


@dashboard_router.get("/dashboard/version")
def version_check():
try:
latest_version = fetch_latest_version()

# normalize the versions as github will return them with a 'v' prefix
current_version = __version__.lstrip('v')
latest_version_stripped = latest_version.lstrip('v')
current_version = __version__.lstrip("v")
latest_version_stripped = latest_version.lstrip("v")

is_latest: bool = latest_version_stripped == current_version

return {
"current_version": current_version,
"latest_version": latest_version_stripped,
Expand All @@ -95,28 +95,13 @@ def version_check():
"current_version": __version__,
"latest_version": "unknown",
"is_latest": None,
"error": "An error occurred while fetching the latest version"
"error": "An error occurred while fetching the latest version",
}
except Exception as e:
logger.error(f"Unexpected error: {str(e)}")
return {
"current_version": __version__,
"latest_version": "unknown",
"is_latest": None,
"error": "An unexpected error occurred"
"error": "An unexpected error occurred",
}


def generate_openapi():
# Create a temporary FastAPI app instance
app = FastAPI()

# Include your defined router
app.include_router(dashboard_router)

# Generate OpenAPI JSON
openapi_schema = app.openapi()

# Convert the schema to JSON string for easier handling or storage
openapi_json = json.dumps(openapi_schema, indent=2)
print(openapi_json)
13 changes: 13 additions & 0 deletions src/codegate/server.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
import traceback

import structlog
Expand Down Expand Up @@ -102,3 +103,15 @@ async def health_check():
app.include_router(v1, prefix="/api/v1", tags=["CodeGate API"])

return app


def generate_openapi():
# Create a temporary FastAPI app instance
app = init_app(None)

# Generate OpenAPI JSON
openapi_schema = app.openapi()

# Convert the schema to JSON string for easier handling or storage
openapi_json = json.dumps(openapi_schema, indent=2)
print(openapi_json)
8 changes: 2 additions & 6 deletions tests/pipeline/workspace/test_workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,7 @@ async def test_add_workspaces(args, existing_workspaces, expected_message):
workspace_commands._db_reader = mock_db_reader

# We'll also patch DbRecorder to ensure no real DB operations happen
with patch(
"codegate.pipeline.cli.commands.WorkspaceCrud", autospec=True
) as mock_recorder_cls:
with patch("codegate.pipeline.cli.commands.WorkspaceCrud", autospec=True) as mock_recorder_cls:
mock_recorder = mock_recorder_cls.return_value
workspace_commands.workspace_crud = mock_recorder
mock_recorder.add_workspace = AsyncMock()
Expand Down Expand Up @@ -115,9 +113,7 @@ async def test_parse_execute_cmd(
"""
workspace_commands = Workspace()

with patch.object(
workspace_commands, "run", return_value=mocked_execute_response
) as mock_run:
with patch.object(workspace_commands, "run", return_value=mocked_execute_response) as mock_run:
result = await workspace_commands.exec(user_message)
assert result == mocked_execute_response

Expand Down
4 changes: 3 additions & 1 deletion tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ def test_health_check(test_client: TestClient) -> None:
assert response.status_code == 200
assert response.json() == {"status": "healthy"}


@patch("codegate.dashboard.dashboard.fetch_latest_version", return_value="foo")
def test_version_endpoint(mock_fetch_latest_version, test_client: TestClient) -> None:
"""Test the version endpoint."""
Expand All @@ -89,11 +90,12 @@ def test_version_endpoint(mock_fetch_latest_version, test_client: TestClient) ->

response_data = response.json()

assert response_data["current_version"] == __version__.lstrip('v')
assert response_data["current_version"] == __version__.lstrip("v")
assert response_data["latest_version"] == "foo"
assert isinstance(response_data["is_latest"], bool)
assert response_data["is_latest"] is False


@patch("codegate.pipeline.secrets.manager.SecretsManager")
@patch("codegate.server.ProviderRegistry")
def test_provider_registration(mock_registry, mock_secrets_mgr, mock_pipeline_factory) -> None:
Expand Down
Loading