#! /usr/bin/groovy

final String NODE_LABEL = "h2o-3"
final String DOCKER_STASH = 'h2o-3-xgb-docker-stash'
final String BUILD_TAG = '1'

def pipelineContext = null

properties(
    [
        parameters(
            [
                string(defaultValue: 'master', description: 'Branch to checkout', name: 'gitBranch'),
                string(name: 'dockerRegistry', defaultValue: 'harbor.h2o.ai'),
                booleanParam(name: 'noCache', defaultValue: false, description: 'If set to true, the docker image is built from scratch, with no stages used from the cache.')
            ]
        )
    ]
)

node (NODE_LABEL) {
    final String stageName = 'Checkout and Prepare'
    stage (stageName) {
        def scmEnv = git credentialsId: 'c6bab81a-6bb5-4497-9ec9-285ef5db36ea',
                poll: false,
                url: 'https://github.com/h2oai/h2o-3',
                branch: params.gitBranch

        def pipelineContextFactory = load('scripts/jenkins/groovy/pipelineContext.groovy')
        pipelineContext = pipelineContextFactory('.', 'MODE_HADOOP', scmEnv, true)

        try {
            pipelineContext.getBuildSummary().addStageSummary(this, stageName, '')
            pipelineContext.getBuildSummary().setStageDetails(this, stageName, env.NODE_NAME, env.WORKSPACE)

            pipelineContext.getBuildSummary().addSection(this, 'docker-details', "<a href=\"${currentBuild.rawBuild.getAbsoluteUrl()}\" style=\"color: black;\">Details</a>", """
                <ul>
                <li><strong>Git Branch:</strong> ${env.BRANCH_NAME}</li>
                <li><strong>No cache:</strong> ${params.noCache}</li>
                </ul>
            """)

            dir('docker') {
                withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'AWS S3 Credentials', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) {
                    docker.image('harbor.h2o.ai/opsh2oai/s3cmd').inside("-e AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} -e AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}") {
                        sh "s3cmd -f get s3://artifacts.h2o.ai/releases/oracle/jdk-8/x64-linux/jdk1.8.0_171.zip"
                    }
                }
            }
            pipelineContext.getUtils().stashFiles(this, DOCKER_STASH, 'docker/xgb/**,docker/xgb_build/**,docker/scripts/*,docker/jdk1.8.0_171.zip')
            
            pipelineContext.getBuildSummary().markStageSuccessful(this, stageName)
        } catch (Exception e) {
            pipelineContext.getBuildSummary().markStageFailed(this, stageName)
            throw e
        }
    }
}

final String noCache = params.noCache ? "--no-cache" : ""

parallel(pipelineContext.getBuildConfig().getSupportedXGBEnvironments().collectEntries { osName, xgbEnvs ->
    [
        "Build Images for ${osName}", {
            node(pipelineContext.getBuildConfig().getDefaultNodeLabel()) {
                xgbEnvs.each {xgbEnv ->
                    final String buildStageName = "Build ${xgbEnv.name}"
                    stage(buildStageName) {
                        try {
                            pipelineContext.getBuildSummary().addStageSummary(this, buildStageName, '')
                            pipelineContext.getBuildSummary().setStageDetails(this, buildStageName, env.NODE_NAME, env.WORKSPACE)

                            pipelineContext.getUtils().unstashFiles(this, DOCKER_STASH)

                            dir('docker') {
                                sh """
                                docker build \
                                    ${noCache} \
                                    -t ${pipelineContext.getBuildConfig().getXGBImageForEnvironment(osName, xgbEnv, BUILD_TAG)} \
                                    -f ${xgbEnv.dockerfile} \
                                    --build-arg FROM_IMAGE=${xgbEnv.fromImage} \
                                    --build-arg H2O_BRANCH=${params.gitBranch} \
                                    .
                                """
                            }

                            pipelineContext.getBuildSummary().markStageSuccessful(this, buildStageName)
                        } catch (Exception e) {
                            pipelineContext.getBuildSummary().markStageFailed(this, buildStageName)
                            throw e
                        }
                    }

                    final String publishStageName = "Publish ${xgbEnv.name}"
                    stage(publishStageName) {
                        try {
                            pipelineContext.getBuildSummary().addStageSummary(this, publishStageName, '')
                            pipelineContext.getBuildSummary().setStageDetails(this, publishStageName, env.NODE_NAME, env.WORKSPACE)

                            withCredentials([usernamePassword(credentialsId: "${params.dockerRegistry}", usernameVariable: 'REGISTRY_USERNAME', passwordVariable: 'REGISTRY_PASSWORD')]) {
                                sh """
                                    docker login -u $REGISTRY_USERNAME -p $REGISTRY_PASSWORD ${params.dockerRegistry}
                                    docker push ${pipelineContext.getBuildConfig().getXGBImageForEnvironment(osName, xgbEnv, BUILD_TAG)}
                                """
                                echo "###### Docker image ${pipelineContext.getBuildConfig().getXGBImageForEnvironment(osName, xgbEnv, BUILD_TAG)} built and pushed. ######"
                            }

                            pipelineContext.getBuildSummary().markStageSuccessful(this, publishStageName)
                        } catch (Exception e) {
                            pipelineContext.getBuildSummary().markStageFailed(this, publishStageName)
                            throw e
                        }
                    }
                }
            }
        }
    ]
})
