Skip to content

ProgramadoresSemPatria/HB03-2025_BUG_TO_PR

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

119 Commits
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸš€ Bug to PR Agent

Automated system that analyzes error stack traces and generates Pull Requests with fixes using Artificial Intelligence.

Live Project: Bug to PR πŸš€

πŸ“‹ Table of Contents


🎯 Overview

Bug to PR Agent is a full-stack application that automates the bug fixing process. The system:

  1. Receives an error stack trace from the user
  2. Analyzes the repository code on GitHub in the specified branch
  3. Uses AI (Gemini or OpenAI) to generate a fix patch
  4. Creates a new branch and applies the patch
  5. Opens a Pull Request automatically

Workflow

Stack Trace β†’ Parser β†’ AI Analysis β†’ Patch Generation β†’ GitHub PR Creation

πŸ—οΈ Architecture

General Architecture

The project follows a layered architecture with clear separation of concerns:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Frontend (Next.js)                    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”‚
β”‚  β”‚  Pages   β”‚β†’ β”‚ Services β”‚β†’ β”‚   API    β”‚              β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                          ↕ HTTP/REST
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Backend (Express)                     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”‚
β”‚  β”‚ Routes   β”‚β†’ β”‚Controllersβ”‚β†’ β”‚Use Casesβ”‚              β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β”‚
β”‚                          ↕                               β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”‚
β”‚  β”‚Services  β”‚  β”‚Repositoryβ”‚  β”‚Contracts β”‚              β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                          ↕
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              Database (PostgreSQL + Prisma)              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”§ Backend - Design Patterns

The backend was developed following Clean Architecture and SOLID principles, utilizing various design patterns:

1. Factory Pattern 🏭

Location: backend/src/modules/*/factory/

Purpose: Centralize controller creation, ensuring correct dependency injection.

Example:

// auth.factory.ts
export function makeCreateUserController() {
  return new CreateUserController(authContainer.createUserUseCase);
}

Benefits:

  • Isolation of creation logic
  • Facilitates testing (mocks can be injected)
  • Single Responsibility Principle

2. Dependency Injection (DI) Container πŸ’‰

Location: backend/src/modules/*/di/

Purpose: Manage dependencies and ensure singleton instances when necessary.

Example:

// auth.container.ts
class AuthContainer {
  get repository(): IAuthContract {
    if (!this._repository) {
      this._repository = new PrismaAuthRepository(prisma);
    }
    return this._repository;
  }
  
  get createUserUseCase(): CreateUserUseCase {
    return new CreateUserUseCase(
      this.repository, 
      this.hashService, 
      this.tokenEncrypter
    );
  }
}

Benefits:

  • Centralized dependency control
  • Lazy loading (instances created on demand)
  • Facilitates maintenance and testing

3. Repository Pattern πŸ“¦

Location: backend/src/modules/*/repository/

Purpose: Abstract data access, allowing implementation swap without affecting business logic.

Structure:

Contract (Interface) β†’ Repository (Implementation) β†’ Database

Example:

// Contract
export interface IAuthContract {
  createUser: (dto: CreateUserDto) => Promise<CreateUserResponseDto>;
  getUserByEmail: (email: string) => Promise<CreateSessionUserDto | null>;
}

// Implementation
export class PrismaAuthRepository implements IAuthContract {
  constructor(private readonly prisma: PrismaClient) {}
  // ... implementation
}

Benefits:

  • Decoupling of data layer
  • Facilitates testing (mocks)
  • Allows swapping ORM without affecting use cases

4. Use Case Pattern (Clean Architecture) 🎯

Location: backend/src/modules/*/use-cases/

Purpose: Encapsulate business rules in specific use cases.

Characteristics:

  • Each use case has a single responsibility
  • Receives DTOs as input
  • Returns Either<Error, Success> (Functional Error Handling)
  • Doesn't know implementation details (HTTP, Database, etc)

Example:

