Skip to content

Version 6.13

Version 6.13 #260

name: End To End test run
on:
pull_request:
workflow_call:
inputs:
git_reference_for_application_image:
description: The git reference for deploying containerized mavis application
type: string
required: false
git_reference_for_database_image:
description: The environment to build the base image against
type: string
required: false
default: "next"
secrets:
HTTP_AUTH_TOKEN_FOR_TESTS:
description: HTTP Basic Auth token for the environment under test
required: true
MAVIS_TESTING_REPO_ACCESS_TOKEN:
description: Access token for the manage-vaccinations-in-schools-testing repository
required: true
workflow_dispatch:
inputs:
git_reference_for_application_image:
description: The git reference for deploying containerized mavis application
type: string
required: false
git_reference_for_database_image:
description: The environment to build the base image against
type: string
required: false
default: "next"
permissions: { }
jobs:
check-if-run-needed:
name: Check if tests are required
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
repository: nhsuk/manage-vaccinations-in-schools
- name: Check if end-to-end tests need to run
id: check
uses: ./.github/actions/run-test-suites-check
outputs:
run-test-suites: ${{ steps.check.outputs.run-test-suites }}
check-development-image-presence:
name: Check if mavis docker image already exists
runs-on: ubuntu-latest
permissions:
id-token: write
outputs:
build-needed: ${{ steps.check-image.outputs.build-needed }}
application-image-git-ref: ${{ steps.check-image.outputs.GIT_REF_SHA }}
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
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Check if image exists
id: check-image
env:
GIT_REF: ${{ (inputs.git_reference_for_application_image == 'next' && 'origin/next') || github.event.pull_request.head.sha || github.sha }}
run: |
GIT_REF_SHA=$(git rev-parse $GIT_REF)
echo "GIT_REF_SHA=$GIT_REF_SHA" >> $GITHUB_OUTPUT
if aws ecr describe-images --repository-name mavis/development --image-ids imageTag=$GIT_REF_SHA > /dev/null 2>&1; then
echo "Docker image with given tag already exists"
echo "build-needed=false" >> $GITHUB_OUTPUT
else
echo "Docker image does not exist. Build needed"
echo "build-needed=true" >> $GITHUB_OUTPUT
fi
build-and-push-development-image:
needs: [ check-development-image-presence, check-if-run-needed ]
if: ${{ !cancelled() && needs.check-development-image-presence.outputs.build-needed == 'true' && (github.event_name != 'pull_request' || needs.check-if-run-needed.outputs.run-test-suites == 'true') }}
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
ref: ${{ needs.check-development-image-presence.outputs.application-image-git-ref }}
repository: nhsuk/manage-vaccinations-in-schools
- 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: Login to ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build and push mavis/development docker image
run: |
docker build \
--build-arg BUNDLE_WITHOUT=test \
--build-arg RAILS_ENV=development \
-t "393416225559.dkr.ecr.eu-west-2.amazonaws.com/mavis/development:${{ needs.check-development-image-presence.outputs.application-image-git-ref }}" \
.
docker push "393416225559.dkr.ecr.eu-west-2.amazonaws.com/mavis/development:${{ needs.check-development-image-presence.outputs.application-image-git-ref }}"
check-database-image-presence:
name: Check if database docker image already exists
runs-on: ubuntu-latest
permissions:
id-token: write
outputs:
build-needed: ${{ steps.check-image.outputs.build-needed }}
db_git_ref_sha: ${{ steps.check-image.outputs.GIT_REF_SHA }}
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
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Check if image exists
id: check-image
env:
GIT_REF: ${{ ( inputs.git_reference_for_database_image == 'next' && 'origin/next' ) || github.event.pull_request.base.sha || github.sha }}
run: |
GIT_REF_SHA=$(git rev-parse $GIT_REF)
echo "GIT_REF_SHA=$GIT_REF_SHA" >> $GITHUB_OUTPUT
if aws ecr describe-images --repository-name mavis/development --image-ids imageTag=$GIT_REF_SHA > /dev/null 2>&1; then
echo "Docker image with given tag already exists"
echo "build-needed=false" >> $GITHUB_OUTPUT
else
echo "Docker image does not exist. Build needed"
echo "build-needed=true" >> $GITHUB_OUTPUT
fi
build-and-push-database-image:
needs: [ check-database-image-presence, check-if-run-needed ]
if: ${{ !cancelled() && needs.check-database-image-presence.outputs.build-needed == 'true' && (github.event_name != 'pull_request' || needs.check-if-run-needed.outputs.run-test-suites == 'true') }}
permissions:
id-token: write
contents: read
uses: ./.github/workflows/create_dockerized_db.yml
with:
github_ref: ${{ needs.check-database-image-presence.outputs.db_git_ref_sha }}
launch-dockerized-devimage:
needs: [ check-development-image-presence,
build-and-push-development-image,
check-database-image-presence,
build-and-push-database-image,
check-if-run-needed ]
if: ${{ !cancelled() &&
(needs.build-and-push-development-image.result == 'success' ||
(needs.check-development-image-presence.result == 'success' && needs.build-and-push-development-image.result == 'skipped')) &&
(needs.build-and-push-database-image.result == 'success' ||
(needs.check-database-image-presence.result == 'success' && needs.build-and-push-database-image.result == 'skipped'))
&& (github.event_name != 'pull_request' || needs.check-if-run-needed.outputs.run-test-suites == 'true') }}
runs-on: ubuntu-latest
permissions:
id-token: write
outputs:
run_task_arn: ${{ steps.run-task.outputs.run-task-arn }}
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: Render task definition web
id: render-task-definition-web
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition-family: "assurance-testing-mavis-development-task-definition-template"
container-name: "mavis-development-web"
image: "393416225559.dkr.ecr.eu-west-2.amazonaws.com/mavis/development:${{ needs.check-development-image-presence.outputs.application-image-git-ref }}"
- name: Render task definition database
id: render-task-definition-database
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: ${{ steps.render-task-definition-web.outputs.task-definition }}
container-name: "mavis-development-db"
image: "393416225559.dkr.ecr.eu-west-2.amazonaws.com/mavis/development/postgres_db:${{ needs.check-database-image-presence.outputs.db_git_ref_sha }}"
- name: Render task definition sidekiq
id: render-task-definition-sidekiq
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: ${{ steps.render-task-definition-database.outputs.task-definition }}
container-name: "mavis-development-sidekiq"
image: "393416225559.dkr.ecr.eu-west-2.amazonaws.com/mavis/development:${{ needs.check-development-image-presence.outputs.application-image-git-ref }}"
- name: Prepare deployment
id: prepare-deployment
run: |
file_path="assurance-testing-mavis-development-task-definition.json"
family_name="assurance-testing-mavis-development-task-definition"
echo "$(jq --arg f "$family_name" '.family = $f' "${{ steps.render-task-definition-sidekiq.outputs.task-definition }}")" > "$file_path"
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-mavis-development-sg --query 'SecurityGroups[0].GroupId' --output text)
echo "run-task-subnets=$subnet_id" >> $GITHUB_OUTPUT
echo "run-task-security-groups=$security_group_id" >> $GITHUB_OUTPUT
- name: Deploy task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v2
id: run-task
with:
task-definition: 'assurance-testing-mavis-development-task-definition.json'
cluster: assurance-testing
run-task: true
run-task-subnets: ${{ steps.prepare-deployment.outputs.run-task-subnets }}
run-task-launch-type: 'FARGATE'
run-task-security-groups: ${{ steps.prepare-deployment.outputs.run-task-security-groups }}
run-task-assign-public-IP: ENABLED
wait-for-task-stability:
needs: launch-dockerized-devimage
if: ${{ !cancelled() && needs.launch-dockerized-devimage.result == 'success'}}
runs-on: ubuntu-latest
permissions:
id-token: write
outputs:
task_arn: ${{ steps.compile-outputs.outputs.task_arn }}
container_ip: ${{ steps.compile-outputs.outputs.container_ip }}
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: Get container logs
run: |
TASK_ARN=$(echo '${{ needs.launch-dockerized-devimage.outputs.run_task_arn }}' | jq -r '.[0]')
TASK_ID=$(sed 's:^.*/::' <<< $TASK_ARN)
WEB_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\$252Fmavis-development-web\$252F${TASK_ID}\$3Fstart\$3D$(date +%s)000\$26end\$3D$(date -d '+30 minutes' +%s)000"
SIDEKIQ_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\$252Fmavis-development-sidekiq\$252F${TASK_ID}\$3Fstart\$3D$(date +%s)000\$26end\$3D$(date -d '+30 minutes' +%s)000"
echo "**Task ID:** $TASK_ID" >> $GITHUB_STEP_SUMMARY
echo "**Container Logs:** " >> $GITHUB_STEP_SUMMARY
echo " * WEB logs: $WEB_CLOUDWATCH_URL" >> $GITHUB_STEP_SUMMARY
echo " * SIDEKIQ logs: $SIDEKIQ_CLOUDWATCH_URL" >> $GITHUB_STEP_SUMMARY
echo "Logs for server: [web](${WEB_CLOUDWATCH_URL}) and [sidekiq](${SIDEKIQ_CLOUDWATCH_URL})"
- name: Wait for task to stabilise
run: |
set -euo pipefail
ELAPSED=0
POLL_INTERVAL=10
TASK_ARN=$(echo '${{ needs.launch-dockerized-devimage.outputs.run_task_arn }}' | jq -r '.[0]')
echo "Waiting for ECS task $TASK_ARN to become HEALTHY"
while (( ELAPSED < 300 )); do
HEALTH_STATUS=$(aws ecs describe-tasks \
--cluster "assurance-testing" \
--tasks "$TASK_ARN" \
--query 'tasks[0].healthStatus' \
--output text 2>/dev/null || echo "UNKNOWN")
LAST_EVENT=$(aws ecs describe-tasks \
--cluster "assurance-testing" \
--tasks "$TASK_ARN" \
--query 'tasks[0].lastStatus' \
--output text 2>/dev/null || echo "UNKNOWN")
case "$HEALTH_STATUS" in
"HEALTHY")
echo "Task is HEALTHY"
exit 0
;;
"UNHEALTHY")
echo "Task reported UNHEALTHY"
aws ecs describe-tasks --cluster "assurance-testing" --tasks "$TASK_ARN" --query 'tasks[0].containers[].{Name:name,Health:health,Reason:lastStatusReason}' --output table
exit 1
;;
"UNKNOWN"|"")
# Task might not exist or API error
if [[ "$LAST_EVENT" == "STOPPED" || "$LAST_EVENT" == "DEACTIVATED" ]]; then
echo "Task is no longer running (lastStatus: $LAST_EVENT)"
exit 1
fi
echo "Task not found or not reporting health yet (healthStatus: UNKNOWN, lastStatus: $LAST_EVENT). Retrying..."
;;
*)
# HEALTHY/UNHEALTHY not reported yet (common in early lifecycle)
echo "Task health check in progress... (healthStatus: $HEALTH_STATUS, lastStatus: $LAST_EVENT)"
;;
esac
sleep "$POLL_INTERVAL"
ELAPSED=$((ELAPSED + POLL_INTERVAL))
done
echo "Timeout reached (300 seconds) while waiting for task to become HEALTHY"
echo "Final status:"
aws ecs describe-tasks --cluster "assurance-testing" --tasks "$TASK_ARN" --query 'tasks[0]' --output json || true
exit 1
- name: Compile outputs
id: compile-outputs
run: |
TASK_ARN=$(echo '${{ needs.launch-dockerized-devimage.outputs.run_task_arn }}' | jq -r '.[0]')
NETWORK_INTERFACE=$(aws ecs describe-tasks \
--cluster assurance-testing \
--tasks "$TASK_ARN" \
| jq -r '.tasks[0].attachments[0].details[] | select(.name == "networkInterfaceId") | .value')
CONTAINER_IP=$(aws ec2 describe-network-interfaces \
--network-interface-ids $NETWORK_INTERFACE \
--query 'NetworkInterfaces[0].Association.PublicIp' \
--output text)
echo "container_ip=$CONTAINER_IP" >> $GITHUB_OUTPUT
echo "task_arn=$TASK_ARN" >> $GITHUB_OUTPUT
echo "Started task: $TASK_ARN"
find-correct-test-branch:
needs: [ wait-for-task-stability ]
if: ${{ !cancelled() && needs.wait-for-task-stability.result == 'success'}}
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
test_branch: ${{ steps.check-branch.outputs.test_branch }}
steps:
- name: Check if branch exists
id: check-branch
run: |
if git ls-remote --exit-code --heads https://github.com/NHSDigital/manage-vaccinations-in-schools-testing.git "$BRANCH_TO_CHECK" > /dev/null 2>&1; then
echo "test_branch=$BRANCH_TO_CHECK" >> $GITHUB_OUTPUT
else
echo "test_branch=main" >> $GITHUB_OUTPUT
fi
env:
BRANCH_TO_CHECK: ${{ github.head_ref }}
call-end-to-end-tests:
needs: [ launch-dockerized-devimage, wait-for-task-stability, find-correct-test-branch ]
if: ${{ !cancelled() && needs.launch-dockerized-devimage.result == 'success' && needs.wait-for-task-stability.result == 'success'}}
uses: NHSDigital/manage-vaccinations-in-schools-testing/.github/workflows/end-to-end-tests.yaml@main
permissions:
contents: write
with:
cross_service_tests: false
github_ref: ${{ needs.find-correct-test-branch.outputs.test_branch }}
endpoint: 'http://${{ needs.wait-for-task-stability.outputs.container_ip }}:4000'
secrets:
HTTP_AUTH_TOKEN_FOR_TESTS: ${{ secrets.HTTP_AUTH_TOKEN_FOR_TESTS }}
MAVIS_TESTING_REPO_ACCESS_TOKEN: ${{ secrets.MAVIS_TESTING_REPO_ACCESS_TOKEN }}
stop-docker-environment:
needs: [ call-end-to-end-tests, launch-dockerized-devimage, wait-for-task-stability ]
if: ${{ always() && needs.launch-dockerized-devimage.result != 'skipped'}}
runs-on: ubuntu-latest
permissions:
id-token: write
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: Stop dockerized dev image
run: aws ecs stop-task --cluster assurance-testing --task ${{ needs.wait-for-task-stability.outputs.task_arn }}