FHIR API and Batch Automation - E2E Tests #75
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: FHIR API and Batch Automation - E2E Tests | |
| on: | |
| workflow_call: | |
| inputs: | |
| apigee_environment: | |
| required: true | |
| type: string | |
| environment: | |
| required: true | |
| type: string | |
| sub_environment: | |
| required: true | |
| type: string | |
| service_under_test: | |
| required: true | |
| type: string | |
| suite_to_run: | |
| required: true | |
| type: string | |
| secrets: | |
| APIGEE_PASSWORD: | |
| required: true | |
| APIGEE_BASIC_AUTH_TOKEN: | |
| required: true | |
| APIGEE_OTP_KEY: | |
| required: true | |
| CIS2_E2E_USERNAME: | |
| required: true | |
| STATUS_API_KEY: | |
| required: true | |
| workflow_dispatch: | |
| inputs: | |
| apigee_environment: | |
| type: choice | |
| description: Select the Apigee proxy environment | |
| options: | |
| - internal-dev | |
| - internal-dev-sandbox | |
| - sandbox | |
| - internal-qa | |
| - int | |
| - ref | |
| environment: | |
| type: choice | |
| description: Select the AWS backend environment | |
| options: | |
| - dev | |
| - preprod | |
| sub_environment: | |
| type: string | |
| description: Set the sub environment name e.g. pr-xxx, internal-qa, internal-dev, int-green or int-blue | |
| service_under_test: | |
| description: Select the service you want to test | |
| required: true | |
| type: choice | |
| options: | |
| - fhir_api | |
| - batch | |
| - all | |
| suite_to_run: | |
| description: Select the suite you would like to run | |
| default: "functional" | |
| type: choice | |
| options: | |
| - smoke | |
| - functional | |
| - sandbox | |
| - proxy_smoke | |
| env: | |
| APIGEE_AUTH_ENV: ${{ inputs.apigee_environment == 'int' && inputs.apigee_environment || 'internal-dev' }} | |
| APIGEE_ENVIRONMENT: ${{ inputs.apigee_environment }} | |
| ENVIRONMENT: ${{ inputs.environment }} | |
| SUB_ENVIRONMENT: ${{ inputs.sub_environment }} | |
| SERVICE_BASE_PATH: ${{ startsWith(inputs.sub_environment, 'pr-') && format('immunisation-fhir-api/FHIR/R4-{0}', inputs.sub_environment) || 'immunisation-fhir-api/FHIR/R4' }} | |
| PROXY_NAME: ${{ startsWith(inputs.sub_environment, 'pr-') && format('immunisation-fhir-api-{0}', inputs.sub_environment) || format('immunisation-fhir-api-{0}', inputs.apigee_environment) }} | |
| STATUS_API_KEY: ${{ secrets.STATUS_API_KEY }} | |
| SOURCE_COMMIT_ID: ${{ github.sha }} | |
| jobs: | |
| wait-for-deployment: | |
| permissions: | |
| contents: read | |
| runs-on: ubuntu-latest | |
| environment: ${{ inputs.apigee_environment }} | |
| steps: | |
| - name: Wait for API to be available | |
| if: github.event_name != 'workflow_dispatch' | |
| run: | | |
| endpoint="" | |
| if [[ ${APIGEE_ENVIRONMENT} =~ "prod" ]]; then | |
| endpoint="https://api.service.nhs.uk/${SERVICE_BASE_PATH}/_status" | |
| else | |
| endpoint="https://${APIGEE_ENVIRONMENT}.api.service.nhs.uk/${SERVICE_BASE_PATH}/_status" | |
| fi | |
| counter=0 | |
| while [[ ${counter} -lt 31 ]]; do | |
| response=$(curl -H "apikey: ${STATUS_API_KEY}" -s "${endpoint}") | |
| response_code=$(jq -r '.checks.healthcheck.responseCode' <<< "${response}") | |
| response_body=$(jq -r '.checks.healthcheck.outcome' <<< "${response}") | |
| status=$(jq -r '.status' <<< "${response}") | |
| commitId=$(jq -r '.commitId' <<< "${response}") | |
| if [[ "${response_code}" -eq 200 ]] && [[ "${response_body}" == "OK" ]] && [[ "${status}" == "pass" ]]; then | |
| echo "Status test successful" | |
| if [[ "${commitId}" == "${SOURCE_COMMIT_ID}" ]]; then | |
| echo "Commit hash test successful" | |
| break | |
| else | |
| echo "Waiting for ${endpoint} to return the correct commit hash..." | |
| fi | |
| else | |
| echo "Waiting for ${endpoint} to return a 200 response with 'OK' body..." | |
| fi | |
| ((counter=counter+1)) # Increment counter by 1 | |
| echo "Attempt ${counter}" | |
| sleep 30 | |
| done | |
| if [[ ${counter} -eq 31 ]]; then | |
| echo "Status test failed: Maximum number of attempts reached" | |
| echo "Last response received:" | |
| echo "${response}" | |
| exit 1 | |
| fi | |
| e2e-automation-tests: | |
| permissions: | |
| id-token: write | |
| checks: write | |
| contents: write | |
| runs-on: ubuntu-latest | |
| needs: [wait-for-deployment] | |
| environment: ${{ inputs.apigee_environment }} | |
| env: | |
| APIGEE_USERNAME: ${{ vars.APIGEE_USERNAME }} | |
| TF_OUTPUTS_REQUIRED: ${{ inputs.suite_to_run != 'sandbox' }} | |
| steps: | |
| - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 | |
| - name: Connect to AWS | |
| if: ${{ env.TF_OUTPUTS_REQUIRED == 'true' }} | |
| uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 | |
| with: | |
| aws-region: eu-west-2 | |
| role-to-assume: arn:aws:iam::${{ vars.AWS_ACCOUNT_ID }}:role/auto-ops | |
| role-session-name: github-actions | |
| - uses: hashicorp/setup-terraform@5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 | |
| if: ${{ env.TF_OUTPUTS_REQUIRED == 'true' }} | |
| with: | |
| terraform_version: "1.12.2" | |
| - name: Terraform Init | |
| if: ${{ env.TF_OUTPUTS_REQUIRED == 'true' }} | |
| working-directory: infrastructure/instance | |
| run: make init | |
| - name: Set Terraform workspace | |
| if: ${{ env.TF_OUTPUTS_REQUIRED == 'true' }} | |
| working-directory: infrastructure/instance | |
| run: make workspace | |
| - name: Read Terraform outputs | |
| if: ${{ env.TF_OUTPUTS_REQUIRED == 'true' }} | |
| working-directory: infrastructure/instance | |
| run: | | |
| echo "AWS_DOMAIN_NAME=$(make -s output name=service_domain_name)" >> $GITHUB_ENV | |
| - name: Install poetry | |
| run: pip install poetry==2.1.4 | |
| - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 | |
| with: | |
| python-version: 3.11 | |
| cache: "poetry" | |
| cache-dependency-path: tests/e2e_automation/poetry.lock | |
| - name: Install e2e test dependencies | |
| working-directory: tests/e2e_automation | |
| run: poetry install --no-root | |
| - name: Get Apigee access token | |
| if: inputs.apigee_environment != 'int' && inputs.apigee_environment != 'sandbox' | |
| working-directory: tests/e2e_automation | |
| env: | |
| APIGEE_PASSWORD: ${{ secrets.APIGEE_PASSWORD }} | |
| APIGEE_BASIC_AUTH_TOKEN: ${{ secrets.APIGEE_BASIC_AUTH_TOKEN }} | |
| APIGEE_OTP_KEY: ${{ secrets.APIGEE_OTP_KEY }} | |
| run: | | |
| CODE=$(poetry run python utilities/compute_totp_code.py "$APIGEE_OTP_KEY") | |
| echo "::add-mask::$CODE" | |
| echo "Requesting access token from Apigee..." | |
| response=$(curl -s --retry 3 -X POST "https://login.apigee.com/oauth/token" \ | |
| -H "Content-Type: application/x-www-form-urlencoded" \ | |
| -H "Accept: application/json;charset=utf-8" \ | |
| -H "Authorization: Basic $APIGEE_BASIC_AUTH_TOKEN" \ | |
| -d "username=$APIGEE_USERNAME&password=$APIGEE_PASSWORD&mfa_token=$CODE&grant_type=password") | |
| token=$(jq -e -r '.access_token' <<< "$response") | |
| echo "::add-mask::$token" | |
| echo "APIGEE_ACCESS_TOKEN=$token" >> $GITHUB_ENV | |
| - name: Run Pytest-BDD ${{ inputs.service_under_test }} tests with the ${{ inputs.suite_to_run }} filter | |
| working-directory: tests/e2e_automation | |
| env: | |
| S3_env: ${{ startsWith(inputs.sub_environment, 'int-') && 'preprod' || inputs.sub_environment }} | |
| auth_url: https://${{ env.APIGEE_AUTH_ENV }}.api.service.nhs.uk/oauth2-mock/authorize | |
| token_url: https://${{ env.APIGEE_AUTH_ENV }}.api.service.nhs.uk/oauth2-mock/token | |
| baseUrl: https://${{ inputs.apigee_environment }}.api.service.nhs.uk/${{env.SERVICE_BASE_PATH}} | |
| callback_url: "https://oauth.pstmn.io/v1/callback" | |
| username: ${{ secrets.CIS2_E2E_USERNAME }} | |
| scope: "nhs-cis2" | |
| sub_environment: ${{ inputs.sub_environment }} | |
| USE_STATIC_APPS: ${{ inputs.apigee_environment == 'int' && 'True' || 'False' }} | |
| Postman_Auth_client_Id: ${{ secrets.Postman_Auth_client_Id }} # The following static app values are only needed in INT | |
| Postman_Auth_client_Secret: ${{ secrets.Postman_Auth_client_Secret }} | |
| RAVS_client_Id: ${{ secrets.RAVS_client_Id }} | |
| RAVS_client_Secret: ${{ secrets.RAVS_client_Secret }} | |
| MAVIS_client_Id: ${{ secrets.MAVIS_client_Id }} | |
| MAVIS_client_Secret: ${{ secrets.MAVIS_client_Secret }} | |
| EMIS_client_Id: ${{ secrets.OPTUM_client_Id }} | |
| EMIS_client_Secret: ${{ secrets.OPTUM_client_Secret }} | |
| TPP_client_Id: ${{ secrets.TPP_client_Id }} | |
| TPP_client_Secret: ${{ secrets.TPP_client_Secret }} | |
| SONAR_client_Id: ${{ secrets.SONAR_client_Id }} | |
| SONAR_client_Secret: ${{ secrets.SONAR_client_Secret }} | |
| MEDICUS_client_Id: ${{ secrets.MEDICUS_client_Id }} | |
| MEDICUS_client_Secret: ${{ secrets.MEDICUS_client_Secret }} | |
| aws_token_refresh: "False" | |
| TEST_PATH: ${{ inputs.service_under_test == 'batch' && 'features/batchTests' || inputs.service_under_test == 'fhir_api' && 'features/APITests' || 'features' }} | |
| TEST_FILTER: ${{ inputs.suite_to_run == 'proxy_smoke' && 'Status_feature' || inputs.suite_to_run }} | |
| run: poetry run pytest "$TEST_PATH" -m "$TEST_FILTER" --junitxml=output/test-results.xml --alluredir=output/allure-results | |
| - name: Upload e2e automation test artifact | |
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f | |
| if: always() | |
| with: | |
| name: ${{ env.ENVIRONMENT }}-${{ env.SUB_ENVIRONMENT }}-${{ env.APIGEE_ENVIRONMENT }}-e2e-test-output | |
| path: tests/e2e_automation/output | |
| publish-test-report: | |
| permissions: | |
| id-token: write | |
| checks: write | |
| contents: write | |
| runs-on: ubuntu-latest | |
| needs: [e2e-automation-tests] | |
| if: always() | |
| environment: ${{ inputs.apigee_environment }} | |
| steps: | |
| - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 | |
| - name: Download e2e automation test artifact | |
| uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 | |
| with: | |
| name: ${{ env.ENVIRONMENT }}-${{ env.SUB_ENVIRONMENT }}-${{ env.APIGEE_ENVIRONMENT }}-e2e-test-output | |
| path: tests/e2e_automation/output | |
| - uses: dorny/test-reporter@3d76b34a4535afbd0600d347b09a6ee5deb3ed7f | |
| with: | |
| name: BDD Test Summary | |
| path: "**/output/test-results.xml" | |
| reporter: java-junit | |
| fail-on-error: false | |
| - name: Load test report history | |
| uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 | |
| if: github.event_name == 'workflow_dispatch' | |
| continue-on-error: true | |
| with: | |
| ref: gh-pages | |
| path: gh-pages | |
| - name: Build Allure report | |
| if: github.event_name == 'workflow_dispatch' | |
| uses: simple-elf/allure-report-action@53ebb757a2097edc77c53ecef4d454fc2f2f774c | |
| with: | |
| allure_results: tests/e2e_automation/output/allure-results | |
| gh_pages: gh-pages | |
| allure_report: allure-report | |
| allure_history: allure-history | |
| - name: Publish Allure report to GitHub Pages | |
| if: github.event_name == 'workflow_dispatch' | |
| uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e | |
| with: | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| publish_branch: gh-pages | |
| publish_dir: allure-history | |
| - name: Add link to Allure report | |
| if: github.event_name == 'workflow_dispatch' | |
| uses: actions/github-script@v8 | |
| with: | |
| script: | | |
| const url = `https://${context.repo.owner}.github.io/${context.repo.repo}/`; | |
| core.summary.addHeading('Allure Report').addLink('View Report', url).write(); |