Skip to main content

Development SOPs

Standard operating procedures for code development across Burdenoff products.

Development Environment Setup

Prerequisites

# Required tools
- Node.js 18+
- Python 3.12+
- Docker & Docker Compose
- Git
- GitHub CLI (gh)
- Azure CLI (az)
- kubectl
- Helm

Repository Setup

# Clone repository
gh repo clone algoshred/[product]-[service]

# Install dependencies
cd [product]-[service]

# Frontend
npm install

# Python backend
poetry install
poetry shell

# Run development server
npm run dev # or poetry run python main.py

Environment Variables

# Copy example env file
cp .env.example .env.local

# Edit with your values
# Required variables:
- DATABASE_URL
- JWT_SECRET
- REDIS_URL
- API_KEY (if applicable)

Code Development

Feature Development

1. Create Feature Branch

# Update main branch
git checkout main
git pull origin main

# Create feature branch
git checkout -b feature/add-user-profile

# Push to remote
git push -u origin feature/add-user-profile

2. Write Code

// Follow coding standards
// Use strict typing
// Add error handling
// Write clear comments

interface UserProfile {
id: string;
name: string;
email: string;
}

async function getUserProfile(userId: string): Promise<UserProfile> {
try {
const profile = await db.users.findUnique({ where: { id: userId } });
if (!profile) {
throw new Error('User not found');
}
return profile;
} catch (error) {
logger.error('Failed to fetch user profile', { userId, error });
throw error;
}
}

3. Write Tests

import { describe, it, expect } from 'vitest';
import { getUserProfile } from './user-profile';

describe('getUserProfile', () => {
it('should return user profile when user exists', async () => {
const profile = await getUserProfile('user-123');
expect(profile).toBeDefined();
expect(profile.id).toBe('user-123');
});

it('should throw error when user does not exist', async () => {
await expect(getUserProfile('invalid')).rejects.toThrow('User not found');
});
});

4. Run Tests

# Run all tests
npm test

# Run with coverage
npm run test:coverage

# Run in watch mode
npm run test:watch

# Run specific test
npm test -- user-profile.test.ts

5. Lint and Format

# Check formatting
npm run format:check

# Fix formatting
npm run format

# Run linter
npm run lint

# Fix linting issues
npm run lint:fix

Code Review Checklist

Before Creating PR

  • All tests pass
  • Code is formatted
  • No linting errors
  • No TypeScript errors
  • Documentation updated
  • Changelog updated
  • Commit messages clear
  • No console.log statements
  • No commented code
  • Environment variables documented

Code Quality

  • Functions are small and focused
  • Variables have descriptive names
  • No magic numbers
  • Error handling implemented
  • Edge cases handled
  • Performance considered
  • Security best practices followed

Testing

  • Unit tests written
  • Integration tests (if applicable)
  • Test coverage >80%
  • Edge cases tested
  • Error cases tested

Pull Request Process

Creating a PR

# Ensure branch is up to date
git checkout main
git pull origin main
git checkout feature/add-user-profile
git rebase main

# Push changes
git push origin feature/add-user-profile

# Create PR using GitHub CLI
gh pr create --title "Add user profile feature" \
--body "$(cat <<EOF
## Description
Implements user profile functionality with CRUD operations.

## Changes
- Add user profile model
- Implement profile API endpoints
- Add profile UI components
- Write tests

## Testing
- Unit tests: ✅ Passing
- Integration tests: ✅ Passing
- Manual testing: ✅ Complete

## Screenshots
[Add screenshots if applicable]
EOF
)"

PR Template

## Description
Brief description of what this PR does

## Type of Change
- [ ] Bug fix (non-breaking change)
- [ ] New feature (non-breaking change)
- [ ] Breaking change (fix or feature that would break existing functionality)
- [ ] Documentation update
- [ ] Refactoring
- [ ] Performance improvement

## Related Issues
Closes #123
Related to #456

## Changes Made
- Change 1
- Change 2
- Change 3

## Testing
- [ ] Unit tests pass
- [ ] Integration tests pass
- [ ] E2E tests pass (if applicable)
- [ ] Manual testing completed

## Screenshots
(if applicable)

