From 4bcb8c3618602b24513daf2f742b7348b5ad36c4 Mon Sep 17 00:00:00 2001 From: Yetkin Timocin Date: Mon, 29 Apr 2024 13:19:51 -0700 Subject: [PATCH] Workflow and playwright test updates (#1360) Signed-off-by: ytimocin Signed-off-by: sk593 --- .github/scripts/delete-aws-resources.sh | 60 +++++----- .github/workflows/test-aks.yaml | 45 ++++--- .github/workflows/test.yaml | 76 ++++++------ playwright/package-lock.json | 111 ++++-------------- playwright/package.json | 8 +- playwright/playwright.config.ts | 3 +- playwright/tests/eshop/eshop.app.spec.ts | 82 ++++++++----- .../eshop-dapr/services/webshopping-agg.bicep | 6 +- samples/eshop-dapr/services/webstatus.bicep | 14 +-- samples/eshop/services/basket.bicep | 17 ++- samples/eshop/services/catalog.bicep | 14 ++- samples/eshop/services/identity.bicep | 15 ++- samples/eshop/services/ordering.bicep | 13 +- samples/eshop/services/payment.bicep | 13 +- samples/eshop/services/web.bicep | 18 +-- samples/eshop/services/webhooks.bicep | 14 ++- samples/eshop/services/webshopping.bicep | 30 +++-- samples/eshop/services/webstatus.bicep | 27 ++--- 18 files changed, 277 insertions(+), 289 deletions(-) diff --git a/.github/scripts/delete-aws-resources.sh b/.github/scripts/delete-aws-resources.sh index 3465c41f..fdf0c141 100755 --- a/.github/scripts/delete-aws-resources.sh +++ b/.github/scripts/delete-aws-resources.sh @@ -6,7 +6,7 @@ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software @@ -16,7 +16,6 @@ # limitations under the License. # ------------------------------------------------------------ - APP_ID=$1 APP_LABEL='radapp.io/application' RESOURCE_TYPES='AWS::RDS::DBInstance,AWS::RDS::DBSubnetGroup,AWS::MemoryDB::Cluster,AWS::MemoryDB::SubnetGroup' @@ -34,21 +33,16 @@ function delete_aws_resources() { # Empty the file truncate -s 0 $DELETED_RESOURCES_FILE - for resource_type in ${RESOURCE_TYPES//,/ } - do - aws cloudcontrol list-resources --type-name "$resource_type" --query "ResourceDescriptions[].Identifier" --output text | tr '\t' '\n' | while read identifier - do - aws cloudcontrol get-resource --type-name "$resource_type" --identifier "$identifier" --query "ResourceDescription.Properties" --output text | while read resource - do - resource_tags=$(jq -c -r .Tags <<< "$resource") - for tag in $(jq -c -r '.[]' <<< "$resource_tags") - do - key=$(jq -r '.Key' <<< "$tag") - value=$(jq -r '.Value' <<< "$tag") - if [[ "$key" == "$APP_LABEL" && "$value" == "$APP_ID" ]] - then + for resource_type in ${RESOURCE_TYPES//,/ }; do + aws cloudcontrol list-resources --type-name "$resource_type" --query "ResourceDescriptions[].Identifier" --output text | tr '\t' '\n' | while read identifier; do + aws cloudcontrol get-resource --type-name "$resource_type" --identifier "$identifier" --query "ResourceDescription.Properties" --output text | while read resource; do + resource_tags=$(jq -c -r .Tags <<<"$resource") + for tag in $(jq -c -r '.[]' <<<"$resource_tags"); do + key=$(jq -r '.Key' <<<"$tag") + value=$(jq -r '.Value' <<<"$tag") + if [[ "$key" == "$APP_LABEL" && "$value" == "$APP_ID" ]]; then echo "Deleting resource of type: $resource_type with identifier: $identifier" - echo "$identifier\n" >> $DELETED_RESOURCES_FILE + echo "$identifier\n" >>$DELETED_RESOURCES_FILE aws cloudcontrol delete-resource --type-name "$resource_type" --identifier "$identifier" fi done @@ -65,28 +59,28 @@ function delete_aws_resources() { RETRY_COUNT=0 while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do - # Trigger the function to delete the resources - delete_aws_resources + # Trigger the function to delete the resources + delete_aws_resources - # If the function returned 0, then no resources needed to be deleted - # on this run. This means that all resources have been deleted. - if [ $? -eq 0 ]; then - echo "All resources deleted successfully" - break - fi + # If the function returned 0, then no resources needed to be deleted + # on this run. This means that all resources have been deleted. + if [ $? -eq 0 ]; then + echo "All resources deleted successfully" + break + fi - # Still have resources to delete, increase the retry count - RETRY_COUNT=$((RETRY_COUNT + 1)) + # Still have resources to delete, increase the retry count + RETRY_COUNT=$((RETRY_COUNT + 1)) - # Check if there are more retries left - if [ $RETRY_COUNT -lt $MAX_RETRIES ]; then - # Retry after delay - echo "Retrying in $RETRY_DELAY seconds..." - sleep $RETRY_DELAY - fi + # Check if there are more retries left + if [ $RETRY_COUNT -lt $MAX_RETRIES ]; then + # Retry after delay + echo "Retrying in $RETRY_DELAY seconds..." + sleep $RETRY_DELAY + fi done # Check if the maximum number of retries exceeded if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then - echo "Maximum number of retries exceeded" + echo "Maximum number of retries exceeded" fi diff --git a/.github/workflows/test-aks.yaml b/.github/workflows/test-aks.yaml index 390a6d4d..f6a30b77 100644 --- a/.github/workflows/test-aks.yaml +++ b/.github/workflows/test-aks.yaml @@ -111,7 +111,7 @@ jobs: deployArgs: -p environment='/planes/radius/local/resourceGroups/eshop-containers/providers/Applications.Core/environments/containers' - name: eshop-azure os: ubuntu-latest-m - runOnPullRequest: true + runOnPullRequest: false app: eshop-azure env: azure path: ./samples/eshop/eshop.bicep @@ -120,7 +120,7 @@ jobs: credential: azure - name: eshop-aws os: ubuntu-latest-m - runOnPullRequest: true + runOnPullRequest: false app: eshop-aws env: aws path: ./samples/eshop/eshop.bicep @@ -283,14 +283,12 @@ jobs: - name: Deploy app if: steps.gen-id.outputs.RUN_TEST == 'true' id: deploy-app - run: rad deploy ${{ matrix.path }} ${{ matrix.deployArgs }} -e ${{ matrix.env }} - - name: Wait for all pods to be ready - if: steps.gen-id.outputs.RUN_TEST == 'true' - id: wait-for-pods - run: | - namespace="${{ matrix.env }}-${{ matrix.app }}" - label="radapp.io/application=${{ matrix.app }}" - kubectl rollout status deployment -l $label -n $namespace --timeout=90s + uses: nick-fields/retry@v3 + with: + timeout_minutes: 30 + max_attempts: 3 + retry_wait_seconds: 30 + command: rad deploy ${{ matrix.path }} ${{ matrix.deployArgs }} -e ${{ matrix.env }} - name: Run Playwright Test if: steps.gen-id.outputs.RUN_TEST == 'true' && matrix.uiTestFile != '' id: run-playwright-test @@ -308,18 +306,28 @@ jobs: npm ci npx playwright install --with-deps npx playwright test ${{ matrix.uiTestFile }} --retries 3 + # Upload Playwright test results even if the workflow is cancelled. - name: Upload Playwright Results uses: actions/upload-artifact@v3 - if: always() && ( steps.run-playwright-test.outcome == 'success' || steps.run-playwright-test.outcome == 'failure' ) + if: always() && (steps.run-playwright-test.outcome == 'success' || steps.run-playwright-test.outcome == 'failure') with: name: playwright-report-${{ matrix.name }} path: playwright/playwright-report/ retention-days: 30 if-no-files-found: error + # Upload Playwright test videos in case of test failure even if the workflow is cancelled. + - name: Upload Playwright Videos + uses: actions/upload-artifact@v4 + if: always() && steps.run-playwright-test.outcome == 'failure' + with: + name: playwright-video-${{ matrix.name }} + path: playwright/test-results/ + retention-days: 30 + if-no-files-found: error # Handle failures - name: Get Pod logs for failed tests id: get-pod-logs - if: failure() && (steps.run-playwright-test.outcome == 'failure' || steps.wait-for-pods.outcome == 'failure' || steps.deploy-app.outcome == 'failure') + if: failure() && (steps.run-playwright-test.outcome == 'failure' || steps.deploy-app.outcome == 'failure') run: | # Create pod-logs directory mkdir -p playwright/pod-logs/${{ matrix.name }} @@ -343,17 +351,17 @@ jobs: if-no-files-found: error - name: Create GitHub issue on failure if: failure() && github.event_name == 'schedule' - run: gh issue create --title "Samples deployment failed for ${{ matrix.app }}" --body "Test failed on ${{ github.repository }}. See [workflow logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details." --repo ${{ github.repository }} --label test-failure + run: gh issue create --title "Samples deployment failed for ${{ matrix.name }}" --body "Test failed on ${{ github.repository }}. See [workflow logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details." --repo ${{ github.repository }} --label test-failure # Cleanup - name: Delete app and environment - if: always() && steps.gen-id.outputs.RUN_TEST == 'true' + if: steps.gen-id.outputs.RUN_TEST == 'true' && steps.deploy-app.outcome == 'success' run: | if command -v rad &> /dev/null; then rad app delete ${{ matrix.app }} -y rad env delete ${{ matrix.env }} -y fi - name: Delete Azure resource group - if: always() && steps.gen-id.outputs.RUN_TEST == 'true' && steps.create-azure-resource-group.outcome == 'success' + if: steps.gen-id.outputs.RUN_TEST == 'true' && steps.create-azure-resource-group.outcome == 'success' run: | # Delete Azure resources created by the test # if deletion fails, purge workflow will purge the resource group and its resources later @@ -362,13 +370,12 @@ jobs: --name ${{ steps.gen-id.outputs.TEST_AZURE_RESOURCE_GROUP }} \ --yes - name: Delete AWS Resources - if: always() && steps.gen-id.outputs.RUN_TEST == 'true' && matrix.credential == 'aws' + if: steps.gen-id.outputs.RUN_TEST == 'true' && matrix.credential == 'aws' && steps.deploy-app.outcome == 'success' run: | # Delete all AWS resources created by the test ./.github/scripts/delete-aws-resources.sh '/planes/radius/local/resourcegroups/${{ matrix.env }}/providers/Applications.Core/applications/${{ matrix.app }}' - - name: Delete EKS Cluster - if: always() && steps.gen-id.outputs.RUN_TEST == 'true' && matrix.credential == 'aws' + - name: Delete EKS Cluster ${{ steps.gen-id.outputs.TEST_EKS_CLUSTER_NAME }} + if: steps.create-eks.outcome == 'success' run: | - # Delete EKS cluster echo "Deleting EKS cluster: ${{ steps.gen-id.outputs.TEST_EKS_CLUSTER_NAME }}" eksctl delete cluster --name ${{ steps.gen-id.outputs.TEST_EKS_CLUSTER_NAME }} --region ${{ env.AWS_REGION }} --wait --force diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index aa377ffe..da9fc36c 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -256,51 +256,53 @@ jobs: fi rad env switch ${{ matrix.env }} # Deploy application and run tests + # Retry the deployment step in case of transient failures - name: Deploy app if: steps.gen-id.outputs.RUN_TEST == 'true' id: deploy-app - run: rad deploy ${{ matrix.path }} ${{ matrix.deployArgs }} - - name: Wait for all pods to be ready - if: steps.gen-id.outputs.RUN_TEST == 'true' - id: wait-for-pods - run: | - namespace="${{ matrix.env }}-${{ matrix.app }}" - label="radapp.io/application=${{ matrix.app }}" - kubectl rollout status deployment -l $label -n $namespace --timeout=90s - - name: Run Playwright Test - if: steps.gen-id.outputs.RUN_TEST == 'true' && matrix.uiTestFile != '' - id: run-playwright-test uses: nick-fields/retry@v3 with: - timeout_minutes: 5 + timeout_minutes: 30 max_attempts: 3 retry_wait_seconds: 30 - command: | - if [[ "${{ matrix.container }}" != "" ]]; then - rad resource expose containers ${{ matrix.container }} ${{ matrix.exposeArgs }} --port ${{ matrix.port }} & - echo "Endpoint: http://localhost:${{ matrix.port }}" - export ENDPOINT="http://localhost:${{ matrix.port }}" - else - endpoint="$(rad app status -a ${{ matrix.app }} | sed 's/ /\n/g' | grep http)" - echo "Endpoint: $endpoint" - export ENDPOINT=$endpoint - fi - cd playwright/ - npm ci - npx playwright install --with-deps - npx playwright test ${{ matrix.uiTestFile }} --retries 3 + command: rad deploy ${{ matrix.path }} ${{ matrix.deployArgs }} + - name: Run Playwright Test + if: steps.gen-id.outputs.RUN_TEST == 'true' && matrix.uiTestFile != '' + id: run-playwright-test + run: | + if [[ "${{ matrix.container }}" != "" ]]; then + rad resource expose containers ${{ matrix.container }} ${{ matrix.exposeArgs }} --port ${{ matrix.port }} & + export ENDPOINT="http://localhost:3000/" + else + endpoint="$(rad app status -a ${{ matrix.app }} | sed 's/ /\n/g' | grep http)" + echo "Endpoint: $endpoint" + export ENDPOINT=$endpoint + fi + + cd playwright/ + npm ci + npx playwright install --with-deps + npx playwright test ${{ matrix.uiTestFile }} --retries 3 - name: Upload Playwright Results uses: actions/upload-artifact@v4 - if: always() && ( steps.run-playwright-test.outcome == 'success' || steps.run-playwright-test.outcome == 'failure' ) + if: always() && (steps.run-playwright-test.outcome == 'success' || steps.run-playwright-test.outcome == 'failure') with: name: playwright-report-${{ matrix.name }} path: playwright/playwright-report/ retention-days: 30 if-no-files-found: error + - name: Upload Playwright Videos + uses: actions/upload-artifact@v4 + if: always() && steps.run-playwright-test.outcome == 'failure' + with: + name: playwright-video-${{ matrix.name }} + path: playwright/test-results/ + retention-days: 30 + if-no-files-found: error # Handle failures - name: Get Pod logs for failed tests id: get-pod-logs - if: failure() && (steps.run-playwright-test.outcome == 'failure' || steps.wait-for-pods.outcome == 'failure' || steps.deploy-app.outcome == 'failure') + if: failure() && (steps.run-playwright-test.outcome == 'failure' || steps.deploy-app.outcome == 'failure') run: | # Create pod-logs directory mkdir -p playwright/pod-logs/${{ matrix.name }} @@ -324,16 +326,16 @@ jobs: if-no-files-found: error - name: Create GitHub issue on failure if: failure() && github.event_name == 'schedule' - run: gh issue create --title "Samples deployment failed for ${{ matrix.app }}" --body "Test failed on ${{ github.repository }}. See [workflow logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details." --repo ${{ github.repository }} --label test-failure + run: gh issue create --title "Samples deployment failed for ${{ matrix.name }}" --body "Test failed on ${{ github.repository }}. See [workflow logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details." --repo ${{ github.repository }} --label test-failure # Cleanup - name: Delete app - if: always() && steps.gen-id.outputs.RUN_TEST == 'true' + if: steps.gen-id.outputs.RUN_TEST == 'true' && steps.deploy-app.outcome == 'success' run: | if command -v rad &> /dev/null; then rad app delete ${{ matrix.app }} -y fi - name: Delete Azure resource group - if: always() && steps.gen-id.outputs.RUN_TEST == 'true' && steps.create-azure-resource-group.outcome == 'success' + if: steps.gen-id.outputs.RUN_TEST == 'true' && steps.create-azure-resource-group.outcome == 'success' run: | # Delete Azure resources created by the test # if deletion fails, purge workflow will purge the resource group and its resources later @@ -342,18 +344,12 @@ jobs: --name ${{ steps.gen-id.outputs.TEST_AZURE_RESOURCE_GROUP }} \ --yes - name: Delete AWS Resources - if: always() && steps.gen-id.outputs.RUN_TEST == 'true' && matrix.credential == 'aws' + if: steps.gen-id.outputs.RUN_TEST == 'true' && matrix.credential == 'aws' && steps.deploy-app.outcome == 'success' run: | # Delete all AWS resources created by the test ./.github/scripts/delete-aws-resources.sh '/planes/radius/local/resourcegroups/default/providers/Applications.Core/applications/${{ matrix.app }}' - - name: Delete EKS Cluster - if: always() && steps.gen-id.outputs.RUN_TEST == 'true' && matrix.credential == 'aws' + - name: Delete EKS Cluster ${{ steps.gen-id.outputs.TEST_EKS_CLUSTER_NAME }} + if: steps.create-eks.outcome == 'success' run: | - # Uninstall Radius from EKS cluster - # if rad cli exists - if command -v rad &> /dev/null; then - rad uninstall kubernetes - fi - # Delete EKS cluster echo "Deleting EKS cluster: ${{ steps.gen-id.outputs.TEST_EKS_CLUSTER_NAME }}" eksctl delete cluster --name ${{ steps.gen-id.outputs.TEST_EKS_CLUSTER_NAME }} --region ${{ env.AWS_REGION }} --wait --force diff --git a/playwright/package-lock.json b/playwright/package-lock.json index 91d85551..fded1ea1 100644 --- a/playwright/package-lock.json +++ b/playwright/package-lock.json @@ -12,19 +12,19 @@ "uuid": "^9.0.1" }, "devDependencies": { - "@playwright/test": "^1.43.0", - "@types/node": "^20.12.6", + "@playwright/test": "^1.43.1", + "@types/node": "^20.12.7", "@types/uuid": "^9.0.8", - "typescript": "^5.4.4" + "typescript": "^5.4.5" } }, "node_modules/@playwright/test": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.43.0.tgz", - "integrity": "sha512-Ebw0+MCqoYflop7wVKj711ccbNlrwTBCtjY5rlbiY9kHL2bCYxq+qltK6uPsVBGGAOb033H2VO0YobcQVxoW7Q==", + "version": "1.43.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.43.1.tgz", + "integrity": "sha512-HgtQzFgNEEo4TE22K/X7sYTYNqEMMTZmFS8kTq6m8hXj+m1D8TgwgIbumHddJa9h4yl4GkKb8/bgAl2+g7eDgA==", "dev": true, "dependencies": { - "playwright": "1.43.0" + "playwright": "1.43.1" }, "bin": { "playwright": "cli.js" @@ -34,9 +34,9 @@ } }, "node_modules/@types/node": { - "version": "20.12.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.6.tgz", - "integrity": "sha512-3KurE8taB8GCvZBPngVbp0lk5CKi8M9f9k1rsADh0Evdz5SzJ+Q+Hx9uHoFGsLnLnd1xmkDQr2hVhlA0Mn0lKQ==", + "version": "20.12.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", + "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -48,72 +48,6 @@ "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", "dev": true }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/axios": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", - "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", - "dependencies": { - "follow-redirects": "^1.15.4", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -129,12 +63,12 @@ } }, "node_modules/playwright": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.43.0.tgz", - "integrity": "sha512-SiOKHbVjTSf6wHuGCbqrEyzlm6qvXcv7mENP+OZon1I07brfZLGdfWV0l/efAzVx7TF3Z45ov1gPEkku9q25YQ==", + "version": "1.43.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.43.1.tgz", + "integrity": "sha512-V7SoH0ai2kNt1Md9E3Gwas5B9m8KR2GVvwZnAI6Pg0m3sh7UvgiYhRrhsziCmqMJNouPckiOhk8T+9bSAK0VIA==", "dev": true, "dependencies": { - "playwright-core": "1.43.0" + "playwright-core": "1.43.1" }, "bin": { "playwright": "cli.js" @@ -147,9 +81,9 @@ } }, "node_modules/playwright-core": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.43.0.tgz", - "integrity": "sha512-iWFjyBUH97+pUFiyTqSLd8cDMMOS0r2ZYz2qEsPjH8/bX++sbIJT35MSwKnp1r/OQBAqC5XO99xFbJ9XClhf4w==", + "version": "1.43.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.43.1.tgz", + "integrity": "sha512-EI36Mto2Vrx6VF7rm708qSnesVQKbxEWvPrfA1IPY6HgczBplDx7ENtx+K2n4kJ41sLLkuGfmb0ZLSSXlDhqPg==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -158,15 +92,10 @@ "node": ">=16" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, "node_modules/typescript": { - "version": "5.4.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz", - "integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, "bin": { "tsc": "bin/tsc", diff --git a/playwright/package.json b/playwright/package.json index f29f910b..de7517cd 100644 --- a/playwright/package.json +++ b/playwright/package.json @@ -8,12 +8,12 @@ "author": "", "license": "ISC", "devDependencies": { - "@playwright/test": "^1.43.0", - "@types/node": "^20.12.6", + "@playwright/test": "^1.43.1", + "@types/node": "^20.12.7", "@types/uuid": "^9.0.8", - "typescript": "^5.4.4" + "typescript": "^5.4.5" }, "dependencies": { "uuid": "^9.0.1" } -} +} \ No newline at end of file diff --git a/playwright/playwright.config.ts b/playwright/playwright.config.ts index 4e300a13..23dca4b8 100644 --- a/playwright/playwright.config.ts +++ b/playwright/playwright.config.ts @@ -28,6 +28,7 @@ export default defineConfig({ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: "on-first-retry", + video: "retain-on-failure", }, /* Configure projects for major browsers */ projects: [ @@ -46,7 +47,7 @@ export default defineConfig({ use: { ...devices["Desktop Safari"] }, }, ], - timeout: 1 * 60 * 1000, + timeout: 5 * 60 * 1000, expect: { timeout: 30 * 1000, }, diff --git a/playwright/tests/eshop/eshop.app.spec.ts b/playwright/tests/eshop/eshop.app.spec.ts index d5cd59bf..143321bc 100644 --- a/playwright/tests/eshop/eshop.app.spec.ts +++ b/playwright/tests/eshop/eshop.app.spec.ts @@ -3,61 +3,73 @@ import { test, expect } from "@playwright/test"; test("eShop on Containers App Basic UI and Functionality Checks", async ({ page, }) => { - // Listen for all console events and handle errors - page.on("console", (msg) => { - if (msg.type() === "error") { - console.log(`Error text: "${msg.text()}"`); - } - }); + console.log("Starting the eShop App UI tests"); + console.log("Checking the necessary environment variables"); let endpoint = process.env.ENDPOINT; expect(endpoint).toBeDefined(); // Remove quotes from the endpoint if they exist - endpoint = (endpoint as string).replace(/['"]+/g, ""); - console.log(`Endpoint: ${endpoint}`); - await page.goto(endpoint); + try { + console.log("Navigating to the endpoint"); + endpoint = (endpoint as string).replace(/['"]+/g, ""); + console.log(`Endpoint: ${endpoint}`); + await page.goto(endpoint); + } catch (error) { + console.error("Failed to navigate to the endpoint:", error); + } // Expect page to have proper URL + console.log("Checking the URL"); await expect(page).toHaveURL(new RegExp(`${endpoint}/catalog.*`)); // Expect page to have proper title + console.log("Checking the title"); await expect(page).toHaveTitle("eShopOnContainers - SPA"); // Check for the LOGIN button in the home page + console.log("Checking the LOGIN button"); const loginButton = page.getByText("LOGIN"); await expect(loginButton).toBeVisible(); await loginButton.click(); // Expect login page to have proper title + console.log("Checking the login page title"); await expect(page).toHaveTitle("eShopOnContainers - Identity"); // Fill in the username and password + console.log("Filling in the username"); const username = page.getByPlaceholder("Username"); await expect(username).toBeVisible(); await username.click(); await username.fill("alice"); + console.log("Filling in the password"); const password = page.getByPlaceholder("Password"); await expect(password).toBeVisible(); await password.click(); await password.fill("Pass123$"); // Click on the LOGIN button + console.log("Clicking the LOGIN button"); await page.getByRole("button", { name: "Login" }).click(); // After login, expect to be redirected to the catalog page // Expect page to have proper URL + console.log("Checking the URL after login"); await expect(page).toHaveURL(new RegExp(`${endpoint}/catalog.*`)); // Expect page to have proper title + console.log("Checking the title after login"); await expect(page).toHaveTitle("eShopOnContainers - SPA"); // Logged user details should be visible + console.log("Checking the user details"); const user = page.getByText("AliceSmith@email.com"); await expect(user).toBeVisible(); // Click on the user details await user.click(); // Check dropdown menu + console.log("Checking the dropdown menu"); await expect(page.getByText("My orders")).toBeVisible(); await expect(page.getByText("Log Out")).toBeVisible(); @@ -70,39 +82,55 @@ test("eShop on Containers App Basic UI and Functionality Checks", async ({ console.log("Catalog found"); let numberOfItemsAdded = 0; - // Add an item to the cart - console.log("Adding the first item to the cart"); + // Add the first item to the cart + console.log("Adding an item to the cart"); const firstItemSelector = "div:nth-child(1) > .esh-catalog-item"; - await page.waitForSelector(firstItemSelector); - const firstItem = page.locator(firstItemSelector); - await expect(firstItem).toBeVisible(); - await firstItem.click(); - console.log("Item added to the cart"); - numberOfItemsAdded++; - - // Add an item to the cart - console.log("Adding the second item to the cart"); - const secondItemSelector = "div:nth-child(2) > .esh-catalog-item"; - await page.waitForSelector(secondItemSelector); - const secondItem = page.locator(secondItemSelector); - await expect(secondItem).toBeVisible(); - await secondItem.click(); - console.log("Item added to the cart"); - numberOfItemsAdded++; + + let attempts = 0; + let maxAttempts = 5; + let firstItem; + + while (attempts < maxAttempts) { + try { + await page.waitForSelector(firstItemSelector); + firstItem = page.locator(firstItemSelector); + await expect(firstItem).toBeVisible(); + await firstItem.click(); + console.log("Item added to the cart"); + numberOfItemsAdded++; + break; + } catch (error) { + // If the item is not found within 5 seconds, an error will be thrown here, then the page will be reloaded + console.error("Item not found:", error); + await page.reload(); + attempts++; + } + } + + if (!firstItem) { + throw new Error("First item not found after " + maxAttempts + " attempts"); + } // Go to the cart + console.log("Going to the cart"); const cartLink = page.getByRole("link", { name: `${numberOfItemsAdded}` }); await expect(cartLink).toBeVisible(); await cartLink.click(); + console.log("Cart page loaded"); // Expect page to have proper URL + console.log("Checking the URL after going to the cart"); await expect(page).toHaveURL(new RegExp(`${endpoint}/basket.*`)); // Checkout + console.log("Checking out"); await page.getByRole("button", { name: "Checkout" }).click(); // Place the order + console.log("Placing the order"); await page.getByRole("button", { name: "Place Order" }).click(); // Continue Shopping + console.log("Continuing shopping"); await page.getByRole("link", { name: "Continue Shopping" }).click(); // Logout + console.log("Logging out"); await page.locator("div").filter({ hasText: "Log Out" }).nth(0).click(); }); diff --git a/samples/eshop-dapr/services/webshopping-agg.bicep b/samples/eshop-dapr/services/webshopping-agg.bicep index 52c3eba3..a4ffbe29 100644 --- a/samples/eshop-dapr/services/webshopping-agg.bicep +++ b/samples/eshop-dapr/services/webshopping-agg.bicep @@ -33,9 +33,9 @@ resource webshoppingAgg 'Applications.Core/containers@2023-10-01-preview' = { IdentityUrl: 'http://identity-api:80' IdentityUrlExternal: '${gateway.properties.url}/identity/' SeqServerUrl: 'http://seq:5340' - BasketUrlHC: 'http://localhost:3500/v1.0/invoke/basket-api/method/hc' - CatalogUrlHC: 'http://localhost:3500/v1.0/invoke/catalog-api/method/hc' - IdentityUrlHC: 'http://localhost:3500/v1.0/invoke/identity-api/method/hc' + BasketUrlHC: 'http://localhost:3500/v1.0/invoke/basket-api/method/liveness' + CatalogUrlHC: 'http://localhost:3500/v1.0/invoke/catalog-api/method/liveness' + IdentityUrlHC: 'http://localhost:3500/v1.0/invoke/identity-api/method/liveness' } ports: { http: { diff --git a/samples/eshop-dapr/services/webstatus.bicep b/samples/eshop-dapr/services/webstatus.bicep index c4fe40d6..639a2933 100644 --- a/samples/eshop-dapr/services/webstatus.bicep +++ b/samples/eshop-dapr/services/webstatus.bicep @@ -21,19 +21,19 @@ resource webstatus 'Applications.Core/containers@2023-10-01-preview' = { ASPNETCORE_URLS: 'http://0.0.0.0:80' PATH_BASE: '/health' HealthChecksUI__HealthChecks__0__Name: 'Blazor UI Host' - HealthChecksUI__HealthChecks__0__Uri: 'http://blazor-client:80/hc' + HealthChecksUI__HealthChecks__0__Uri: 'http://blazor-client:80/liveness' HealthChecksUI__HealthChecks__1__Name: 'Identity API' - HealthChecksUI__HealthChecks__1__Uri: 'http://localhost:3500/v1.0/invoke/identity-api/method/hc' + HealthChecksUI__HealthChecks__1__Uri: 'http://localhost:3500/v1.0/invoke/identity-api/method/liveness' HealthChecksUI__HealthChecks__2__Name: 'Basket API' - HealthChecksUI__HealthChecks__2__Uri: 'http://localhost:3500/v1.0/invoke/basket-api/method/hc' + HealthChecksUI__HealthChecks__2__Uri: 'http://localhost:3500/v1.0/invoke/basket-api/method/liveness' HealthChecksUI__HealthChecks__3__Name: 'Catalog API' - HealthChecksUI__HealthChecks__3__Uri: 'http://localhost:3500/v1.0/invoke/catalog-api/method/hc' + HealthChecksUI__HealthChecks__3__Uri: 'http://localhost:3500/v1.0/invoke/catalog-api/method/liveness' HealthChecksUI__HealthChecks__4__Name: 'Ordering API' - HealthChecksUI__HealthChecks__4__Uri: 'http://localhost:3500/v1.0/invoke/ordering-api/method/hc' + HealthChecksUI__HealthChecks__4__Uri: 'http://localhost:3500/v1.0/invoke/ordering-api/method/liveness' HealthChecksUI__HealthChecks__5__Name: 'Payment API' - HealthChecksUI__HealthChecks__5__Uri: 'http://localhost:3500/v1.0/invoke/payment-api/method/hc' + HealthChecksUI__HealthChecks__5__Uri: 'http://localhost:3500/v1.0/invoke/payment-api/method/liveness' HealthChecksUI__HealthChecks__6__Name: 'Web Shopping Aggregator' - HealthChecksUI__HealthChecks__6__Uri: 'http://localhost:3500/v1.0/invoke/webshoppingagg/method/hc' + HealthChecksUI__HealthChecks__6__Uri: 'http://localhost:3500/v1.0/invoke/webshoppingagg/method/liveness' } ports: { http: { diff --git a/samples/eshop/services/basket.bicep b/samples/eshop/services/basket.bicep index 466eb296..c3b9e327 100644 --- a/samples/eshop/services/basket.bicep +++ b/samples/eshop/services/basket.bicep @@ -61,11 +61,16 @@ resource basket 'Applications.Core/containers@2023-10-01-preview' = { port: 9103 } } - livenessProbe:{ - kind:'httpGet' - path:'/hc' - containerPort:80 - } + livenessProbe: { + kind: 'httpGet' + path: '/liveness' + containerPort: 80 + } + readinessProbe: { + kind: 'httpGet' + path: '/hc' + containerPort: 80 + } } connections: { @@ -78,7 +83,7 @@ resource basket 'Applications.Core/containers@2023-10-01-preview' = { disableDefaultEnvVars: true } } - + } } diff --git a/samples/eshop/services/catalog.bicep b/samples/eshop/services/catalog.bicep index 0ea748cd..ec78da17 100644 --- a/samples/eshop/services/catalog.bicep +++ b/samples/eshop/services/catalog.bicep @@ -64,10 +64,15 @@ resource catalog 'Applications.Core/containers@2023-10-01-preview' = { port: 9101 } } - livenessProbe:{ - kind:'httpGet' - path:'/hc' - containerPort:80 + livenessProbe: { + kind: 'httpGet' + path: '/liveness' + containerPort: 80 + } + readinessProbe: { + kind: 'httpGet' + path: '/hc' + containerPort: 80 } } connections: { @@ -84,7 +89,6 @@ resource gateway 'Applications.Core/gateways@2023-10-01-preview' existing = { name: gatewayName } - // PORTABLE RESOURCES ----------------------------------------------------------- resource sqlCatalogDb 'Applications.Datastores/sqlDatabases@2023-10-01-preview' existing = { diff --git a/samples/eshop/services/identity.bicep b/samples/eshop/services/identity.bicep index 845a15a9..e95c4638 100644 --- a/samples/eshop/services/identity.bicep +++ b/samples/eshop/services/identity.bicep @@ -52,10 +52,15 @@ resource identity 'Applications.Core/containers@2023-10-01-preview' = { port: 5105 } } - livenessProbe:{ - kind:'httpGet' - path:'/hc' - containerPort:80 + livenessProbe: { + kind: 'httpGet' + path: '/liveness' + containerPort: 80 + } + readinessProbe: { + kind: 'httpGet' + path: '/hc' + containerPort: 80 } } connections: { @@ -101,7 +106,6 @@ resource gateway 'Applications.Core/gateways@2023-10-01-preview' existing = { name: gatewayName } - // PORTABLE RESOURCES ----------------------------------------------------------- resource sqlIdentityDb 'Applications.Datastores/sqlDatabases@2023-10-01-preview' existing = { @@ -112,7 +116,6 @@ resource redisKeystore 'Applications.Datastores/redisCaches@2023-10-01-preview' name: redisKeystoreName } - // Output @description('Name of the Identity container') output container string = identity.name diff --git a/samples/eshop/services/ordering.bicep b/samples/eshop/services/ordering.bicep index e6b6f6fc..edf366a3 100644 --- a/samples/eshop/services/ordering.bicep +++ b/samples/eshop/services/ordering.bicep @@ -143,10 +143,15 @@ resource orderingsignalrhub 'Applications.Core/containers@2023-10-01-preview' = port: 5112 } } - livenessProbe:{ - kind:'httpGet' - path:'/hc' - containerPort:80 + livenessProbe: { + kind: 'httpGet' + path: '/liveness' + containerPort: 80 + } + readinessProbe: { + kind: 'httpGet' + path: '/hc' + containerPort: 80 } } connections: { diff --git a/samples/eshop/services/payment.bicep b/samples/eshop/services/payment.bicep index 5b43ce95..32c6c38f 100644 --- a/samples/eshop/services/payment.bicep +++ b/samples/eshop/services/payment.bicep @@ -44,10 +44,15 @@ resource payment 'Applications.Core/containers@2023-10-01-preview' = { port: 5108 } } - livenessProbe:{ - kind:'httpGet' - path:'/hc' - containerPort:80 + livenessProbe: { + kind: 'httpGet' + path: '/liveness' + containerPort: 80 + } + readinessProbe: { + kind: 'httpGet' + path: '/hc' + containerPort: 80 } } } diff --git a/samples/eshop/services/web.bicep b/samples/eshop/services/web.bicep index 58cd8cf2..4a2af4a6 100644 --- a/samples/eshop/services/web.bicep +++ b/samples/eshop/services/web.bicep @@ -36,7 +36,7 @@ resource webspa 'Applications.Core/containers@2023-10-01-preview' = { CallBackUrl: '${gateway.properties.url}/' DPConnectionString: redisKeystore.connectionString() IdentityUrl: '${gateway.properties.url}/identity-api' - IdentityUrlHC: 'http://identity-api:5105/hc' + IdentityUrlHC: 'http://identity-api:5105/liveness' PurchaseUrl: '${gateway.properties.url}/webshoppingapigw' SignalrHubUrl: 'http://ordering-signalrhub:5112' } @@ -46,10 +46,15 @@ resource webspa 'Applications.Core/containers@2023-10-01-preview' = { port: 5104 } } - livenessProbe:{ - kind:'httpGet' - path:'/hc' - containerPort:80 + livenessProbe: { + kind: 'httpGet' + path: '/liveness' + containerPort: 80 + } + readinessProbe: { + kind: 'httpGet' + path: '/hc' + containerPort: 80 } } connections: { @@ -96,7 +101,7 @@ resource webmvc 'Applications.Core/containers@2023-10-01-preview' = { ExternalPurchaseUrl: '${gateway.properties.url}/webshoppingapigw' CallBackUrl: '${gateway.properties.url}/webmvc' IdentityUrl: '${gateway.properties.url}/identity-api' - IdentityUrlHC: 'http://identity-api:5105/hc' + IdentityUrlHC: 'http://identity-api:5105/liveness' PurchaseUrl: 'http://webshoppingapigw:5202' SignalrHubUrl: 'http://ordering-signalrhub:5112' } @@ -144,7 +149,6 @@ resource redisKeystore 'Applications.Datastores/redisCaches@2023-10-01-preview' name: redisKeystoreName } - // Output @description('Name of the Web spa container') output spacontainer string = webspa.name diff --git a/samples/eshop/services/webhooks.bicep b/samples/eshop/services/webhooks.bicep index e91085e2..6a65df17 100644 --- a/samples/eshop/services/webhooks.bicep +++ b/samples/eshop/services/webhooks.bicep @@ -54,10 +54,15 @@ resource webhooks 'Applications.Core/containers@2023-10-01-preview' = { port: 5113 } } - livenessProbe:{ - kind:'httpGet' - path:'/hc' - containerPort:80 + livenessProbe: { + kind: 'httpGet' + path: '/liveness' + containerPort: 80 + } + readinessProbe: { + kind: 'httpGet' + path: '/hc' + containerPort: 80 } } connections: { @@ -73,7 +78,6 @@ resource webhooks 'Applications.Core/containers@2023-10-01-preview' = { } } - // Based on https://github.com/dotnet-architecture/eShopOnContainers/tree/dev/deploy/k8s/helm/webhooks-web resource webhooksclient 'Applications.Core/containers@2023-10-01-preview' = { name: 'webhooks-client' diff --git a/samples/eshop/services/webshopping.bicep b/samples/eshop/services/webshopping.bicep index 2686eb9a..a27f37bc 100644 --- a/samples/eshop/services/webshopping.bicep +++ b/samples/eshop/services/webshopping.bicep @@ -34,11 +34,11 @@ resource webshoppingagg 'Applications.Core/containers@2023-10-01-preview' = { urls__grpcBasket: 'grpc://basket-api:9103' urls__grpcCatalog: 'grpc://catalog-api:9101' urls__grpcOrdering: 'grpc://ordering-api:9102' - CatalogUrlHC: 'http://catalog-api:5101/hc' - OrderingUrlHC: 'http://ordering-api:5102/hc' - IdentityUrlHC: 'http://identity-api:5105/hc' - BasketUrlHC: 'http://basket-api:5103/hc' - PaymentUrlHC: 'http://payment-api:5108/hc' + CatalogUrlHC: 'http://catalog-api:5101/liveness' + OrderingUrlHC: 'http://ordering-api:5102/liveness' + IdentityUrlHC: 'http://identity-api:5105/liveness' + BasketUrlHC: 'http://basket-api:5103/liveness' + PaymentUrlHC: 'http://payment-api:5108/liveness' IdentityUrlExternal: '${gateway.properties.url}/identity-api' } ports: { @@ -47,10 +47,15 @@ resource webshoppingagg 'Applications.Core/containers@2023-10-01-preview' = { port: 5121 } } - livenessProbe:{ - kind:'httpGet' - path:'/hc' - containerPort:80 + livenessProbe: { + kind: 'httpGet' + path: '/liveness' + containerPort: 80 + } + readinessProbe: { + kind: 'httpGet' + path: '/hc' + containerPort: 80 } } connections: { @@ -74,7 +79,6 @@ resource webshoppingagg 'Applications.Core/containers@2023-10-01-preview' = { } } - // Based on https://github.com/dotnet-architecture/eShopOnContainers/tree/dev/deploy/k8s/helm/apigwws resource webshoppingapigw 'Applications.Core/containers@2023-10-01-preview' = { name: 'webshoppingapigw' @@ -92,9 +96,9 @@ resource webshoppingapigw 'Applications.Core/containers@2023-10-01-preview' = { port: 15202 } } - livenessProbe:{ - kind:'tcp' - containerPort:80 + livenessProbe: { + kind: 'tcp' + containerPort: 80 } } } diff --git a/samples/eshop/services/webstatus.bicep b/samples/eshop/services/webstatus.bicep index dd4a44eb..b2f7fe10 100644 --- a/samples/eshop/services/webstatus.bicep +++ b/samples/eshop/services/webstatus.bicep @@ -11,7 +11,6 @@ param imageRegistry string @description('Container image tag to use for eshop images') param imageTag string - // CONTAINAERS --------------------------------------------------------- // Based on https://github.com/dotnet-architecture/eShopOnContainers/tree/dev/deploy/k8s/helm/webstatus @@ -25,25 +24,25 @@ resource webstatus 'Applications.Core/containers@2023-10-01-preview' = { ASPNETCORE_ENVIRONMENT: 'Development' ASPNETCORE_URLS: 'http://0.0.0.0:80' HealthChecksUI__HealthChecks__0__Name: 'WebMVC HTTP Check' - HealthChecksUI__HealthChecks__0__Uri: 'http://webmvc:5100/hc' + HealthChecksUI__HealthChecks__0__Uri: 'http://webmvc:5100/liveness' HealthChecksUI__HealthChecks__1__Name: 'WebSPA HTTP Check' - HealthChecksUI__HealthChecks__1__Uri: 'http://web-spa:5104/hc' + HealthChecksUI__HealthChecks__1__Uri: 'http://web-spa:5104/liveness' HealthChecksUI__HealthChecks__2__Name: 'Web Shopping Aggregator GW HTTP Check' - HealthChecksUI__HealthChecks__2__Uri: 'http://webshoppingagg:5121/hc' + HealthChecksUI__HealthChecks__2__Uri: 'http://webshoppingagg:5121/liveness' HealthChecksUI__HealthChecks__4__Name: 'Ordering HTTP Check' - HealthChecksUI__HealthChecks__4__Uri: 'http://ordering-api:5102/hc' + HealthChecksUI__HealthChecks__4__Uri: 'http://ordering-api:5102/liveness' HealthChecksUI__HealthChecks__5__Name: 'Basket HTTP Check' - HealthChecksUI__HealthChecks__5__Uri: 'http://basket-api:5103/hc' + HealthChecksUI__HealthChecks__5__Uri: 'http://basket-api:5103/liveness' HealthChecksUI__HealthChecks__6__Name: 'Catalog HTTP Check' - HealthChecksUI__HealthChecks__6__Uri: 'http://catalog-api/hc' + HealthChecksUI__HealthChecks__6__Uri: 'http://catalog-api/liveness' HealthChecksUI__HealthChecks__7__Name: 'Identity HTTP Check' - HealthChecksUI__HealthChecks__7__Uri: 'http://identity-api:5105/hc' + HealthChecksUI__HealthChecks__7__Uri: 'http://identity-api:5105/liveness' HealthChecksUI__HealthChecks__8__Name: 'Payments HTTP Check' - HealthChecksUI__HealthChecks__8__Uri: 'http://payment-api:5108/hc' + HealthChecksUI__HealthChecks__8__Uri: 'http://payment-api:5108/liveness' HealthChecksUI__HealthChecks__9__Name: 'Ordering SignalRHub HTTP Check' - HealthChecksUI__HealthChecks__9__Uri: 'http://ordering-signalrhub:5112/hc' + HealthChecksUI__HealthChecks__9__Uri: 'http://ordering-signalrhub:5112/liveness' HealthChecksUI__HealthChecks__10__Name: 'Ordering HTTP Background Check' - HealthChecksUI__HealthChecks__10__Uri: 'http://ordering-backgroundtasks:5111/hc' + HealthChecksUI__HealthChecks__10__Uri: 'http://ordering-backgroundtasks:5111/liveness' ORCHESTRATOR_TYPE: 'K8S' } ports: { @@ -52,9 +51,9 @@ resource webstatus 'Applications.Core/containers@2023-10-01-preview' = { port: 8107 } } - livenessProbe:{ - kind:'tcp' - containerPort:80 + livenessProbe: { + kind: 'tcp' + containerPort: 80 } } }