name: Execute nightly tests

on:
  workflow_dispatch:
    inputs:
      tags:
        required: true 
        description: 'Select tests to run'
        default: '@allEnv'
        type: choice
        options:
        - '@allEnv'
        - '@critical'
        - '@stable'
        - '@oldRelease'
      environment:
        required: true 
        description: 'Environment to run tests against'
        default: 'https://automation-dashboard.staging.saleor.cloud/'
        type: choice
        options:
        - https://automation-dashboard.staging.saleor.cloud/
        - https://master.staging.saleor.cloud/
        - https://latest.staging.saleor.cloud/
        - https://qa.staging.saleor.cloud/
        - Other
      otherEnvironment:
        required: false
        description: 'Type env if "Other" option is selected'
        type: string
        default: 'https://vXX.staging.saleor.cloud/' 

  schedule:
    - cron: '00 2 * * 1-5'

  repository_dispatch:
    types: [automation-tests-event]

jobs:

  revert-automation-env-to-snap:
    if: ${{ github.event.inputs.environment == null && github.event_name != 'repository_dispatch' }}
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:

      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          # use explicit version as this job does not checkout code
          node-version: '18'

      - name: Install saleor cli
        id: install-saleor-cli
        run: npm i -g @saleor/cli

      - name: Cache node modules
        uses: actions/cache@v2
        env:
          cache-name: cache-node-modules-cli
        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: Write config file
        id: write-config-file
        env:
          ACCESS_TOKEN: ${{ secrets.CLOUD_ACCESS_TOKEN }}
        run: echo '{"token":"Token ${{ secrets.CLOUD_ACCESS_TOKEN }}","telemetry":"false","organization_slug":"qa","organization_name":"QA","environment_id":"lHECN87U"}' > ~/.config/saleor.json

      - name: revert snapshot
        env:
          CI: true
          SALEOR_CLI_ENV: staging
        run: npx saleor backup restore 9S4PckyI --skip-webhooks-update

      - name: Notify Slack
        if: ${{ failure() }}
        uses: rtCamp/action-slack-notify@v2
        env:
          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_SNAP_RESTORE }}
          SLACK_USERNAME: RevertSnapshotBot
          SLACK_COLOR: ${{ job.status }}
          SLACK_TITLE: "Revert to snapshot job failed"
          SLACK_MESSAGE: "https://github.com/saleor/saleor-dashboard/actions/workflows/tests-nightly.yml"
          MSG_MINIMAL: true

  run-tests-in-parallel:
    needs: ['revert-automation-env-to-snap']
    if: ${{ always() && github.event_name != 'repository_dispatch'  }} #Wait for revert-automation-env-to-snap, bot run always, even if skipped
    runs-on: ubuntu-latest
    env:
      NODE_OPTIONS: "--max_old_space_size=4096"
    outputs:
      status: ${{ steps.cypress.outcome }}
    container: cypress/browsers:node18.12.0-chrome106-ff106
    strategy:
      fail-fast: false
      matrix:
        # run copies of the current job in parallel
        containers: [1, 2, 3, 4, 5, 6, 7, 8, 9]
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Check if other env
        id: get-typed-env-uri
        if: ${{ github.event.inputs.environment == 'Other' }}
        run: |
          echo "ENV_URI=${{github.event.inputs.otherEnvironment}}" >> $GITHUB_OUTPUT
      - name: Get env
        id: get-env-uri
        env:
          DEFAULT_ENV_URI: 'https://automation-dashboard.staging.saleor.cloud/'
          TYPED_ENV_URI: ''
        run: |
          echo "ENV_URI=${{ steps.get-typed-env-uri.outputs.ENV_URI || github.event.inputs.environment || env.DEFAULT_ENV_URI }}" >> $GITHUB_OUTPUT

      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version-file: '.nvmrc'

      - name: Cypress run
        id: cypress
        continue-on-error: true
        if: ${{ github.event.inputs.tests != 'Critical' && github.event_name != 'repository_dispatch'}}
        uses: cypress-io/github-action@v4
        env:
          API_URI: ${{ steps.get-env-uri.outputs.ENV_URI }}graphql/
          APP_MOUNT_URI: ${{ secrets.APP_MOUNT_URI }}
          CYPRESS_baseUrl: ${{ steps.get-env-uri.outputs.ENV_URI }}dashboard/
          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 }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          CYPRESS_mailHogUrl: ${{ secrets.CYPRESS_MAILHOG }}
          COMMIT_INFO_MESSAGE: All tests triggered via ${{ github.event_name}} on ${{ steps.get-env-uri.outputs.ENV_URI }}
          CYPRESS_grepTags: ${{ github.event.inputs.tags }}
          STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }}
          STRIPE_PUBLIC_KEY: ${{ secrets.STRIPE_PUBLIC_KEY }}
        with:
          parallel: true
          group: 'UI - Chrome'
          record: true
          tag: ${{ steps.get-env-uri.outputs.ENV_URI }},${{ github.event.inputs.tags }}

  get-environment-variables:
    if: ${{ github.event_name == 'repository_dispatch' && (github.event.client_payload.environment == 'SANDBOX' || github.event.client_payload.environment == 'STAGING')}}
    runs-on: ubuntu-latest
    timeout-minutes: 30
    outputs:
      url: ${{ steps.get-environment-variables.outputs.url }}
      is_old_version: ${{ steps.get-environment-variables.outputs.IS_OLD_VERSION }}
    env:
      REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      TOKEN: ${{ secrets.CLOUD_ACCESS_TOKEN }}
      VERSION: ${{github.event.client_payload.version}}
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version-file: '.nvmrc'
          
      - name: Install dependencies
        run: |
              cd .github/workflows
              npm ci

      - name: get environment variables
        id: get-environment-variables
        run: |
              node .github/workflows/getEnvironmentVariables.js \
              --version $VERSION \
              --token "$TOKEN" \
              --repo_token "$REPO_TOKEN"

  run-tests-on-release:
    if: ${{ github.event_name == 'repository_dispatch' && (github.event.client_payload.environment == 'SANDBOX' || github.event.client_payload.environment == 'STAGING')}}
    needs: get-environment-variables
    runs-on: ubuntu-latest
    env:
        NODE_OPTIONS: "--max_old_space_size=4096"
    outputs:
      status: ${{ steps.cypress.outcome }}
      dashboard_url: ${{ steps.cypress.outputs.dashboardUrl }}
    container: cypress/browsers:node18.12.0-chrome106-ff106
    strategy:
      fail-fast: false
      matrix:
        # run copies of the current job in parallel
        containers: [1, 2, 3, 4, 5, 6, 7, 8, 9]
    steps:

      - name: Get branch
        id: branch
        env:
          version: ${{github.event.client_payload.version}}
        run: |
          echo "ref=$(echo $version | grep -ohE "[0-9]\.[0-9]+" )" >> $GITHUB_OUTPUT

      - name: Checkout
        uses: actions/checkout@v3
        with:
          ref: ${{ steps.branch.outputs.ref }}

      - name: Set tag for tests
        id: set-tag-for-tests
        uses: actions/github-script@v6
        env:
          is_old_version: ${{ needs.get-environment-variables.outputs.is_old_version }}
        with:
          result-encoding: string
          script: |
            const { is_old_version } = process.env
            if(is_old_version == "true"){
              return "@oldRelease"
            }else{
              return "@stable"
            }
              
      - name: Cypress run - automatically
        id: cypress
        continue-on-error: true
        uses: cypress-io/github-action@v4
        env:
          API_URI: ${{ needs.get-environment-variables.outputs.url }}graphql/
          APP_MOUNT_URI: ${{ secrets.APP_MOUNT_URI }}
          CYPRESS_baseUrl: ${{ needs.get-environment-variables.outputs.url }}dashboard/
          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 }}
          STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }}
          STRIPE_PUBLIC_KEY: ${{ secrets.STRIPE_PUBLIC_KEY }}
          CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          CYPRESS_mailHogUrl: ${{ secrets.CYPRESS_MAILHOG }}
          COMMIT_INFO_MESSAGE: Triggered via release - ${{github.event.client_payload.project}} ${{github.event.client_payload.version}}, ${{github.event.client_payload.pullRequestUrl}}
          CYPRESS_grepTags: ${{steps.set-tag-for-tests.outputs.result}}
        with:
          parallel: true
          group: 'UI - Chrome'
          record: true
          tag: ${{github.event.client_payload.project}}, ${{github.event.client_payload.environment}}, ${{ needs.get-environment-variables.outputs.url }}


  add-review-and-merge-patch:
    if: ${{ always() && (needs.run-tests-on-release.outputs.status == 'success' || needs.run-tests-on-release.outputs.status == 'failure') }}
    runs-on: ubuntu-latest
    needs: [run-tests-on-release]
    steps:

      - name: Checkout
        uses: actions/checkout@v3

      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version-file: '.nvmrc'

      - name: Install dependencies
        run: |
              cd .github/workflows
              npm ci

      - name: Add review and merge if patch DASHBOARD
        env: 
         tests_status: ${{ needs.run-tests-on-release.outputs.status }}
         version: ${{ github.event.client_payload.version }}
         pull_request_number: ${{ github.event.client_payload.pullRequestNumber }}
         dashboard_url: ${{ needs.run-tests-on-release.outputs.dashboard_url }}
         auto_release: ${{ (github.event.client_payload.autoRelease && '--auto_release') || '' }}
        run: |
            export GITHUB_TOKEN=$( \
            curl --request GET --url ${{ secrets.VAULT_URL}} --header "Authorization: JWT ${{ secrets.VAULT_JWT }}" | jq -r .token \
            )
            node .github/workflows/approveAndMergeReleasePR.js \
            --version $version \
            --pull_request_number $pull_request_number \
            --dashboard_url $dashboard_url \
            $auto_release

  send-slack-notification:
    if: ${{ failure() && github.event_name == 'repository_dispatch'}}
    runs-on: ubuntu-latest
    steps:
      - name: Notify Slack
        env:
          JOB_DEPLOYMENT_KIND: staging
          JOB_STATUS: ${{ job.status }}
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_RELEASES_WEBHOOK_URL }}
          JOB_TITLE: "Test release workflow - ${{github.event.client_payload.project}} ${{github.event.client_payload.version}}"
          JOB_KIND: "release tests"
        run: |
          python3 ./.github/workflows/notify/notify-slack.py