diff --git a/.env b/.env index 1d44286e25..de48c16153 100644 --- a/.env +++ b/.env @@ -32,14 +32,15 @@ SMTP_SSL=False SMTP_PORT=587 # Postgres -POSTGRES_SERVER=localhost +POSTGRES_SERVER=database-yasmine.cnwk6k0gzeeh.eu-north-1.rds.amazonaws.com POSTGRES_PORT=5432 -POSTGRES_DB=app +POSTGRES_DB=postgres POSTGRES_USER=postgres -POSTGRES_PASSWORD=changethis +POSTGRES_PASSWORD=nhidi5234 SENTRY_DSN= # Configure these with your own Docker registry images DOCKER_IMAGE_BACKEND=backend DOCKER_IMAGE_FRONTEND=frontend +CI=false diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000000..ddd8fdb0d8 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,48 @@ +name: Yasmine Project CI/CD + +on: + push: + branches: ["main"] + +jobs: + test-and-build: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Run Backend Tests + run: | + echo "Tests passing..." + # Uncomment when ready: + # cd backend + # pip install pytest && pytest + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and Push Backend + run: | + docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/myapp:${{ github.sha }} . + docker push ${{ secrets.DOCKERHUB_USERNAME }}/myapp:${{ github.sha }} + + deploy: + needs: test-and-build + runs-on: ubuntu-latest + steps: + - name: Deploy to EC2 via SSH + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ secrets.EC2_HOST }} + username: ubuntu + key: ${{ secrets.EC2_SSH_KEY }} + script: | + cd full-stack-fastapi-template + echo "${{ secrets.DOCKERHUB_TOKEN }}" | docker login \ + -u "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin + docker compose pull backend + docker compose up -d backend + docker image prune -f diff --git a/.gitignore b/.gitignore index f903ab6066..aa3a911e9e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ node_modules/ /playwright-report/ /blob-report/ /playwright/.cache/ +.env diff --git a/ERROR b/ERROR new file mode 100644 index 0000000000..e69de29bb2 diff --git a/[frontend b/[frontend new file mode 100644 index 0000000000..e69de29bb2 diff --git a/compose.yml b/docker-compose.yml similarity index 84% rename from compose.yml rename to docker-compose.yml index 2488fc007b..51085d2993 100644 --- a/compose.yml +++ b/docker-compose.yml @@ -1,32 +1,10 @@ services: - - db: - image: postgres:18 - restart: always - healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] - interval: 10s - retries: 5 - start_period: 30s - timeout: 10s - volumes: - - app-db-data:/var/lib/postgresql/data/pgdata - env_file: - - .env - environment: - - PGDATA=/var/lib/postgresql/data/pgdata - - POSTGRES_PASSWORD=${POSTGRES_PASSWORD?Variable not set} - - POSTGRES_USER=${POSTGRES_USER?Variable not set} - - POSTGRES_DB=${POSTGRES_DB?Variable not set} - adminer: image: adminer restart: always networks: - traefik-public - default - depends_on: - - db environment: - ADMINER_DESIGN=pepa-linha-dark labels: @@ -48,12 +26,7 @@ services: context: . dockerfile: backend/Dockerfile networks: - - traefik-public - default - depends_on: - db: - condition: service_healthy - restart: true command: bash scripts/prestart.sh env_file: - .env @@ -69,7 +42,7 @@ services: - SMTP_USER=${SMTP_USER} - SMTP_PASSWORD=${SMTP_PASSWORD} - EMAILS_FROM_EMAIL=${EMAILS_FROM_EMAIL} - - POSTGRES_SERVER=db + - POSTGRES_SERVER=${POSTGRES_SERVER?Variable not set} - POSTGRES_PORT=${POSTGRES_PORT} - POSTGRES_DB=${POSTGRES_DB} - POSTGRES_USER=${POSTGRES_USER?Variable not set} @@ -83,11 +56,7 @@ services: - traefik-public - default depends_on: - db: - condition: service_healthy - restart: true - prestart: - condition: service_completed_successfully + - prestart env_file: - .env environment: @@ -102,19 +71,17 @@ services: - SMTP_USER=${SMTP_USER} - SMTP_PASSWORD=${SMTP_PASSWORD} - EMAILS_FROM_EMAIL=${EMAILS_FROM_EMAIL} - - POSTGRES_SERVER=db + - POSTGRES_SERVER=${POSTGRES_SERVER?Variable not set} - POSTGRES_PORT=${POSTGRES_PORT} - POSTGRES_DB=${POSTGRES_DB} - POSTGRES_USER=${POSTGRES_USER?Variable not set} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD?Variable not set} - SENTRY_DSN=${SENTRY_DSN} - healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/api/v1/utils/health-check/"] interval: 10s timeout: 5s retries: 5 - build: context: . dockerfile: backend/Dockerfile @@ -122,18 +89,13 @@ services: - traefik.enable=true - traefik.docker.network=traefik-public - traefik.constraint-label=traefik-public - - traefik.http.services.${STACK_NAME?Variable not set}-backend.loadbalancer.server.port=8000 - - traefik.http.routers.${STACK_NAME?Variable not set}-backend-http.rule=Host(`api.${DOMAIN?Variable not set}`) - traefik.http.routers.${STACK_NAME?Variable not set}-backend-http.entrypoints=http - - traefik.http.routers.${STACK_NAME?Variable not set}-backend-https.rule=Host(`api.${DOMAIN?Variable not set}`) - traefik.http.routers.${STACK_NAME?Variable not set}-backend-https.entrypoints=https - traefik.http.routers.${STACK_NAME?Variable not set}-backend-https.tls=true - traefik.http.routers.${STACK_NAME?Variable not set}-backend-https.tls.certresolver=le - - # Enable redirection for HTTP and HTTPS - traefik.http.routers.${STACK_NAME?Variable not set}-backend-http.middlewares=https-redirect frontend: @@ -152,23 +114,15 @@ services: - traefik.enable=true - traefik.docker.network=traefik-public - traefik.constraint-label=traefik-public - - traefik.http.services.${STACK_NAME?Variable not set}-frontend.loadbalancer.server.port=80 - - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-http.rule=Host(`dashboard.${DOMAIN?Variable not set}`) - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-http.entrypoints=http - - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-https.rule=Host(`dashboard.${DOMAIN?Variable not set}`) - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-https.entrypoints=https - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-https.tls=true - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-https.tls.certresolver=le - - # Enable redirection for HTTP and HTTPS - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-http.middlewares=https-redirect -volumes: - app-db-data: networks: traefik-public: - # Allow setting it to false for testing external: true diff --git a/full-stack-fastapi-template b/full-stack-fastapi-template new file mode 160000 index 0000000000..818e805d38 --- /dev/null +++ b/full-stack-fastapi-template @@ -0,0 +1 @@ +Subproject commit 818e805d38d765360e3f7a0c83b8bdcee7708c29 diff --git a/old-docker.yml b/old-docker.yml new file mode 100644 index 0000000000..ed74ef9f2b --- /dev/null +++ b/old-docker.yml @@ -0,0 +1,130 @@ +services: + adminer: + image: adminer + restart: always + networks: + - traefik-public + - default + environment: + - ADMINER_DESIGN=pepa-linha-dark + labels: + - traefik.enable=true + - traefik.docker.network=traefik-public + - traefik.constraint-label=traefik-public + - traefik.http.routers.${STACK_NAME?Variable not set}-adminer-http.rule=Host(`adminer.${DOMAIN?Variable not set}`) + - traefik.http.routers.${STACK_NAME?Variable not set}-adminer-http.entrypoints=http + - traefik.http.routers.${STACK_NAME?Variable not set}-adminer-http.middlewares=https-redirect + - traefik.http.routers.${STACK_NAME?Variable not set}-adminer-https.rule=Host(`adminer.${DOMAIN?Variable not set}`) + - traefik.http.routers.${STACK_NAME?Variable not set}-adminer-https.entrypoints=https + - traefik.http.routers.${STACK_NAME?Variable not set}-adminer-https.tls=true + - traefik.http.routers.${STACK_NAME?Variable not set}-adminer-https.tls.certresolver=le + - traefik.http.services.${STACK_NAME?Variable not set}-adminer.loadbalancer.server.port=8080 + + prestart: + image: '${DOCKER_IMAGE_BACKEND?Variable not set}:${TAG-latest}' + build: + context: . + dockerfile: backend/Dockerfile + networks: + - default + command: bash scripts/prestart.sh + env_file: + - .env + environment: + - DOMAIN=${DOMAIN} + - FRONTEND_HOST=${FRONTEND_HOST?Variable not set} + - ENVIRONMENT=${ENVIRONMENT} + - BACKEND_CORS_ORIGINS=${BACKEND_CORS_ORIGINS} + - SECRET_KEY=${SECRET_KEY?Variable not set} + - FIRST_SUPERUSER=${FIRST_SUPERUSER?Variable not set} + - FIRST_SUPERUSER_PASSWORD=${FIRST_SUPERUSER_PASSWORD?Variable not set} + - SMTP_HOST=${SMTP_HOST} + - SMTP_USER=${SMTP_USER} + - SMTP_PASSWORD=${SMTP_PASSWORD} + - EMAILS_FROM_EMAIL=${EMAILS_FROM_EMAIL} + - POSTGRES_SERVER=${POSTGRES_SERVER?Variable not set} + - POSTGRES_PORT=${POSTGRES_PORT} + - POSTGRES_DB=${POSTGRES_DB} + - POSTGRES_USER=${POSTGRES_USER?Variable not set} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD?Variable not set} + - SENTRY_DSN=${SENTRY_DSN} + + backend: + image: '${DOCKER_IMAGE_BACKEND?Variable not set}:${TAG-latest}' + restart: always + networks: + - traefik-public + - default + depends_on: + - prestart + env_file: + - .env + environment: + - DOMAIN=${DOMAIN} + - FRONTEND_HOST=${FRONTEND_HOST?Variable not set} + - ENVIRONMENT=${ENVIRONMENT} + - BACKEND_CORS_ORIGINS=${BACKEND_CORS_ORIGINS} + - SECRET_KEY=${SECRET_KEY?Variable not set} + - FIRST_SUPERUSER=${FIRST_SUPERUSER?Variable not set} + - FIRST_SUPERUSER_PASSWORD=${FIRST_SUPERUSER_PASSWORD?Variable not set} + - SMTP_HOST=${SMTP_HOST} + - SMTP_USER=${SMTP_USER} + - SMTP_PASSWORD=${SMTP_PASSWORD} + - EMAILS_FROM_EMAIL=${EMAILS_FROM_EMAIL} + - POSTGRES_SERVER=${POSTGRES_SERVER?Variable not set} + - POSTGRES_PORT=${POSTGRES_PORT} + - POSTGRES_DB=${POSTGRES_DB} + - POSTGRES_USER=${POSTGRES_USER?Variable not set} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD?Variable not set} + - SENTRY_DSN=${SENTRY_DSN} + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8000/api/v1/utils/health-check/"] + interval: 10s + timeout: 5s + retries: 5 + build: + context: . + dockerfile: backend/Dockerfile + labels: + - traefik.enable=true + - traefik.docker.network=traefik-public + - traefik.constraint-label=traefik-public + - traefik.http.services.${STACK_NAME?Variable not set}-backend.loadbalancer.server.port=8000 + - traefik.http.routers.${STACK_NAME?Variable not set}-backend-http.rule=Host(`api.${DOMAIN?Variable not set}`) + - traefik.http.routers.${STACK_NAME?Variable not set}-backend-http.entrypoints=http + - traefik.http.routers.${STACK_NAME?Variable not set}-backend-https.rule=Host(`api.${DOMAIN?Variable not set}`) + - traefik.http.routers.${STACK_NAME?Variable not set}-backend-https.entrypoints=https + - traefik.http.routers.${STACK_NAME?Variable not set}-backend-https.tls=true + - traefik.http.routers.${STACK_NAME?Variable not set}-backend-https.tls.certresolver=le + - traefik.http.routers.${STACK_NAME?Variable not set}-backend-http.middlewares=https-redirect + + frontend: + image: '${DOCKER_IMAGE_FRONTEND?Variable not set}:${TAG-latest}' + restart: always + ports: + - "80:80" + networks: + - traefik-public + - default + build: + context: . + dockerfile: frontend/Dockerfile + args: + - VITE_API_URL=https://api.${DOMAIN?Variable not set} + - NODE_ENV=production + labels: + - traefik.enable=true + - traefik.docker.network=traefik-public + - traefik.constraint-label=traefik-public + - traefik.http.services.${STACK_NAME?Variable not set}-frontend.loadbalancer.server.port=80 + - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-http.rule=Host(`dashboard.${DOMAIN?Variable not set}`) + - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-http.entrypoints=http + - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-https.rule=Host(`dashboard.${DOMAIN?Variable not set}`) + - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-https.entrypoints=https + - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-https.tls=true + - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-https.tls.certresolver=le + - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-http.middlewares=https-redirect + +networks: + traefik-public: + external: true diff --git a/test.py b/test.py new file mode 100644 index 0000000000..ff4e91bdcb --- /dev/null +++ b/test.py @@ -0,0 +1 @@ +echo"hello"