@Library('infraLib') _

pipeline {
  agent {
    label 'linux-agents-2xlarge'
  }
  options {
    timeout(time: 40, 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 gdb-delphi-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-apps"
    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="gdb-delphi-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"'
          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('Scalastyle') {
          steps { sh 'sbt scalastyle test:scalastyle scalafmtCheckAll' }
        }

        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 publishWithPom' }
        }
      }

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

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

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

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

    stage('Git Tag') {
      when {
        branch 'master'
        expression {
            sshagent(['theorchard-ci-ssh-key']) {
                !sh(returnStdout: true, script: "git ls-remote origin refs/tags/v${env.BUILD_VERSION}")?.trim()
            }
        }
      }
      steps {
          sshagent(['theorchard-ci-ssh-key']) {
            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)
      }
    }
  }
}
