@Library('infraLib') _

pipeline {
  agent {
    label 'linux-agents-xlarge'
  }

  options {
    timeout(time: 20, unit: 'MINUTES')
  }

  environment {
    PROJECT_GROUP = "delphi"
    OCTOPUS_CLI_SERVER = "https://octopus.delphi.zone"
    OCTOPUS_CLI_API_KEY = sh(script: "aws secretsmanager get-secret-value --profile sme-dev --secret-id 'infra/jenkins/octopus_api_key' --output json | jq .SecretString | tr -d '\"'", , returnStdout: true).trim()
    OCTOPUS_CHANNEL = octopus.setOctoChannel(env.BRANCH_NAME)
    OCTOPUS_PROJECT = "delphi.etl-conversion"
    DEPLOY_ENV = octopus.setDeploymentEnv(params.DEPLOY_ENV_CHOICE, env.PROJECT_GROUP, env.BRANCH_NAME)
    NOTIFICATIONS_CHANNEL = 'delphi-etl-cicd-alerts'
  }

  parameters {
    choice(
        choices: [
            'default',
            'yes',
            'no',
        ],
        description: '''Whether to trigger creation of octopus release.
                By default it\'s only triggered for develop, release* and master branches.
                ''',
        name: 'TRIGGER_DEPLOY'
    )
    choice(
        choices: [
            'default',
            'dev',
            'qa',
            'stage',
            'skip_deployment'
        ],
        description: 'Set environment for deployment. Skipped by default for master/release*, dev by default for all other branches',
        name: 'DEPLOY_ENV_CHOICE'
    )
    booleanParam(
      defaultValue: true,
      description: "Fail if release with the same version already exists in Octopus",
      name: 'FAIL_IF_RELEASE_EXISTS'
    )
    booleanParam(
      defaultValue: true,
      description: "Publish artifact to nexus repository",
      name: 'PUBLISH_ARTIFACT'
    )
  }

  stages {

    stage('Docker login') {
      environment { AWS_PROFILE="sme-dev" }
      steps {
        sh '$(aws ecr get-login --no-include-email --region us-east-1)'
      }
    }

    stage('Set Maven credentials') {
      steps {
        script {
          nexus.generateAuthorizedMavenConfig("./.credentials")
        }
      }
    }

    stage('Docker stage') {

      agent {
        docker {
          image '475275892927.dkr.ecr.us-east-1.amazonaws.com/sbt:1.3.3'
          // 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 "" -e JAVA_OPTS="-Dsbt.color=false -Dsbt.global.base=.sbt -Dsbt.boot.directory=.sbt -Dsbt.ivy.home=.ivy2 -XX:MaxMetaspaceSize=1G -Xmx2G"'
          reuseNode true
        }
      }

      stages {
        stage('Export SBT Settings') {
          steps {
            script {
              def (version, normalizedName, organization, scalaBinaryVersion) = sh(
                script: "sbt -Dsbt.supershell=false -error 'print version normalizedName organization scalaBinaryVersion' | awk 'NR%2==0' | xargs",
                returnStdout: true
              ).split(" ")

              env.BUILD_VERSION = version
              env.PACKAGE_ID = organization + ':' + normalizedName + '_' + scalaBinaryVersion
            }
          }
        }

        stage('Style Check') {
          steps { sh 'sbt validate' }
        }

        stage('Test') {
          steps { sh 'sbt coverage test' }
        }

        stage("Coverage") {
          steps { sh 'sbt coverageReport' }
        }

        stage('Publish') {
          when {
            expression { params.PUBLISH_ARTIFACT }
            anyOf {
              // publish from `master`
              branch 'master'

              allOf {
                // publish RC versions only from the `release/*`
                branch 'release/*'
                expression { BUILD_VERSION ==~ /.*-RC[1-9]+[0-9]*$/ }
              }

              allOf {
                // publish SNAPSHOT versions from the `develop`
                anyOf {
                  branch 'develop'
                }
                expression { BUILD_VERSION ==~ /.*-SNAPSHOT$/ }
              }
            }
          }
          steps { sh 'sbt publish' }
        }
      }

      post {
        always {
          junit '**/target/test-reports/*.xml'

          recordIssues(
              enabledForFailure: false,
              tool: scala()
          )

          recordIssues(
              enabledForFailure: true,
              tool: checkStyle(pattern: '**/target/scalastyle-result.xml')
          )
        }

        success {
          step([
            $class: 'ScoveragePublisher',
            reportDir: 'target/scala-2.12/scoverage-report',
            reportFile: 'scoverage.xml']
          )
        }

      }
    }

    stage('Git Tag') {
      when {
        branch 'master'
        expression {
            sshagent(['dna-ci']) {
                !sh(returnStdout: true, script: "git ls-remote origin refs/tags/v${env.BUILD_VERSION}")?.trim()
            }
        }
      }
      steps {
          sshagent(['dna-ci']) {
            sh "git tag v${env.BUILD_VERSION}"
            sh 'git push --tags'
          }
      }
    }

    stage("Octopus release") {
      steps {
        script {
          def pipelineParams = scalaPackage
            .setScalaPipelineParams(
              env.OCTOPUS_PROJECT,
              env.PACKAGE_ID,
              env.BUILD_VERSION,
              params.TRIGGER_DEPLOY,
              params.FAIL_IF_RELEASE_EXISTS)

          scalaPackage.scalaPipeline(pipelineParams)
        }
      }
    }
  }

  post {
    failure {
      script {
        utility.slackNotifyMainBranches(currentBuild.currentResult, env.NOTIFICATIONS_CHANNEL)
      }
    }
  }
}
