@Library("cadoles") _

pipeline {

    agent {
        label 'common'
    }
    
    environment {
        projectDir = "${env.project_name}_${env.BUILD_ID}" 
    }

    triggers {
        // Execute pipeline every day at 7h30 to prepare docker images
        cron('30 7 * * 1-5')
    }

    stages {

        stage("Prepare build environment") {
            when {
                anyOf {
                    triggeredBy 'TimerTrigger'
                }   
            }
            steps {
                script {
                    tamarin.prepareEnvironment()
                }
            }
        }

        stage("Package project") {
            when {
                not {
                    triggeredBy 'TimerTrigger'
                }
            }
            steps {
                script {
                    stage("Clone repository") {
                        checkout scm: 
                            [
                                $class: 'GitSCM', 
                                userRemoteConfigs: [[url: env.repository_url, credentialsId: 'jenkins-forge-ssh']], 
                                branches: [[name: env.ref]],
                                extensions: [
                                    [$class: 'RelativeTargetDirectory', relativeTargetDir: env.projectDir ],
                                    [$class: 'CloneOption', noTags: false, shallow: false, depth: 0, reference: ''],
                                    [$class: 'WipeWorkspace' ]
                                ]
                            ], 
                            changelog: false, 
                            poll: false
                    }
                    
                    stage("Ensure packaging branch") {
                        dir(env.projectDir) {
                            sh 'git checkout "${packageBranch}"'
                            def commitOrRef = env.commit ? env.commit : env.ref
                            def branchesWithCommitOrRef = sh(script: "git branch --contains '${commitOrRef}'", returnStdout: true).split(' ')
                            if (branchesWithCommitOrRef.findAll{env.packageBranch.contains(it)}.any{true}) {
                                currentBuild.result = 'ABORTED'
                                error("La référence `${env.ref}` ne fait pas partie de la branche `${env.packageBranch}` !")
                            }
                        }
                    }

                    stage("Check [ci skip] in tag message") {
                        dir(env.projectDir) {
                            sh 'git checkout "${packageBranch}"'
                            def commitTags = sh(script: 'git describe --exact-match --abbrev=0', returnStdout: true).split(' ')
                            for (tag in commitTags) {
                                tag = tag.trim()
                                def tagMessage = sh(script: "git tag --format='%(subject)' -l '${tag}'", returnStdout: true).trim()
                                println("Tag '${tag}' message is: '${tagMessage}'")
                                if (tagMessage.contains('[ci skip]')) {
                                    currentBuild.result = 'ABORTED'
                                    error("Le message du tag '${tag}' contient le marqueur '[ci-skip]' !")
                                }
                            }
                        }
                    }
                    
                    stage("Checkout ref") {
                        dir(env.projectDir) {
                            sh """
                            git checkout ${env.ref}
                            """
                        }
                    }
                
                    stage("Build package") {
                        dir(env.projectDir) {  
                            // On construit les paquets à partir des informations
                            // de contexte provenant de CPKG et du webhook
                            def result = tamarin.buildPackageWithCPKG(
                                env.packageProfile ? env.packageProfile : "debian",
                                env.packageArch ? env.packageArch : "",
                                env.packageBranch ? env.packageBranch : "",
                                env.baseImage ? env.baseImage : ""
                            )
                            
                            // On publie chacun des paquets construits
                            result.each { r ->
                                vulcain.publish(
                                    r.packages,
                                    r.env,
                                    env.packageBranch
                                )
                            }

                            // On attend que les paquets soient disponibles
                            // sur Vulcain pour envoyer la notification de diffusion
                            // si la distribution est spécifiée
                            waitForPackages(env.ref, result)
                            
                            // On liste l'ensemble des paquets construits
                            def publishedPackages = result.collect { r ->
                                return r.packages.collect { p ->
                                    def file = new File(p)
                                    return "- Paquet `${file.getName()}`, Dépôt `${r.env}`, Distribution `${r.distrib}`"
                                }
                            }.transpose().collectMany { it }
                            
                            // On notifie le canal Rocket.Chat de la publication des paquets
                            rocketSend (
                                avatar: 'https://jenkins.cadol.es/static/b5f67753/images/headshot.png',
                                message: """
                                Les paquets suivants ont été publiés pour le projet ${env.project_name}:
                                
                                ${publishedPackages.join('\n')}
                        
                                [Visualiser le job](${env.RUN_DISPLAY_URL})
                                
                                @${env.sender_login}
                                """.stripIndent(),
                                rawMessage: true,
                                attachments: lolops.getRandomDeliveryAttachment()
                            )

                            if (env.testPackageInstall != 'yes') {
                                println "Test d'intallation des paquets désactivé."
                                return
                            }
                            
                            // Pour chaque construction de paquets...
                            result.each { r ->
                                // On essaye de trouver un template de VM compatible
                                // avec la distribution cible de la construction
                                def vmTemplate = findMatchingVMTemplate(r.distrib)
                                if (vmTemplate == null) {
                                    println "Aucun template de VM n'a été trouvé correspondant à la distribution `${r.distrib}`."
                                    return
                                }

                                // Pour chaque paquets construits...
                                r.packages.each { p ->
                                    def packageFullName = new File(p).getName()
                                    def packageRepository = r.distrib.split('-')[1] + '-' + r.env
                                    def packageNameParts = packageFullName.split('_')
                                    def packageName = packageNameParts[0]
                                    def packageVersion = packageNameParts[1]

                                    stage("Test package '${packageName}' installation") {
                                        build job: 'Test de paquet Debian', wait: false, parameters: [
                                            [$class: 'StringParameterValue', name: 'packageName', value: packageName], 
                                            [$class: 'StringParameterValue', name: 'packageVersion', value: packageVersion],
                                            [$class: 'StringParameterValue', name: 'packageRepository', value: packageRepository],
                                            [$class: 'StringParameterValue', name: 'vmTemplate', value: vmTemplate]
                                        ]
                                    }
                                }
                            }
                            
                        }
                    }
                }
            }
            post {
                always {
                    sh "rm -rf '${env.projectDir}'"
                }
            }
        }

    }
    
   
}

// Cette fonction fait un simple "mapping"
// entre les distributions cibles des paquets et
// les templates de VM disponibles sur l'OpenNebula
def findMatchingVMTemplate(String distrib) {
    def vmTemplatesMap = [
        'eole-2.7.0': 'eolebase-2.7.0-cadoles',
        'eole-2.6.2': 'eolebase-2.6.2-cadoles'
    ]
    return vmTemplatesMap.get(distrib, null)
}

def waitForPackages(String tagRef, buildResults) {
    def packageVersion = tagRef.split('/')[3];
    def packageDistrib = env.packageBranch.split('/')[2];
        
    buildResults.each { r ->
        def distrib = "${packageDistrib}-${r.env}"

        r.packages.each { p ->
            def file = new File(p)
            def fileNameParts = file.getName().take(file.getName().lastIndexOf('.')).split('_')
            def packageName = fileNameParts[0]
            def packageArch = fileNameParts[2]
            
            debian.waitForRepoPackage(packageName, [
                baseURL: 'https://vulcain.cadoles.com',
                distrib: distrib,
                component: 'main',
                type: 'binary',
                arch: packageArch,
                expectedVersion: packageVersion
            ])
        }
    }
}