@Library('infraLib') _

def test_status = "missing"

pipeline {
  agent {
    label 'linux-agents-xlarge'
  }
  options {
    ansiColor('xterm')
    timestamps()
    buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '', numToKeepStr: '30')
  }
  //triggers {
  //  parameterizedCron('H 4 * * 1,3,5  %ENVIRONMENT=stage;GRADLE_TARGET=allSwaggerTests_JavaApi')
  //}
  environment {
    REPORTSDIR_SHORT = "allure-results"
    NOTIFICATIONS_CHANNEL = 'delphi-autotests-status'
    AWS_ASSUME_PROFILE = "gdb-delphi-dev"
//     JAVA_OPTS="-Xmx1024m -Xms256m -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap  -XX:MaxRAMFraction=1"
//     JAVA_OPTS="-Xmx4048m -Xms1024m -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap  -XX:MaxRAMFraction=1"
//     JAVA_OPTS="-Xmx4g -Xms2g -XX:+UnlockExperimentalVMOptions -XX:+UseContainerSupport -XX:+DoEscapeAnalysis -XX:+UseCompressedOops"
    JAVA_OPTS="-Xmx8g -Xms4g -XX:+UseContainerSupport -XX:+UnlockExperimentalVMOptions -XX:+DoEscapeAnalysis -XX:+UseCompressedOops"
    /*
    AWS_ROLE_ARN = sh(script: "aws configure get ${env.AWS_ASSUME_PROFILE}.role_arn", returnStdout: true).trim()
    AWS_CREDS_JSON = sh(script: "aws sts assume-role --output json --role-arn ${env.AWS_ROLE_ARN} --duration-seconds 3600 --role-session-name session-${env.AWS_PROFILE}", returnStdout: true).trim()
    AWS_DEFAULT_REGION = sh(script: "aws configure get ${env.AWS_ASSUME_PROFILE}.region", returnStdout: true).trim()
    AWS_ACCESS_KEY_ID = sh(script: "set -euo pipefail; echo '${env.AWS_CREDS_JSON}' | jq -r .Credentials.AccessKeyId", returnStdout: true).trim()
    AWS_SECRET_ACCESS_KEY = sh(script: "set -euo pipefail; echo '${env.AWS_CREDS_JSON}' | jq -r .Credentials.SecretAccessKey", returnStdout: true).trim()
    AWS_SESSION_TOKEN = sh(script: "set -euo pipefail; echo '${env.AWS_CREDS_JSON}' | jq -r .Credentials.SessionToken", returnStdout: true).trim()
    */
    ENVIRONMENT = "${params.ENVIRONMENT}"
    PROXY = "no"
    ECR_REGISTRY_URL = '475275892927.dkr.ecr.us-east-1.amazonaws.com/delphi/qa-automation'
  }
  parameters {
    choice(
      choices: ['dev', 'qa', 'stage'],
      description: 'Set environment for deployment. Skipped by default for master/release*, dev by default for all other branches',
      name: 'ENVIRONMENT'
    )
    choice(
      choices: [
        'allSwaggerTests_JavaApi'
        , 'api_smoke_prod_JavaApi'
        , 'ads_JavaApi'
        , 'charts_JavaApi'
        , 'playlists_JavaApi'
        , 'dataHealth_JavaApi'
        , 'streams_JavaApi'
        , 'trackPosition_JavaApi'
        , 'video_JavaApi'
        , 'ciDelphiUnitTests'
        , 'ciDelphiDAPDApiComparison'
        , 'underReview_JavaApi'],
      description: 'Set GRADLE_TARGET to run',
      name: 'GRADLE_TARGET'
    )

    choice(
            choices: [
                    '%s-delphi-api.delphiplatform.io'
                    , '%s-mobile-delphi-api.delphiplatform.io'],
            description: 'Set API HOST pattern to run;' +
                    'To run tests against stage-mobile take option 2',
            name: 'HOST'
    )
    extendedChoice(
        defaultValue: '',
        description: 'Set TestNg groups should be included to run',
        multiSelectDelimiter: ',',
        name: 'TESTNG_GROUPS',
        quoteValue: false,
        saveJSONParameterToFile: false,
        type: 'PT_MULTI_SELECT',
        value: 'swagger,client,regression,apollo,decibel,shazam,json,csv',
        visibleItemCount: 3
    )
    booleanParam description: 'Check if you need to build a new docker image', name: 'BUILD_DOCKER_IMAGE'
  }
  stages {
    stage('Build test image') {
      when {
        expression { return params.BUILD_DOCKER_IMAGE }
      }
      steps {
        sh 'make docker/build'
        sh 'make docker/push'
      }
    }
    stage('Pull test image') {
      when {
        not { expression { return params.BUILD_DOCKER_IMAGE } }
      }
      steps {
        sh 'make docker/pull'
      }
    }
    stage('Docker stage') {
      agent {
        docker {
          image "${env.ECR_REGISTRY_URL}:latest"
          // The following args are aimed to workaround some issues with using Docker container as a Jenkins agent:
          // 1. Disable image entrypoint to let Jenkins verify container was started correctly using custom commands.
          // 2. Explicitly tell SBT locations for configs and local cache because Jenkins runs container using a
          //    custom user (with `-u 1000:1000`) and SBT cannot resolve these paths automatically.
          // 3. Set MaxMetaspaceSize to 1G due to OOM
          args " --entrypoint '' -v ${env.HOME}/.aws:/home/gradle/.aws -v ${env.WORKSPACE}:/app --ulimit nofile=15000:16192"
          reuseNode true
        }
      }
      stages {
        stage('Run the tests') {
          environment {
            REPORTSDIR = "/app/${env.REPORTSDIR_SHORT}"
          }
          steps {
            sh '''
            unset AWS_ROLE_ARN
            unset AWS_CREDS_JSON
            unset AWS_DEFAULT_REGION
            unset AWS_ACCESS_KEY_ID
            unset AWS_SECRET_ACCESS_KEY
            unset AWS_SESSION_TOKEN
            set +x
            echo "=== Debug Limits ========"
            ulimit -a
            echo "========================="
            #export  AWS_ROLE_ARN="$(aws configure get ${AWS_ASSUME_PROFILE}.role_arn)"
            export  AWS_ROLE_ARN="arn:aws:iam::475275892927:role/cross_account_autotest_role"
            export  AWS_CREDS_JSON="$(aws sts assume-role --output json --role-arn ${AWS_ROLE_ARN} --duration-seconds 22000 --role-session-name session-${AWS_ASSUME_PROFILE})"
            export  AWS_DEFAULT_REGION="$(aws configure get ${AWS_ASSUME_PROFILE}.region)"
            export  AWS_ACCESS_KEY_ID="$(echo ${AWS_CREDS_JSON} | jq -r .Credentials.AccessKeyId)"
            export  AWS_SECRET_ACCESS_KEY="$(echo ${AWS_CREDS_JSON} | jq -r .Credentials.SecretAccessKey)"
            export  AWS_SESSION_TOKEN="$(echo ${AWS_CREDS_JSON} | jq -r .Credentials.SessionToken)"
            aws sts get-caller-identity
            set -x
            ./gradlew clean ${GRADLE_TARGET} -P"delphi.env.run=${ENVIRONMENT}" -P"delphi.env.run.testNg.groups=${TESTNG_GROUPS}" -P"delphi.api.host=${HOST}" | tee runtime.log
            set +x
            if [ -d * ./build/allure-result/ ];
                then
                    echo "====== DEBUG: allure results exists"
                    ./gradlew _0copyAllureCategories
                else
                    echo "====== DEBUG: allure results NOT exists"
            fi
            '''
            script {
              test_status = sh(script: "cat runtime.log", returnStdout: true).trim()
            }
            sh '''
              if echo ${GRADLE_TARGET} | grep "JavaApi" > /dev/null ; then
                yes | cp -rf $WORKSPACE/src/test/resources/categories.json $WORKSPACE/build/allure-results/
                ./openapi/1_download_java_api_latest_as_openapi_3_yaml.sh &&
                ./openapi/2_download_swagger_coverage_commandline_tool_latest.sh &&
                ./openapi/3_convert_openapi_3_yaml_2_openapi_2_json.sh &&
                ./openapi/4_generate_java_api_coverage_from_swagger_2.sh
              else
                echo "INFO: GRADLE_TARGET=${GRADLE_TARGET} is not related to JavaApi, skipping report pre-processing..."
              fi
            '''
          }
        }
      }
    }
  }
  post {
    always {
      sh "sudo chown -R ec2-user:ec2-user ${env.WORKSPACE}"
      script{
        allure([
          includeProperties: false,
          jdk: '',
          properties: [],
          reportBuildPolicy: 'ALWAYS',
          results: [[path: "build/allure-results"]]
        ])
      }
      archive includes: 'swagger-coverage-report.html'
//       script{
//         publishHTML (target : [allowMissing: false,
//                                alwaysLinkToLastBuild: true,
//                                keepAll: true,
//                                reportDir: './',
//                                reportFiles: 'swagger-coverage-report.html',
//                                reportName: 'swagger-coverage-report',
//                                reportTitles: 'swagger-coverage-report'])
//       }
    }
    success {
      slackSend (
        channel: "${env.NOTIFICATIONS_CHANNEL}",
        iconEmoji: ':rocket:',
        color: "good",
        message: "Environment: ${params.ENVIRONMENT} <${env.BUILD_URL}/allure/|${env.JOB_NAME}>\n${test_status}"
      )
    }
    unsuccessful {
      slackSend (
        channel: "${env.NOTIFICATIONS_CHANNEL}",
        iconEmoji: ':flying_saucer:',
        color: "danger",
        message: "Environment: ${params.ENVIRONMENT} <${env.BUILD_URL}/allure/|${env.JOB_NAME}>\n${test_status}"
      )
    }
  }
}
