Skip to content

Performance test against performance.mavistesting.com #243

Performance test against performance.mavistesting.com

Performance test against performance.mavistesting.com #243

Workflow file for this run

name: Performance
run-name: Performance test against ${{ inputs.BaseURL }}
on:
push:
branches:
- performance-testing
workflow_dispatch:
inputs:
AddNewSession:
description: "Add a new session date (not needed if there are already enough patients)"
required: true
type: boolean
default: true
runConsent:
description: "Run consent journey"
required: true
type: boolean
default: true
runNurse:
description: "Run the nurse journey"
required: true
type: boolean
default: true
duration:
description: "Optional (default 3600) Duration of nurse journey test, in seconds. This will include ramp-up."
required: false
type: number
default: 3600
threads:
description: "Optional (default 70) Threads to run. Equivalent to the number of nurses using the system."
required: false
type: number
default: 70
ramp_up:
description: "Optional (default 900) Ramp-up time in seconds. Threads will be gradually started up over this time."
required: false
type: number
default: 900
user:
description: "Optional (default Nurse perftest) user."
required: true
type: string
default: '[email protected]'
BaseURL:
description: "Optional (default performance.mavistesting.com) URL"
required: true
type: string
default: 'performance.mavistesting.com'
jobs:
check-image-presence:
name: Check if docker image already exists
runs-on: ubuntu-latest
permissions:
id-token: write
outputs:
build-needed: ${{ steps.check-image.outputs.build-needed }}
steps:
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v5
with:
role-to-assume: arn:aws:iam::393416225559:role/GitHubAssuranceTestRole
aws-region: eu-west-2
- name: Check if image exists
id: check-image
run: |
if aws ecr describe-images --repository-name performancetest --image-ids imageTag=${{ github.sha }} > /dev/null 2>&1; then
echo "Docker image with given tag already exists"
else
echo "Docker image does not exist. Build needed"
echo "build-needed=true" >> $GITHUB_OUTPUT
fi
build-and-push:
needs: check-image-presence
if: needs.check-image-presence.outputs.build-needed == 'true'
runs-on: ubuntu-latest
defaults:
run:
working-directory: performance-tests/
permissions:
id-token: write
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v5
with:
role-to-assume: arn:aws:iam::393416225559:role/GitHubAssuranceTestRole
aws-region: eu-west-2
- name: Cache base jmeter image
id: jmeter-base
uses: actions/cache@v5
env:
cache-name: cache-jmeter
with:
path: ${{ runner.temp }}/jmeter-image.tar
key: jmeter-image-${{ hashFiles('performance-tests/base.Dockerfile') }}
- name: Build base jmeter image
if: steps.jmeter-base.outputs.cache-hit != 'true'
run: |
docker build -t base-jmeter-image:latest -f base.Dockerfile .
docker save -o ${{ runner.temp }}/jmeter-image.tar base-jmeter-image:latest
- name: Login to ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build and push performancetest docker image
run: |
docker load -i ${{ runner.temp }}/jmeter-image.tar
docker build -t "393416225559.dkr.ecr.eu-west-2.amazonaws.com/performancetest:${{ github.sha }}" .
docker push "393416225559.dkr.ecr.eu-west-2.amazonaws.com/performancetest:${{ github.sha }}"
run-performance-test:
needs: [build-and-push, check-image-presence]
if: ${{ !cancelled() &&
(needs.build-and-push.result == 'success' ||
(needs.check-image-presence.result == 'success' && needs.build-and-push.result == 'skipped')
) }}
runs-on: ubuntu-latest
permissions:
id-token: write
contents: write
timeout-minutes: 180
env:
RESULT_PATH: ${{ github.run_number }}
steps:
- uses: actions/checkout@v6
- name: Set timestamp
run: echo "timestamp=$(date '+%Y%m%d%H%M%S')" >> $GITHUB_ENV
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v5
with:
role-to-assume: arn:aws:iam::393416225559:role/GitHubAssuranceTestRole
aws-region: eu-west-2
role-duration-seconds: 14400 # 4 hours
- name: Create task definition
id: create-task-definition
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition-family: "assurance-testing-performance-task-definition-template"
container-name: "performancetest-container"
image: "393416225559.dkr.ecr.eu-west-2.amazonaws.com/performancetest:${{ github.sha }}"
environment-variables: |
ADD_NEW_SESSION=${{ inputs.AddNewSession }}
RUN_CONSENT=${{ inputs.runConsent }}
RUN_NURSE=${{ inputs.runNurse }}
RESULT_PATH=${{ env.RESULT_PATH }}
BASE_URL=${{ inputs.BaseURL }}
USER=${{ inputs.user }}
DURATION=${{ inputs.duration }}
THREADS=${{ inputs.threads }}
RAMP_UP=${{ inputs.ramp_up }}
secrets: |
AUTH_TOKEN=arn:aws:secretsmanager:eu-west-2:393416225559:secret:performancetest/auth-token
- name: Register task definition
id: register-task-definition
run: |
file_path="assurance-testing-performance-task-definition.json"
family_name="assurance-testing-performance-task-definition"
echo "$(jq --arg f "$family_name" '.family = $f' "${{ steps.create-task-definition.outputs.task-definition }}")" > "$file_path"
task_definition_arn=$(aws ecs register-task-definition \
--cli-input-json file://$file_path \
--query 'taskDefinition.taskDefinitionArn' \
--output text
)
echo "task_definition_arn=$task_definition_arn" >> $GITHUB_OUTPUT
- name: Start performance test
id: run-task
run: |
echo "Starting ECS task to run performance test against ${{ inputs.BaseURL }}"
subnet_id=$(aws ec2 describe-subnets --filters Name=tag:Name,Values=assurance-testing-subnet --query 'Subnets[0].SubnetId' --output text)
security_group_id=$(aws ec2 describe-security-groups --filters Name=group-name,Values=assurance-testing-performance-sg --query 'SecurityGroups[0].GroupId' --output text)
task_arn=$(aws ecs run-task \
--cluster assurance-testing \
--task-definition ${{ steps.register-task-definition.outputs.task_definition_arn }} \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[$subnet_id],securityGroups=[$security_group_id],assignPublicIp=ENABLED}" \
--overrides '{
"containerOverrides": [{
"name": "performancetest-container"
}]
}' \
--query 'tasks[0].taskArn' \
--enable-execute-command \
--output text)
echo "task_arn=$task_arn" >> $GITHUB_OUTPUT
echo "test_start_time=$(date +%s)000" >> $GITHUB_ENV
echo "Started task: $task_arn"
- name: Wait for performance test to complete
id: wait-for-completion
run: |
echo "Waiting for task to complete: ${{ steps.run-task.outputs.task_arn }}"
TASK_ID=$(sed 's:^.*/::' <<< ${{ steps.run-task.outputs.task_arn }})
CLOUDWATCH_URL="https://eu-west-2.console.aws.amazon.com/cloudwatch/home?region=eu-west-2#logsV2:log-groups/log-group/assurance-testing-ecs/log-events/assurance-testing-logs\$252Fperformancetest-container\$252F${TASK_ID}\$3Fstart\$3D${test_start_time}\$26end\$3D$(date -d '+1 hour + 15 minutes' +%s)000"
echo "Performance test logs: $CLOUDWATCH_URL"
echo "CLOUDWATCH_URL=$CLOUDWATCH_URL" >> $GITHUB_ENV
while true; do
task_status=$(aws ecs describe-tasks \
--cluster assurance-testing \
--tasks ${{ steps.run-task.outputs.task_arn }} \
--query 'tasks[0].lastStatus' \
--output text)
echo "Current task status: $task_status"
if [ "$task_status" == "STOPPED" ]; then
echo "Task has stopped"
break
fi
sleep 30 # Check every 30 seconds
done
exit_code=$(aws ecs describe-tasks \
--cluster assurance-testing \
--tasks ${{ steps.run-task.outputs.task_arn }} \
--query 'tasks[0].containers[0].exitCode' \
--output text)
echo "Container exit code: $exit_code"
if [ "$exit_code" != "0" ]; then
echo "ECS task failed with exit code: $exit_code"
exit 1
fi
- name: Collect test result
id: collect-results
run: |
echo "Downloading test results from S3"
S3_PATH="s3://performancetest-reports/${{ env.RESULT_PATH }}"
aws s3 sync "${S3_PATH}" ./test-results --no-progress
- name: Upload nurse journey JMeter output
if: inputs.runNurse == true
uses: actions/upload-artifact@v5
with:
name: jmeter-nurse-journey-output-${{ env.timestamp }}
path: test-results/nurse
if-no-files-found: warn
- name: Upload consent journey JMeter output
if: inputs.runConsent == true
uses: actions/upload-artifact@v5
with:
name: jmeter-consent-journey-output-${{ env.timestamp }}
path: test-results/consent
if-no-files-found: warn
- name: Publish report to GH Pages
if: inputs.runNurse == true
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_branch: gh-pages
publish_dir: test-results/nurse/report
destination_dir: JMeter/${{ env.RESULT_PATH }}
keep_files: true
- name: Set Job Summary
run: |
# Extract task ID from task ARN
TASK_ARN="${{ steps.run-task.outputs.task_arn }}"
TASK_ID=$(echo $TASK_ARN | awk -F/ '{print $NF}')
# Construct CloudWatch Logs URL
LOG_GROUP="/ecs/performancetest-task-definition"
LOG_STREAM="ecs/performancetest-container/${TASK_ID}"
# URL encode the log group and stream names
ENCODED_LOG_GROUP=$(echo "$LOG_GROUP" | sed 's/\//%252F/g')
ENCODED_LOG_STREAM=$(echo "$LOG_STREAM" | sed 's/\//%252F/g')
CLOUDWATCH_URL="https://eu-west-2.console.aws.amazon.com/cloudwatch/home?region=eu-west-2#logsV2:log-groups/log-group/${ENCODED_LOG_GROUP}/log-events/${ENCODED_LOG_STREAM}"
echo "## Performance Test Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **BaseURL:** ${{ inputs.BaseURL }}" >> $GITHUB_STEP_SUMMARY
echo "- **Run Number:** ${{ github.run_number }}" >> $GITHUB_STEP_SUMMARY
echo "- **Test Logs:** $CLOUDWATCH_URL" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "📊 [View Test Report](https://nhsdigital.github.io/manage-vaccinations-in-schools-testing/JMeter/${{ env.RESULT_PATH }}/)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "📋 [View CloudWatch Logs](${CLOUDWATCH_URL})" >> $GITHUB_STEP_SUMMARY