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
226 changes: 131 additions & 95 deletions claudedocs/SESSION.md
Original file line number Diff line number Diff line change
@@ -1,98 +1,134 @@
# CI/CD Deployment Workflow Implementation

## Session Goal
Create GitHub Actions CI/CD workflow for automated deployment to staging and production environments using SSH-based deployment.

## GitHub Secrets Required

### Connection Secrets (already configured)
- `HOST` - Server hostname
- `USER` - SSH username
- `SSH_KEY` - SSH private key
- `PROJECT_PATH` - Deployment path on server

### Environment Secrets (need to add to staging environment)
- `ANTHROPIC_API_KEY` - Anthropic API key for Claude
- `OPENAI_API_KEY` - OpenAI API key (optional)
- `CORS_ORIGINS` - CORS allowed origins (e.g., `https://dev.codeframeapp.com`)
- `API_URL` - Backend API URL (e.g., `https://api.dev.codeframeapp.com`)
- `WS_URL` - WebSocket URL (e.g., `wss://api.dev.codeframeapp.com/ws`)

## Execution Plan

### Phase 1: Analysis & Planning
- Understand existing test workflow structure
- Verify GitHub environments (staging, production)
- Analyze deployment mechanism

### Phase 2: Workflow Design
- Deployment trigger strategy (main → staging, tags → production)
- Pre-deployment quality gates
- SSH connection security patterns

### Phase 3: Implementation
- `.github/workflows/deploy.yml` - Main deployment workflow
- Environment-specific configurations
- SSH key handling with security best practices

### Phase 4: Quality Gates Integration
- Test suite dependency (deploy only if tests pass)
- Coverage threshold enforcement (≥65%)
- Code quality checks

### Phase 5: Security Hardening
- SSH key usage validation (no key exposure in logs)
- Least-privilege deployment permissions

### Phase 6: Testing & Validation
- Dry-run deployment test
- Staging deployment verification

### Phase 7: Documentation
- Deployment workflow guide
- Environment setup instructions

## Risk Mitigations
1. SSH Key Security - Use ssh-agent, never echo secrets
2. Production Environment - Create if needed
3. Port Conflicts - Document port configuration
4. Zero-Downtime - Simple restart strategy for MVP
# Active Session: Implement Database-Backed Tasks Endpoint

**Branch**: `feature/implement-tasks-endpoint-database`
**Started**: 2025-12-17
**Estimated Time**: ~55 minutes
**Token Budget**: ~22k tokens

## Objective

Replace hardcoded mock data in `GET /api/projects/{project_id}/tasks` endpoint with actual database queries, implementing filtering and pagination while maintaining consistency with existing endpoint patterns.

## Workflow Phases

### Phase 1: Analysis & Validation (Sequential)
**Status**: Pending
**Goal**: Understand current implementation patterns and validate the approach before making changes

**Tasks**:
- Read `codeframe/ui/routers/projects.py` (lines 220-238) - current endpoint implementation
- Read `codeframe/ui/routers/blockers.py` - reference pattern for validation and DB dependency injection
- Read `tests/api/test_endpoints_database.py` - test pattern reference

**Expected Outcome**:
- Clear understanding of current mock implementation
- Confirmed patterns for project validation, DB dependency injection, error handling
- Test patterns identified for verification

---

### Phase 2: Implementation (Sequential)
**Status**: Pending
**Goal**: Update the endpoint with database queries and filtering logic

**Implementation Steps**:

1. **Update Endpoint Signature**: Add `db: Database = Depends(get_db)`, `offset: int = 0` parameters
2. **Add Project Validation**: Call `db.get_project()`, raise 404 if None
3. **Query Tasks**: Call `db.get_project_tasks(project_id)` wrapped in try-except
4. **Apply Status Filtering**: Client-side filter if status param provided
5. **Calculate Total & Paginate**: Store total count, apply offset/limit slicing
6. **Return Formatted Response**: `{"tasks": [...], "total": N}`
7. **Add Error Handling**: Catch `sqlite3.Error`, log and raise 500
8. **Update Documentation**: Proper docstring with params, return values, errors

**Expected Outcome**:
- Endpoint updated with actual database queries
- All 8 implementation steps completed
- Consistent with existing patterns (blockers endpoint, project status endpoint)
- Proper error handling and logging

---

### Phase 3: Testing (Sequential)
**Status**: Pending
**Goal**: Verify the implementation with comprehensive test coverage

**Test Cases**:
1. Empty database - Returns `{"tasks": [], "total": 0}`
2. Status filtering - Only returns matching tasks
3. Pagination - Correctly applies limit and offset
4. Project not found - Returns 404 with error message
5. Database errors - Returns 500, logs exception
6. Multiple tasks with various statuses - Verifies total count accuracy
7. Edge cases - Offset > total, limit=0, invalid project_id

**Expected Outcome**:
- All 7 test cases passing (100% pass rate)
- >85% coverage on modified endpoint code
- Verified behavior matches expected sequence diagram

---

## Implementation Complete

### Files Created/Modified
- `.github/workflows/deploy.yml` - New deployment workflow
- `.github/workflows/test.yml` - Added `workflow_call` trigger for reusability

### Deployment Triggers
| Trigger | Environment | Condition |
|---------|-------------|-----------|
| Push to `main` | Staging | Automatic after tests pass |
| GitHub Release | Production | Automatic after tests pass |
| Manual dispatch | Either | Select environment in UI |

### Required GitHub Setup
1. **Staging environment** - Already exists, needs additional secrets:
- Add: ANTHROPIC_API_KEY, OPENAI_API_KEY, CORS_ORIGINS, API_URL, WS_URL
2. **Production environment** - Create manually when ready:
- Go to repo Settings → Environments → New environment
- Name: `production`
- Add all secrets from staging
- Optional: Add required reviewers for production deployments

