// SPDX-License-Identifier: BSD-3-Clause
/* Copyright 2019-2020, Intel Corporation */

/* pmemkv.jenkins - pipeline for pmemkv jenkins job. */

/* declare a map object for holding loaded libraries: */
libs = [:]

currentBuild.displayName = "#$currentBuild.id $LABEL: $BRANCH - $TEST_TYPE, coverage: $COVERAGE"
currentBuild.description = "$DESCRIPTION"

PMEMKV_DIR='pmemkv'

/* Send report summary via email. */
def send_mail(attachments, msg) {

    def recipients = params.EMAIL_RECIPIENTS
    def message_title = "[Jenkins/pmemkv] Report ${currentBuild.projectName} ${currentBuild.displayName}"
    def message_body = """
        <p>---<br />Auto-generated by <a href="${env.JENKINS_URL}">Jenkins</a></p>
        <p>---<br /><a href="${params.REPO_URL}">${params.REPO_URL}</a> BRANCH: ${params.BRANCH}</p>
        <p><br /><a href="${env.JENKINS_URL}view/all/job/${currentBuild.projectName}/${currentBuild.id}">Build link</a></p>
        <p> <b> Description: </b> ${params.DESCRIPTION} </p>
    """

    message_body += msg

    emailext (
        to: recipients,
        subject: message_title,
        body: message_body,
        mimeType: "text/html",
        attachmentsPattern: attachments
    )
}

pipeline {
	/* put timestamps in output log. */
	options { timestamps () }

	/* execute this pipeline job on node in "LABEL" group in Jenkins. */
	agent { label params.LABEL }

	/* each stage represents pipeline step. */
	stages {
		/* preparation stage: clean workspace, create output directories, log file,
		clone repository containing Jenkins pipelines, load libraries, set warning on DUT, etc. */
		stage('Prepare') {
			steps {
				print "Deleting ${WORKSPACE} directory"
				deleteDir()

				print "Creating ${WORKSPACE}/output directory"
				dir('output') {
					writeFile file: 'console.log', text: ''
				}

				print "Checkout repository containing Jenkins pipelines"
				checkout([$class: 'GitSCM', branches: [[name: jenkins_files_branch]], doGenerateSubmoduleConfigurations: false, extensions: [[$class: 'RelativeTargetDirectory', relativeTargetDir: 'jenkins_files']], submoduleCfg: [], userRemoteConfigs: [[url: jenkins_files_repo]]])

				print "Loading pipeline libraries"
				script {
					libs.api = load api_lib
					libs.api.set_jenkins_warning_on_dut()
				}
			}
		}
		/* gather system info. */
		stage('System-info'){
			steps {
				script {
					libs.api.system_info()
				}
			}
		}
		/* clone pmemkv repository to be tested */
		stage('Repo checkout') {
			steps {
				script {
					def PMEMKV_PATH="${WORKSPACE_DIR}/${PMEMKV_DIR}"
					libs.api.clone_repository(params.REPO_URL, params.BRANCH, PMEMKV_DIR)
				}
			}
		}
		stage('Run test') {
			steps {
				script {
				warnError('Build unstable.') {
						libs.api.echo_header("Running tests")
						def COV_PARAM=""
						def TEST_DIR
						if (params.COVERAGE == 'yes') {
								COV_PARAM="export COVERAGE=1"
							}
						def PMEMKV_PATH="${WORKSPACE}/${PMEMKV_DIR}"
						switch (params.DEVICE_TYPE) {
							case 'DAX':
								libs.api.run_bash_script("""
									${SCRIPTS_DIR}/createNamespace.sh -d --size=100G
								""")
								TEST_DIR = "/dev/" + libs.api.run_bash_script("""
									sudo ndctl list -M -N | jq -r '.[] | select(.mode=="devdax").chardev' | head -n 1
								""").output
								break
							case 'PMEM':
								libs.api.run_bash_script("""
									${SCRIPTS_DIR}/createNamespace.sh -p --size=100G
								""")
								TEST_DIR = "/mnt/pmem0"
								break
							case 'NONE':
								TEST_DIR = "/dev/shm"
								break
							}
						def ENV_VAL="export DEFAULT_TEST_DIR=${TEST_DIR}; export WORKDIR=${WORKSPACE_DIR}/${PMEMKV_DIR}; export SCRIPTSDIR=\$WORKDIR/utils/docker; export TESTS_LONG=ON; export TERM=xterm-256color; export TEST_TIMEOUT=3600; export TESTS_USE_FORCED_PMEM=0; ${COV_PARAM}"
						libs.api.echo_header("Running test type: ${params.TEST_TYPE}")
						dir("${PMEMKV_PATH}/utils/docker")
						{
							switch (params.TEST_TYPE) {
								case 'normal':
									libs.api.echo_header("Test options: ${params.TEST_OPTIONS}")
									params.TEST_OPTIONS.split().each { build ->
										stage("${build}") {
											catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
										libs.api.run_bash_script("""
											${ENV_VAL}
											./run-build.sh ${build}
										""")
										}
										}
									}
									break;
								case 'building':
									libs.api.run_bash_script("""
										${ENV_VAL}
										./run-test-building.sh
									""")
									break;
								case 'compatibility':
									libs.api.run_bash_script("""
										${ENV_VAL}
										./run-compatibility.sh
									""")
									break;
								default:
									throw new java.lang.UnsupportedOperationException("TEST_TYPE value '${params.TEST_TYPE}' is not supported. Select: normal, building or compatibility.");
							}
						}
						libs.api.echo_header("Finished running tests.")
					}
				}
			}
		}
	}
/* 
	generate post-build artifacts
	write "fail" or "success" in result.txt file
	archive results
*/
	post {
		/* 'always' declarations must be declared first. */
		always {
			script {
				libs.api.unset_jenkins_warning_on_dut()
				libs.api.write_os_branch_repo(params.LABEL, params.BRANCH, params.REPO_URL)
				libs.api.archive_output()
				/* Make sure to uninstall pmemkv from the DUT. */
				def PMEMKV_PATH="${WORKSPACE_DIR}/${PMEMKV_DIR}"
				libs.api.run_bash_script("""
							cd ${PMEMKV_PATH}/build || true
							sudo make uninstall || true
							sudo rm /usr/lib64/pkgconfig/libpmemkv.pc || true
							sudo rm /usr/lib/x86_64-linux-gnu/pkgconfig/libpmemkv.pc || true
						""")
			}
		}
		success {
			script {
				libs.api.write_result_and_archive('success')
				if (params.SEND_RESULTS) {
                    def build_info = "Build" + " #$currentBuild.id " + "succeeded"
                    send_mail('', build_info)
                }
			}
		}
		failure {
			script {
				libs.api.write_result_and_archive('fail')
				if (params.SEND_RESULTS) {
                    def build_info = "Build" + " #$currentBuild.id " + "failed"
                    send_mail('', build_info)
                }
			}
		}
		unstable {
			script {
				libs.api.write_result_and_archive('fail')
				if (params.SEND_RESULTS) {
                    def build_info = "Build" + " #$currentBuild.id " + "failed"
                    send_mail('', build_info)
                }
			}
		}
	}
}
