Skip to content
Open
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
88 changes: 88 additions & 0 deletions .github/workflows/backend.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# =============================================================================
# Pipeline do Backend — Lint → Test → Build → Push
# =============================================================================
name: Backend CI

on:
push:
branches: [main]
paths: ['backend/**']
pull_request:
branches: [main]
paths: ['backend/**']

jobs:
lint:
name: Lint Backend
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.12'

- name: Install Ruff
run: pip install ruff

- name: Run Ruff
working-directory: ./backend
run: ruff check app/

test:
name: Test Backend
runs-on: ubuntu-latest
needs: lint
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.12'

- name: Install dependencies
working-directory: ./backend
run: |
pip install -e .
pip install pytest pytest-asyncio httpx aiosqlite

- name: Run tests
working-directory: ./backend
env:
SECRET_KEY: test-secret-key-for-ci-only
DATABASE_URL: sqlite+aiosqlite:///test.db
run: pytest __tests__/ -v

build-and-push:
name: Build and Push Docker Image
runs-on: ubuntu-latest
needs: test
if: github.ref == 'refs/heads/main'
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build and push
uses: docker/build-push-action@v5
with:
context: ./backend
file: ./backend/Dockerfile
push: true
tags: |
${{ secrets.DOCKERHUB_USERNAME }}/condocombat-backend:latest
${{ secrets.DOCKERHUB_USERNAME }}/condocombat-backend:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
79 changes: 79 additions & 0 deletions .github/workflows/deploy-landing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: Deploy Landing Page

on:
push:
branches: [main, master]
paths:
- 'landing/**'
- '.github/workflows/deploy-landing.yml'
workflow_dispatch:

env:
NODE_VERSION: '20'

jobs:
ci:
name: CI — Test & Build
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./landing

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
cache-dependency-path: ./landing/package-lock.json

- name: Install dependencies
run: npm ci

- name: Run tests
run: npm test

- name: Build
run: npm run build
env:
PUBLIC_APP_URL: ${{ secrets.PUBLIC_APP_URL }}

- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: landing-dist
path: landing/dist/

cd:
name: CD — Deploy to Netlify
needs: ci
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}

- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: landing-dist
path: landing/dist/

- name: Install Netlify CLI
run: npm install -g netlify-cli

- name: Deploy to Netlify
run: |
netlify deploy \
--dir=landing/dist \
--prod \
--auth=${{ secrets.NETLIFY_AUTH_TOKEN }} \
--site=${{ secrets.NETLIFY_SITE_ID }}
88 changes: 88 additions & 0 deletions .github/workflows/frontend.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# =============================================================================
# Pipeline do Frontend — Lint → Test → Build → Push
# =============================================================================
name: Frontend CI

on:
push:
branches: [main]
paths: ['frontend/**']
pull_request:
branches: [main]
paths: ['frontend/**']

jobs:
lint:
name: Lint Frontend
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json

- name: Install dependencies
working-directory: ./frontend
run: npm ci

- name: Run ESLint
working-directory: ./frontend
run: npm run lint

test:
name: Test Frontend
runs-on: ubuntu-latest
needs: lint
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json

- name: Install dependencies
working-directory: ./frontend
run: npm ci

- name: Run tests
working-directory: ./frontend
run: npm run test

build-and-push:
name: Build and Push Docker Image
runs-on: ubuntu-latest
needs: test
if: github.ref == 'refs/heads/main'
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build and push
uses: docker/build-push-action@v5
with:
context: ./frontend
file: ./frontend/Dockerfile
push: true
tags: |
${{ secrets.DOCKERHUB_USERNAME }}/condocombat-frontend:latest
${{ secrets.DOCKERHUB_USERNAME }}/condocombat-frontend:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ skills-lock.json
.tmp
.omo
AGENTS.md
.env

# Node / General
node_modules/
Expand Down
55 changes: 55 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# =============================================================================
# Stage 1: Dependencies — instala dependências Python
# =============================================================================
FROM python:3.12-slim AS deps

WORKDIR /app

# Instala sistema básico e dependências de compilação
RUN apt-get update && apt-get install -y \
gcc \
postgresql-client \
&& rm -rf /var/lib/apt/lists/*

# Copia requirements e instala dependências
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# =============================================================================
# Stage 2: Runtime — imagem final
# =============================================================================
FROM python:3.12-slim AS runtime

WORKDIR /app

# Instala dependências de runtime
RUN apt-get update && apt-get install -y \
postgresql-client \
&& rm -rf /var/lib/apt/lists/*

# Cria usuário não-root
RUN useradd --create-home --shell /bin/bash app

# Copia dependências do stage deps
COPY --from=deps /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY --from=deps /usr/local/bin /usr/local/bin

# Copia código fonte
COPY app/ app/
COPY alembic/ alembic/
COPY alembic.ini .

# Copia e configura script de entrada
COPY entrypoint.sh .
RUN chmod +x entrypoint.sh

# Troca para usuário não-root
USER app

# Expõe porta e health check
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1

# Entry point
ENTRYPOINT ["./entrypoint.sh"]
15 changes: 15 additions & 0 deletions backend/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash
set -e

# Valida SECRET_KEY obrigatória
if [ -z "$SECRET_KEY" ]; then
echo "❌ ERRO: SECRET_KEY não está definida!"
echo " Gere uma com: python -c 'import secrets; print(secrets.token_urlsafe(32))'"
exit 1
fi

echo "🔧 Rodando migrations do Alembic..."
alembic upgrade head

echo "🚀 Iniciando servidor FastAPI..."
exec uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
53 changes: 53 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# =============================================================================
# CondoCombat — Docker Compose (Backend + Frontend + Database)
# =============================================================================
version: '3.8'

services:
# PostgreSQL Database
db:
image: postgres:16-alpine
container_name: condocombat-db
environment:
POSTGRES_USER: ${POSTGRES_USER:-condocombat}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-condocombat}
POSTGRES_DB: ${POSTGRES_DB:-condocombat}
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-condocombat}"]
interval: 10s
timeout: 5s
retries: 5

# Backend API (FastAPI)
api:
image: mxliaf/condocombat-backend:latest
container_name: condocombat-api
environment:
DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-condocombat}:${POSTGRES_PASSWORD:-condocombat}@db:5432/${POSTGRES_DB:-condocombat}
SECRET_KEY: ${SECRET_KEY}
ports:
- "8000:8000"
depends_on:
db:
condition: service_healthy
restart: unless-stopped

# Frontend (Next.js)
web:
image: mxliaf/condocombat-frontend:latest
container_name: condocombat-web
environment:
NEXT_PUBLIC_API_URL: http://localhost:8000
ports:
- "3000:3000"
depends_on:
- api
restart: unless-stopped

volumes:
pgdata:
driver: local
Loading