name: Backend CI/CD on: push: branches: [main] pull_request: branches: [main] permissions: contents: read jobs: test: runs-on: ubuntu-latest timeout-minutes: 30 services: postgres: image: postgres:16-alpine env: POSTGRES_DB: app POSTGRES_PASSWORD: password POSTGRES_USER: app ports: - 5432:5432 options: >- --health-cmd "pg_isready -U app -d app" --health-interval 10s --health-timeout 5s --health-retries 5 redis: image: redis:7-alpine ports: - 6379:6379 options: >- --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5 env: SECRET_KEY: github-ci-secret-key DEBUG: "False" DJANGO_SETTINGS_MODULE: config.settings.test ALLOWED_HOSTS: localhost,127.0.0.1,testserver DJANGO_HOST: http://localhost:8000 DB_ENGINE: django.db.backends.postgresql DB_NAME: app DB_USER: app DB_PASSWORD: password DB_HOST: localhost DB_PORT: "5432" TEST_DB_ENGINE: django.db.backends.postgresql TEST_DB_NAME: app TEST_DB_USER: app TEST_DB_PASSWORD: password TEST_DB_HOST: localhost TEST_DB_PORT: "5432" REDIS_PASSWORD: "" REDIS_URL: redis://localhost:6379/0 CELERY_BROKER_URL: redis://localhost:6379/0 CELERY_RESULT_BACKEND: redis://localhost:6379/1 EMAIL_BACKEND: django.core.mail.backends.console.EmailBackend EMAIL_HOST: localhost EMAIL_PORT: "1025" EMAIL_USE_TLS: "False" EMAIL_HOST_USER: "" EMAIL_HOST_PASSWORD: "" DEFAULT_FROM_EMAIL: noreply@example.com CORS_ALLOWED_ORIGINS: http://localhost:3000 FRONTEND_ROOT: http://localhost:3000 FRONTEND_PASSWORD_RESET_PAGE: http://localhost:3000/reset-password FRONTEND_CALLBACK_URL: http://localhost:3000/payments/result JWT_SECRET_KEY: test-jwt-key JWT_ALGORITHM: HS256 JWT_ACCESS_TOKEN_LIFETIME: "3600" JWT_REFRESH_TOKEN_LIFETIME: "86400" ZARINPAL_MERCHANT_ID: sandbox-merchant ZARINPAL_USE_SANDBOX: "True" ZARINPAL_CALLBACK_URL: http://localhost:8000/api/payments/callback PYTHON_VERSION: "3.12" steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ env.PYTHON_VERSION }} cache: pip cache-dependency-path: requirements.txt - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt pip install coverage - name: Prepare environment file run: cp .env.test .env - name: Run migrations run: python manage.py migrate --noinput - name: Run tests with coverage run: | coverage run --rcfile=.coveragerc manage.py test --settings=config.settings.test --verbosity 2 coverage report -m deploy: runs-on: ubuntu-latest needs: test if: github.event_name == 'push' && github.ref == 'refs/heads/main' timeout-minutes: 30 steps: - name: Deploy backend services uses: appleboy/ssh-action@v1.2.0 with: host: ${{ secrets.DEPLOY_HOST }} username: ${{ secrets.DEPLOY_USER }} key: ${{ secrets.DEPLOY_SSH_KEY }} port: ${{ secrets.DEPLOY_PORT }} script: | set -e cd "${{ secrets.DEPLOY_PATH }}/backend/guilan-ace-backend" git fetch --prune origin git checkout "${{ vars.BACKEND_BRANCH || 'main' }}" git pull --ff-only origin "${{ vars.BACKEND_BRANCH || 'main' }}" cd "${{ secrets.DEPLOY_PATH }}" docker compose up -d --build web worker beat docker image prune -f