#! /usr/bin/groovy

final String NODE_LABEL = "h2o-3"
final String DOCKER_STASH = 'h2o-3-k8s-docker-stash'
final String REGISTRY_PREFIX = "${params.dockerRegistry}"
final String IMAGE_NAME_PREFIX = "opsh2oai/h2o-3-k8s"
final String IMAGE_NAME_PREFIX_RUNNER = "opsh2oai/h2o-3-k8s-runner"

def pipelineContext = null
def version = null

properties(
    [
        parameters(
            [
                string(defaultValue: 'master', description: 'Branch to checkout', name: 'gitBranch'),
                string(name: 'dockerRegistry', defaultValue: 'harbor.h2o.ai'),
                booleanParam(name: 'force', defaultValue: false, description: 'If false and image with version specified by BuildConfig exists in repository, then the build fails.'),
                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('.', '', scmEnv, true)

        try {
            version = pipelineContext.getBuildConfig().getK8STestImageVersion()
            currentBuild.displayName += " v${version}"

            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>Version:</strong> ${version}</li>
                <li><strong>Force Overwrite:</strong> ${params.force}</li>
                <li><strong>No cache:</strong> ${params.noCache}</li>
                </ul>
            """)

            pipelineContext.getUtils().stashFiles(this, DOCKER_STASH, 'docker/hadoop/**,docker/scripts/*,docker/jenkins-images/*')

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

    final String buildStageName = "Build [${IMAGE_NAME_PREFIX}, ${IMAGE_NAME_PREFIX_RUNNER}]"
    final String imageName = "${IMAGE_NAME_PREFIX}"
    final String imageNameRunner = "${IMAGE_NAME_PREFIX_RUNNER}"
    final String noCache = params.noCache ? "--no-cache" : ""
    
    stage(buildStageName) {
        try {
            pipelineContext.getBuildSummary().addStageSummary(this, buildStageName, '')
            pipelineContext.getBuildSummary().setStageDetails(this, buildStageName, env.NODE_NAME, env.WORKSPACE)

            boolean conflict = pipelineContext.getUtils()
                    .dockerImageExistsInRegistry(this, params.dockerRegistry, imageName, version)
            if (conflict && !params.force) {
                error "Tag ${imageName}:${version} already exists in the repository"
            }
            
            boolean conflictRunner = pipelineContext.getUtils()
                    .dockerImageExistsInRegistry(this, params.dockerRegistry, imageNameRunner, version)
            if (conflictRunner && !params.force) {
                error "Tag ${imageNameRunner}:${version} already exists in the repository"
            }

            dir("${imageName}.${version}") {
                pipelineContext.getUtils().unstashFiles(this, DOCKER_STASH)
                sh """
                    cd docker
                    pwd
                    ls

                    docker build \
                        ${noCache} \
                        -t ${REGISTRY_PREFIX}/${imageName}:${version} \
                        -f jenkins-images/Dockerfile-k8s-test \
                    .
                """
            }
            
            dir("${imageNameRunner}.${version}") {
                pipelineContext.getUtils().unstashFiles(this, DOCKER_STASH)
                sh """
                    cd docker
                    pwd
                    ls

                    docker build \
                        ${noCache} \
                        -t ${REGISTRY_PREFIX}/${imageNameRunner}:${version} \
                        -f jenkins-images/Dockerfile-k8s-test-h2o \
                    .
                """
            }
            pipelineContext.getBuildSummary().markStageSuccessful(this, buildStageName)
        } catch (Exception e) {
            pipelineContext.getBuildSummary().markStageFailed(this, buildStageName)
            throw e
        }
    }

    final String publishStageName = "Publish [${imageName}:${version}, ${imageNameRunner}:${version}]"
    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 ${REGISTRY_PREFIX}/${imageName}:${version}
                """
                echo "###### Docker image ${imageName}:${version} built and pushed. ######"
                
                sh """
                    docker login -u $REGISTRY_USERNAME -p $REGISTRY_PASSWORD ${params.dockerRegistry}
                    docker push ${REGISTRY_PREFIX}/${imageNameRunner}:${version}
                """
                echo "###### Docker image ${imageName}:${version} built and pushed. ######"
            }
            pipelineContext.getBuildSummary().markStageSuccessful(this, publishStageName)
        } catch (Exception e) {
            pipelineContext.getBuildSummary().markStageFailed(this, publishStageName)
            throw e
        }
    }
}
