Skip to content

Load Testing

Load Testing #6

Workflow file for this run

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 }}