trigger:
  branches:
    include: [ develop, release/* ]
  paths:
    exclude:
      - deployment/*
    include:
      - "*"
pr:
  branches:
    include: [ '*' ]
  paths:
    exclude:
      - deployment/*
    include:
      - "*"

resources:
  containers:
    - container: node
      image: ghcr.io/safelite/node-build:20
      endpoint: GitHub Docker
    - container: awscli
      image: ghcr.io/safelite/awscli2-build:3.9
      endpoint: GitHub Docker
  repositories:
    - repository: AzureDevOps
      type: github
      name: Safelite/AzureDevOps
      endpoint: Safelite
      ref: refs/tags/t5.5.40

variables:
  - group: Digital-Infrastructure
  - group: ISS-BuildBranches
  - name: dockerImageName
    value: 'playwright-tests'
  - name: imageTag
    value: '$(Build.BuildId)'
  - name: totalShards
    value: 2
  - name: IS_REGRESSION
    value: 'false'

stages:
  # PR's
  - ${{ if eq(variables['Build.Reason'], 'PullRequest') }}:
    - stage: TestPr
      displayName: Run Tests For PullRequest
      jobs:
      - template: templates/digital/vue-jest-run-unit-tests.yml@AzureDevOps
        parameters:
          nodeContainer: node
          npmLocation: $(Build.SourcesDirectory)
          testResultsFile: junit.xml
          summaryFileLocation: $(Build.SourcesDirectory)/coverage/cobertura-coverage.xml
      - job: playwright_tests
        continueOnError: true
        strategy:
          matrix:
            shard1:
              shardNumber: 1
            shard2:
              shardNumber: 2
            # shard3:
            #   shardNumber: 3
            # shard4:
            #   shardNumber: 4

        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 CCIS_API_AUTH=$(CCIS_API_AUTH) \
              -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 ENABLE_MOCK_TESTING=true \
              -e ENABLE_ACCESSIBILITY_TESTING=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 && 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()

      - 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" \
              $(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 }}:
    # Dev Build/Deploy
    - stage: Dev
      condition: eq(variables['Build.SourceBranch'], variables['dev-branch'] )
      variables:
        - group: ISS-Dev
      jobs:
      - deployment: devBuildDeployment
        displayName: Build and Deploy ISS - Dev
        environment: digitalCloud-dev
        container: node
        workspace:
          clean: all
        strategy:
          runOnce:
            deploy:
              steps:
                - checkout: self
                  clean: true
                - task: CopyFiles@2
                  inputs:
                    SourceFolder: 'public/apple-pay/dev'
                    Contents: '**'
                    TargetFolder: 'public/.well-known'
                    CleanTargetFolder: true
                - task: CopyFiles@2
                  inputs:
                    SourceFolder: 'public/apple-pay/non-prod'
                    Contents: '**'
                    TargetFolder: 'public/.well-known'
                - task: DeleteFiles@1
                  inputs:
                    SourceFolder: 'public/apple-pay'
                    Contents: '**'
                    RemoveSourceFolder: true
                - template: templates/digital/step-build-vue.yml@AzureDevOps
                  parameters:
                    buildOutputDir: dist
                    environment: Dev
                - template: templates/digital/step-deploy-vue.yml@AzureDevOps
                  parameters:
                    artifactName: vueDistDev
                    awsProfile: $(devDeploymentProfile)
                    deployBuckets:
                      safelite-dev-iss-us-east-2:
                        clearFolder: true
                        deployFolder: ''
                        region: us-east-2
                      safelite-dev-iss-us-east-1:
                        clearFolder: true
                        deployFolder: ''
                        region: us-east-1
                    appDeployVariables:
                      __VUE_APP_CONSUMER_CF_DISTRO__: $(__VUE_APP_CONSUMER_CF_DISTRO__)
                      __VUE_APP_CURRENT_ENVIRONMENT__: $(__VUE_APP_CURRENT_ENVIRONMENT__)
                      __VUE_APP_CUSTOMER_PORTAL_URL__: $(__VUE_APP_CUSTOMER_PORTAL_URL__)
                      __VUE_APP_GOOGLE_PLACES_API_KEY__: $(__VUE_APP_GOOGLE_PLACES_API_KEY__)
                      __VUE_APP_SAFELITE_HOP__: $(__VUE_APP_SAFELITE_HOP__)
                      __VUE_APP_ADYEN_ENVIRONMENT__: $(__VUE_APP_ADYEN_ENVIRONMENT__)
                      __VUE_APP_ADYEN_CLIENT_KEY__: $(__VUE_APP_ADYEN_CLIENT_KEY__)
                    indexDeployVariables:
                      __VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
                      __VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__)
                      __VUE_APP_GOOGLE_MAPS_API_SCRIPT__: $(__VUE_APP_GOOGLE_MAPS_API_SCRIPT__)
                - template: templates/digital/invalidate-cloudfront-cache.yml@AzureDevOps
                  parameters:
                    awsCliContainer: awscli
                    distributionId: $(cfDistributionId)
                    paths: /*
                    awsProfile: $(devDeploymentProfile)

    # Test Build/Deploy
    - stage: Test
      condition: eq(variables['Build.SourceBranch'], variables['test-branch'] )
      variables:
        - group: ISS-Test
      jobs:
        - deployment: testBuildDeployment
          displayName: Build and Deploy ISS - Test
          environment: NoApproval-All
          container: node
          workspace:
            clean: all
          strategy:
            runOnce:
              deploy:
                steps:
                  - checkout: self
                    clean: true
                  - task: CopyFiles@2
                    inputs:
                      SourceFolder: 'public/apple-pay/test'
                      Contents: '**'
                      TargetFolder: 'public/.well-known'
                      CleanTargetFolder: true
                  - task: CopyFiles@2
                    inputs:
                      SourceFolder: 'public/apple-pay/non-prod'
                      Contents: '**'
                      TargetFolder: 'public/.well-known'
                  - task: DeleteFiles@1
                    inputs:
                      SourceFolder: 'public/apple-pay'
                      Contents: '**'
                      RemoveSourceFolder: true
                  - template: templates/digital/step-build-vue.yml@AzureDevOps
                    parameters:
                      buildOutputDir: dist
                      environment: Test
                  - template: templates/digital/step-deploy-vue.yml@AzureDevOps
                    parameters:
                      artifactName: vueDistTest
                      awsProfile: $(sysDeploymentProfile)
                      deployBuckets:
                        safelite-sys-iss-us-east-1:
                          clearFolder: true
                          deployFolder: ""
                          region: us-east-1
                        safelite-sys-iss-us-east-2:
                          clearFolder: true
                          deployFolder: ""
                          region: us-east-2
                      appDeployVariables:
                        __VUE_APP_CONSUMER_CF_DISTRO__: $(__VUE_APP_CONSUMER_CF_DISTRO__)
                        __VUE_APP_CURRENT_ENVIRONMENT__: $(__VUE_APP_CURRENT_ENVIRONMENT__)
                        __VUE_APP_CUSTOMER_PORTAL_URL__: $(__VUE_APP_CUSTOMER_PORTAL_URL__)
                        __VUE_APP_GOOGLE_PLACES_API_KEY__: $(__VUE_APP_GOOGLE_PLACES_API_KEY__)
                        __VUE_APP_SAFELITE_HOP__: $(__VUE_APP_SAFELITE_HOP__)
                        __VUE_APP_ADYEN_ENVIRONMENT__: $(__VUE_APP_ADYEN_ENVIRONMENT__)
                        __VUE_APP_ADYEN_CLIENT_KEY__: $(__VUE_APP_ADYEN_CLIENT_KEY__)
                      indexDeployVariables:
                        __VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
                        __VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__)
                        __VUE_APP_GOOGLE_MAPS_API_SCRIPT__: $(__VUE_APP_GOOGLE_MAPS_API_SCRIPT__)
                  - template: templates/digital/invalidate-cloudfront-cache.yml@AzureDevOps
                    parameters:
                      awsCliContainer: awscli
                      distributionId: $(cfDistributionId)
                      paths: /*
                      awsProfile: $(sysDeploymentProfile)

    # QA Build/Deploy
    - stage: QA
      condition: eq(variables['Build.SourceBranch'], variables['qa-branch'] )
      variables:
        - group: ISS-QA
      jobs:
        - deployment: qaBuildDeployment
          displayName: Build and Deploy ISS - QA
          environment: NoApproval-All
          container: node
          workspace:
            clean: all
          strategy:
            runOnce:
              deploy:
                steps:
                  - checkout: self
                    clean: true
                  - task: CopyFiles@2
                    inputs:
                      SourceFolder: 'public/apple-pay/qa'
                      Contents: '**'
                      TargetFolder: 'public/.well-known'
                      CleanTargetFolder: true
                  - task: CopyFiles@2
                    inputs:
                      SourceFolder: 'public/apple-pay/non-prod'
                      Contents: '**'
                      TargetFolder: 'public/.well-known'
                  - task: DeleteFiles@1
                    inputs:
                      SourceFolder: 'public/apple-pay'
                      Contents: '**'
                      RemoveSourceFolder: true
                  - template: templates/digital/step-build-vue.yml@AzureDevOps
                    parameters:
                      buildOutputDir: dist
                      environment: Qa
                  - template: templates/digital/step-deploy-vue.yml@AzureDevOps
                    parameters:
                      artifactName: vueDistQa
                      awsProfile: $(qaDeploymentProfile)
                      deployBuckets:
                        safelite-qa-iss-us-east-1:
                          clearFolder: true
                          deployFolder: ""
                          region: us-east-1
                        safelite-qa-iss-us-east-2:
                          clearFolder: true
                          deployFolder: ""
                          region: us-east-2
                      appDeployVariables:
                        __VUE_APP_CONSUMER_CF_DISTRO__: $(__VUE_APP_CONSUMER_CF_DISTRO__)
                        __VUE_APP_CURRENT_ENVIRONMENT__: $(__VUE_APP_CURRENT_ENVIRONMENT__)
                        __VUE_APP_CUSTOMER_PORTAL_URL__: $(__VUE_APP_CUSTOMER_PORTAL_URL__)
                        __VUE_APP_GOOGLE_PLACES_API_KEY__: $(__VUE_APP_GOOGLE_PLACES_API_KEY__)
                        __VUE_APP_SAFELITE_HOP__: $(__VUE_APP_SAFELITE_HOP__)
                        __VUE_APP_ADYEN_ENVIRONMENT__: $(__VUE_APP_ADYEN_ENVIRONMENT__)
                        __VUE_APP_ADYEN_CLIENT_KEY__: $(__VUE_APP_ADYEN_CLIENT_KEY__)
                      indexDeployVariables:
                        __VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
                        __VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__)
                        __VUE_APP_GOOGLE_MAPS_API_SCRIPT__: $(__VUE_APP_GOOGLE_MAPS_API_SCRIPT__)
                  - template: templates/digital/invalidate-cloudfront-cache.yml@AzureDevOps
                    parameters:
                      awsCliContainer: awscli
                      distributionId: $(cfDistributionId)
                      paths: /*
                      awsProfile: $(qaDeploymentProfile)

    # Prod Build/Deploy
    - stage: Prod
      condition: succeeded('QA')
      variables:
        - group: ISS-Prod
      jobs:
        - deployment: prodBuildDeployment
          displayName: Build and Deploy ISS - Prod
          environment: digitalCloud-prod
          container: node
          workspace:
            clean: all
          strategy:
            runOnce:
              deploy:
                steps:
                  - checkout: self
                    clean: true
                  - task: CopyFiles@2
                    inputs:
                      SourceFolder: 'public/apple-pay/prod'
                      Contents: '**'
                      TargetFolder: 'public/.well-known'
                      CleanTargetFolder: true
                  - task: DeleteFiles@1
                    inputs:
                      SourceFolder: 'public/apple-pay'
                      Contents: '**'
                      RemoveSourceFolder: true
                  - template: templates/digital/step-build-vue.yml@AzureDevOps
                    parameters:
                      buildOutputDir: dist
                      environment: Prod
                  - template: templates/digital/step-deploy-vue.yml@AzureDevOps
                    parameters:
                      artifactName: vueDistProd
                      awsProfile: $(prodDeploymentProfile)
                      deployBuckets:
                        safelite-prod-iss-us-east-1:
                          clearFolder: true
                          deployFolder: ""
                          region: us-east-1
                        safelite-prod-iss-us-east-2:
                          clearFolder: true
                          deployFolder: ""
                          region: us-east-2
                      appDeployVariables:
                        __VUE_APP_CONSUMER_CF_DISTRO__: $(__VUE_APP_CONSUMER_CF_DISTRO__)
                        __VUE_APP_CURRENT_ENVIRONMENT__: $(__VUE_APP_CURRENT_ENVIRONMENT__)
                        __VUE_APP_CUSTOMER_PORTAL_URL__: $(__VUE_APP_CUSTOMER_PORTAL_URL__)
                        __VUE_APP_GOOGLE_PLACES_API_KEY__: $(__VUE_APP_GOOGLE_PLACES_API_KEY__)
                        __VUE_APP_SAFELITE_HOP__: $(__VUE_APP_SAFELITE_HOP__)
                        __VUE_APP_ADYEN_ENVIRONMENT__: $(__VUE_APP_ADYEN_ENVIRONMENT__)
                        __VUE_APP_ADYEN_CLIENT_KEY__: $(__VUE_APP_ADYEN_CLIENT_KEY__)
                      indexDeployVariables:
                        __VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
                        __VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__)
                        __VUE_APP_GOOGLE_MAPS_API_SCRIPT__: $(__VUE_APP_GOOGLE_MAPS_API_SCRIPT__)
                  - template: templates/digital/invalidate-cloudfront-cache.yml@AzureDevOps
                    parameters:
                      awsCliContainer: awscli
                      distributionId: $(cfDistributionId)
                      paths: /*
                      awsProfile: $(prodDeploymentProfile)
        - template: templates/digital/auto-tag.yml@AzureDevOps
          parameters:
            dependsOn: prodBuildDeployment
            userName: SafeliteAzureDevops
            userEmail: githubazuredevops@safelite.com