export class CreateUserUseCase {
  constructor(
    private readonly authContract: IAuthContract,
    private readonly hashGenerator: HashGenerator,
    private readonly tokenEncrypter: TokenEncrypter
  ) {}

  async execute(dto: CreateUserDto): Promise<Either<UserAlreadyExistsError, CreateUserResponseDto>> {
    // Pure business logic
  }
}

Benefits:

  • Testability
  • Reusability
  • Maintainability

5. Strategy Pattern 🎨

Location: backend/src/modules/bug-to-pr/strategies/

Purpose: Allow swapping algorithms (AI providers) at runtime.

Structure:

IAIStrategy (Interface)
  β”œβ”€β”€ GeminiStrategy
  β”œβ”€β”€ OpenAIStrategy
  └── MockStrategy (for tests)

Example:

// Factory that chooses the strategy
export class AIStrategyFactory {
  static create(provider?: AIProvider): IAIStrategy {
    switch (provider || env.AI_PROVIDER) {
      case 'gemini': return new GeminiStrategy(env.GEMINI_API_KEY);
      case 'openai': return new OpenAIStrategy(env.OPENAI_API_KEY);
    }
  }
}

// Usage in Service
const strategy = AIStrategyFactory.create(dto.aiProvider);
const aiService = new AIService(strategy);

Benefits:

  • Extensibility (easy to add new providers)
  • Open/Closed Principle
  • Testability

6. Contract Pattern (Interface Segregation) πŸ“‹

Location: backend/src/modules/*/contract/

Purpose: Define clear contracts between layers, following Interface Segregation Principle.

Example:

export interface IGithubService {
  getFileContent(...): Promise<GitHubFileContent>;
  createBranch(...): Promise<void>;
  getUserRepositories(...): Promise<GitHubRepositoryDto[]>;
  // ... specific methods
}

Benefits:

  • Decoupling
  • Testability (mocks)
  • Implicit documentation

7. Either Pattern (Functional Error Handling) βš–οΈ

Location: backend/src/@types/either.ts

Purpose: Handle errors functionally, without exceptions.

Structure:

type Either<L, R> = Left<L, R> | Right<L, R>

// Left = Error
// Right = Success

Example:

async execute(dto: Dto): Promise<Either<GithubError, SuccessDto>> {
  if (error) {
    return left(new GithubError(400));
  }
  return right(successData);
}

// Usage in Controller
if (result.isLeft()) {
  return response.status(result.value.statusCode).json({
    error: result.value.message
  });
}

Benefits:

  • Explicit errors in type
  • Forces error handling
  • More predictable code

8. DTO Pattern (Data Transfer Object) πŸ“€

Location: backend/src/modules/*/dto/

Purpose: Transfer data between layers in a typed and validated way.

Example:

export interface GeneratePRDto {
  stackTrace: string;
  owner: string;
  repo: string;
  branch: string;
  userId?: string;
  aiProvider?: 'gemini' | 'openai';
}

Benefits:

  • Type safety
  • Centralized validation
  • Documentation

9. Middleware Pattern πŸ”’

Location: backend/src/modules/auth/middleware/

Purpose: Intercept requests for authentication/authorization.

Example:

export const authenticate = (req, res, next) => {
  // Validates JWT token
  // Injects user into request
  next();
}

10. Validator Pattern (Zod) βœ…

