name: TEST-ENV-DEPLOYMENT
# Build and deploy test instance for every pull request

on: [pull_request]

jobs:
  deploy:
    if: github.event.pull_request.head.repo.full_name == 'saleor/saleor-dashboard'
    runs-on: ubuntu-latest
    outputs:
      base_URL: ${{ steps.set-domain.outputs.domain }}
    steps:
      - uses: actions/checkout@v2
      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version-file: ".nvmrc"

      - uses: rlespinasse/github-slug-action@3.1.0

      - name: Start deployment
        uses: bobheadxi/deployments@v0.4.2
        id: deployment
        with:
          step: start
          token: ${{ secrets.GITHUB_TOKEN }}
          env: ${{ env.GITHUB_HEAD_REF_SLUG_URL }}
          ref: ${{ github.head_ref }}

      - name: Start storybook deployment
        uses: bobheadxi/deployments@v0.4.2
        id: storybook-deployment
        with:
          step: start
          token: ${{ secrets.GITHUB_TOKEN }}
          env: storybook ${{ env.GITHUB_HEAD_REF_SLUG_URL }}
          ref: ${{ github.head_ref }}

      - name: Cache node modules
        uses: actions/cache@v2
        env:
          cache-name: cache-node-modules
        with:
          path: ~/.npm
          key: ${{ runner.os }}-qa-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-qa-${{ env.cache-name }}-
            ${{ runner.os }}-qa-
            ${{ runner.os }}-
      - name: Install deps
        run: |
          npm ci
      - name: Get custom API_URI
        id: api_uri
        # Search for API_URI in PR description
        env:
          pull_request_body: ${{ github.event.pull_request.body }}
          prefix: API_URI=
          pattern: (http|https)://[a-zA-Z0-9.-]+/graphql/?
        run: |
          echo "custom_api_uri=$(echo "$pull_request_body" | grep -Eo "$prefix$pattern" | sed s/$prefix// | head -n 1)" >> $GITHUB_OUTPUT
      - name: Get APPS_MARKETPLACE_API_URI
        id: apps_marketplace_api_uri
        # Search for APPS_MARKETPLACE_API_URI in PR description
        env:
          pull_request_body: ${{ github.event.pull_request.body }}
          prefix: APPS_MARKETPLACE_API_URI=
          pattern: (http|https)://[a-zA-Z0-9.-]+[a-zA-Z0-9/-]+/?
        run: |
          echo "custom_apps_marketplace_api_uri=$(echo "$pull_request_body" | grep -Eo "$prefix$pattern" | sed s/$prefix// | head -n 1)" >> $GITHUB_OUTPUT
      - name: Run build
        env:
          # Use custom API_URI or the default one
          API_URI: ${{ steps.api_uri.outputs.custom_api_uri || 'https://qa.staging.saleor.cloud/graphql/' }}
          APPS_MARKETPLACE_API_URI: ${{ steps.apps_marketplace_api_uri.outputs.custom_apps_marketplace_api_uri }}
          APP_MOUNT_URI: /
          STATIC_URL: /
          IS_CLOUD_INSTANCE: true
        run: |
          npm run build
      - name: Run build storybook
        run: |
          npm run build-storybook
      - name: Set domain
        id: set-domain
        # Set test instance domain based on branch name slug
        run: |
          echo "domain=${{ env.GITHUB_HEAD_REF_SLUG_URL }}.dashboard.saleor.rocks" >> $GITHUB_OUTPUT
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ secrets.AWS_DEFAULT_REGION }}

      - name: Deploy to S3
        run: |
          aws s3 sync ./build/dashboard s3://${{ secrets.AWS_TEST_DEPLOYMENT_BUCKET }}/${{ steps.set-domain.outputs.domain }}
          aws s3 sync ./build/storybook s3://${{ secrets.AWS_TEST_DEPLOYMENT_BUCKET }}/${{ steps.set-domain.outputs.domain }}/storybook
      - name: Invalidate cache
        run: aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_TEST_CF_DIST_ID }} --paths "/${{ steps.set-domain.outputs.domain }}/*"

      - name: Update deployment status
        uses: bobheadxi/deployments@v0.4.2
        if: always()
        with:
          step: finish
          token: ${{ secrets.GITHUB_TOKEN }}
          status: ${{ job.status }}
          env_url: https://${{ steps.set-domain.outputs.domain }}/
          deployment_id: ${{ steps.deployment.outputs.deployment_id }}

      - name: Update storybook deployment status
        uses: bobheadxi/deployments@v0.4.2
        if: always()
        with:
          step: finish
          token: ${{ secrets.GITHUB_TOKEN }}
          status: ${{ job.status }}
          env_url: https://${{ steps.set-domain.outputs.domain }}/storybook/index.html
          deployment_id: ${{ steps.storybook-deployment.outputs.deployment_id }}

  prepare-tests:
    runs-on: ubuntu-latest
    outputs:
      tags: ${{steps.get_tags.outputs.result}}
      containers: ${{ steps.get_containers.outputs.result}}

    steps:
      - name: Get tags
        id: get_tags
        uses: actions/github-script@v6
        env:
          pullRequestBody: ${{ github.event.pull_request.body }}
        with:
          result-encoding: string
          script: |
            const { pullRequestBody } = process.env
            const tags = ["@critical"];
            try{
              const removedPullRequestBodyBeforeTests = pullRequestBody.split(`### Do you want to run more stable tests?`);
              const removedPullRequestBodyAfterTests = removedPullRequestBodyBeforeTests[1].split(`CONTAINERS`);
              let tagsInString = removedPullRequestBodyAfterTests[0];
              tagsInString = tagsInString.split('\n');
              tagsInString.forEach(line => {
                if (line.includes('[x]')) tags.push(line.replace(/[0-9]+\. \[x\] /, "@stable+@"))
              });
              const tagsToReturn = tags.join(",").toString();
              return tagsToReturn.replace(/\r/g, '')
            }catch{
              return '@critical'
            }

      - name: get-containers
        id: get_containers
        uses: actions/github-script@v6
        env:
          pullRequestBody: ${{ github.event.pull_request.body }}
        with:
          script: |
            const { pullRequestBody } = process.env
            const containers = [];
              const numberOfContainersRegex = /CONTAINERS=(\d*)/
              const numberOfContainers = pullRequestBody.match(numberOfContainersRegex);
              for(let i=1; i<=numberOfContainers[1]; i++){
                containers.push(i)
              }
            return {"containers": containers}

      - name: echo-tags
        run: |
          echo ${{steps.get_tags.outputs.result}}

  cypress-run-selected:
    runs-on: ubuntu-latest
    needs: [prepare-tests, deploy]
    container: cypress/browsers:node18.12.0-chrome106-ff106
    strategy:
      fail-fast: false
      max-parallel: 10
      matrix: ${{ fromJson(needs.prepare-tests.outputs.containers) }}

    steps:
      - name: Checkout
        uses: actions/checkout@v1

      - name: Get API_URI
        id: api_uri
        # Search for API_URI in PR description and use default if not defined
        env:
          pull_request_body: ${{ github.event.pull_request.body }}
          prefix: API_URI=
          pattern: (http|https)://[a-zA-Z0-9.-]+/graphql/?
          fallback_uri: ${{ secrets.CYPRESS_API_URI }}
        run: |
          echo "custom_api_uri=$(echo "$pull_request_body" | grep -Eo "$prefix$pattern" | sed s/$prefix// | head -n 1 | { read custom_uri; if [ -z "$custom_uri" ]; then echo "$fallback_uri"; else echo "$custom_uri"; fi })" >> $GITHUB_OUTPUT
      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version-file: ".nvmrc"

      - name: Cache node modules
        uses: actions/cache@v2
        env:
          cache-name: cache-node-modules
        with:
          path: ~/.npm
          key: ${{ runner.os }}-qa-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-qa-${{ env.cache-name }}-
            ${{ runner.os }}-qa-
            ${{ runner.os }}-
      - name: Install Dependencies
        if: steps.cache-node-modules.outputs.cache-hit != 'true'
        run: NODE_OPTIONS=--max_old_space_size=4096 npm install

      - name: Cypress run critical
        uses: cypress-io/github-action@v4
        env:
          API_URI: ${{ steps.api_uri.outputs.custom_api_uri }}
          APP_MOUNT_URI: ${{ secrets.APP_MOUNT_URI }}
          CYPRESS_baseUrl: https://${{needs.deploy.outputs.base_URL}}
          CYPRESS_USER_NAME: ${{ secrets.CYPRESS_USER_NAME }}
          CYPRESS_SECOND_USER_NAME: ${{ secrets.CYPRESS_SECOND_USER_NAME }}
          CYPRESS_USER_PASSWORD: ${{ secrets.CYPRESS_USER_PASSWORD }}
          CYPRESS_PERMISSIONS_USERS_PASSWORD: ${{ secrets.CYPRESS_PERMISSIONS_USERS_PASSWORD }}
          CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
          CYPRESS_mailHogUrl: ${{ secrets.CYPRESS_MAILHOG }}
          COMMIT_INFO_MESSAGE: ${{github.event.inputs.tags}} tests triggered on PR - https://github.com/${{ github.repository }}/pull/${{ github.ref_name }}
          CYPRESS_grepTags: ${{ needs.prepare-tests.outputs.tags }}
        with:
          parallel: true
          group: "UI - Chrome"
          record: true
          tag: Critical, ${{github.event.action}}
