name: Build and Deploy on: push: branches: [master, production-deployment] pull_request: branches: [master] env: REGISTRY: ghcr.io IMAGE_PREFIX: ${{ github.repository }} jobs: # ---- Backend Tests ---- test-backend: name: Backend Tests runs-on: ubuntu-latest services: postgres: image: postgres:16-alpine env: POSTGRES_USER: translate POSTGRES_PASSWORD: test_password POSTGRES_DB: translate_test ports: - 5432:5432 options: >- --health-cmd pg_isready --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 steps: - uses: actions/checkout@v4 - name: Set up Python 3.12 uses: actions/setup-python@v5 with: python-version: "3.12" cache: pip - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt - name: Run tests env: ENV: test DATABASE_URL: postgresql+asyncpg://translate:test_password@localhost:5432/translate_test REDIS_URL: redis://localhost:6379/0 JWT_SECRET_KEY: test_jwt_secret_key_for_ci ADMIN_USERNAME: admin ADMIN_PASSWORD: test_admin_password ADMIN_TOKEN_SECRET: test_admin_token_secret_ci CORS_ORIGINS: http://localhost:3000 run: | pytest tests/ -v --tb=short -x # ---- Frontend Build Check ---- test-frontend: name: Frontend Build Check runs-on: ubuntu-latest defaults: run: working-directory: frontend steps: - 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 run: npm ci - name: Lint run: npm run lint --if-present - name: Build run: npm run build env: NEXT_PUBLIC_API_URL: http://localhost:8000 # ---- Build and Push Docker Images ---- build: name: Build Docker Images runs-on: ubuntu-latest needs: [test-backend, test-frontend] if: github.event_name == 'push' && github.ref == 'refs/heads/production-deployment' permissions: contents: read packages: write steps: - uses: actions/checkout@v4 - name: Log in to Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Extract metadata for backend id: meta-backend uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/backend tags: | type=sha,prefix= type=raw,value=latest,enable={{is_default_branch}} - name: Build and push backend uses: docker/build-push-action@v5 with: context: . file: docker/backend/Dockerfile target: production push: true tags: ${{ steps.meta-backend.outputs.tags }} labels: ${{ steps.meta-backend.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max - name: Extract metadata for frontend id: meta-frontend uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/frontend tags: | type=sha,prefix= type=raw,value=latest,enable={{is_default_branch}} - name: Build and push frontend uses: docker/build-push-action@v5 with: context: . file: docker/frontend/Dockerfile target: production build-args: NEXT_PUBLIC_API_URL= push: true tags: ${{ steps.meta-frontend.outputs.tags }} labels: ${{ steps.meta-frontend.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max # ---- Deploy to Server ---- deploy: name: Deploy to Server runs-on: ubuntu-latest needs: [build] if: github.ref == 'refs/heads/production-deployment' environment: production steps: - name: Deploy via SSH uses: appleboy/ssh-action@v1 with: host: ${{ secrets.SERVER_HOST }} username: ${{ secrets.SERVER_USER }} key: ${{ secrets.SERVER_SSH_KEY }} script: | cd ${{ secrets.DEPLOY_PATH }} docker compose pull docker compose up -d --remove-orphans docker compose ps