diff --git a/README.md b/README.md index 2b09d74..6a9b823 100644 --- a/README.md +++ b/README.md @@ -41,3 +41,7 @@ Le tag pkg remplit deux offices : * marquer un état du code empaqueté dans le dépôt. Une question reste en suspens : seuls les paquets en stable portent un numéro important ; faut-il ajouter des tags pour les paquets en développement (ce qui implique de mettre en place un moyen de filtrer les tags stable et develop). + +## Jenkins + +Pour définir une variable globale, il faut le faire dans un contexte global diff --git a/pipeline b/pipeline new file mode 100644 index 0000000..1143b18 --- /dev/null +++ b/pipeline @@ -0,0 +1,256 @@ +@Library("cadoles@build_pipeline_bbohard") _ +def buildTag +def buildContext +def distBranch + +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 cause: "UserIdCause", detail: "wpetit" + triggeredBy 'TimerTrigger' + } + } + steps { + script { + tamarin.prepareEnvironment() + } + } + } + + stage("Package project") { + when { + not { + triggeredBy 'TimerTrigger' + } + } + steps { + script { + stage("Check tag") { + buildTag = env.ref + if (!buildTag.startsWith('build/')) { + currentBuild.result= 'ABORTED' + error("La référence `${buildTag}` n’est pas une demande de paquet valide.") + } + } + 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("Check dist branch") { + dir(env.projectDir) { + containsBranch = sh(script: "git branch -a --contains '${buildTag}'", returnStdout: true).replace('* ', '').split('\n') + // si distBranch contient plus d’une valeur, il y a un problème : on attend que le tag de build soit sur un + // commit propre à une seule branche de packaging (merge ou modification du dossier debian) + echo("`${containsBranch}`") + def distBranches = [] + for (branch in containsBranch) { + branch=branch.replace(' remotes/origin/','') + if (branch.startsWith('dist/')) { + distBranches.add(branch) + } + } + echo("`${distBranches}`") + buildContext = distBranches[0].split('/') + env.packageBranch = distBranches[0] + echo("`${buildContext}`") + env.packageProfile = buildContext[1] + '-' + buildContext[2] + if (!buildContext[0].matches('dist')) { + currentBuild.result = 'ABORTED' + error("La branche portant la référence `${buildTag}` n’est pas une branche de packaging") + } + } + } + stage("Checkout ref") { + dir(env.projectDir) { + withCredentials([ + sshUserPrivateKey(credentialsId: 'jenkins-forge-ssh', keyFileVariable: 'FORGE_SSH_KEY')]) { + writeFile( + file : "./sshForJenkins.sh", + text: ''' + #!/bin/sh + ssh -i "${FORGE_SSH_KEY}" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$@" + ''' + ) + sh(script: "chmod +x ./sshForJenkins.sh") + withEnv(["GIT_SSH=./sshForJenkins.sh"]) { + sh """ + git checkout ${env.ref} + """ + sh """ + git tag -am "paquet" pkg/${buildContext[-1]}/${buildContext[1]}/${buildContext[2]}/numero + """ + sh """ + git tag -d ${env.ref} + git push origin :${env.ref} + """ + sh """ + git push --tag origin + """ + return + } + } + } + } + + //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 + ]) + } + } +}