pipeline {
    agent { label 'osx && arm64' }

    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 macOS', 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 macOS'){
            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{
                    mac_sources_workspace = WORKSPACE
                    sh "echo ${BUILD_OPTIONS}" 
                }
            }
        }
        stage('Build macOS'){
            options{
                timeout(time: 120, unit: 'MINUTES')
            }
            environment{
                PATH = "/usr/local/bin:${env.PATH}"
                VCPKGPATH = "${env.HOME}/jenkins/3rdparty"
                BUILD_DIR = "contrib/cmake/build_dir"
            }
            steps{
                dir(mac_sources_workspace){
                    sh "rm -rf ${BUILD_DIR}; mkdir ${BUILD_DIR}"

                    //Build SDK
                    sh "echo Building SDK"
                    sh "cmake -DENABLE_WERROR=1 -DENABLE_CHAT=1 -DCMAKE_BUILD_TYPE=Debug -DMega3rdPartyDir=${VCPKGPATH} ${BUILD_OPTIONS} -DCMAKE_VERBOSE_MAKEFILE=1 -DUSE_THIRDPARTY_FROM_VCPKG=1 \
                    -S ${mac_sources_workspace}/contrib/cmake -B ${mac_sources_workspace}/${BUILD_DIR}"
                    sh "cmake --build ${mac_sources_workspace}/${BUILD_DIR} --target Mega -j1"
                    sh "cmake --build ${mac_sources_workspace}/${BUILD_DIR} --target megacli -j1"
                    sh "cmake --build ${mac_sources_workspace}/${BUILD_DIR} --target megasimplesync -j1"
                    sh "cmake --build ${mac_sources_workspace}/${BUILD_DIR} --target test_unit -j1"
                    sh "cmake --build ${mac_sources_workspace}/${BUILD_DIR} --target test_integration -j1"
                    sh "cmake --build ${mac_sources_workspace}/${BUILD_DIR} --target tool_tcprelay -j1"
                    
                    //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 ${BUILD_DIR}/megacli ./examples-${BUILD_ID}"
                    sh "cp ${BUILD_DIR}/megasimplesync ./examples-${BUILD_ID}"
                    sh "install_name_tool -add_rpath @executable_path/.libs ./examples-${BUILD_ID}/megacli"
                    sh "install_name_tool -add_rpath @executable_path/.libs ./examples-${BUILD_ID}/megasimplesync"
                    sh "mkdir ./examples-${BUILD_ID}/.libs; cp -RP ${VCPKGPATH}/vcpkg/installed/arm64-osx-mega/debug/lib/*.dylib ./examples-${BUILD_ID}/.libs || :"
                    sh "cp -RP ${VCPKGPATH}/vcpkg/installed/arm64-osx-mega/debug/lib/*.dylib ./examples-${BUILD_ID}/.libs || :"
                    sh "tar czf examples-${BUILD_ID}.tar.gz ./examples-${BUILD_ID} || :"
                }
            }
        }
        stage('Run macOS 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')
                BUILD_DIR = "contrib/cmake/build_dir"  
                }
            steps{
                lock(label: 'SDK_Concurrent_Test_Accounts', variable: 'ACCOUNTS_COMBINATION', quantity: 1, resource: null){
                    dir(mac_sources_workspace){
                        script{
                            env.MEGA_EMAIL = "${env.ACCOUNTS_COMBINATION}"
                            echo "${env.ACCOUNTS_COMBINATION}"
                        }
                        sh "echo Running tests"
                        sh """#!/bin/zsh
                        set -x
                        cd ${env.BUILD_DIR}
                        ./test_unit &
                        pid=\$!
                        wait \$pid || FAILED=1

                        if [ -z \"\$FAILED\" ]; then
                            if [ -z \"${TESTS_PARALLEL}\" ]; then
                                # Sequential run
                                ./test_integration --CI --USERAGENT:${env.USER_AGENT_TESTS} --APIURL:${APIURL_TO_TEST} &
                                pid=\$!
                                wait \$pid || FAILED=2
                            else
                                # Parallel run
                                ./test_integration --CI --USERAGENT:${env.USER_AGENT_TESTS} --APIURL:${APIURL_TO_TEST} ${TESTS_PARALLEL} 2>&1 | tee tests.stdout
                                [ \"\${pipestatus[1]}\" != \"0\" ] && FAILED=2
                            fi
                        fi

                        if [ -n \"\$FAILED\" ]; then
                            if [ \"\$FAILED\" -eq 1 ]; then
                                procFailed=\$pid
                            else # FAILED=2
                                if [ -z \"${TESTS_PARALLEL}\" ]; then
                                    # Sequential run
                                    procFailed=\$pid
                                else
                                    # Parallel run
                                    procFailed=`grep \"<< PROCESS\" tests.stdout | sed 's/.*PID:\\([0-9]*\\).*/\\1/' | tr '\\n' ' '`
                                fi
                            fi
                            if [ -n \"\$procFailed\" ]; then
                                sleep 10
                                for i in `echo \$procFailed`; do
                                    last_core=`grep \"test_.*\$i\" -rn \$HOME/Library/Logs/DiagnosticReports | cut -d':' -f1`
                                    if [ -n \"\$last_core\" ]; then
                                        cat \"\$last_core\"
                                        rm \"\$last_core\"
                                    fi
                                done
                            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: 'contrib/cmake/build_dir/test_integration*log*, examples-*.tar.gz', fingerprint: true
            script{
                if (currentBuild.currentResult == 'SUCCESS'){
                    addGitLabMRComment(comment: ":white_check_mark: ${currentBuild.projectName} :green_apple: <b>macOS</b> SUCCEEDED :muscle:<br/>Build results: [Jenkins [${currentBuild.displayName}]](${currentBuild.absoluteUrl})<br/>Commit: ${env.GIT_COMMIT}" )
                    updateGitlabCommitStatus(name: 'Build & test macOS', state: 'success')
                }                                
                if (currentBuild.currentResult == 'FAILURE'){
                    addGitLabMRComment(comment: ":red_circle: ${currentBuild.projectName} :green_apple: <b>macOS</b> FAILURE  :worried:<br/>Build results: [Jenkins [${currentBuild.displayName}]](${currentBuild.absoluteUrl})<br/>Commit: ${env.GIT_COMMIT}" )
                    updateGitlabCommitStatus(name: 'Build & test macOS', state: 'failed')
                }
                if (currentBuild.currentResult == 'ABORTED'){
                    addGitLabMRComment(comment: ":interrobang: ${currentBuild.projectName} :green_apple: <b>macOS</b> ABORTED  :confused:<br/>Build results: [Jenkins [${currentBuild.displayName}]](${currentBuild.absoluteUrl})<br/>Commit: ${env.GIT_COMMIT}" )
                    updateGitlabCommitStatus(name: 'Build & test macOS', state: 'canceled')
                }                                
                if (currentBuild.currentResult == 'UNSTABLE'){
                    addGitLabMRComment(comment: ":interrobang: ${currentBuild.projectName} :green_apple: <b>macOS</b> UNSTABLE  :confused:<br/>Build results: [Jenkins [${currentBuild.displayName}]](${currentBuild.absoluteUrl})<br/>Commit: ${env.GIT_COMMIT}" )
                    updateGitlabCommitStatus(name: 'Build & test macOS', state: 'failed')
                }
            }
        }
    }
}
