name: Deploy to Testing Server on: pull_request: branches: - develop types: [opened, synchronize, reopened] jobs: deploy: name: Deploy to Testing Server runs-on: ubuntu-latest if: github.event.pull_request.merged == false # Только для открытых PR steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: "18" cache: "yarn" - name: Install dependencies run: yarn install --frozen-lockfile - name: Run linting run: yarn lint:check - name: Build application run: yarn build - name: Build Docker image run: | docker build -t low-code-engine:testing-${{ github.event.pull_request.number }} . - name: Save Docker image run: | docker save low-code-engine:testing-${{ github.event.pull_request.number }} | gzip > low-code-engine-testing.tar.gz - name: Deploy to Testing Server uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.TESTING_SERVER_HOST }} username: ${{ secrets.TESTING_SERVER_USER }} key: ${{ secrets.TESTING_SERVER_SSH_KEY }} port: ${{ secrets.TESTING_SERVER_PORT || 22 }} script: | # Создаем директорию для приложения если её нет mkdir -p /opt/low-code-engine/testing-pr-${{ github.event.pull_request.number }} cd /opt/low-code-engine/testing-pr-${{ github.event.pull_request.number }} # Останавливаем существующие контейнеры если они есть docker-compose down || true # Удаляем старые образы docker image prune -f || true - name: Copy files to server uses: appleboy/scp-action@v0.1.7 with: host: ${{ secrets.TESTING_SERVER_HOST }} username: ${{ secrets.TESTING_SERVER_USER }} key: ${{ secrets.TESTING_SERVER_SSH_KEY }} port: ${{ secrets.TESTING_SERVER_PORT || 22 }} source: "low-code-engine-testing.tar.gz,docker-compose.yml,docker/" target: "/opt/low-code-engine/testing-pr-${{ github.event.pull_request.number }}/" - name: Load and run Docker containers uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.TESTING_SERVER_HOST }} username: ${{ secrets.TESTING_SERVER_USER }} key: ${{ secrets.TESTING_SERVER_SSH_KEY }} port: ${{ secrets.TESTING_SERVER_PORT || 22 }} script: | cd /opt/low-code-engine/testing-pr-${{ github.event.pull_request.number }} # Загружаем Docker образ gunzip -c low-code-engine-testing.tar.gz | docker load # Создаем .env файл для тестового окружения cat > .env << EOF NODE_ENV=testing DB_ROOT_PASSWORD=${{ secrets.TESTING_DB_ROOT_PASSWORD }} DB_DATABASE=low_code_engine_pr_${{ github.event.pull_request.number }} DB_USERNAME=${{ secrets.TESTING_DB_USERNAME }} DB_PASSWORD=${{ secrets.TESTING_DB_PASSWORD }} DB_PORT=3306 APP_PORT=${{ vars.TESTING_BASE_PORT || 3000 }}${{ github.event.pull_request.number }} REDIS_HOST=redis REDIS_PORT=6379 EOF # Создаем docker-compose.override.yml для тестового окружения cat > docker-compose.override.yml << EOF version: "3.8" services: app: image: low-code-engine:testing-${{ github.event.pull_request.number }} ports: - "\${APP_PORT}:3000" environment: NODE_ENV: testing DB_HOST: mariadb DB_PORT: 3306 DB_USERNAME: \${DB_USERNAME} DB_PASSWORD: \${DB_PASSWORD} DB_DATABASE: \${DB_DATABASE} REDIS_HOST: redis REDIS_PORT: 6379 mariadb: ports: - "${{ vars.TESTING_BASE_DB_PORT || 3306 }}${{ github.event.pull_request.number }}:3306" environment: MYSQL_DATABASE: \${DB_DATABASE} redis: image: redis:7-alpine ports: - "${{ vars.TESTING_BASE_REDIS_PORT || 6379 }}${{ github.event.pull_request.number }}:6379" EOF # Запускаем контейнеры docker-compose up -d # Ждем пока база данных запустится sleep 30 # Запускаем миграции docker-compose exec -T app yarn migration:run || true # Проверяем статус контейнеров docker-compose ps - name: Health check uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.TESTING_SERVER_HOST }} username: ${{ secrets.TESTING_SERVER_USER }} key: ${{ secrets.TESTING_SERVER_SSH_KEY }} port: ${{ secrets.TESTING_SERVER_PORT || 22 }} script: | cd /opt/low-code-engine/testing-pr-${{ github.event.pull_request.number }} # Проверяем доступность приложения APP_PORT=${{ vars.TESTING_BASE_PORT || 3000 }}${{ github.event.pull_request.number }} for i in {1..10}; do if curl -f http://localhost:$APP_PORT/health > /dev/null 2>&1; then echo "✅ Application is healthy on port $APP_PORT" break fi echo "⏳ Waiting for application to start... (attempt $i/10)" sleep 10 done - name: Comment PR with deployment info uses: actions/github-script@v7 with: script: | const prNumber = context.payload.pull_request.number; const appPort = ${{ vars.TESTING_BASE_PORT || 3000 }} + prNumber; const dbPort = ${{ vars.TESTING_BASE_DB_PORT || 3306 }} + prNumber; const redisPort = ${{ vars.TESTING_BASE_REDIS_PORT || 6379 }} + prNumber; const comment = `## 🚀 Testing Deployment Your PR has been deployed to the testing server! **Deployment Details:** - 🌐 Application URL: http://${{ secrets.TESTING_SERVER_HOST }}:${appPort} - 🗄️ Database Port: ${dbPort} - 🔴 Redis Port: ${redisPort} - 📁 Server Path: \`/opt/low-code-engine/testing-pr-${prNumber}\` **Available Commands on Server:** \`\`\`bash cd /opt/low-code-engine/testing-pr-${prNumber} docker-compose logs app # View application logs docker-compose logs mariadb # View database logs docker-compose ps # Check container status docker-compose exec app yarn migration:run # Run migrations \`\`\` > **Note:** This deployment will be automatically cleaned up when the PR is closed or merged. `; github.rest.issues.createComment({ issue_number: prNumber, owner: context.repo.owner, repo: context.repo.repo, body: comment }); cleanup: name: Cleanup on PR Close runs-on: ubuntu-latest if: github.event.pull_request.state == 'closed' steps: - name: Cleanup testing environment uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.TESTING_SERVER_HOST }} username: ${{ secrets.TESTING_SERVER_USER }} key: ${{ secrets.TESTING_SERVER_SSH_KEY }} port: ${{ secrets.TESTING_SERVER_PORT || 22 }} script: | cd /opt/low-code-engine/testing-pr-${{ github.event.pull_request.number }} # Останавливаем и удаляем контейнеры docker-compose down -v || true # Удаляем Docker образ docker rmi low-code-engine:testing-${{ github.event.pull_request.number }} || true # Удаляем директорию развертывания cd .. rm -rf testing-pr-${{ github.event.pull_request.number }} echo "✅ Cleanup completed for PR #${{ github.event.pull_request.number }}" - name: Comment PR with cleanup info uses: actions/github-script@v7 with: script: | const comment = `## 🧹 Testing Environment Cleaned Up The testing deployment for this PR has been cleaned up: - ✅ Docker containers stopped and removed - ✅ Docker images cleaned up - ✅ Server files removed Thank you for testing! 🎉 `; github.rest.issues.createComment({ issue_number: context.payload.pull_request.number, owner: context.repo.owner, repo: context.repo.repo, body: comment });