pipeline {
    agent { label 'linux && amd64' }
    options { 
        buildDiscarder(logRotator(numToKeepStr: '135', daysToKeepStr: '21'))
        gitLabConnection('GitLabConnectionJenkins')
    }

    environment {
        BUILD_OPTIONS = ''
        TESTS_PARALLEL = ''
        APIURL_TO_TEST = ''
    }

    stages {
        stage('clean previous runs and update gitlab commit status'){
            steps{
                deleteDir()
                updateGitlabCommitStatus(name: 'build & test linux', state: 'running')
            }
        }
        stage('Get parameters'){
            parallel{
                stage('Get build and run paramters'){
                    steps {
                        script{
                            BUILD_OPTIONS = sh(script: 'echo "$gitlabTriggerPhrase" | grep BUILD_OPTIONS | awk -F "BUILD_OPTIONS="  \'{print \$2}\' | cut -d"\\"" -f2 || :', returnStdout: true).trim()
                            TESTS_PARALLEL = sh(script: 'echo "$gitlabTriggerPhrase" | grep "\\-\\-sequence" >/dev/null 2>&1 && echo "" || echo "--INSTANCES:10"', returnStdout: true).trim()
                            println BUILD_OPTIONS
                            println TESTS_PARALLEL
                        }
                    }
                    post{
                        always {
                            script{                        
                                if (currentBuild.currentResult == 'FAILURE'){
                                    addGitLabMRComment(comment: ":red_circle: ${env.JOB_NAME} FAILURE when getting the additional build parameters :worried:<br/>Build results: [Jenkins [${env.JOB_NAME} ${env.BUILD_DISPLAY_NAME}]](${env.RUN_DISPLAY_URL})<br/>Commit: ${env.GIT_COMMIT}" )
                                }
                            }
                        }
                    }
                }

                stage('Get API URL'){
                    steps {
                        script{
                            APIURL_TO_TEST = sh(script: 'echo "$gitlabMergeRequestDescription" | grep USE_APIURL_TO_TEST | awk -F "USE_APIURL_TO_TEST="  \'{print \$2}\' | cut -d" " -f1', returnStdout: true).trim()
                            println APIURL_TO_TEST
                            if (APIURL_TO_TEST == ""){
                                APIURL_TO_TEST = "https://g.api.mega.co.nz/"
                                echo "APIURL_TO_TEST was not found on description so ${APIURL_TO_TEST} will be used by default"
                            }
                            echo "APIURL_TO_TEST will be ${APIURL_TO_TEST}"
                        }
                    }
                    post{
                        always {
                            script{                        
                                if (currentBuild.currentResult == 'FAILURE'){
                                    addGitLabMRComment(comment: ":red_circle: ${env.JOB_NAME} FAILURE when getting the SDK branch :worried:<br/>Build results: [Jenkins [${env.JOB_NAME} ${env.BUILD_DISPLAY_NAME}]](${env.RUN_DISPLAY_URL})<br/>Commit: ${env.GIT_COMMIT}" )
                                }
                            }
                        }
                    }
                }

            }
        }
                   
        stage('Checkout Linux'){
            steps {
                checkout([
                    $class: 'GitSCM', 
                    branches: [[name: "origin/${env.gitlabSourceBranch}"]],
                    userRemoteConfigs: [[ url: "${env.GIT_URL_SDK}", credentialsId: "12492eb8-0278-4402-98f0-4412abfb65c1" ]],
                    extensions: [
                        [$class: "UserIdentity",name: "jenkins", email: "jenkins@jenkins"],
                        [$class: 'PreBuildMerge', options: [fastForwardMode: 'FF', mergeRemote: "origin", mergeStrategy: 'DEFAULT', mergeTarget: "${env.gitlabTargetBranch}"]]
                        ]                        
                ])
                script{
                    linux_sources_workspace = WORKSPACE
                    //linux_build_agent = "${NODE_NAME}"
                }
            }
        }
        stage('Build Linux'){
            options{
                timeout(time: 120, unit: 'MINUTES')
            }
            steps{
                dir("${linux_sources_workspace}") {
                    sh "rm test_integration.log test_integration_*.gz || :"
                    sh "./clean.sh; mv sdk_build_keep sdk_build || :"
                    sh "./contrib/build_sdk.sh -b -g -f -I -i -s -n -z -o ${linux_sources_workspace}/3rd_pkgs -p ${linux_sources_workspace}/3rd_deps"
                    sh "rm ./3rd_deps/include/sqlite* ./3rd_deps/lib/libsqlite* || :"

                    //Build SDK
                    sh "echo Building SDK"                                   
                    sh "./autogen.sh"
                    sh "./configure --disable-silent-rules --enable-debug --enable-tests --enable-chat --with-gtest=/opt/gtest/gtest-1.10.0 --with-curl=${linux_sources_workspace}/3rd_deps \
                    --disable-curl-checks --enable-rotative-performance-logger --enable-werror ${BUILD_OPTIONS}"
                    sh "sed -i 's/#define ENABLE_LOG_PERFORMANCE 1//g' ./include/mega/config.h"
                    sh "make clean"
                    sh "make"

                    //Package megacli and megasimplesync to be archived
                    sh "echo Packaging megacli and megasimplesync to be archived"
                    sh "rm -r examples-* || :; mkdir examples-${BUILD_ID}"
                    sh "cp -r ./examples/.libs ./examples-${BUILD_ID}"
                    sh "cp -P ./src/.libs/libmega.so* ./examples-${BUILD_ID}/.libs/" 
                    sh "echo \"LD_LIBRARY_PATH=\\`dirname \\\$0\\`/.libs \\`dirname \\\$0\\`/.libs/megacli\" > examples-${BUILD_ID}/megacli"
                    sh "echo \"LD_LIBRARY_PATH=\\`dirname \\\$0\\`/.libs \\`dirname \\\$0\\`/.libs/megasimplesync\" > examples-${BUILD_ID}/megasimplesync"
                    sh "chmod +x examples-${BUILD_ID}/megacli && chmod +x examples-${BUILD_ID}/megasimplesync" 
                    sh "tar czf examples-${BUILD_ID}.tar.gz examples-${BUILD_ID}"
                }
            }
        }
        stage('Run Linux tests'){
            options{
                timeout(time: 250, unit: 'MINUTES')
            }
            environment {
                MEGA_PWD = credentials('MEGA_PWD_DEFAULT')
                MEGA_PWD_AUX = credentials('MEGA_PWD_DEFAULT')
                MEGA_PWD_AUX2 = credentials('MEGA_PWD_DEFAULT')
                MEGA_REAL_PWD=credentials('MEGA_REAL_PWD_TEST')
            }
            steps{
                lock(label: 'SDK_Concurrent_Test_Accounts', variable: 'ACCOUNTS_COMBINATION', quantity: 1, resource: null){    
                    dir("${linux_sources_workspace}") {
                        script{
                            env.MEGA_EMAIL = "${env.ACCOUNTS_COMBINATION}"
                            echo "${env.ACCOUNTS_COMBINATION}"
                        }
                        sh "echo Running tests"
                        sh """#!/bin/bash
                        set -x
                        ulimit -c unlimited
                        ./tests/test_unit || FAILED=1
                        
                        if [ -z \"\$FAILED\" ]; then
                            if [ -z \"${TESTS_PARALLEL}\" ]; then
                                # Sequential run
                                ./tests/test_integration --CI --USERAGENT:${env.USER_AGENT_TESTS} --APIURL:${APIURL_TO_TEST} &
                                pid=\$!
                                wait \$pid || FAILED=2
                            else
                                # Parallel run
                                ./tests/test_integration --CI --USERAGENT:${env.USER_AGENT_TESTS} --APIURL:${APIURL_TO_TEST} ${TESTS_PARALLEL} 2>&1 | tee tests.stdout
                                [ \"\${PIPESTATUS[0]}\" != \"0\" ] && FAILED=2
                            fi
                        fi
                        if [ -n \"\$FAILED\" ]; then
                            if [ \"\$FAILED\" -eq 1 ]; then
                                coreFiles=core
                            else # FAILED=2
                                if [ -z \"${TESTS_PARALLEL}\" ]; then
                                    # Sequential run
                                    coreFiles=\"pid_\$pid/core\"
                                else
                                    # Parallel run
                                    procFailed=`grep \"<< PROCESS\" tests.stdout | sed 's/.*PID:\\([0-9]*\\).*/\\1/'`
                                    if [ -n \"\$procFailed\" ]; then
                                        # Parallel run
                                        for i in \$procFailed; do
                                            coreFiles=\"\$coreFiles pid_\$i/core\"
                                        done
                                    fi
                                fi
                            fi
                            if [ -n \"\$coreFiles\" ]; then
                                maxTime=10
                                startTime=`date +%s`
                                coresProcessed=0
                                coresTotal=`echo \$coreFiles | wc -w`
                                # While there are pending cores
                                while [ \$coresProcessed -lt \$coresTotal ] && [ \$( expr `date +%s` - \$startTime ) -lt \$maxTime ]; do
                                    echo "Waiting for core dumps..."
                                    sleep 1
                                    for i in \$coreFiles; do
                                        if [ -e \"\$i\" ] && [ -z \"\$( lsof \$i 2>/dev/null )\" ]; then
                                            echo \"Processing core dump \$i :: \$(grep `echo \$i | sed 's#pid_\\([0-9].*\\)/core#\\1#'` tests.stdout)\"
                                            echo thread apply all bt > backtrace
                                            echo quit >> backtrace
                                            [ \"\$FAILED\" = \"1\" ] && gdb -q ./tests/.libs/test_unit \$i -x ${linux_sources_workspace}/backtrace
                                            [ \"\$FAILED\" = \"2\" ] && gdb -q ./tests/.libs/test_integration \$i -x ${linux_sources_workspace}/backtrace
                                            tar rf core.tar \$i
                                            coresProcessed=`expr \$coresProcessed + 1`
                                            coreFiles=`echo \$coreFiles | sed -e \"s#\$i##\"`
                                        fi
                                    done
                                done
                                if [ -e core.tar ]; then
                                    [ \"\$FAILED\" = \"1\" ] && tar rf core.tar -C ./tests/.libs test_unit
                                    [ \"\$FAILED\" = \"2\" ] && tar rf core.tar -C ./tests/.libs test_integration
                                    gzip core.tar
                                fi
                            fi
                        fi

                        gzip -c test_integration.log > test_integration_${BUILD_ID}.log.gz || :
                        rm test_integration.log || :
                        if [ -n \"\$FAILED\" ]; then
                            exit \"\$FAILED\"
                        fi
                        """
                    }
                }
            }
        }
    }            
    post{
        always {
            archiveArtifacts artifacts: 'test_integration*, examples-*.tar.gz, core.tar.gz', fingerprint: true
            script{
                if (currentBuild.currentResult == 'SUCCESS'){
                    addGitLabMRComment(comment: ":white_check_mark: ${currentBuild.projectName} :penguin: <b>Linux</b> SUCCEEDED :muscle:<br/>Build results: [Jenkins [${currentBuild.displayName}]](${currentBuild.absoluteUrl})<br/>Commit: ${env.GIT_COMMIT}" )
                    updateGitlabCommitStatus(name: 'build & test linux', state: 'success')
                }                                
                if (currentBuild.currentResult == 'FAILURE'){
                    addGitLabMRComment(comment: ":red_circle: ${currentBuild.projectName} :penguin: <b>Linux</b> FAILURE  :worried:<br/>Build results: [Jenkins [${currentBuild.displayName}]](${currentBuild.absoluteUrl})<br/>Commit: ${env.GIT_COMMIT}" )
                    updateGitlabCommitStatus(name: 'build & test linux', state: 'failed')
                }
                if (currentBuild.currentResult == 'ABORTED'){
                    addGitLabMRComment(comment: ":interrobang: ${currentBuild.projectName} :penguin: <b>Linux</b> ABORTED  :confused:<br/>Build results: [Jenkins [${currentBuild.displayName}]](${currentBuild.absoluteUrl})<br/>Commit: ${env.GIT_COMMIT}" )
                    updateGitlabCommitStatus(name: 'build & test linux', state: 'canceled')
                }                                
                if (currentBuild.currentResult == 'UNSTABLE'){
                    addGitLabMRComment(comment: ":interrobang: ${currentBuild.projectName} :penguin: <b>Linux</b> UNSTABLE  :confused:<br/>Build results: [Jenkins [${currentBuild.displayName}]](${currentBuild.absoluteUrl})<br/>Commit: ${env.GIT_COMMIT}" )
                    updateGitlabCommitStatus(name: 'build & test linux', state: 'failed')
                }
            }
        }
    }
}
