diff --git a/.env.example b/.env.example index 568a4d2..9e95b9e 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,6 @@ OPENAI_API_KEY=ADD-YOUR-OPENAI_API_KEY-HERE ENVIRONMENT=local -DOCKERHUB_USERNAME=ADD-YOUR-DOCKERHUB_USERNAME-HERE +DOCKERHUB_USERNAME=jwu-labs DOCKERHUB_ACCESS_TOKEN=ADD-YOUR-DOCKERHUB_ACCESS_TOKEN-HERE LLM_TOOL_CHOICE=required LOGGING_LEVEL=20 diff --git a/.github/workflows/testsPython.yml b/.github/workflows/testsPython.yml index 452f71d..880d52c 100644 --- a/.github/workflows/testsPython.yml +++ b/.github/workflows/testsPython.yml @@ -69,11 +69,93 @@ jobs: notifications: needs: python-unit-tests runs-on: ubuntu-latest + if: always() + permissions: + contents: read + actions: read steps: - - name: Notify on test results + - name: Notify on successful test results + if: needs.python-unit-tests.result == 'success' + run: | + echo "### ✅ Build Passed!" >> $GITHUB_STEP_SUMMARY + echo "All unit tests completed successfully for commit ${GITHUB_SHA::7}." >> $GITHUB_STEP_SUMMARY + + - name: Notify on failed test results (summary) + if: needs.python-unit-tests.result == 'failure' + run: | + echo "### ❌ Build Failed!" >> $GITHUB_STEP_SUMMARY + echo "The Python Unit Tests failed on commit [${GITHUB_SHA::7}](${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }})." >> $GITHUB_STEP_SUMMARY + echo "**Triggered by**: ${{ github.actor }}" >> $GITHUB_STEP_SUMMARY + echo "Please check the logs in the 'python-unit-tests' job to identify the error." >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "---" >> $GITHUB_STEP_SUMMARY + echo "**Note:** An automated incident report with failure details has been emailed to the designated recipients." >> $GITHUB_STEP_SUMMARY + + - name: Build incident report + id: report + if: needs.python-unit-tests.result == 'failure' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + echo "short_sha=${GITHUB_SHA::7}" >> $GITHUB_OUTPUT + sleep 10 + + # Fetch Job ID for python-unit-tests + JOB_ID=$(gh api repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/jobs \ + --jq '.jobs[] | select(.name=="python-unit-tests") | .id') + + # Fetch job logs and strip ANSI color codes and ISO8601 timestamps + CLEAN_LOGS=$(gh api repos/${{ github.repository }}/actions/jobs/$JOB_ID/logs | \ + sed -r "s/\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[mGK]//g" | \ + sed -r 's/^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]+Z //') + + # Extract summaries + FAILED_TESTS=$(echo "$CLEAN_LOGS" | grep -Ei "ERROR: test_|FAILED \(errors=[0-9]+\)" || echo "No test failures identified.") + ROOT_CAUSE=$(echo "$CLEAN_LOGS" | grep -Ei "ImportError:|AssertionError:|ValueError:|TypeError:|NameError:|AttributeError:" | sort -u || echo "Could not determine root cause. Please see full logs for details.") + + # Build report + { + echo "incident_report<> $GITHUB_OUTPUT + + - name: Notify on failed test results (email) + if: needs.python-unit-tests.result == 'failure' + uses: dawidd6/action-send-mail@v3 + with: + server_address: smtp.gmail.com + server_port: 465 + username: ${{ secrets.EMAIL_USERNAME }} + password: ${{ secrets.EMAIL_PASSWORD }} + subject: "❌ Python Unit Tests Failed - ${{ github.repository }} (${{ steps.report.outputs.short_sha }})" + to: ${{ secrets.NOTIFY_EMAIL }} + from: "GitHub Actions Notifications <${{ secrets.EMAIL_USERNAME }}>" + body: | + ${{ steps.report.outputs.incident_report }} + + - name: Notify on cancelled test runs + if: needs.python-unit-tests.result == 'cancelled' run: | - if [ "${{ needs.python-unit-tests.result }}" == "success" ]; then - echo "success notifications go here" - else - echo "failure notifications go here" - fi + echo "### ⚠️ Build Cancelled" >> $GITHUB_STEP_SUMMARY + echo "The workflow was cancelled before completion." >> $GITHUB_STEP_SUMMARY + echo "**Commit:** [${GITHUB_SHA::7}](${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }})" >> $GITHUB_STEP_SUMMARY diff --git a/.gitignore b/.gitignore index c7d04ba..08f0dbf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# temp directory for type checks +.mypy_cache/ + # my own homegrown file to store coverage report output from Docker. coverage.out diff --git a/Makefile b/Makefile index 7bebd1b..570b1fc 100644 --- a/Makefile +++ b/Makefile @@ -129,8 +129,8 @@ docker-coverage: /bin/bash -c "python -m coverage run --source=app --omit='app/tests/*' -m unittest discover -s app/tests && python -m coverage report -m --omit='app/tests/*' && python -m coverage xml --omit='app/tests/*'" docker-prune: - @if [ "`docker ps -aq`" ]; then \ - docker stop $(docker ps -aq); \ + @if [ -n "$$(docker ps -aq)" ]; then \ + docker stop $$(docker ps -aq); \ fi @docker container prune -f @docker image prune -af