Location: backend/src/modules/*/validator/ and backend/src/shared/zod-validator.middleware.ts

Purpose: Validate input data using Zod schemas.

Example:

const schema = z.object({
  email: z.string().email(),
  password: z.string().min(8)
});

// Middleware
export const validate = (schema: ZodSchema) => {
  return (req, res, next) => {
    const validatedData = schema.parse(req.body);
    req.body = validatedData;
    next();
  };
};

🎨 Frontend - Design Patterns

The frontend was developed following Component-Based Architecture and Separation of Concerns:

1. Service Layer Pattern πŸ”Œ

Location: frontend/src/services/

Purpose: Abstract API communication, centralizing HTTP logic.

Structure:

ApiClient (base) β†’ Services (specific) β†’ Components

Example:

// api.ts - Base client
class ApiClient {
  private async request<T>(endpoint: string, options: RequestInit) {
    // Centralized HTTP logic
    // JWT injection
    // Error handling
  }
}

// auth.ts - Specific service
class AuthService {
  async login(credentials: LoginCredentials): Promise<User> {
    const response = await api.post("/auth/sessions", credentials);
    // Data transformation
    return mappedUser;
  }
}

Benefits:

  • Reusability
  • Maintainability
  • Testability

2. Custom Hooks Pattern 🎣

Location: frontend/src/hooks/

Purpose: Encapsulate state logic and side effects.

Examples:

  • useRepositories() - Manages GitHub repositories state
  • useAnalysis() - Manages stack trace analysis flow
  • useLocalStorage() - Abstracts localStorage
  • useScroll() - Manages scroll behavior

Example:

export function useRepositories() {
  const [repositories, setRepositories] = useState([]);
  const [isLoading, setIsLoading] = useState(true);
  
  // Fetch logic, grouping, etc.
  
  return { repositories, owners, repositoriesByOwner, isLoading, refetch };
}

Benefits:

  • Logic reusability
  • Separation of concerns
  • Testability

3. Component Composition Pattern 🧩

Location: frontend/src/components/

Structure:

shared/          β†’ Reusable components (Header, Footer, AuthGuard)
features/        β†’ Feature-specific components
  β”œβ”€β”€ analysis/  β†’ Analysis-related components
  β”œβ”€β”€ hero/      β†’ Landing page components
  └── home/      β†’ Home components
ui/              β†’ Base components (Button, Input, Card)

Example:

// Component composition
<AuthGuard>
  <Header variant="app" />
  <AnalysisForm />
  <Footer />
</AuthGuard>

Benefits:

  • Reusability
  • Maintainability
  • Isolated testability

4. Auth Guard Pattern πŸ›‘οΈ

Location: frontend/src/components/shared/auth-guard.tsx

Purpose: Protect routes that require authentication.

Example:

export function AuthGuard({ children }: AuthGuardProps) {
  const isAuthenticated = authService.isAuthenticated();
  
  if (!isAuthenticated) {
    router.push(ROUTES.LOGIN);
    return null;
  }
  
  return <>{children}</>;
}

Usage:

<AuthGuard>
  <DashboardPage />
</AuthGuard>

5. Validator Pattern (Zod) βœ…

Location: frontend/src/validators/

Purpose: Validate forms on the frontend, mirroring backend validations.

Example:

export const createUserSchema = z.object({
  email: z.string().email("Invalid email"),
  password: z.string().min(8, "Password must be at least 8 characters"),
  githubToken: z.string().min(1, "GitHub Token is required"),
});

Benefits:

  • Consistent frontend/backend validation
  • Type safety
  • Standardized error messages

6. Type System (TypeScript) πŸ“

Location: frontend/src/types/

Purpose: Centralize type definitions.

Structure:

types/
  β”œβ”€β”€ auth.ts
  β”œβ”€β”€ analysis.ts
  β”œβ”€β”€ api.ts
  β”œβ”€β”€ repositories.ts
  └── index.ts (barrel export)

Benefits:

  • Type safety
  • Autocomplete
  • Documentation

7. Constants Pattern πŸ“Œ

Location: frontend/src/constants/

Purpose: Centralize constant values (routes, configurations).

Example:

export const ROUTES = {
  HOME: "/",
  LOGIN: "/login",
  DASHBOARD: "/dashboard",
  HISTORY: "/history",
} as const;

8. Feature-Based Organization πŸ“

Structure:

features/
  analysis/
    β”œβ”€β”€ analysis-form.tsx
    β”œβ”€β”€ history-list.tsx
    β”œβ”€β”€ pr-result.tsx
    └── index.ts

Benefits:

  • Domain-based organization
  • Facilitates code location
  • Scalability

πŸ“‚ Project Structure

Backend

backend/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ @types/              # Custom types (Either)
β”‚   β”œβ”€β”€ config/              # Configurations (env)
β”‚   β”œβ”€β”€ models/              # Prisma Client
β”‚   β”œβ”€β”€ modules/             # Application modules
β”‚   β”‚   β”œβ”€β”€ auth/            # Authentication module
β”‚   β”‚   β”‚   β”œβ”€β”€ contract/    # Interfaces
β”‚   β”‚   β”‚   β”œβ”€β”€ controllers/ # HTTP Controllers
β”‚   β”‚   β”‚   β”œβ”€β”€ cryptography/# Cryptography (JWT, AES)
β”‚   β”‚   β”‚   β”œβ”€β”€ di/          # Dependency Injection
β”‚   β”‚   β”‚   β”œβ”€β”€ dto/         # Data Transfer Objects
β”‚   β”‚   β”‚   β”œβ”€β”€ errors/      # Custom errors
β”‚   β”‚   β”‚   β”œβ”€β”€ factory/     # Factory Pattern
β”‚   β”‚   β”‚   β”œβ”€β”€ middleware/  # Express Middleware
β”‚   β”‚   β”‚   β”œβ”€β”€ repository/  # Repository Pattern
β”‚   β”‚   β”‚   β”œβ”€β”€ routes/      # Express Routes
β”‚   β”‚   β”‚   β”œβ”€β”€ use-cases/   # Business Logic
β”‚   β”‚   β”‚   └── validator/   # Zod Schemas
β”‚   β”‚   └── bug-to-pr/       # Main module
β”‚   β”‚       β”œβ”€β”€ constants/   # Constants
β”‚   β”‚       β”œβ”€β”€ contract/     # Interfaces
β”‚   β”‚       β”œβ”€β”€ controllers/  # HTTP Controllers
β”‚   β”‚       β”œβ”€β”€ di/          # Dependency Injection
β”‚   β”‚       β”œβ”€β”€ dto/         # Data Transfer Objects
β”‚   β”‚       β”œβ”€β”€ errors/      # Custom errors
β”‚   β”‚       β”œβ”€β”€ factory/     # Factory Pattern
β”‚   β”‚       β”œβ”€β”€ repository/  # Repository Pattern
β”‚   β”‚       β”œβ”€β”€ routes/      # Express Routes
β”‚   β”‚       β”œβ”€β”€ services/    # Domain Services
β”‚   β”‚       β”œβ”€β”€ strategies/  # Strategy Pattern (AI)
β”‚   β”‚       β”œβ”€β”€ use-cases/   # Business Logic
β”‚   β”‚       β”œβ”€β”€ utils/       # Utilities
β”‚   β”‚       └── validator/   # Zod Schemas
β”‚   β”œβ”€β”€ routes/              # Route binding
β”‚   β”œβ”€β”€ shared/              # Shared code
β”‚   └── server.ts            # Entry point
β”œβ”€β”€ prisma/
β”‚   └── schema.prisma        # Database schema
└── package.json

Frontend

frontend/
β”œβ”€β”€ app/                     # Next.js App Router
β”‚   β”œβ”€β”€ dashboard/           # Dashboard page
β”‚   β”œβ”€β”€ history/             # History page
β”‚   β”œβ”€β”€ login/               # Login page
β”‚   └── page.tsx             # Landing page
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ components/          # React Components
β”‚   β”‚   β”œβ”€β”€ features/        # Feature components
β”‚   β”‚   β”œβ”€β”€ shared/          # Shared components
β”‚   β”‚   └── ui/              # Base components (shadcn)
β”‚   β”œβ”€β”€ config/              # Configurations
β”‚   β”œβ”€β”€ constants/           # Constants
β”‚   β”œβ”€β”€ hooks/               # Custom Hooks
β”‚   β”œβ”€β”€ lib/                 # Utilities
β”‚   β”œβ”€β”€ services/            # API Services
β”‚   β”œβ”€β”€ types/               # TypeScript Types
β”‚   └── validators/          # Zod Validators
└── package.json

πŸ› οΈ Technologies

Backend

  • Runtime: Node.js
  • Framework: Express.js
  • Language: TypeScript
  • ORM: Prisma
  • Database: PostgreSQL
  • Validation: Zod
  • Authentication: JWT (jsonwebtoken)
  • Cryptography: bcryptjs, AES (token encryption)
  • AI Providers:
    • Google Gemini (@google/generative-ai)
    • OpenAI (openai)
  • GitHub API: @octokit/rest
  • Testing: Vitest
  • Code Quality: TypeScript strict mode

Frontend

  • Framework: Next.js 16 (App Router)
  • Language: TypeScript
  • UI Library: React 19
  • Styling: Tailwind CSS 4
  • UI Components: Shadcn UI (Radix UI)
  • Icons: Lucide React
  • Animations: Framer Motion, GSAP
  • Forms: React (controlled components)
  • Validation: Zod
  • State Management: React Hooks (useState, useEffect, useCallback)
  • HTTP Client: Fetch API (custom ApiClient)
  • Notifications: Sonner
  • Theming: next-themes (dark mode)

βš™οΈ Configuration and Execution

Prerequisites

  • Node.js 20+
  • PostgreSQL
  • pnpm (or npm/yarn)

Backend

cd backend

# Install dependencies
npm install

# Configure environment variables
cp .env.example .env
# Edit .env with your credentials

# Configure database
npm run prisma:generate
npm run prisma:migrate

# Run in development
npm run dev

# Build for production
npm run build
npm start

Frontend

cd frontend

# Install dependencies
pnpm install

# Configure environment variables
# Create .env.local with NEXT_PUBLIC_API_URL

# Run in development
pnpm dev

# Build for production
pnpm build
pnpm start

Environment Variables

Backend (.env):

NODE_ENV=development
PORT=3001
JWT_SECRET=your-secret-key
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
ENCRYPTION_KEY=your-32-char-encryption-key
AI_PROVIDER=gemini
GEMINI_API_KEY=your-gemini-key
OPENAI_API_KEY=your-openai-key

Frontend (.env.local):

NEXT_PUBLIC_API_URL=http://localhost:3001/api/v1

πŸ”Œ API Endpoints

Authentication

  • POST /api/v1/auth/users - Create user
  • POST /api/v1/auth/sessions - Login

Bug to PR

  • POST /api/v1/bug-to-pr/generate - Generate PR from stack trace
  • GET /api/v1/bug-to-pr/repositories - List user repositories
  • GET /api/v1/bug-to-pr/history - History of generated PRs

Health Check

  • GET /api/v1/health - Server status

πŸŽ“ Applied Principles

SOLID

  • Single Responsibility: Each class/component has one responsibility
  • Open/Closed: Extensible via Strategy Pattern
  • Liskov Substitution: Well-defined interfaces
  • Interface Segregation: Specific contracts
  • Dependency Inversion: Dependencies via interfaces

Clean Architecture

  • Well-defined layers: Controllers β†’ Use Cases β†’ Services/Repository
  • Framework independence: Business logic doesn't depend on Express
  • Testability: Easy to create mocks and unit tests
  • UI independence: Use cases don't know about HTTP

DRY (Don't Repeat Yourself)

  • Shared validations (Zod schemas)
  • Reusable services
  • Custom hooks
  • Composed components

πŸ“ Development Notes

Architectural Decisions

  1. Either Pattern: Chosen for functional error handling, avoiding unhandled exceptions
  2. Repository Pattern: Allows swapping ORM without affecting business logic
  3. Strategy Pattern for AI: Facilitates adding new AI providers
  4. DI Containers: Centralizes dependencies, facilitates testing
  5. Zod in Frontend and Backend: Ensures consistent validation

πŸ“„ License

ISC


πŸ‘₯ Authors

Gabriel Melo, Lucas Nery, Luiz Renan and Eduardo Zago Project developed for Hackathon Base 2025.

About

Gabriel Melo, Luiz Renan, Eduardo Zago, Lucas Nery

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •