Retry deployment with updated IAM policy #16
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: LearnMate CI/CD | |
| on: | |
| push: | |
| branches: [main, master, dinura-deployment, dinura-feedback-deploy] | |
| pull_request: | |
| branches: [main, master, dinura-deployment, dinura-feedback-deploy] | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| ci: | |
| name: CI - 15-case quality gate | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: "20" | |
| cache: npm | |
| cache-dependency-path: integrated-frontend/package-lock.json | |
| - name: Install test dependencies | |
| run: python -m pip install -r testing/requirements.txt | |
| - name: Run 15 comprehensive CI test cases | |
| run: | | |
| python -m pytest \ | |
| testing/unit/test_auth_security.py::test_access_token_round_trip \ | |
| testing/unit/test_auth_security.py::test_tampered_token_is_rejected \ | |
| testing/unit/test_password_rules.py::test_strong_enough_password_passes \ | |
| testing/unit/test_password_rules.py::test_password_over_72_bytes_rejected \ | |
| testing/unit/test_pdf_validate.py::test_valid_pdf_returns_page_count \ | |
| testing/unit/test_pdf_validate.py::test_garbage_bytes_are_corrupt \ | |
| testing/unit/test_error_handlers.py::test_unhandled_is_500_without_traceback_in_body \ | |
| testing/unit/test_evaluator_mcq.py::test_valid_question_passes \ | |
| testing/unit/test_chunking.py::test_prose_chunks_carry_page_and_index \ | |
| testing/integration/test_auth_api.py::test_register_201_returns_token_and_user \ | |
| testing/integration/test_auth_api.py::test_login_401_does_not_reveal_which_half_failed \ | |
| testing/integration/test_documents_api.py::test_upload_202_returns_document_and_job_id \ | |
| testing/integration/test_jobs_api.py::test_get_job_200_serializes_status_and_progress \ | |
| testing/integration/test_cors_and_root.py::test_root_points_at_health_and_docs \ | |
| testing/unit/test_frontend_contracts.py::test_auth_api_paths | |
| - name: Frontend lint | |
| run: | | |
| npm ci --prefix integrated-frontend | |
| npm run lint --prefix integrated-frontend | |
| - name: Frontend production build | |
| run: npm run build --prefix integrated-frontend | |
| - name: Validate Compose configuration | |
| run: docker compose --env-file .env.example config --quiet | |
| cd: | |
| name: CD - deploy full stack to AWS EC2 | |
| needs: ci | |
| if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@v4 | |
| with: | |
| aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
| aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| aws-region: ${{ secrets.AWS_REGION }} | |
| - name: Deploy through AWS Systems Manager | |
| env: | |
| EC2_INSTANCE_ID: ${{ secrets.EC2_INSTANCE_ID }} | |
| EC2_APP_DIR: ${{ secrets.EC2_APP_DIR || '/home/ubuntu/learnmate' }} | |
| APP_ENV_FILE_B64: ${{ secrets.APP_ENV_FILE_B64 }} | |
| DEPLOY_BRANCH: ${{ github.ref_name }} | |
| run: | | |
| set -euo pipefail | |
| test -n "$EC2_INSTANCE_ID" | |
| test -n "$APP_ENV_FILE_B64" | |
| COMMAND_ID=$(aws ssm send-command \ | |
| --instance-ids "$EC2_INSTANCE_ID" \ | |
| --document-name "AWS-RunShellScript" \ | |
| --comment "LearnMate deployment $GITHUB_SHA" \ | |
| --parameters "commands=[\"set -euo pipefail\",\"cd '$EC2_APP_DIR'\",\"test -d .git\",\"printf '%s' '$APP_ENV_FILE_B64' | base64 --decode > .env\",\"chmod 600 .env\",\"git fetch --prune origin '$DEPLOY_BRANCH'\",\"git checkout -B '$DEPLOY_BRANCH' 'origin/$DEPLOY_BRANCH'\",\"docker compose --env-file .env config --quiet\",\"docker compose --env-file .env build\",\"docker compose --env-file .env up -d --remove-orphans\",\"for attempt in \\\$(seq 1 30); do curl --fail --silent http://127.0.0.1/api/health >/dev/null && exit 0; sleep 10; done\",\"docker compose logs --tail 200 backend keycloak nginx\",\"exit 1\"]" \ | |
| --query 'Command.CommandId' \ | |
| --output text) | |
| aws ssm wait command-executed --command-id "$COMMAND_ID" --instance-id "$EC2_INSTANCE_ID" | |
| aws ssm get-command-invocation --command-id "$COMMAND_ID" --instance-id "$EC2_INSTANCE_ID" \ | |
| --query 'StandardOutputContent' --output text |