@Library('nf-jenkins-shared-libraries')_  

def slavepool = "slave01 slave02 master"
def SLEEP = 5
def repo = "network"
def services = ["data", "engine", "infra", "edge"]
def changedFrameworks=["processor"]
def specialfiles = [ "Jenkinsfile" ]
def changedProjects = ["data", "engine", "infra", "edge"]
MVN_HOME='mvn_local_repository'


pipeline {
    agent any
    environment {
        DOCKER_HUB = credentials('dockerhub')
        SONAR_CLOUD = credentials('sonar')
        X_RAY = credentials("x_ray_user")
        BITBUCKET_AUTH = credentials('bitbucket_auth')
        SRCCLR_API_TOKEN = credentials('SRCCLR_API_TOKEN')
    }
    tools {
        maven 'apache-maven-3.6.0'
    }
    stages {
        stage('Detect Changes') {
            steps {
                script {
                    echo "Running on ${NODE_NAME}"
                    bitbucketStatus repo: "${repo}", BRANCH_NAME: "${BRANCH_NAME}", GIT_COMMIT: "${GIT_COMMIT}", status: "INPROGRESS"
                    changedFrameworks = gitDetectChanges changeset: ["processor"], opts: "egrep / | awk -F/ '{print \$1;}' | sort -u"
                    changedProjects = gitDetectChanges changeset: services, opts: "egrep / | awk -F/ '{print \$1;}' | sort -u"
                    changedSpecialFiles = gitDetectChanges changeset: specialfiles, opts: "sort -u"
                    println "Changed Frameworks:- ${changedFrameworks}"
                    println "Changed Projects:- ${changedProjects}"
                    println "Changed Special Files:- ${changedSpecialFiles}"
                    changedProjects = services
                    if( changedFrameworks == ["processor"]) {
                        changedProjects = services
                    }
                    if(BRANCH_NAME == "develop" || BRANCH_NAME ==~ /(release.*|bugfix.*|hotfix.*)/) {
                        changedProjects = services
                    }
                    sh "mkdir -p ${MVN_HOME}/${BUILD_NUMBER}"
                    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"
                    }
                }
            }
        }
        
        stage('Build Processor') {
            steps {
                script {
                    dir("processor") {
                        sh "export JAVA_HOME=/usr/lib/jvm/java-11-amazon-corretto.x86_64/; mvn -Dmaven.repo.local=../${MVN_HOME}/${BUILD_NUMBER} clean install"
                        sh "export JAVA_HOME=/usr/lib/jvm/java-11-amazon-corretto.x86_64/; mvn -T 2 sonar:sonar -Dmaven.repo.local=../${MVN_HOME}/${BUILD_NUMBER} -Dsonar.host.url=https://sonarcloud.io "+
                            "-Dsonar.organization=netfoundry -Dsonar.projectName=processor "+
                            "-Dsonar.branch.name=${BRANCH_NAME} -Dsonar.login=${SONAR_CLOUD_PSW}"
                    }
                }
            }
        }

        stage('Build Services') {
            steps {
                script {
                    def buildServices = [:]
                    for( String service: changedProjects) {
                        def serviceStep = "${service}"
                        buildServices[serviceStep] = { ->
                            dir("${serviceStep}") {
                                sh "export JAVA_HOME=/usr/lib/jvm/java-11-amazon-corretto.x86_64/; mvn -Dmaven.repo.local=../${MVN_HOME}/${BUILD_NUMBER} -T 2 clean install"
                            }
                        }
                    }
                    parallel buildServices
                }
            }
        }
/*
        stage('Xray Scan'){
            when { expression { BRANCH_NAME == "develop" }}
            steps{
                script {
                    x_ray X_RAY_USR: "${X_RAY_USR}", X_RAY_PSW: "${X_RAY_PSW}", BUILD_NAME: "${repo}", BUILD_NUMBER: "${BUILD_NUMBER}", JOB_NAME: "${env.JOB_NAME}"
                }
            }
        }
*/
        stage('Sonar') {
            steps {
                script {
                    def buildSonar = [:]
                    for( String sonar: changedProjects) {
                        def serviceStep = "${sonar}"
                        buildSonar[serviceStep] = { ->
                            dir("${serviceStep}") {
                                sh "export JAVA_HOME=/usr/lib/jvm/java-11-amazon-corretto.x86_64/; mvn -T 2 sonar:sonar -Dmaven.repo.local=../${MVN_HOME}/${BUILD_NUMBER} -Dsonar.host.url=https://sonarcloud.io "+
                                "-Dsonar.organization=netfoundry -Dsonar.projectName=${serviceStep} "+
                                "-Dsonar.branch.name=${BRANCH_NAME} -Dsonar.login=${SONAR_CLOUD_PSW}"
                            }
                        }
                    }
                    parallel buildSonar
                }
            }
        }
        stage('JUnit') {
            steps {
                script {
                    def buildServices = [:]
                    for( String service: changedProjects) {
                        def serviceStep = "${service}"
                        buildServices[service] = { ->
                            dir("${serviceStep}") {
                                junitParse services: [serviceStep], parallelize: false, dir: "", xml: "target/surefire-reports/*.xml"
                            }
                        }
                    }
                    parallel buildServices
                }
            }
        }

        stage('Artifactory') {
            when { expression { BRANCH_NAME == "develop" || BRANCH_NAME ==~ /(release.*)/ }}
            steps {
                script {
                    def buildServices = [:]
                    for( String service: changedProjects) {
                        def serviceStep = "${service}"
                        buildServices[serviceStep] = { ->
                            dir("${serviceStep}") {
                                if( BRANCH_NAME == "develop") {
                                    artifactory REPO: "${serviceStep}",  BUILDPATH: "../${MVN_HOME}/${BUILD_NUMBER}"
                                    artifactoryVeracode REPO: "${serviceStep}",  BUILDPATH: "../${MVN_HOME}/${BUILD_NUMBER}", ACTION: "upload"
                                }
                            }
                        }
                    }
                    buildServices["processor"] = { ->
                        dir("processor") {
                            if( BRANCH_NAME == "develop") {
                                artifactory REPO: "processor",  BUILDPATH: "../${MVN_HOME}/${BUILD_NUMBER}"
                                artifactoryVeracode REPO: "processor",  BUILDPATH: "../${MVN_HOME}/${BUILD_NUMBER}", ACTION: "upload"
                            }
                        }
                    }
                    parallel buildServices
                }
            }
        }

        stage('Docker') {
            when { expression { BRANCH_NAME == "develop" || BRANCH_NAME ==~ /(release.*)/ || BRANCH_NAME ==~ /(hotfix.*)/ }}
            steps {
                script {
                    def buildServices = [:]
                    for( String service: services) {
                        def serviceStep = "${service}"
                        buildServices[serviceStep] = { ->
                            dir("${serviceStep}") {
                                buildDocker REPO: "${serviceStep}", GIT_COMMIT: "${GIT_COMMIT}", BUILD_NUMBER: "${BUILD_NUMBER}", BRANCH_NAME: "${BRANCH_NAME}"
                                veracodeContainerScan REPO: "${serviceStep}"
                            }
                            try {
                                sh "docker rmi netfoundry/${serviceStep}:${GIT_COMMIT}"
                                sh "docker rmi netfoundry/${serviceStep}:sandbox"
                                sh "docker rmi netfoundry/${serviceStep}:latest"
                            } catch(err) {
                                echo "Docker images cleanup not done: ${err}"
                            }
                        }
                    }
                    parallel buildServices
                }
            }
        }

        stage('Terraform'){
            when { expression { BRANCH_NAME == "develop"  }}
            steps {
                script { 
                    def buildServices = [:]
                    for( String service: services) {
                        def serviceStep = "${service}"
                        buildServices[serviceStep] = { ->
                            dir("${serviceStep}") {
                                terraform directory: "terraform", environment: "sandbox", auth_env: "../../auth-env.sh"
                            }
                        }
                    }
                    parallel buildServices
                }
            }
        }

        stage('Deployment') {
            when { expression { BRANCH_NAME == "develop" }}
            steps {
                script {
                    withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', credentialsId: "aws_sandbox", variable: 'AWS_ACCESS_KEY_ID']]) {
                        def buildServices = [:]
                        for( String service: services) {
                            def serviceStep = "${service}"
                            buildServices[serviceStep] = { ->
                                sh "ecs deploy --region us-east-1 --timeout 600 ecs-cluster-nfn-internal-env-private ecs-${serviceStep}-service"
                            }
                        }
                        parallel buildServices
                    }
                }
            }
        }

        stage('Promote to Staging') {
            when { expression { BRANCH_NAME == "develop" }}
            steps {
                script {
                    build_job = build job: 'Continous_Deployment_Env_Testing', parameters: [
                        [$class: 'StringParameterValue', name: 'branch', value: "${GIT_COMMIT}"],
                        [$class: 'StringParameterValue', name: 'REPO', value: "${repo}"],
                        [$class: 'StringParameterValue', name: 'environment', value: "staging"],
                        [$class: 'BooleanParameterValue', name: 'promote', value: true],
                        [$class: 'BooleanParameterValue', name: 'slack_notify', value: true],
                    ], propagate: false, wait: false
                }
            }
        }

        stage("Deploy RapidAPI") {
            when { expression { BRANCH_NAME == "develop" }}
            steps {
                script {
                    try {
                        build_job = build job: 'DeployRapidAPI', 
                                    parameters: [[ $class: 'StringParameterValue', name: 'deployment_environment', value: "sandbox" ]],
                                    propagate: true, 
                                    wait: false
                    } catch(e) {
                        error("RapidAPI Deploy Failed with error: ${e}")
                    }
                }
            }
        }
    }

    post {
        always {
            sh "rm -rf ${MVN_HOME}/${BUILD_NUMBER}"
        }
        aborted {
            bitbucketStatus repo: "${repo}", BRANCH_NAME: BRANCH_NAME, GIT_COMMIT: GIT_COMMIT, status: "STOPPED"
        }
        failure {
            bitbucketStatus repo: "${repo}", BRANCH_NAME: BRANCH_NAME, GIT_COMMIT: GIT_COMMIT, status: "FAILED"
            mattermostFailureNotification repo: "${repo}", commit: GIT_COMMIT, build_url: RUN_DISPLAY_URL
        }
        success {
            bitbucketStatus repo: "${repo}", BRANCH_NAME: BRANCH_NAME, GIT_COMMIT: GIT_COMMIT, status: "SUCCESSFUL"
        }
    }
}
