name: CI/CD on: pull_request: types: [opened, synchronize, reopened] branches: - main - test workflow_dispatch: jobs: test-backend: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.11' - name: Install dependencies run: | cd api pip install -r requirements.txt - name: Verify build run: | python -c "from api.main import app" - name: Run tests run: | pytest -q test-frontend: needs: test-backend 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' - name: Install dependencies run: | cd web npm ci - name: Build frontend run: | cd web npm run build create-archives: needs: [test-backend, test-frontend] runs-on: ubuntu-latest if: always() && !cancelled() steps: - name: Checkout code uses: actions/checkout@v4 - name: Create archives run: | zip -r api.zip api/ -x "*.pyc" "*__pycache__*" "*.git*" "*.pytest_cache*" zip -r web.zip web/ -x "node_modules/*" ".git*" "dist/*" "*.log" - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: build-artifacts-${{ github.run_id }} path: | api.zip web.zip retention-days: 7 # Явный статус для PR pr-status: needs: [test-backend, test-frontend] runs-on: ubuntu-latest if: always() && github.event_name == 'pull_request' steps: - name: Check status and update PR env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | # Определяем общий статус проверок if [[ "${{ needs.test-backend.result }}" == "success" ]] && \ [[ "${{ needs.test-frontend.result }}" == "success" ]]; then STATE="success" DESCRIPTION="✅ All checks passed successfully" EXIT_CODE=0 else STATE="failure" DESCRIPTION="❌ Some checks failed" EXIT_CODE=1 fi # Формируем URL для API статусов REPO="${{ github.repository }}" SHA="${{ github.event.pull_request.head.sha }}" API_URL="${{ github.api_url }}/repos/${REPO}/statuses/${SHA}" # Отправляем статус в Gitea curl -X POST "$API_URL" \ -H "Authorization: token $GITHUB_TOKEN" \ -H "Content-Type: application/json" \ -d "{ \"state\": \"$STATE\", \"context\": \"CI/CD Pipeline / Overall Status\", \"description\": \"$DESCRIPTION\", \"target_url\": \"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\" }" echo "Status $STATE sent for commit $SHA" # Выходим с соответствующим кодом, чтобы блокировать PR при неудаче exit $EXIT_CODE # Опционально: добавляем комментарий в PR при неудаче comment-on-failure: needs: [test-backend, test-frontend, pr-status] runs-on: ubuntu-latest if: failure() && github.event_name == 'pull_request' steps: - name: Add failure comment to PR env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | # Определяем какие проверки не прошли BACKEND_STATUS="${{ needs.test-backend.result }}" FRONTEND_STATUS="${{ needs.test-frontend.result }}" COMMENT="## ❌ Проверки не пройдены! ### Результаты проверок: | Проверка | Статус | |----------|--------| | **Backend tests** | $( [ "$BACKEND_STATUS" = "success" ] && echo "✅ Успешно" || echo "❌ Ошибка" ) | | **Frontend build** | $( [ "$FRONTEND_STATUS" = "success" ] && echo "✅ Успешно" || echo "❌ Ошибка" ) | ### Детали: - **Ветка**: ${{ github.head_ref }} - **Коммит**: \`${{ github.event.pull_request.head.sha }}\` - **Запуск**: [Смотреть детали](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) Пожалуйста, исправьте ошибки перед слиянием. 🚨" # Находим PR номер PR_NUMBER=$(jq --raw-output .number "$GITHUB_EVENT_PATH") # Добавляем комментарий curl -X POST "${{ github.api_url }}/repos/${{ github.repository }}/issues/${PR_NUMBER}/comments" \ -H "Authorization: token $GITHUB_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"body\": $(echo "$COMMENT" | jq -Rs .)}" echo "Comment added to PR #$PR_NUMBER" # Опционально: удаляем старые артефакты cleanup: needs: [create-archives, pr-status] runs-on: ubuntu-latest if: always() steps: - name: Clean up old artifacts run: | echo "Cleaning up temporary files" # Здесь можно добавить логику очистки, если нужно