## Checklist
- [ ] Code follows style guidelines
- [ ] Self-review completed
- [ ] Comments added for complex logic
- [ ] Documentation updated
- [ ] No new warnings
- [ ] Tests added/updated
- [ ] All tests passing

Review Process

Reviewer Responsibilities

  1. Review within 24 hours
  2. Check code quality
  3. Test locally if needed
  4. Provide constructive feedback
  5. Approve or request changes

Addressing Feedback

# Make requested changes
git add .
git commit -m "Address review feedback"
git push origin feature/add-user-profile

# Respond to comments in GitHub
# Mark resolved when complete

Database Changes

Creating Migrations

Prisma (Node.js)

# Create migration
npm run migrate:dev -- --name add_user_profile

# Apply migration
npm run migrate:deploy

# Generate client
npm run gendb

Alembic (Python)

# Auto-generate migration
poetry run alembic revision --autogenerate -m "Add user profile table"

# Review generated migration
# Edit if needed

# Apply migration
poetry run alembic upgrade head

# Rollback if needed
poetry run alembic downgrade -1

Migration Guidelines

  • Always review auto-generated migrations
  • Add data migrations separately
  • Test migrations locally
  • Include rollback plan
  • Document breaking changes

API Development

REST API

from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel

router = APIRouter()

class UserProfileCreate(BaseModel):
name: str
email: str

class UserProfileResponse(BaseModel):
id: str
name: str
email: str

@router.post("/profiles", response_model=UserProfileResponse)
async def create_profile(
profile: UserProfileCreate,
current_user = Depends(get_current_user)
):
"""Create a new user profile."""
try:
new_profile = await db.profiles.create({
"user_id": current_user.id,
"name": profile.name,
"email": profile.email
})
return new_profile
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))

GraphQL API

import { builder } from './builder';

const UserProfile = builder.objectType('UserProfile', {
fields: (t) => ({
id: t.exposeID('id'),
name: t.exposeString('name'),
email: t.exposeString('email'),
}),
});

builder.queryField('userProfile', (t) =>
t.field({
type: UserProfile,
args: {
id: t.arg.id({ required: true }),
},
resolve: async (_, { id }, ctx) => {
return ctx.db.userProfile.findUnique({ where: { id } });
},
})
);

Frontend Development

Component Development

import { useState } from 'react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';

interface UserProfileProps {
userId: string;
}

export function UserProfile({ userId }: UserProfileProps) {
const [name, setName] = useState('');
const [email, setEmail] = useState('');

const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
try {
await apiClient.post('/profiles', { name, email });
// Handle success
} catch (error) {
// Handle error
}
};

return (
<form onSubmit={handleSubmit}>
<Input
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Name"
/>
<Input
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Email"
type="email"
/>
<Button type="submit">Save Profile</Button>
</form>
);
}

Styling Guidelines

// Use semantic tokens (defined in theme)
// Don't hardcode colors

// Good
<div className="bg-background text-foreground border border-border">

// Avoid
<div className="bg-white text-black border border-gray-300">

// Use Tailwind utilities
<div className="flex items-center gap-4 p-4 rounded-lg shadow-md">

Documentation

Code Documentation

/**
* Fetches user profile by ID
*
* @param userId - The unique identifier of the user
* @returns Promise resolving to UserProfile
* @throws {Error} If user is not found
*
* @example
* ```ts
* const profile = await getUserProfile('user-123');
* console.log(profile.name);
* ```
*/
async function getUserProfile(userId: string): Promise<UserProfile> {
// Implementation
}

README Updates

# Feature: User Profiles

## Overview
User profiles allow users to manage their personal information.

## API Endpoints

### Create Profile
`POST /api/profiles`

Request:
```json
{
"name": "John Doe",
"email": "[email protected]"
}

Response:

{
"id": "prof-123",
"name": "John Doe",
"email": "[email protected]"
}

## Performance Optimization

### Best Practices
- Lazy load components
- Memoize expensive calculations
- Optimize images
- Use pagination
- Implement caching
- Profile performance

### Example
```typescript
import { useMemo } from 'react';

function ExpensiveComponent({ data }) {
const processedData = useMemo(() => {
return data.map(item => {
// Expensive processing
return processItem(item);
});
}, [data]);

return <div>{processedData}</div>;
}

Next Steps