pipeline {
    agent { label "docker" }

    options {
        buildDiscarder(logRotator(numToKeepStr: '135', daysToKeepStr: '21'))
        gitLabConnection('GitLabConnectionJenkins')
        timestamps() // Add timestamps to all console output
    }

    stages {
        stage('Clean previous runs') {
            steps {
                deleteDir()
            }
        }

        stage('Checkout SDK') {
            steps {
                script {
                    megacmd_scm = checkout scm
                    megacmd_branch = megacmd_scm.GIT_BRANCH
                }
                dir('sdk') {
                    checkout([
                        $class: 'GitSCM',
                        branches: [[name: "origin/${SDK_BRANCH}"]],
                        userRemoteConfigs: [[url: "${env.GIT_URL_SDK}", credentialsId: "12492eb8-0278-4402-98f0-4412abfb65c1"]],
                        extensions: [
                            [$class: "UserIdentity",name: "jenkins", email: "jenkins@jenkins"],
                            [$class: "CloneOption", depth: 1, shallow: true, noTags: false, reference: '']
                        ]
                    ])
                }
                script {
                    megacmd_sources_workspace = WORKSPACE
                    sdk_sources_workspace = "${megacmd_sources_workspace}/sdk"
                }
            }
        }

        stage("Build and test MEGAcmd") {
            matrix {
                axes {
                    axis {
                        name 'SANITIZERS'
                        values 'baseline', 'ubsan', 'asan', 'tsan'
                    }
                    axis {
                        name 'BUILD_SYSTEM'
                        values 'cmake'
                    }
                }
                stages {
                    stage("Build MEGAcmd container image") {
                        options {
                            timeout(time: 3, unit: 'HOURS')
                        }
                        environment {
                            DOCKER_BUILDKIT=1
                        }
                        steps {
                            sh "docker build -t meganz/megacmd-branchstatus-${BUILD_SYSTEM}-${SANITIZERS}:${env.BUILD_NUMBER} -f ${megacmd_sources_workspace}/build-with-docker/Dockerfile.${BUILD_SYSTEM} --build-arg=ENABLE_${SANITIZERS}=ON --ulimit=core=-1 --cpuset-cpus=0,1 -- ${megacmd_sources_workspace}"
                        }
                    }
                    stage("MEGAcmd unit tests") {
                        agent {
                            docker {
                                image "meganz/megacmd-branchstatus-${BUILD_SYSTEM}-${SANITIZERS}:${env.BUILD_NUMBER}"
                                reuseNode true
                                args "--name megacmd-branchstatus-${BUILD_SYSTEM}-${SANITIZERS}-${env.BUILD_NUMBER}"
                            }
                        }
                        options {
                            timeout(time: 10, unit: 'MINUTES')
                        }
                        environment {
                            ASAN_OPTIONS="print_stats=1,log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/unit-asan-report.log"
                            TSAN_OPTIONS="log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/unit-tsan-report.log"
                            UBSAN_OPTIONS="log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/unit-ubsan-report.log"
                            HOME="${megacmd_sources_workspace}/test-dir-${SANITIZERS}"
                        }
                        steps {
                            dir("test-dir-${SANITIZERS}") {
                                sh """
                                    /usr/bin/mega-cmd-tests-unit \
                                        --gtest_output=xml:${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/mega-cmd-tests-unit.xml \
                                        --gtest_shuffle
                                """
                            }
                        }
                        post {
                            always {
                                archiveArtifacts artifacts: "test-dir-${SANITIZERS}/.megaCmd/megacmdserver.log*", allowEmptyArchive: true
                                archiveArtifacts artifacts: "test-dir-${SANITIZERS}/results/unit-*-report.log.*", allowEmptyArchive: true
                                junit "test-dir-${SANITIZERS}/results/mega-cmd-tests-unit.xml"
                            }
                        }
                    }
                    stage("MEGAcmd integration tests") {
                        agent {
                            docker {
                                image "meganz/megacmd-branchstatus-${BUILD_SYSTEM}-${SANITIZERS}:${env.BUILD_NUMBER}"
                                reuseNode true
                                args "--name megacmd-branchstatus-${BUILD_SYSTEM}-${SANITIZERS}-${env.BUILD_NUMBER}"
                            }
                        }
                        options {
                            timeout(time: 1, unit: 'HOURS')
                        }
                        environment {
                            MEGACMD_TEST_USER=''
                            MEGACMD_TEST_PASS=credentials('MEGACMD_TESTS_PASSWORD')
                            ASAN_OPTIONS="print_stats=1,log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/integration-asan-report.log"
                            TSAN_OPTIONS="log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/integration-tsan-report.log"
                            UBSAN_OPTIONS="log_path=${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/integration-ubsan-report.log"
                            HOME="${megacmd_sources_workspace}/test-dir-${SANITIZERS}"
                        }
                        steps {
                            lock(label: 'testing_accounts_megacmd', variable: 'MEGACMD_TEST_USER', quantity: 1, resource: null) {
                                dir("test-dir-${SANITIZERS}") {
                                    sh """
                                        /usr/bin/mega-cmd-tests-integration \
                                            --gtest_output=xml:${megacmd_sources_workspace}/test-dir-${SANITIZERS}/results/mega-cmd-tests-integration.xml \
                                            --gtest_shuffle \
                                            --gtest_filter=-FuseTests.*
                                    """
                                }
                            }
                        }
                        post {
                            always {
                                archiveArtifacts "test-dir-${SANITIZERS}/.megaCmd/megacmdserver.log*"
                                archiveArtifacts artifacts: "test-dir-${SANITIZERS}/results/integration-*-report.log.*", allowEmptyArchive: true
                                junit "test-dir-${SANITIZERS}/results/mega-cmd-tests-integration.xml"
                            }
                        }
                    }
                    stage("MEGAcmd Python tests") {
                        agent {
                            docker {
                                image "meganz/megacmd-branchstatus-${BUILD_SYSTEM}-${SANITIZERS}:${env.BUILD_NUMBER}"
                                reuseNode true
                                args "--name megacmd-branchstatus-${BUILD_SYSTEM}-${SANITIZERS}-${env.BUILD_NUMBER}"
                            }
                        }
                        options {
                            timeout(time: 2, unit: 'HOURS')
                        }
                        environment {
                            MEGA_EMAILS=''
                            MEGA_PWD=credentials('MEGACMD_TESTS_PASSWORD')
                            MEGA_PWD_AUX=credentials('MEGACMD_TESTS_PASSWORD')
                            ASAN_OPTIONS="print_stats=1,log_path=${megacmd_sources_workspace}/pytest-dir-${SANITIZERS}/results/pyserver-asan-report.log"
                            TSAN_OPTIONS="log_path=${megacmd_sources_workspace}/pytest-dir-${SANITIZERS}/results/pyserver-tsan-report.log"
                            UBSAN_OPTIONS="log_path=${megacmd_sources_workspace}/pytest-dir-${SANITIZERS}/results/pyserver-ubsan-report.log"
                            HOME="${megacmd_sources_workspace}/pytest-dir-${SANITIZERS}"
                            YES_I_KNOW_THIS_WILL_CLEAR_MY_MEGA_ACCOUNT=1
                            VERBOSE=1
                        }
                        steps {
                            dir("pytest-dir-${SANITIZERS}") {
                                sh 'nohup /usr/bin/mega-cmd-server --verbose-full --log-to-file &'
                            }
                            sleep 1
                            lock(label: 'testing_accounts_megacmd', variable: 'MEGA_EMAILS', quantity: 2, resource: null) {
                                script {
                                    // Skipping the 'serving' test until CMD-389 is resolved
                                    for (test in ['misc', 'put', 'rm', 'find', 'get']) {
                                        for (cmdshell in ['', 'cmdshell-']) {
                                            def testDir = "pytest-dir-${SANITIZERS}/${cmdshell}${test}-results"
                                            def asanOptions = "print_stats=1,log_path=${megacmd_sources_workspace}/${testDir}/py-asan-report.log"
                                            def tsanOptions = "log_path=${megacmd_sources_workspace}/${testDir}/py-tsan-report.log"
                                            def ubsanOptions = "log_path=${megacmd_sources_workspace}/${testDir}/py-ubsan-report.log"
                                            stage("MEGAcmd Python ${cmdshell}${test} test") {
                                                withEnv([
                                                    "MEGA_EMAIL=${env.MEGA_EMAILS0}",
                                                    "MEGA_EMAIL_AUX=${env.MEGA_EMAILS1}",
                                                    "ASAN_OPTIONS=${asanOptions}",
                                                    "TSAN_OPTIONS=${tsanOptions}",
                                                    "UBSAN_OPTIONS=${ubsanOptions}",
                                                    "OUT_DIR_JUNIT_XML=${megacmd_sources_workspace}/${testDir}"
                                                ]) {
                                                    def envStr = ''
                                                    if (cmdshell != '') {
                                                        envStr = "MEGACMDSHELL=/usr/bin/mega-cmd "
                                                    }
                                                    try {
                                                        dir("pytest-dir-${SANITIZERS}/working-dir") {
                                                            sh "${envStr}/usr/local/bin/megacmd_${test}_test.py"
                                                        }
                                                        junit "${testDir}/TEST-*.xml"
                                                    } finally {
                                                        archiveArtifacts artifacts: "${testDir}/py-*-report.log.*", allowEmptyArchive: true
                                                        dir("pytest-dir-${SANITIZERS}/working-dir") {
                                                            deleteDir()
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        post {
                            always {
                                sh "/usr/bin/mega-exec logout || true"
                                sh "/usr/bin/mega-exec quit || true"
                                archiveArtifacts "pytest-dir-${SANITIZERS}/.megaCmd/megacmdserver.log*"
                                archiveArtifacts artifacts: "pytest-dir-${SANITIZERS}/results/pyserver-*-report.log.*", allowEmptyArchive: true
                            }
                        }
                    }
                }
                post {
                    always {
                        sh "docker image rm -f -- meganz/megacmd-branchstatus-${BUILD_SYSTEM}-${SANITIZERS}:${env.BUILD_NUMBER} || true"
                    }
                }
            }
        }
    }

    post {
        always {
            script {
                sdk_commit = sh(script: "git -C ${sdk_sources_workspace} rev-parse HEAD", returnStdout: true).trim()
                megacmd_commit = sh(script: "git -C ${megacmd_sources_workspace} rev-parse HEAD", returnStdout: true).trim()
                messageStatus = currentBuild.currentResult
                messageColor = messageStatus == 'SUCCESS'? "#00FF00": "#FF0000" //green or red
                message = """
                    Jenkins job #${BUILD_ID} ended with status '${messageStatus}'.
                    See: ${BUILD_URL}

                    SDK branch: `${SDK_BRANCH}` commit: `${sdk_commit}`
                    MEGAcmd branch: `${megacmd_branch}` commit: `${megacmd_commit}`
                """.stripIndent()
                withCredentials([string(credentialsId: 'megacmd_slack_webhook_url', variable: 'SLACK_WEBHOOK_URL')]) {
                    sh """
                        curl -X POST -H 'Content-type: application/json' --data '
                            {
                               "attachments": [
                                  {
                                      "color": "${messageColor}",
                                      "blocks": [
                                       {
                                           "type": "section",
                                           "text": {
                                                "type": "mrkdwn",
                                                "text": "${message}"
                                           }
                                       }
                                     ]
                                   }
                                ]
                            }' ${SLACK_WEBHOOK_URL}
                    """
                }
            }
        }
    }
}
