commit 9864802b768ef17ec199a672a8b2514933036871 Author: unai Date: Sun Feb 1 17:51:28 2026 +0000 Initial commit diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..13eb708 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,5 @@ +FROM python:3.14-slim +# Instalar git y herramientas básicas +RUN apt-get update && apt-get install -y git curl && rm -rf /var/lib/apt/lists/* +# Instalar Poetry +RUN pip install poetry diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..db404d3 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,38 @@ +{ + "name": "Python Poetry Dev", + "build": { + "dockerfile": "Dockerfile" + }, + "customizations": { + "vscode": { + "extensions": [ + "ms-python.python", + "charliermarsh.ruff", + "tamasfe.even-better-toml" + ], + "settings": { + "python.defaultInterpreterPath": "/usr/local/bin/python", + "editor.formatOnSave": true, + "[python]": { + "editor.defaultFormatter": "charliermarsh.ruff", + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit" + } + } + } + } + }, + "runArgs": [ + "--privileged", + "-v", + "/dev:/dev" + ], + "mounts": [ + "source=${localEnv:XDG_RUNTIME_DIR}/ssh-agent.socket,target=/tmp/ssh-agent.socket,type=bind" + ], + "remoteEnv": { + "SSH_AUTH_SOCK": "/tmp/ssh-agent.socket" + }, + "remoteUser": "root", + "postCreateCommand": "poetry install" +} \ No newline at end of file diff --git a/.gitea/ci.yml b/.gitea/ci.yml new file mode 100644 index 0000000..0c6e37a --- /dev/null +++ b/.gitea/ci.yml @@ -0,0 +1,54 @@ +name: CI/CD Pipeline + +on: + push: + branches: [main] + tags: ['v*'] + pull_request: + +jobs: + test-and-lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.14' + + - name: Install Poetry + run: pip install poetry + + - name: Install dependencies + run: poetry install + + - name: Lint with Ruff (PEP-8 & Docstrings) + run: poetry run ruff check . + + - name: Run Tests with Coverage + run: poetry run pytest --cov=my_project --cov-report=term-missing --cov-fail-under=80 + + publish-container: + needs: test-and-lint + if: startsWith(github.ref, 'refs/tags/v') + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Login to Gitea Container Registry + uses: docker/login-action@v2 + with: + registry: ${{ gitea.server_url }} + # Nota: Quita 'https://' si server_url lo incluye y falla, suele ser solo dominio:puerto + username: ${{ gitea.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and Push Docker Image + uses: docker/build-push-action@v4 + with: + context: . + push: true + tags: | + ${{ gitea.server_url }}/${{ gitea.repository }}:latest + ${{ gitea.server_url }}/${{ gitea.repository }}:${{ gitea.ref_name }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6448c00 --- /dev/null +++ b/.gitignore @@ -0,0 +1,44 @@ +# --- Python (Bytecode y cache) --- +__pycache__/ +*.py[cod] +*$py.class +poetry.lock +# --- Distribución y Build --- +dist/ +build/ +*.egg-info/ +.eggs/ + +# --- Entornos Virtuales (Poetry suele crear .venv) --- +.venv/ +venv/ +env/ +ENV/ + +# --- Testing y Coverage --- +.coverage +.coverage.* +htmlcov/ +.pytest_cache/ +coverage.xml + +# --- Herramientas de Calidad (Ruff, Mypy) --- +.ruff_cache/ +.mypy_cache/ +.dmypy.json + +# --- Variables de Entorno (¡Seguridad!) --- +.env + +# --- IDEs y Editores --- +.vscode/ +.idea/ +*.sw +*.swo + +# --- Sistema Operativo --- +.DS_Store +Thumbs.db + +# --- Logs --- +*.log diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ae6429c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,39 @@ +# Stage 1: Builder (Compilación y dependencias) +FROM python:3.14-slim as builder + +WORKDIR /app + +# Variables de entorno para optimizar Poetry y Pip +ENV POETRY_NO_INTERACTION=1 \ + POETRY_VIRTUALENVS_IN_PROJECT=1 \ + POETRY_VIRTUALENVS_CREATE=1 \ + PIP_NO_CACHE_DIR=1 + +# Instalar Poetry +RUN pip install poetry + +# Copiar archivos de configuración primero para aprovechar el caché de capas +COPY pyproject.toml poetry.lock ./ + +# Instalar dependencias de producción (sin dev) +RUN poetry install --without dev --no-root + +# Stage 2: Runtime (Imagen final limpia) +FROM python:3.14-slim as runtime + +WORKDIR /app +ENV VIRTUAL_ENV=/app/.venv \ + PATH="/app/.venv/bin:$PATH" + +# Copiar el entorno virtual generado en el stage anterior +COPY --from=builder /app/.venv /app/.venv + +# Copiar el código fuente +COPY ./src /app/src + +# Usuario no privilegiado por seguridad +RUN useradd -m appuser && chown -R appuser /app +USER appuser + +# Punto de entrada +CMD ["python", "-m", "my_project.main"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..c812d5a --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,41 @@ +[tool.poetry] +name = "my-project" +version = "0.0.0" +description = "Python boilerplate for Gitea with Docker and Poetry" +authors = ["Unai Blazquez "] +readme = "README.md" +packages = [{include = "my_project", from = "src"}] + +[tool.poetry.dependencies] +python = "^3.14" + +[tool.poetry.group.dev.dependencies] +pytest = "^9.0.2" +pytest-cov = "^7.0.0" +ruff = "^0.14.14" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" + +# --- Configuración de Ruff (Linter & Formatter) --- +[tool.ruff] +line-length = 88 +target-version = "py314" + +[tool.ruff.lint] +# E/F: Errores base, I: Imports (isort), D: Docstrings +select = ["E", "F", "I", "D"] +ignore = ["D100", "D104"] # Ignorar docstring en modulos/paquetes vacíos si se desea + +[tool.ruff.lint.pydocstyle] +convention = "google" # Estilo de docstring (Google, NumPy o PEP 257) + +# --- Configuración de Coverage --- +[tool.coverage.run] +source = ["src"] +branch = true + +[tool.coverage.report] +fail_under = 80 # CI falla si el coverage es menor al 80% +show_missing = true diff --git a/src/my-project/__init__.py b/src/my-project/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/my-project/main.py b/src/my-project/main.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/.gitkeep b/tests/.gitkeep new file mode 100644 index 0000000..e69de29