Refactors automated testing pipelines with template
Migrates automated testing configurations to new pipeline structure. This change streamlines the test execution process by leveraging templates and parameters for increased flexibility and maintainability. It introduces a dedicated template for Playwright tests, enabling easier configuration and reuse across different testing scenarios. The previous monolithic pipelines are replaced with modular components, improving readability and reducing redundancy. This also allows for better control over test execution, including shard management and result aggregation.
This commit is contained in:
parent
2e514c8671
commit
44541ba00c
3 changed files with 344 additions and 374 deletions
|
|
@ -1,210 +1,45 @@
|
||||||
trigger: none
|
trigger: none
|
||||||
schedules:
|
schedules:
|
||||||
- cron: 0 9 * * MON-FRI
|
- cron: 0 9 * * MON-FRI
|
||||||
always: true
|
always: true
|
||||||
displayName: Daily Test Automation Run for FMG-NextGen
|
displayName: Daily Test Automation Run for FMG-NextGen
|
||||||
branches:
|
branches:
|
||||||
include:
|
include:
|
||||||
- develop
|
- develop
|
||||||
pool: "Default"
|
pool: 'Default'
|
||||||
|
# TODO: CHange vue distro to test
|
||||||
variables:
|
variables:
|
||||||
# - group: Digital-Infrastructure
|
# - group: Digital-Infrastructure
|
||||||
# - group: FMG-BuildBranches
|
# - group: FMG-BuildBranches
|
||||||
- name: dockerImageName
|
- name: dockerImageName
|
||||||
value: "playwright-tests"
|
value: 'playwright-tests'
|
||||||
- name: imageTag
|
- name: imageTag
|
||||||
value: "$(Build.BuildId)"
|
value: '$(Build.BuildId)'
|
||||||
- name: totalShards
|
- name: totalShards
|
||||||
value: 4
|
value: 4
|
||||||
- name: IS_REGRESSION
|
- name: IS_REGRESSION
|
||||||
value: "true"
|
value: 'true'
|
||||||
- name: JIRA_BOARD_ID
|
- name: JIRA_BOARD_ID
|
||||||
value: "845"
|
value: '845'
|
||||||
- name: JIRA_EPIC_KEY
|
- name: JIRA_EPIC_KEY
|
||||||
value: "CASH-208"
|
value: 'CASH-208'
|
||||||
- name: JIRA_PROJECT_KEY
|
- name: JIRA_PROJECT_KEY
|
||||||
value: "CASH"
|
value: 'CASH'
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- stage: TestPr
|
- stage: TestPr
|
||||||
displayName: Run Playwright Test
|
displayName: Run Playwright Test
|
||||||
jobs:
|
jobs:
|
||||||
- job: playwright_tests
|
- template: temp/playwright-test.yml
|
||||||
continueOnError: true
|
parameters:
|
||||||
strategy:
|
totalShards: 2
|
||||||
matrix:
|
targetUrl: $(BASE_URL)
|
||||||
shard1:
|
dockerFileName: 'Dockerfile.playwright'
|
||||||
shardNumber: 1
|
isRegression: false
|
||||||
shard2:
|
filterTags: ''
|
||||||
shardNumber: 2
|
playwrightTestsPath: 'playwright-tests'
|
||||||
shard3:
|
npmServePath: '.'
|
||||||
shardNumber: 3
|
npmrcPath: 'playwright-tests/.npmrc'
|
||||||
shard4:
|
secrets:
|
||||||
shardNumber: 4
|
CCIS_API_AUTH: $(CCIS_API_AUTH)
|
||||||
|
JIRA_API_KEY: $(JIRA_API_KEY)
|
||||||
steps:
|
|
||||||
- script: |
|
|
||||||
echo "Starting Docker cleanup to free space..."
|
|
||||||
|
|
||||||
# Remove all stopped containers
|
|
||||||
echo "Removing stopped containers..."
|
|
||||||
docker container prune -f
|
|
||||||
|
|
||||||
# Remove dangling images (untagged)
|
|
||||||
echo "Removing dangling images..."
|
|
||||||
docker image prune -f
|
|
||||||
|
|
||||||
# Remove unused volumes
|
|
||||||
echo "Removing unused volumes..."
|
|
||||||
docker volume prune -f
|
|
||||||
|
|
||||||
# Show disk usage after cleanup
|
|
||||||
echo "Docker system usage after cleanup:"
|
|
||||||
docker system df
|
|
||||||
|
|
||||||
echo "Docker cleanup completed!"
|
|
||||||
displayName: "Docker Cleanup"
|
|
||||||
|
|
||||||
- task: Docker@2
|
|
||||||
displayName: "Build Docker Image"
|
|
||||||
inputs:
|
|
||||||
command: build
|
|
||||||
dockerfile: Dockerfile.playwright
|
|
||||||
repository: $(dockerImageName)
|
|
||||||
tags: $(imageTag)
|
|
||||||
arguments: "--no-cache --pull"
|
|
||||||
|
|
||||||
- script: |
|
|
||||||
# Create container and run tests
|
|
||||||
container_id=$(docker create \
|
|
||||||
--ipc=host \
|
|
||||||
-e "CCIS_API_AUTH=$(CCIS_API_AUTH)" \
|
|
||||||
-e "SKIP_CONTENT_SITE=$(SKIP_CONTENT_SITE)" \
|
|
||||||
-e "BASE_URL=$(BASE_URL)" \
|
|
||||||
-e "CCIS_API_URL=$(CCIS_API_URL)" \
|
|
||||||
-e "ADMIN_SERVICE_API_URL=$(ADMIN_SERVICE_API_URL)" \
|
|
||||||
-e "SHARD=$(shardNumber)" \
|
|
||||||
-e CI=true \
|
|
||||||
-e "NODE_ENV=$(NODE_ENV)" \
|
|
||||||
$(dockerImageName):$(imageTag) \
|
|
||||||
npx concurrently -k -n "server,playwright"\
|
|
||||||
"sed -i \"s|^process\.env\.VUE_APP_CONSUMER_CF_DISTRO = .*|process\.env\.VUE_APP_CONSUMER_CF_DISTRO='https://digitalapi.test.safelite.io'|\" \"./vue.config.js\" && echo \"Updated config file to use TEST APIs\" && npm run serve -- --port=8080"\
|
|
||||||
"npx wait-on http://localhost:8080/fmg/ && npm run test:playwright -- --shard=$(shardNumber)/$(totalShards) --reporter=list,blob --grep \"@CASH|@Alert\"")
|
|
||||||
|
|
||||||
# Start container and stream logs
|
|
||||||
echo "Starting tests for shard $(shardNumber)..."
|
|
||||||
docker start -a $container_id
|
|
||||||
|
|
||||||
# Create directory for test results
|
|
||||||
echo "Creating test results directory..."
|
|
||||||
mkdir -p $(System.DefaultWorkingDirectory)/blob-reports/shard-$(shardNumber)
|
|
||||||
|
|
||||||
# Copy test results from container
|
|
||||||
echo "Copying test results..."
|
|
||||||
docker cp $container_id:/app/blob-report/. $(System.DefaultWorkingDirectory)/blob-reports/shard-$(shardNumber)/
|
|
||||||
|
|
||||||
# Remove container
|
|
||||||
echo "Cleaning up container..."
|
|
||||||
docker rm $container_id
|
|
||||||
|
|
||||||
# Check if tests failed
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "Tests failed in shard $(shardNumber) or tests don't exist for this shard number!"
|
|
||||||
exit 0 # Suppress error. It will be visible in report.
|
|
||||||
fi
|
|
||||||
displayName: "Run Playwright Tests - Shard $(shardNumber)"
|
|
||||||
|
|
||||||
- task: PublishPipelineArtifact@1
|
|
||||||
displayName: "Publish Test Reports - Shard $(shardNumber)"
|
|
||||||
condition: always()
|
|
||||||
inputs:
|
|
||||||
targetPath: "$(System.DefaultWorkingDirectory)/blob-reports/shard-$(shardNumber)"
|
|
||||||
artifact: "playwright-report-shard-$(shardNumber)"
|
|
||||||
publishLocation: "pipeline"
|
|
||||||
|
|
||||||
- script: |
|
|
||||||
docker rmi $(dockerImageName):$(imageTag) -f
|
|
||||||
displayName: "Cleanup Docker Image"
|
|
||||||
condition: always()
|
|
||||||
|
|
||||||
- job: download_and_merge_reports
|
|
||||||
dependsOn: playwright_tests
|
|
||||||
timeoutInMinutes: 8
|
|
||||||
cancelTimeoutInMinutes: 10
|
|
||||||
steps:
|
|
||||||
- task: DownloadPipelineArtifact@2
|
|
||||||
inputs:
|
|
||||||
targetPath: "$(System.DefaultWorkingDirectory)/playwright-reports"
|
|
||||||
- task: Docker@2
|
|
||||||
displayName: "Build Docker Image"
|
|
||||||
inputs:
|
|
||||||
command: build
|
|
||||||
dockerfile: Dockerfile.playwright
|
|
||||||
repository: $(dockerImageName)
|
|
||||||
tags: $(imageTag)
|
|
||||||
arguments: "--no-cache --pull"
|
|
||||||
- bash: |
|
|
||||||
# Create container for jira writeback
|
|
||||||
container_id=$(docker create \
|
|
||||||
--ipc=host \
|
|
||||||
-e "JIRA_SERVER=$(JIRA_SERVER)" \
|
|
||||||
-e "JIRA_USERNAME=$(JIRA_USERNAME)" \
|
|
||||||
-e "JIRA_API_KEY=$(JIRA_API_KEY)" \
|
|
||||||
-e "IS_REGRESSION=$(IS_REGRESSION)" \
|
|
||||||
-e "JIRA_BOARD_ID=$(JIRA_BOARD_ID)" \
|
|
||||||
-e "JIRA_EPIC_KEY=$(JIRA_EPIC_KEY)" \
|
|
||||||
-e "JIRA_PROJECT_KEY=$(JIRA_PROJECT_KEY)" \
|
|
||||||
$(dockerImageName):$(imageTag) \
|
|
||||||
bash -c "echo \"Moving Playwright reports out of subfolders...\" &&
|
|
||||||
find ./playwright-reports/ -mindepth 2 -type f -exec mv {} ./playwright-reports/ \; &&
|
|
||||||
echo \"Merging reports...\" &&
|
|
||||||
PLAYWRIGHT_JUNIT_OUTPUT_DIR='/app/test-results' PLAYWRIGHT_JUNIT_OUTPUT_NAME='junit_results.xml' npx playwright merge-reports --reporter='playwright-tests/impl/reporter/JiraWritebackReporter.ts',junit ./playwright-reports
|
|
||||||
echo \"Contents of ortoni-report:\" && ls ./ortoni-report &&
|
|
||||||
echo 'Current dir: ' && pwd
|
|
||||||
echo 'Contents of current dir: ' && ls
|
|
||||||
echo 'Contents of /app/test-results' && ls /app/test-results ")
|
|
||||||
|
|
||||||
# Start container and stream logs
|
|
||||||
echo "Starting merge"
|
|
||||||
docker start -a $container_id
|
|
||||||
|
|
||||||
# Create directory for test results
|
|
||||||
echo "Creating test results directory..."
|
|
||||||
mkdir -p $(System.DefaultWorkingDirectory)/ortoni-report
|
|
||||||
mkdir -p $(System.DefaultWorkingDirectory)/test-results
|
|
||||||
|
|
||||||
# Copy test results from container
|
|
||||||
echo "Copying test results..."
|
|
||||||
docker cp $container_id:/app/ortoni-report/. $(System.DefaultWorkingDirectory)/ortoni-report
|
|
||||||
docker cp $container_id:/app/test-results/junit_results.xml $(System.DefaultWorkingDirectory)/test-results
|
|
||||||
|
|
||||||
# Remove container
|
|
||||||
echo "Cleaning up container..."
|
|
||||||
docker rm $container_id
|
|
||||||
env:
|
|
||||||
JIRA_API_KEY: $(JIRA_API_KEY)
|
|
||||||
displayName: merge_and_publish_results_to_jira
|
|
||||||
|
|
||||||
- task: PublishTestResults@2
|
|
||||||
displayName: "Publish test results"
|
|
||||||
inputs:
|
|
||||||
searchFolder: "test-results"
|
|
||||||
testResultsFormat: "JUnit"
|
|
||||||
testResultsFiles: "junit_results.xml"
|
|
||||||
mergeTestResults: true
|
|
||||||
failTaskOnFailedTests: false
|
|
||||||
testRunTitle: "Playwright Tests"
|
|
||||||
condition: succeededOrFailed()
|
|
||||||
|
|
||||||
- task: PublishPipelineArtifact@1
|
|
||||||
displayName: "Publish Merged Report"
|
|
||||||
condition: always()
|
|
||||||
inputs:
|
|
||||||
targetPath: "$(System.DefaultWorkingDirectory)/ortoni-report"
|
|
||||||
artifact: "playwright-merged-report"
|
|
||||||
publishLocation: "pipeline"
|
|
||||||
- script: |
|
|
||||||
docker rmi $(dockerImageName):$(imageTag) -f
|
|
||||||
displayName: "Cleanup Docker Image"
|
|
||||||
condition: always()
|
|
||||||
|
|
@ -36,16 +36,6 @@ resources:
|
||||||
variables:
|
variables:
|
||||||
- group: Digital-Infrastructure
|
- group: Digital-Infrastructure
|
||||||
- group: FixMyGlass-BuildBranches
|
- group: FixMyGlass-BuildBranches
|
||||||
- name: dockerImageName
|
|
||||||
value: "playwright-tests"
|
|
||||||
- name: imageTag
|
|
||||||
value: "$(Build.BuildId)"
|
|
||||||
- name: totalShards
|
|
||||||
value: 2
|
|
||||||
- name: IS_REGRESSION
|
|
||||||
value: "false"
|
|
||||||
- name: "SKIP_CONTENT_SITE"
|
|
||||||
value: "true"
|
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
# PR's
|
# PR's
|
||||||
|
|
@ -69,164 +59,6 @@ stages:
|
||||||
npmLocation: $(Build.SourcesDirectory)
|
npmLocation: $(Build.SourcesDirectory)
|
||||||
testResultsFile: junit.xml
|
testResultsFile: junit.xml
|
||||||
summaryFileLocation: $(Build.SourcesDirectory)/coverage/cobertura-coverage.xml
|
summaryFileLocation: $(Build.SourcesDirectory)/coverage/cobertura-coverage.xml
|
||||||
- job: playwright_tests
|
|
||||||
continueOnError: true
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
shard1:
|
|
||||||
shardNumber: 1
|
|
||||||
shard2:
|
|
||||||
shardNumber: 2
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- task: Docker@2
|
|
||||||
displayName: "Build Docker Image"
|
|
||||||
inputs:
|
|
||||||
command: build
|
|
||||||
dockerfile: Dockerfile.playwright
|
|
||||||
repository: $(dockerImageName)
|
|
||||||
tags: $(imageTag)
|
|
||||||
arguments: "--no-cache --pull"
|
|
||||||
|
|
||||||
- script: |
|
|
||||||
branch_name=$(System.PullRequest.SourceBranch)
|
|
||||||
echo "Retrieved branch name: '$branch_name'"
|
|
||||||
JIRA_CARD_NUMBER="${branch_name##*/}"
|
|
||||||
echo "Extracted JIRA Card number: '$JIRA_CARD_NUMBER'"
|
|
||||||
# Create container and run tests
|
|
||||||
container_id=$(docker create \
|
|
||||||
--ipc=host \
|
|
||||||
-e "BASE_URL=http://localhost:8080/fmg/" \
|
|
||||||
-e "SHARD=$(shardNumber)" \
|
|
||||||
-e "SKIP_CONTENT_SITE=$(SKIP_CONTENT_SITE)" \
|
|
||||||
-e "NODE_ENV=$(NODE_ENV)" \
|
|
||||||
-e CI=true \
|
|
||||||
$(dockerImageName):$(imageTag) \
|
|
||||||
npx concurrently -k -n "server,playwright"\
|
|
||||||
"sed -i \"s|^process\.env\.VUE_APP_CONSUMER_CF_DISTRO = .*|process\.env\.VUE_APP_CONSUMER_CF_DISTRO='https://digitalapi.test.safelite.io'|\" \"./vue.config.js\" && echo \"Updated config file to use TEST APIs\" && npm run serve -- --port=8080"\
|
|
||||||
"npx wait-on http://localhost:8080/fmg/ && npm run test:playwright -- --shard=$(shardNumber)/$(totalShards) --reporter=list,blob --grep \"@$JIRA_CARD_NUMBER\"")
|
|
||||||
|
|
||||||
# Start container and stream logs
|
|
||||||
echo "Starting tests for shard $(shardNumber)..."
|
|
||||||
docker start -a $container_id
|
|
||||||
|
|
||||||
# Create directory for test results
|
|
||||||
echo "Creating test results directory..."
|
|
||||||
mkdir -p $(System.DefaultWorkingDirectory)/blob-reports/shard-$(shardNumber)
|
|
||||||
|
|
||||||
# Copy test results from container
|
|
||||||
echo "Copying test results..."
|
|
||||||
docker cp $container_id:/app/blob-report/. $(System.DefaultWorkingDirectory)/blob-reports/shard-$(shardNumber)/
|
|
||||||
|
|
||||||
# Remove container
|
|
||||||
echo "Cleaning up container..."
|
|
||||||
docker rm $container_id
|
|
||||||
|
|
||||||
# Check if tests failed
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "Tests failed in shard $(shardNumber) or tests don't exist for this shard number!"
|
|
||||||
exit 0 # Suppress error. It will be visible in report.
|
|
||||||
fi
|
|
||||||
displayName: "Run Playwright Tests - Shard $(shardNumber)"
|
|
||||||
|
|
||||||
- task: PublishPipelineArtifact@1
|
|
||||||
displayName: "Publish Test Reports - Shard $(shardNumber)"
|
|
||||||
condition: always()
|
|
||||||
inputs:
|
|
||||||
targetPath: "$(System.DefaultWorkingDirectory)/blob-reports/shard-$(shardNumber)"
|
|
||||||
artifact: "playwright-report-shard-$(shardNumber)"
|
|
||||||
publishLocation: "pipeline"
|
|
||||||
|
|
||||||
- script: |
|
|
||||||
docker rmi $(dockerImageName):$(imageTag) -f
|
|
||||||
displayName: "Cleanup Docker Image"
|
|
||||||
condition: always()
|
|
||||||
|
|
||||||
# Add job to merge test reports and update Jira
|
|
||||||
- job: download_and_merge_reports
|
|
||||||
dependsOn: playwright_tests
|
|
||||||
timeoutInMinutes: 10
|
|
||||||
cancelTimeoutInMinutes: 10
|
|
||||||
steps:
|
|
||||||
- task: DownloadPipelineArtifact@2
|
|
||||||
inputs:
|
|
||||||
targetPath: "$(System.DefaultWorkingDirectory)/playwright-reports"
|
|
||||||
- task: Docker@2
|
|
||||||
displayName: "Build Docker Image"
|
|
||||||
inputs:
|
|
||||||
command: build
|
|
||||||
dockerfile: Dockerfile.playwright
|
|
||||||
repository: $(dockerImageName)
|
|
||||||
tags: $(imageTag)
|
|
||||||
arguments: "--no-cache --pull"
|
|
||||||
- bash: |
|
|
||||||
branch_name=$(System.PullRequest.SourceBranch)
|
|
||||||
echo "Retrieved branch name: '$branch_name'"
|
|
||||||
JIRA_CARD_NUMBER="${branch_name##*/}"
|
|
||||||
echo "Extracted JIRA Card number: '$JIRA_CARD_NUMBER'"
|
|
||||||
# Create container for jira writeback
|
|
||||||
container_id=$(docker create \
|
|
||||||
--ipc=host \
|
|
||||||
-e JIRA_SERVER=$(JIRA_SERVER) \
|
|
||||||
-e JIRA_USERNAME=$(JIRA_USERNAME) \
|
|
||||||
-e JIRA_API_KEY=$(JIRA_API_KEY) \
|
|
||||||
-e IS_REGRESSION=$(IS_REGRESSION) \
|
|
||||||
-e JIRA_CARD_NUMBER="$JIRA_CARD_NUMBER" \
|
|
||||||
-e JIRA_PROJECT_KEY="$JIRA_PROJECT_KEY" \
|
|
||||||
$(dockerImageName):$(imageTag) \
|
|
||||||
bash -c "echo \"Moving Playwright reports out of subfolders...\" &&
|
|
||||||
find ./playwright-reports/ -mindepth 2 -type f -exec mv {} ./playwright-reports/ \; &&
|
|
||||||
echo \"Merging reports...\" &&
|
|
||||||
export NODE_OPTIONS=--max_old_space_size=4096
|
|
||||||
PLAYWRIGHT_JUNIT_OUTPUT_DIR='/app/test-results' PLAYWRIGHT_JUNIT_OUTPUT_NAME='junit_results.xml' npx playwright merge-reports --reporter=junit,\"/app/playwright-tests/impl/reporter/JiraWritebackReporter.ts\" ./playwright-reports
|
|
||||||
echo \"Contents of ortoni-report:\" && ls ./ortoni-report &&
|
|
||||||
echo 'Current dir: ' && pwd
|
|
||||||
echo 'Contents of current dir: ' && ls
|
|
||||||
echo 'Contents of /app/test-results' && ls /app/test-results ")
|
|
||||||
|
|
||||||
# Start container and stream logs
|
|
||||||
echo "Starting merge"
|
|
||||||
docker start -a $container_id
|
|
||||||
|
|
||||||
# Create directory for test results
|
|
||||||
echo "Creating test results directory..."
|
|
||||||
mkdir -p $(System.DefaultWorkingDirectory)/ortoni-report
|
|
||||||
mkdir -p $(System.DefaultWorkingDirectory)/test-results
|
|
||||||
|
|
||||||
# Copy test results from container
|
|
||||||
echo "Copying test results..."
|
|
||||||
docker cp $container_id:/app/ortoni-report/. $(System.DefaultWorkingDirectory)/ortoni-report
|
|
||||||
docker cp $container_id:/app/test-results/junit_results.xml $(System.DefaultWorkingDirectory)/test-results
|
|
||||||
|
|
||||||
# Remove container
|
|
||||||
echo "Cleaning up container..."
|
|
||||||
docker rm $container_id
|
|
||||||
env:
|
|
||||||
JIRA_API_KEY: $(JIRA_API_KEY)
|
|
||||||
displayName: merge_and_publish_results_to_jira
|
|
||||||
|
|
||||||
- task: PublishTestResults@2
|
|
||||||
displayName: "Publish test results"
|
|
||||||
inputs:
|
|
||||||
searchFolder: "test-results"
|
|
||||||
testResultsFormat: "JUnit"
|
|
||||||
testResultsFiles: "junit_results.xml"
|
|
||||||
mergeTestResults: true
|
|
||||||
failTaskOnFailedTests: false
|
|
||||||
testRunTitle: "Playwright Tests"
|
|
||||||
condition: succeededOrFailed()
|
|
||||||
|
|
||||||
- task: PublishPipelineArtifact@1
|
|
||||||
displayName: "Publish Merged Report"
|
|
||||||
condition: always()
|
|
||||||
inputs:
|
|
||||||
targetPath: "$(System.DefaultWorkingDirectory)/ortoni-report"
|
|
||||||
artifact: "playwright-merged-report"
|
|
||||||
publishLocation: "pipeline"
|
|
||||||
- script: |
|
|
||||||
docker rmi $(dockerImageName):$(imageTag) -f
|
|
||||||
displayName: "Cleanup Docker Image"
|
|
||||||
condition: always()
|
|
||||||
- ${{ else }}:
|
- ${{ else }}:
|
||||||
# Dev Build/Deploy
|
# Dev Build/Deploy
|
||||||
- stage: Dev
|
- stage: Dev
|
||||||
|
|
@ -475,4 +307,4 @@ stages:
|
||||||
parameters:
|
parameters:
|
||||||
dependsOn: prodBuildDeployment
|
dependsOn: prodBuildDeployment
|
||||||
userName: SafeliteAzureDevops
|
userName: SafeliteAzureDevops
|
||||||
userEmail: githubazuredevops@safelite.com
|
userEmail: githubazuredevops@safelite.com
|
||||||
303
temp/playwright-test.yml
Normal file
303
temp/playwright-test.yml
Normal file
|
|
@ -0,0 +1,303 @@
|
||||||
|
parameters:
|
||||||
|
- name: totalShards
|
||||||
|
type: number
|
||||||
|
default: 2
|
||||||
|
values: [1, 2, 4, 8]
|
||||||
|
- name: targetUrl
|
||||||
|
type: string
|
||||||
|
- name: dockerFileName
|
||||||
|
type: string
|
||||||
|
default: 'Dockerfile.playwright'
|
||||||
|
- name: isRegression
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
- name: filterTags
|
||||||
|
type: string
|
||||||
|
default: '@smoke'
|
||||||
|
- name: playwrightTestsPath
|
||||||
|
type: string
|
||||||
|
default: 'playwright-tests'
|
||||||
|
- name: npmServePath
|
||||||
|
type: string
|
||||||
|
default: '.'
|
||||||
|
- name: npmrcPath
|
||||||
|
type: string
|
||||||
|
default: 'playwright-tests/.npmrc'
|
||||||
|
- name: secrets
|
||||||
|
type: object
|
||||||
|
default: {}
|
||||||
|
- name: dockerImageName
|
||||||
|
type: string
|
||||||
|
default: 'playwright-tests'
|
||||||
|
- name: imageTag
|
||||||
|
type: string
|
||||||
|
default: '$(Build.BuildId)'
|
||||||
|
- name: envFileName
|
||||||
|
type: string
|
||||||
|
default: '.env.ci'
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
- job: playwright_tests
|
||||||
|
continueOnError: true
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
${{ if eq(parameters.totalShards, 1) }}:
|
||||||
|
shard1:
|
||||||
|
shardNumber: 1
|
||||||
|
${{ if eq(parameters.totalShards, 2) }}:
|
||||||
|
shard1:
|
||||||
|
shardNumber: 1
|
||||||
|
shard2:
|
||||||
|
shardNumber: 2
|
||||||
|
${{ if eq(parameters.totalShards, 4) }}:
|
||||||
|
shard1:
|
||||||
|
shardNumber: 1
|
||||||
|
shard2:
|
||||||
|
shardNumber: 2
|
||||||
|
shard3:
|
||||||
|
shardNumber: 3
|
||||||
|
shard4:
|
||||||
|
shardNumber: 4
|
||||||
|
${{ if eq(parameters.totalShards, 8) }}:
|
||||||
|
shard1:
|
||||||
|
shardNumber: 1
|
||||||
|
shard2:
|
||||||
|
shardNumber: 2
|
||||||
|
shard3:
|
||||||
|
shardNumber: 3
|
||||||
|
shard4:
|
||||||
|
shardNumber: 4
|
||||||
|
shard5:
|
||||||
|
shardNumber: 5
|
||||||
|
shard6:
|
||||||
|
shardNumber: 6
|
||||||
|
shard7:
|
||||||
|
shardNumber: 7
|
||||||
|
shard8:
|
||||||
|
shardNumber: 8
|
||||||
|
steps:
|
||||||
|
- task: npmAuthenticate@0
|
||||||
|
inputs:
|
||||||
|
workingFile: ${{ parameters.npmrcPath }}
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
echo "Starting Docker cleanup to free space..."
|
||||||
|
|
||||||
|
# Remove all stopped containers
|
||||||
|
echo "Removing stopped containers..."
|
||||||
|
docker container prune -f
|
||||||
|
|
||||||
|
# Remove dangling images (untagged)
|
||||||
|
echo "Removing dangling images..."
|
||||||
|
docker image prune -f
|
||||||
|
|
||||||
|
# Remove unused volumes
|
||||||
|
echo "Removing unused volumes..."
|
||||||
|
docker volume prune -f
|
||||||
|
|
||||||
|
# Show disk usage after cleanup
|
||||||
|
echo "Docker system usage after cleanup:"
|
||||||
|
docker system df
|
||||||
|
|
||||||
|
echo "Docker cleanup completed!"
|
||||||
|
displayName: "Docker Cleanup"
|
||||||
|
|
||||||
|
- task: Docker@2
|
||||||
|
displayName: 'Build Docker Image'
|
||||||
|
inputs:
|
||||||
|
command: build
|
||||||
|
dockerfile: ${{ parameters.dockerFileName }}
|
||||||
|
repository: ${{ parameters.dockerImageName }}
|
||||||
|
tags: ${{ parameters.imageTag }}
|
||||||
|
arguments: '--no-cache --pull'
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
printenv > "${{ parameters.envFileName }}"
|
||||||
|
|
||||||
|
JIRA_CARD_NUMBER=""
|
||||||
|
IS_REGRESSION="${{ parameters.isRegression }}"
|
||||||
|
echo "isRegression: $IS_REGRESSION";
|
||||||
|
if [[ "${{ parameters.isRegression }}" == "False" ]]; then
|
||||||
|
branch_name=$(Build.SourceBranch) # TODO: Change back to PullRequest.SourceBranch
|
||||||
|
echo "Retrieved branch name: '$branch_name'"
|
||||||
|
JIRA_CARD_NUMBER="${branch_name##*/}"
|
||||||
|
echo "Extracted JIRA Card number: '$JIRA_CARD_NUMBER'"
|
||||||
|
fi
|
||||||
|
FILTER=""
|
||||||
|
if [[ -n "${{ parameters.filterTags }}" && -n "$JIRA_CARD_NUMBER" ]]; then
|
||||||
|
echo "Filtering by filterTags and Jira Card Number..."
|
||||||
|
FILTER="--grep '$JIRA_CARD_NUMBER|${{ parameters.filterTags }}'"
|
||||||
|
elif [[ -n "${{ parameters.filterTags }}" ]]; then
|
||||||
|
echo "Filtering by filterTags only..."
|
||||||
|
FILTER="--grep '${{ parameters.filterTags }}'"
|
||||||
|
elif [[ -n "$JIRA_CARD_NUMBER" ]]; then
|
||||||
|
echo "Filtering by Jira card number only..."
|
||||||
|
FILTER="--grep '$JIRA_CARD_NUMBER'"
|
||||||
|
else
|
||||||
|
echo "No filter. Running all test cases..."
|
||||||
|
FILTER=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Line 142 targetUrl: ${{ parameters.targetUrl }}"
|
||||||
|
TARGET_URL=${{ parameters.targetUrl }}
|
||||||
|
echo "BASE_URL value: $BASE_URL"
|
||||||
|
|
||||||
|
# Create container and run tests
|
||||||
|
|
||||||
|
if [[ "$TARGET_URL" == *localhost* ]]; then
|
||||||
|
echo 'Npx version:'
|
||||||
|
npx --version
|
||||||
|
port="$TARGET_URL"
|
||||||
|
echo "URL: '$port'"
|
||||||
|
echo "URL '$port' contains 'localhost'. Extracting port... "
|
||||||
|
port=$(echo "$port" | sed -E 's/.*:([0-9]+).*/\1/')
|
||||||
|
echo "Port is '$port'"
|
||||||
|
container_id=$(docker create \
|
||||||
|
--ipc=host \
|
||||||
|
--env-file "${{ parameters.envFileName }}" \
|
||||||
|
-e TARGET_URL="$TARGET_URL" \
|
||||||
|
-e JIRA_CARD_NUMBER="$JIRA_CARD_NUMBER" \
|
||||||
|
-e FILTER="$FILTER" \
|
||||||
|
-e PLAYWRIGHT_PATH="${{ parameters.playwrightTestsPath }}" \
|
||||||
|
-e SERVE_PATH="${{ parameters.npmServePath }}" \
|
||||||
|
-e SHARD_NUMBER=$(shardNumber) \
|
||||||
|
-e TOTAL_SHARDS=$(totalShards) \
|
||||||
|
${{ parameters.dockerImageName }}:${{ parameters.imageTag }} \
|
||||||
|
npx concurrently -k -n 'server,playwright' \
|
||||||
|
"npm --prefix $SERVE_PATH run serve -- --port=$port" \
|
||||||
|
"npx --prefix $PLAYWRIGHT_PATH wait-on $TARGET_URL && npx --prefix $PLAYWRIGHT_PATH playwright test $PLAYWRIGHT_PATH --shard=$SHARD_NUMBER/$TOTAL_SHARDS --reporter=list,blob $FILTER" \
|
||||||
|
)
|
||||||
|
else
|
||||||
|
container_id=$(docker create \
|
||||||
|
--ipc=host \
|
||||||
|
--env-file "${{ parameters.envFileName }}" \
|
||||||
|
-e TARGET_URL="$TARGET_URL" \
|
||||||
|
-e JIRA_CARD_NUMBER="$JIRA_CARD_NUMBER" \
|
||||||
|
-e FILTER="$FILTER" \
|
||||||
|
-e PLAYWRIGHT_PATH=${{ parameters.playwrightTestsPath }} \
|
||||||
|
-e SERVE_PATH=${{ parameters.npmServePath }} \
|
||||||
|
-e SHARD_NUMBER=$(shardNumber) \
|
||||||
|
-e TOTAL_SHARDS=$(totalShards) \
|
||||||
|
${{ parameters.dockerImageName }}:${{ parameters.imageTag }} \
|
||||||
|
npx --prefix $PLAYWRIGHT_PATH playwright test $PLAYWRIGHT_PATH --shard=$SHARD_NUMBER/$TOTAL_SHARDS --reporter=list,blob $FILTER \
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
# Start container and stream logs
|
||||||
|
echo "Starting tests for shard $(shardNumber)..."
|
||||||
|
docker start -a $container_id
|
||||||
|
|
||||||
|
# Create directory for test results
|
||||||
|
echo "Creating test results directory..."
|
||||||
|
mkdir -p $(System.DefaultWorkingDirectory)/blob-reports/shard-$(shardNumber)
|
||||||
|
|
||||||
|
# Copy test results from container
|
||||||
|
echo "Copying test results..."
|
||||||
|
docker cp $container_id:/app/blob-report/. $(System.DefaultWorkingDirectory)/blob-reports/shard-$(shardNumber)/
|
||||||
|
|
||||||
|
# Remove container
|
||||||
|
echo "Cleaning up container..."
|
||||||
|
docker rm $container_id
|
||||||
|
|
||||||
|
# Check if tests failed
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Tests failed in shard $(shardNumber) or tests don't exist for this shard number!"
|
||||||
|
exit 0 # Suppress error. It will be visible in report.
|
||||||
|
fi
|
||||||
|
displayName: 'Run Playwright Tests - Shard $(shardNumber)'
|
||||||
|
env: ${{ parameters.secrets }}
|
||||||
|
|
||||||
|
- task: PublishPipelineArtifact@1
|
||||||
|
displayName: 'Publish Test Reports - Shard $(shardNumber)'
|
||||||
|
condition: always()
|
||||||
|
inputs:
|
||||||
|
targetPath: '$(System.DefaultWorkingDirectory)/blob-reports/shard-$(shardNumber)'
|
||||||
|
artifact: 'playwright-report-shard-$(shardNumber)'
|
||||||
|
publishLocation: 'pipeline'
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
docker rmi ${{ parameters.dockerImageName }}:${{ parameters.imageTag }} -f
|
||||||
|
displayName: 'Cleanup Docker Image'
|
||||||
|
condition: always()
|
||||||
|
- job: download_and_merge_reports
|
||||||
|
dependsOn: playwright_tests
|
||||||
|
timeoutInMinutes: 8
|
||||||
|
cancelTimeoutInMinutes: 10
|
||||||
|
steps:
|
||||||
|
- task: npmAuthenticate@0
|
||||||
|
inputs:
|
||||||
|
workingFile: ${{ parameters.npmrcPath }}
|
||||||
|
- task: DownloadPipelineArtifact@2
|
||||||
|
inputs:
|
||||||
|
targetPath: '$(System.DefaultWorkingDirectory)/playwright-reports'
|
||||||
|
- task: Docker@2
|
||||||
|
displayName: 'Build Docker Image'
|
||||||
|
inputs:
|
||||||
|
command: build
|
||||||
|
dockerfile: ${{ parameters.dockerFileName }}
|
||||||
|
repository: ${{ parameters.dockerImageName }}
|
||||||
|
tags: ${{ parameters.imageTag }}
|
||||||
|
arguments: '--no-cache --pull'
|
||||||
|
- bash: |
|
||||||
|
printenv > "${{ parameters.envFileName }}"
|
||||||
|
branch_name=$(System.PullRequest.SourceBranch)
|
||||||
|
echo "Retrieved branch name: '$branch_name'"
|
||||||
|
JIRA_CARD_NUMBER="${branch_name##*/}"
|
||||||
|
echo "Extracted JIRA Card number: '$JIRA_CARD_NUMBER'"
|
||||||
|
container_id=$(docker create \
|
||||||
|
--ipc=host \
|
||||||
|
--env-file "${{ parameters.envFileName }}" \
|
||||||
|
-e JIRA_CARD_NUMBER="$JIRA_CARD_NUMBER" \
|
||||||
|
${{ parameters.dockerImageName }}:${{ parameters.imageTag }} \
|
||||||
|
export PLAYWRIGHT_PATH=${{ parameters.playwrightTestsPath }} bash -c "
|
||||||
|
echo 'Moving Playwright reports out of subfolders...'
|
||||||
|
find ./playwright-reports/ -mindepth 2 -type f -exec mv {} ./playwright-reports/ \;
|
||||||
|
echo 'Merging reports...'
|
||||||
|
PLAYWRIGHT_JUNIT_OUTPUT_DIR='/app/test-results' PLAYWRIGHT_JUNIT_OUTPUT_NAME='junit_results.xml' npx --prefix $PLAYWRIGHT_PATH playwright merge-reports ./playwright-reports
|
||||||
|
echo 'Contents of ortoni-report:' && ls ./ortoni-report
|
||||||
|
echo 'Current dir: ' && pwd
|
||||||
|
echo 'Contents of current dir: ' && ls
|
||||||
|
echo 'Contents of /app/test-results' && ls /app/test-results
|
||||||
|
")
|
||||||
|
# Start container and stream logs
|
||||||
|
echo "Starting merge"
|
||||||
|
docker start -a $container_id
|
||||||
|
|
||||||
|
# Create directory for test results
|
||||||
|
echo "Creating test results directory..."
|
||||||
|
mkdir -p $(System.DefaultWorkingDirectory)/ortoni-report
|
||||||
|
mkdir -p $(System.DefaultWorkingDirectory)/test-results
|
||||||
|
|
||||||
|
# Copy test results from container
|
||||||
|
echo "Copying test results..."
|
||||||
|
docker cp $container_id:/app/ortoni-report/. $(System.DefaultWorkingDirectory)/ortoni-report
|
||||||
|
docker cp $container_id:/app/test-results/junit_results.xml $(System.DefaultWorkingDirectory)/test-results
|
||||||
|
|
||||||
|
# Remove container
|
||||||
|
echo "Cleaning up container..."
|
||||||
|
docker rm $container_id
|
||||||
|
displayName: merge_and_publish_results_to_jira
|
||||||
|
env: ${{ parameters.secrets }}
|
||||||
|
|
||||||
|
- task: PublishTestResults@2
|
||||||
|
displayName: 'Publish test results'
|
||||||
|
inputs:
|
||||||
|
searchFolder: 'test-results'
|
||||||
|
testResultsFormat: 'JUnit'
|
||||||
|
testResultsFiles: 'junit_results.xml'
|
||||||
|
mergeTestResults: true
|
||||||
|
failTaskOnFailedTests: false
|
||||||
|
testRunTitle: 'Playwright Tests'
|
||||||
|
condition: succeededOrFailed()
|
||||||
|
|
||||||
|
- task: PublishPipelineArtifact@1
|
||||||
|
displayName: 'Publish Merged Report'
|
||||||
|
condition: always()
|
||||||
|
inputs:
|
||||||
|
targetPath: '$(System.DefaultWorkingDirectory)/ortoni-report'
|
||||||
|
artifact: 'playwright-merged-report'
|
||||||
|
publishLocation: 'pipeline'
|
||||||
|
- script: |
|
||||||
|
docker rmi ${{ parameters.dockerImageName }}:${{ parameters.imageTag }} -f
|
||||||
|
displayName: 'Cleanup Docker Image'
|
||||||
|
condition: always()
|
||||||
Loading…
Reference in a new issue