Guía de Contribución

Gracias por tu interés en contribuir a NoxPanel. Esta guía establece las convenciones y procesos para colaborar en el desarrollo del proyecto.

Requisitos de Desarrollo

Para contribuir necesitas:

  • Python 3.10+

  • Docker y Docker Compose (v2+)

  • Git

  • Node.js (opcional, para assets frontend)

  • Un editor con soporte para Python (recomendado: VS Code / Cursor)

Configurar el Entorno

# Clonar el repositorio
git clone https://github.com/ocentelles/NoxPanel.git
cd NoxPanel

# Copiar archivo de configuración
cp env.example .env
# Editar .env con tus credenciales de desarrollo

# Levantar servicios
docker-compose up -d

# Verificar que todo funciona
docker-compose ps
docker-compose logs web

Estilo de Código

Python

Seguimos las convenciones de PEP 8 con las siguientes especificaciones:

  • Indentación: 4 espacios (nunca tabs)

  • Longitud de línea: máximo 120 caracteres

  • Imports: Agrupados en 3 bloques (stdlib, terceros, locales) separados por línea en blanco

  • Docstrings: Formato Google style o reStructuredText

  • Nombres de variables: snake_case

  • Nombres de clases: PascalCase

  • Constantes: UPPER_SNAKE_CASE

Ejemplo de estilo:

"""
Módulo de ejemplo siguiendo las convenciones de NoxPanel.
"""
import logging
from typing import Optional

from django.db import models
from rest_framework import serializers

from .models import HostingSite

logger = logging.getLogger(__name__)


class SiteService:
    """Servicio de gestión de sitios web."""

    def create_site(
        self,
        tenant: 'HostingTenant',
        domain: str,
        ip_address: str = '*',
    ) -> Optional[HostingSite]:
        """
        Crear un nuevo sitio web.

        Args:
            tenant: Tenant propietario del sitio.
            domain: Dominio del sitio web.
            ip_address: Dirección IP (usar '*' para todas).

        Returns:
            El sitio creado o None si falla.

        Raises:
            ValidationError: Si el dominio ya existe.
        """
        ...

Templates HTML

  • Indentación: 2 espacios

  • Usar clases CSS de Bootstrap 5

  • Mantener la lógica de template al mínimo

  • Usar {% block %} y {% include %} para reutilización

JavaScript

  • Indentación: 2 espacios

  • Usar const/let en lugar de var

  • Preferir fetch() sobre jQuery AJAX

  • Documentar funciones con JSDoc

Branching Model

Usamos un modelo simplificado basado en Git Flow:

Rama

Propósito

master

Código estable en producción

develop

Rama de desarrollo / integración

feature/*

Nuevas funcionalidades

bugfix/*

Corrección de bugs

hotfix/*

Correcciones urgentes en producción

release/*

Preparación de releases

Flujo de trabajo

  1. Crear una rama desde develop:

    git checkout develop
    git pull origin develop
    git checkout -b feature/nombre-descriptivo
    
  2. Desarrollar y hacer commits

  3. Abrir Pull Request hacia develop

  4. Esperar revisión y aprobación

  5. Merge tras aprobación

Commits

Formato de Mensajes

Seguimos el formato de Conventional Commits:

<tipo>(<ámbito>): <descripción>

[cuerpo opcional]

[notas de pie opcionales]

Tipos permitidos

Tipo

Descripción

feat

Nueva funcionalidad

fix

Corrección de bug

docs

Cambios en documentación

style

Formato, espacios, puntos y coma (sin cambio de lógica)

refactor

Refactorización sin cambio de funcionalidad

perf

Mejora de rendimiento

test

Añadir o corregir tests

chore

Tareas de mantenimiento (deps, CI, config)

Ejemplos:

feat(hosting): add DNS zone import from hosting engine
fix(billing): correct tax calculation for EUR invoices
docs(api): add curl examples to authentication guide
refactor(ticketing): extract email fetcher to separate service
chore(deps): upgrade Django to 5.2

Testing

Ejecutar tests

# Todos los tests
docker-compose exec web python manage.py test

# Tests de un módulo específico
docker-compose exec web python manage.py test hosting
docker-compose exec web python manage.py test billing
docker-compose exec web python manage.py test ticketing

# Test con verbose
docker-compose exec web python manage.py test --verbosity=2

Escribir tests

  • Cada módulo tiene su archivo tests.py o directorio tests/

  • Usar django.test.TestCase para tests con BD

  • Usar rest_framework.test.APITestCase para tests de API

  • Nombrar tests descriptivamente: test_create_site_exceeds_quota_returns_400

Ejemplo:

from rest_framework.test import APITestCase
from rest_framework import status
from accounts.models import User
from hosting.models import HostingTenant


class SiteAPITest(APITestCase):
    def setUp(self):
        self.user = User.objects.create_user(
            username='test', password='test123',
            can_access_hosting=True,
        )
        self.tenant = HostingTenant.objects.create(
            name='Test Corp', slug='test-corp',
            contact_email='test@example.com',
        )
        self.client.force_authenticate(user=self.user)

    def test_list_sites_returns_200(self):
        response = self.client.get('/hosting/api/rest/sites/')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

Pull Requests

Checklist para PRs

Antes de abrir un PR, verifica que:

  • [ ] Los tests pasan (python manage.py test)

  • [ ] No hay errores de linting

  • [ ] Los commits siguen el formato Conventional Commits

  • [ ] La documentación se ha actualizado si es necesario

  • [ ] Se han añadido migraciones si se cambiaron modelos

  • [ ] El PR tiene una descripción clara del cambio

Descripción del PR

Usa la siguiente plantilla:

## Descripción
Breve descripción del cambio y motivación.

## Cambios
- Cambio 1
- Cambio 2

## Testing
Cómo se ha probado el cambio.

## Screenshots (si aplica)
Capturas de pantalla del cambio visual.

Documentación

La documentación se genera con Sphinx y usa el tema Read the Docs:

# Generar documentación
cd app/docs
make html

# Visualizar
open _build/html/index.html

Al añadir nueva funcionalidad:

  1. Actualizar la documentación RST correspondiente

  2. Añadir ejemplos de uso

  3. Incluir en el toctree de index.rst si es una sección nueva