@Library('nf-jenkins-shared-libraries@master')_
import org.apache.commons.lang3.StringUtils;
import jenkins.model.Jenkins
import hudson.model.*
import hudson.tasks.test.*
import groovy.xml.XmlUtil
import org.json.JSONObject
import org.json.XML

service_repo = []
IGNORE_TITLES = []

kibana_url = ""
smoketest_url = ""
artifact_link = ""
sonar_link = ""
failure_msg = ""
sandbox_image = ""
stage_name = ""

failure = false
blocking = true
send_notification = true
sonar_alert = false
killed_running_job = false
set_kibana_url = false
set_affected_service = false
set_smoketest_url = false
set_artifact_url = false
affected_service = null
flywaymigration_detected = false

pipeline {
    agent {
        dockerfile {
            filename 'jenkinsfiles/utilities/Dockerfile'
            args '-u jenkins -v /var/run/docker.sock:/var/run/docker.sock -v /home/jenkins/.m2:/home/jenkins/.m2 --privileged'
            label "slave02"
        }
    }

    environment {
        BITBUCKET_AUTH = credentials('bitbucket_auth')
        BITBUCKET_ADMIN = credentials('bitbucket_admin')
        DOCKER_HUB = credentials('dockerhub')
        RANCHER_TOKEN = credentials('rancher_dev_token')
    }

    stages {
        stage('Initialize') {
            steps {
                script {
                    stage_name = env.STAGE_NAME
                    bb_request = readJSON text: bb_request_raw
                    REPO = bb_request.pullrequest.source.repository.full_name.split("/")[1]
                    BB_COMMENTS_URL="${bb_request.pullrequest.links.comments.href}"
                    BB_APPROVE_URL="${bb_request.pullrequest.links.approve.href}"
                    BB_DECLINE_URL="${bb_request.pullrequest.links.decline.href}"
                    BB_BRANCH="${bb_request.pullrequest.source.branch.name}"
                    BB_DESTINATION_BRANCH="${bb_request.pullrequest.destination.branch.name}"
                    COMMIT_HASH = "${bb_request.pullrequest.source.commit.hash}"
                    DESCRIPTION="Branch: ${BB_BRANCH} REPO: ${REPO}"

                    // Set Description
                    currentBuild.description = "${DESCRIPTION}"

                    //fetch constants
                    pr_const = readYaml text: libraryResource("pr_builds/const_vars.yaml")

                    MOP_LIBRARIES = pr_const["MOP_LIBRARIES"]
                    SONAR_EXEMPTION = pr_const["SONAR_EXEMPTION"]
                    MVN_HOME = pr_const["MVN_HOME"]
                    JAVA_HOME='/usr/local/jdk-17/'
                    CLUSTER_NAME = pr_const["CLUSTER_NAME"]
                    HELM_TIMEOUT = pr_const["HELM_TIMEOUT"]
                    helm_verbose_level = pr_const["helm_verbose_level"]
                    prenv = pr_const["prenv"]
                    channel = pr_const["channel"]
                    log_lines_capture = pr_const["log_lines_capture"]
                    update_jenkins_build = pr_const["update_jenkins_build"]

                    service_repo = readYaml text: libraryResource("pr_builds/service_repo_list.yaml")
                    IGNORE_TITLES = readYaml text: libraryResource("pr_builds/ignore_titles.yaml")

                    for(String ignoreStr: IGNORE_TITLES) {
                        if(bb_request.pullrequest.rendered.title.raw.toUpperCase().contains("${ignoreStr}")) {
                            failure_msg = "ignore"
                            send_notification = false
                            error "Build ignored as it starts with ${ignoreStr}"
                        }
                    }

                    //Enable build container auth to Bitbucket
                    enableContainerAuthToBitbucket()
                }
            }
        }

        stage('ChangeSet'){
            steps {
                script {
                    stage_name = env.STAGE_NAME
                    git_diff(REPO, BB_BRANCH)

                    // Check that destination branch
                    if(BB_DESTINATION_BRANCH != "develop") {
                        failure_msg = "ignore"
                        error "Only builds PR with destination branch as develop"
                    }

                    //detect flyway changes
                    flywaymigration_detected = gitDetectFlywayChanges()

                    bitbucketStatus repo: "${REPO}", BRANCH_NAME: BB_BRANCH, GIT_COMMIT: COMMIT_HASH, status: "INPROGRESS", PR_CHECK: "false", BUILD_NAME: "Jenkins PR Build"
                }
            }
        }

        stage('Build') {
            steps {
                script {
                    stage_name = env.STAGE_NAME
                    check_dependency("${REPO}", "${REPO}", MOP_LIBRARIES)
                    dir("${MVN_HOME}/${BUILD_NUMBER}") {
                        sh "for dir in \$(ls \$HOME/.m2/repository/ | grep -v 'io'); do ln -s \$HOME/.m2/repository/\$dir \$dir; done"
                    }
                    sh "./mvnw -Dmaven.repo.local=${MVN_HOME}/${BUILD_NUMBER} -T 8 clean install"
                }
            }
        }

        stage('Sonar & Dependencies') {
            when { expression { newCheckAllowedServices(bb_request, SONAR_EXEMPTION, REPO) == true }}
            steps {
                script {
                    sh "./mvnw -Dmaven.repo.local=${MVN_HOME}/${BUILD_NUMBER} -DskipTests dependency-check:check xml:transform"
                }
                script {
                    stage_name = env.STAGE_NAME
                    JAVA_HOME = "${JAVA_HOME}/"
                    sonar_link = check_sonar_quality_gate_mvnw(bb_request, SONAR_EXEMPTION, REPO, BB_BRANCH, MVN_HOME, JAVA_HOME)
                    if( sonar_link != "") {
                        sonar_alert = true
                        error "Sonar Analysis failed. Link -> ${sonar_link}"
                    }
                }
            }
        }

        stage('Flyway Migration') {
            when { expression {flywaymigration_detected == true}}
            steps {
                script {
                    stage_name = env.STAGE_NAME
                    def build_job_result = build job: "flyway_migration_prbuilds", parameters: [
                        [$class: 'StringParameterValue', name: 'REPO', value: "${REPO}"],
                        [$class: 'StringParameterValue', name: 'environment', value: "${prenv}"],
                        [$class: 'StringParameterValue', name: 'BRANCH', value: "${BB_BRANCH}"]
                    ], propagate: true, wait: true
                }
            }
        }
    }

    post {
        always {
            script {
                echo "build completed"
                sh "rm -rf ${MVN_HOME}/${BUILD_NUMBER}"
            }
        }
        failure {
            script {
                failure_reason = "${stage_name} stage failed. ${failure_msg}"
                if (failure_msg != "ignore"){
                    bbReject(bb_request, REPO, BB_BRANCH, COMMIT_HASH, failure_reason, update_jenkins_build, affected_service, set_kibana_url, kibana_url, set_smoketest_url, smoketest_url, set_artifact_url, artifact_link, sonar_alert, sonar_link)
                }
                //Notification
                if(failure_msg != "ignore" && failure_msg != "org.jenkinsci.plugins.workflow.steps.FlowInterruptedException" && send_notification == true ){
                    pr_send_notification_message(bb_request, "${REPO}", failure_reason, channel, get_notification_links(bb_request, affected_service, set_kibana_url, kibana_url, set_smoketest_url, smoketest_url, set_artifact_url, artifact_link, sonar_alert, sonar_link))
                    currentBuild.rawBuild.@result = hudson.model.Result.FAILURE
                }
                if(failure_msg == "ignore") {
                    bitbucketStatus repo: "${REPO}", BRANCH_NAME: BB_BRANCH, GIT_COMMIT: COMMIT_HASH, status: "SUCCESSFUL", PR_CHECK: "false", BUILD_NAME: "Jenkins PR Build"
                    currentBuild.rawBuild.@result = hudson.model.Result.ABORTED
                }
            }
        }
        success {
            script {
                //Notification
                if (failure_msg != "ignore"){
                    bbApprove(bb_request, REPO, BB_BRANCH, COMMIT_HASH)
                }
                if(failure_msg == "ignore") {
                    bitbucketStatus repo: "${REPO}", BRANCH_NAME: BB_BRANCH, GIT_COMMIT: COMMIT_HASH, status: "SUCCESSFUL", PR_CHECK: "false", BUILD_NAME: "Jenkins PR Build"
                    currentBuild.rawBuild.@result = hudson.model.Result.ABORTED
                }
            }
        }
    }
}
