Skip to content
Merged
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
30 changes: 30 additions & 0 deletions app/api/v1/endpoints/pipelines.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,33 @@ async def list_executions(
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Access denied")

return await pipeline_service.list_pipeline_executions(db, pipeline_id=pipeline_id)


@router.get("/{pipeline_id}/executions/{execution_id}", response_model=PipelineExecutionResponse)
async def get_execution(
pipeline_id: int,
execution_id: int,
db: AsyncSession = Depends(deps.get_db),
current_user: User = Depends(deps.get_current_active_user),
) -> Any:
"""Get specific pipeline execution details."""
# Verify pipeline exists and user has access
pipeline = await pipeline_service.get_pipeline(db, pipeline_id=pipeline_id)
if not pipeline:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Pipeline not found")

project = await project_service.get_project(db, project_id=pipeline.project_id)
role = await team_service.get_user_role_in_team(db, team_id=project.team_id, user_id=current_user.id)
if not role and not current_user.is_superuser:
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Access denied")

# Get execution details
execution = await pipeline_service.get_pipeline_execution(db, execution_id=execution_id)
if not execution:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Execution not found")

# Verify execution belongs to the specified pipeline
if execution.pipeline_id != pipeline_id:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Execution not found for this pipeline")

return execution
3 changes: 3 additions & 0 deletions app/services/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
from app.models.base import Pipeline, PipelineExecution
from app.schemas.pipeline import PipelineCreate, PipelineUpdate
from app.services.events import events
import logging

logger = logging.getLogger(__name__)


async def create_pipeline(db: AsyncSession, pipeline_in: PipelineCreate) -> Pipeline:
Expand Down
28 changes: 28 additions & 0 deletions tests/unit/test_pipeline_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,31 @@ async def test_list_pipeline_executions_unit():
assert len(executions) == 1
assert executions[0].status == "success"

@pytest.mark.asyncio
async def test_get_pipeline_execution_unit():
"""Test getting a specific pipeline execution."""
mock_db = AsyncMock()
mock_result = MagicMock()
mock_execution = PipelineExecution(id=1, pipeline_id=1, status="completed")
mock_result.scalars.return_value.first.return_value = mock_execution
mock_db.execute.return_value = mock_result

execution = await pipeline_service.get_pipeline_execution(mock_db, execution_id=1)

assert execution is not None
assert execution.id == 1
assert execution.status == "completed"
assert execution.pipeline_id == 1

@pytest.mark.asyncio
async def test_get_pipeline_execution_not_found_unit():
"""Test getting a non-existent pipeline execution."""
mock_db = AsyncMock()
mock_result = MagicMock()
mock_result.scalars.return_value.first.return_value = None
mock_db.execute.return_value = mock_result

execution = await pipeline_service.get_pipeline_execution(mock_db, execution_id=999)

assert execution is None

Loading