### Server Requirements
The deployment expects:
- Python 3.11+ with ability to create venv
- Node.js 20+ with npm
- PM2 installed globally (`npm install -g pm2`)
- Git installed and repo cloned at PROJECT_PATH
- `ecosystem.config.js` in project root (PM2 configuration)

### Manual Deployment
Use workflow_dispatch in GitHub Actions UI:
1. Go to Actions → Deploy
2. Click "Run workflow"
3. Select environment (staging/production)
4. Click "Run workflow"
### Phase 4: Code Quality & Review (Sequential)
**Status**: Pending
**Goal**: Ensure code quality and consistency before merge

**Review Areas**:
- OWASP compliance (input validation, error messages)
- Pattern consistency with existing endpoints
- Error handling robustness
- Documentation clarity
- Test coverage adequacy

**Expected Outcome**:
- Code review approval
- Any issues flagged resolved
- Ready for production deployment

---

### Phase 5: Documentation & Commit (Sequential)
**Status**: Pending
**Goal**: Document changes and create commit

**Actions**:
- Update endpoint docstring with parameter and return value documentation
- Document breaking changes (if any) in commit message
- Create git commit with clear message following repo patterns
- Verify all tests passing before commit

**Expected Outcome**:
- Commit created with comprehensive message
- Documentation updated
- Ready for PR creation

---

## Risk Assessment

### Low-Risk Areas
- Endpoint signature changes are backward compatible (new params have defaults)
- Error handling follows established patterns
- Database method (`get_project_tasks()`) already tested and stable

### Moderate-Risk Areas
- **Status filtering location**: Implemented client-side (not DB-level) - could be slow with large task lists (1000+ tasks)
- **Mitigation**: Document this in code comment; consider DB-level filtering in future optimization
- **Pagination math**: Ensure offset/limit correctly handle edge cases (offset > total, etc.)
- **Mitigation**: Include comprehensive edge-case tests

### Recommendations
1. Run full endpoint test suite after changes (not just new tests)
2. Verify pagination behavior with realistic data volumes
3. Document the client-side filtering as a future optimization point if needed
4. Consider adding metrics/monitoring on this endpoint given its likely high usage

---

## Session Notes

- **Orchestrator Agent ID**: ae3e721 (for resuming if needed)
- **Feature Branch**: Created from main @ commit 9bd43c0
- **Parent PR**: None (new feature)
- **Related Issues**: None referenced
82 changes: 63 additions & 19 deletions codeframe/ui/routers/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import sqlite3
from datetime import datetime, UTC

from fastapi import APIRouter, Depends, HTTPException
from fastapi import APIRouter, Depends, HTTPException, Query

from codeframe.core.session_manager import SessionManager
from codeframe.persistence.database import Database
Expand Down Expand Up @@ -218,24 +218,68 @@ async def get_project_status(project_id: int, db: Database = Depends(get_db)):


@router.get("/{project_id}/tasks")
async def get_tasks(project_id: int, status: str | None = None, limit: int = 50):
"""Get project tasks."""
# TODO: Query database with filters
return {
"tasks": [
{
"id": 27,
"title": "JWT refresh token flow",
"description": "Implement token refresh endpoint",
"status": "in_progress",
"assigned_to": "backend-1",
"priority": 0,
"workflow_step": 7,
"progress": 45,
}
],
"total": 40,
}
async def get_tasks(
project_id: int,
status: str | None = None,
limit: int = Query(default=50, ge=1, le=1000, description="Max tasks to return (1-1000)"),
offset: int = Query(default=0, ge=0, description="Tasks to skip for pagination"),
db: Database = Depends(get_db),
):
"""Get project tasks with filtering and pagination.

Args:
project_id: Project ID to get tasks for
status: Optional filter by task status (e.g., 'pending', 'in_progress', 'completed')
limit: Maximum number of tasks to return (1-1000, default: 50)
offset: Number of tasks to skip for pagination (>=0, default: 0)
db: Database instance (injected)

Returns:
Dictionary with:
- tasks: List[Dict] - Paginated list of task dictionaries
- total: int - Total number of tasks matching the filter (before pagination)

Raises:
HTTPException:
- 404: Project not found
- 422: Invalid parameters (negative offset, limit out of range)
- 500: Database error

Security Notes:
- Input validation: limit constrained to 1-1000, offset must be >=0
- TODO: Add authorization check when auth infrastructure is implemented
(verify user has access to this project)
"""
try:
# Validate project exists
project = db.get_project(project_id)
if not project:
raise HTTPException(status_code=404, detail=f"Project {project_id} not found")

# TODO: Add authorization check when auth system is implemented
# if not db.user_has_project_access(current_user.id, project_id):
# raise HTTPException(status_code=403, detail="Access denied")

# Query all tasks for the project
tasks = db.get_project_tasks(project_id)

# Apply status filtering if provided
# NOTE: Client-side filtering used here. For large datasets (1000+ tasks),
# consider adding database-level filtering in future optimization.
if status is not None:
tasks = [t for t in tasks if t.get("status") == status]

# Calculate total count before pagination
total = len(tasks)

# Apply pagination
tasks = tasks[offset : offset + limit]

return {"tasks": tasks, "total": total}

except sqlite3.Error as e:
logger.error(f"Database error fetching tasks for project {project_id}: {e}", exc_info=True)
raise HTTPException(status_code=500, detail="Error fetching tasks")


@router.get("/{project_id}/activity")
Expand Down
Loading
Loading