#!/usr/bin/env groovy

@Library('apm@current') _

pipeline {
  agent any
  environment {
    REPO = 'metricbeat-tests-poc'
    BASE_DIR = "src/github.com/elastic/${env.REPO}"
    NOTIFY_TO = credentials('notify-to')
    JOB_GCS_BUCKET = credentials('gcs-bucket')
  }
  options {
    timeout(time: 1, unit: 'HOURS')
    buildDiscarder(logRotator(numToKeepStr: '20', artifactNumToKeepStr: '20', daysToKeepStr: '30'))
    timestamps()
    ansiColor('xterm')
    disableResume()
    durabilityHint('PERFORMANCE_OPTIMIZED')
    rateLimitBuilds(throttle: [count: 60, durationName: 'hour', userBoost: true])
    quietPeriod(10)
  }
  triggers {
    issueCommentTrigger('(?i).*(?:jenkins\\W+)?run\\W+(?:the\\W+)?tests(?:\\W+please)?.*')
  }
  parameters {
    string(name: 'GO_VERSION', defaultValue: '1.12.7', description: "Go version to use.")
  }
  stages {
    stage('Initializing'){
      agent { label 'linux && immutable' }
      options { skipDefaultCheckout() }
      environment {
        HOME = "${env.WORKSPACE}"
        GOPATH = "${env.WORKSPACE}"
        GO_VERSION = "${params.GO_VERSION.trim()}"
        PATH = "${env.PATH}:${env.WORKSPACE}/bin:${env.WORKSPACE}/${env.BASE_DIR}/.ci/scripts"
        GO111MODULE = 'on'
        GOPROXY = 'https://proxy.golang.org'
      }
      stages {
        stage('Checkout') {
          steps {
            gitCheckout(basedir: BASE_DIR, githubNotifyFirstTimeContributor: true)
            stash allowEmpty: true, name: 'source', useDefaultExcludes: false
          }
        }
        stage('Tests') {
          parallel {
            stage('Sanity checks') {
              agent { label 'linux && immutable && docker' }
              environment {
                GOROOT = "${env.WORKSPACE}/.gimme/versions/go${env.GO_VERSION}.linux.amd64"
                PATH = "${env.WORKSPACE}/${env.BASE_DIR}/bin:${env.PATH}:${env.GOROOT}/bin"
              }
              options { skipDefaultCheckout() }
              steps {
                withGithubNotify(context: 'Sanity checks', tab: 'tests') {
                  deleteDir()
                  unstash 'source'
                  dir(BASE_DIR){
                    sh script: """.ci/scripts/install-dependencies.sh "${GO_VERSION}" """, label: 'Install dependencies'
                    preCommit(commit: "${GIT_BASE_COMMIT}", junit: true)
                  }
                }
              }
            }
            stage('Unit Tests') {
              agent { label 'linux && immutable' }
              options { skipDefaultCheckout() }
              steps {
                withGithubNotify(context: 'Tests', tab: 'tests') {
                  deleteDir()
                  unstash 'source'
                  dir(BASE_DIR){
                    sh script: """.ci/scripts/build-test.sh "${GO_VERSION}" """, label: 'Build and test'
                  }
                  stash allowEmpty: false, name: 'build', useDefaultExcludes: false, excludes: '.gimme/**'
                }
              }
              post {
                always {
                  junit(allowEmptyResults: true, keepLongStdio: true, testResults: "${BASE_DIR}/outputs/junit-*.xml")
                }
              }
            }
          }
        }
        stage('Release') {
          options { skipDefaultCheckout() }
          when { tag "v*" }
          steps {
            deleteDir()
            unstash 'source'
            dir("${BASE_DIR}") {
              script {
                def matrix = readYaml(file: '.ci/.package.yaml')
                def parallelTasks = [:]
                matrix['OSS'].each { oss ->
                  matrix['PLATFORM'].each { platform ->
                    parallelTasks["${oss}-${platform}"] = generateStep(oss: "${oss}", platform: "${platform}")
                  }
                }
                parallel(parallelTasks)
              }
            }
          }
        }
      }
    }
  }
  post {
    cleanup {
      notifyBuildResult(to: ['victor.martinez@elastic.co', 'manuel.delapena@elastic.co'])
    }
  }
}

def generateStep(Map params = [:]){
  def oss = params.get('oss')
  def platform = params.get('platform')
  return {
    node('docker && linux && immutable') {
      try {
        deleteDir()
        unstash 'build'
        dir("${BASE_DIR}/cli") {
          withEnv(["GOOS=${oss}", "GOARCH=${platform}"]) {
            sh script: 'make build', label: 'Create releases'
          }
        }
      } catch(e) {
        error(e.toString())
      } finally {
        archiveArtifacts allowEmptyArchive: true, artifacts: "${BASE_DIR}/cli/.github/releases/download/**"
      }
    }
  }
}
