J'utilise Jenkins et Multibranch Pipeline. J'ai un travail pour chaque branche git active .. La nouvelle construction est déclenchée par le dépôt Push in git. Ce que je veux, c'est abandonner les constructions en cours dans la branche actuelle si une nouvelle apparaît dans la même branche.
Par exemple: je commets et Push to branch feature1
. Alors BUILD_1
a commencé à Jenkins. Je fais un autre commit et Push to branch feature1
alors que BUILD_1
est toujours en cours d'exécution. Je veux que BUILD_1
soit abandonné et que je commence BUILD_2
.
J'ai essayé d'utiliser l'option stage concurrency=x
et stage-lock-milestone feature, mais je n'ai pas réussi à résoudre mon problème.
J'ai aussi lu ce fil Arrêter le travail de Jenkins au cas où un nouveau poste serait lancé , mais il n'y a pas de solution à mon problème.
Connaissez-vous une solution à cela?
activer le travail en parallèle pour votre projet avec Execute concurrent builds if necessary
utilisez execute system groovy script
comme première étape de construction:
import hudson.model.Result
import jenkins.model.CauseOfInterruption
//iterate through current project runs
build.getProject()._getRuns().iterator().each{ run ->
def exec = run.getExecutor()
//if the run is not a current build and it has executor (running) then stop it
if( run!=build && exec!=null ){
//prepare the cause of interruption
def cause = { "interrupted by build #${build.getId()}" as String } as CauseOfInterruption
exec.interrupt(Result.ABORTED, cause)
}
}
et dans les travaux interrompus, il y aura un journal:
Build was aborted
interrupted by build #12
Finished: ABORTED
Si quelqu'un en a besoin dans Jenkins Pipeline Multibranch, vous pouvez le faire dans Jenkinsfile comme ceci:
def abortPreviousRunningBuilds() {
def hi = Hudson.instance
def pname = env.JOB_NAME.split('/')[0]
hi.getItem(pname).getItem(env.JOB_BASE_NAME).getBuilds().each{ build ->
def exec = build.getExecutor()
if (build.number != currentBuild.number && exec != null) {
exec.interrupt(
Result.ABORTED,
new CauseOfInterruption.UserInterruption(
"Aborted by #${currentBuild.number}"
)
)
println("Aborted previous running build #${build.number}")
} else {
println("Build is not running or is current build, not aborting - #${build.number}")
}
}
}
Le faire fonctionner en ayant le script suivant dans la bibliothèque partagée globale:
import hudson.model.Result
import jenkins.model.CauseOfInterruption.UserInterruption
def killOldBuilds() {
while(currentBuild.rawBuild.getPreviousBuildInProgress() != null) {
currentBuild.rawBuild.getPreviousBuildInProgress().doKill()
}
}
Et en l'appelant dans mon pipeline:
@Library('librayName')
def pipeline = new killOldBuilds()
[...]
stage 'purge'
pipeline.killOldBuilds()
Edit: En fonction de la force avec laquelle vous souhaitez supprimer oldBuild, vous pouvez utiliser doStop (), doTerm () ou doKill ()!
Sur la base de l’idée de @ C4stor, j’ai réalisé cette version améliorée ... Je la trouve plus lisible depuis la version de @daggett
import hudson.model.Result
import hudson.model.Run
import jenkins.model.CauseOfInterruption.UserInterruption
def abortPreviousBuilds() {
Run previousBuild = currentBuild.rawBuild.getPreviousBuildInProgress()
while (previousBuild != null) {
if (previousBuild.isInProgress()) {
def executor = previousBuild.getExecutor()
if (executor != null) {
echo ">> Aborting older build #${previousBuild.number}"
executor.interrupt(Result.ABORTED, new UserInterruption(
"Aborted by newer build #${currentBuild.number}"
))
}
}
previousBuild = previousBuild.getPreviousBuildInProgress()
}
}