Load Testing #6
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: Load Testing | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| test_type: | |
| description: 'Type of load test to run' | |
| required: true | |
| default: 'main' | |
| type: choice | |
| options: | |
| - main | |
| - stress | |
| - soak | |
| duration: | |
| description: 'Test duration (e.g., 5m, 1h)' | |
| required: false | |
| default: '' | |
| target_url: | |
| description: 'Target URL (leave empty for staging)' | |
| required: false | |
| default: '' | |
| schedule: | |
| # Run main load test weekly on Saturday at 2 AM | |
| - cron: '0 2 * * 6' | |
| jobs: | |
| load-test: | |
| name: Run Load Test | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 120 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up k6 | |
| run: | | |
| sudo gpg -k | |
| sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69 | |
| echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list | |
| sudo apt-get update | |
| sudo apt-get install k6 | |
| - name: Start services (for local testing) | |
| if: ${{ github.event.inputs.target_url == '' }} | |
| run: | | |
| docker compose up -d | |
| echo "Waiting for services to start..." | |
| sleep 60 | |
| # Wait for health check | |
| for i in {1..30}; do | |
| if curl -s http://localhost:8000/api/healthz | grep -q "ok\|healthy"; then | |
| echo "Services are healthy" | |
| break | |
| fi | |
| echo "Waiting for services... ($i/30)" | |
| sleep 10 | |
| done | |
| - name: Determine test parameters | |
| id: params | |
| run: | | |
| TEST_TYPE="${{ github.event.inputs.test_type || 'main' }}" | |
| DURATION="${{ github.event.inputs.duration }}" | |
| TARGET_URL="${{ github.event.inputs.target_url || 'http://localhost:8000' }}" | |
| echo "test_type=$TEST_TYPE" >> $GITHUB_OUTPUT | |
| echo "target_url=$TARGET_URL" >> $GITHUB_OUTPUT | |
| if [ -n "$DURATION" ]; then | |
| echo "duration_flag=--duration $DURATION" >> $GITHUB_OUTPUT | |
| else | |
| echo "duration_flag=" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Run load test | |
| run: | | |
| k6 run \ | |
| --env BASE_URL=${{ steps.params.outputs.target_url }} \ | |
| --out json=results.json \ | |
| ${{ steps.params.outputs.duration_flag }} \ | |
| loadtest/scripts/${{ steps.params.outputs.test_type }}.js \ | |
| 2>&1 | tee test-output.txt | |
| - name: Parse results | |
| if: always() | |
| run: | | |
| echo "## Load Test Results" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Test Type:** ${{ steps.params.outputs.test_type }}" >> $GITHUB_STEP_SUMMARY | |
| echo "**Target:** ${{ steps.params.outputs.target_url }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [ -f results.json ]; then | |
| echo "### Metrics Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY | |
| tail -100 test-output.txt >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| - name: Upload results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: load-test-results-${{ github.run_id }} | |
| path: | | |
| results.json | |
| test-output.txt | |
| *-summary.json | |
| - name: Stop services | |
| if: always() && github.event.inputs.target_url == '' | |
| run: docker compose down | |
| - name: Check thresholds | |
| run: | | |
| # Check if thresholds passed | |
| if grep -q "thresholds.*failed" test-output.txt; then | |
| echo "::error::Load test thresholds failed!" | |
| exit 1 | |
| fi | |
| echo "All thresholds passed!" | |
| notify: | |
| name: Notify Results | |
| runs-on: ubuntu-latest | |
| needs: load-test | |
| if: always() | |
| steps: | |
| - name: Send notification | |
| run: | | |
| STATUS="${{ needs.load-test.result }}" | |
| echo "Load test completed with status: $STATUS" | |
| # Add Slack/Discord/Email notification here if needed | |
| # Example for Slack: | |
| # curl -X POST -H 'Content-type: application/json' \ | |
| # --data '{"text":"Load test completed: '$STATUS'"}' \ | |
| # ${{ secrets.SLACK_WEBHOOK_URL }} |