git - scm - jenkins pipeline stage steps
Jenkins-cancela la ejecuciĆ³n en ejecuciĆ³n si se inicia una nueva (6)
Yo uso Jenkins y Multibranch Pipeline. Tengo un trabajo para cada rama git activa. Nueva construcción es activada por push en el repositorio git. Lo que quiero es abortar las compilaciones en ejecución en la rama actual si aparece una nueva en la misma rama.
Por ejemplo: me comprometo y presiono para ramificar feature1
. Entonces BUILD_1
comenzó en Jenkins. Hago otra confirmación y BUILD_1
feature1
BUILD_1
mientras BUILD_1
aún se está ejecutando. Quiero que se BUILD_1
y que se inicie BUILD_2
.
Intenté usar la opción de stage concurrency=x
, y la función stage-lock-milestone , pero no pude resolver mi problema.
También he leído este hilo Deteniendo el trabajo de Jenkins en caso de que se inicie uno más nuevo , pero no hay solución para mi problema.
¿Conoces alguna solución a esto?
Basado en la idea de @ C4stor, he hecho esta versión mejorada ... Me parece más legible desde la versión 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()
}
}
Con la seguridad del script de Jenkins, muchas de las soluciones aquí se vuelven difíciles ya que utilizan métodos no incluidos en la lista blanca.
Con estos pasos importantes al inicio del archivo Jenkins, esto está funcionando para mí:
def buildNumber = env.BUILD_NUMBER as int
if (buildNumber > 1) milestone(buildNumber - 1)
milestone(buildNumber)
El resultado aquí sería:
- La compilación 1 se ejecuta y crea el hito 1
- Mientras se ejecuta la compilación 1, compila 2 disparos. Tiene el hito 1 y el hito 2. Pasa el hito 1, lo que hace que la compilación # 1 se cancele.
Se puso a trabajar con la siguiente secuencia de comandos en la Biblioteca compartida global:
import hudson.model.Result
import jenkins.model.CauseOfInterruption.UserInterruption
def killOldBuilds() {
while(currentBuild.rawBuild.getPreviousBuildInProgress() != null) {
currentBuild.rawBuild.getPreviousBuildInProgress().doKill()
}
}
Y llamándolo en mi pipeline:
@Library(''librayName'')
def pipeline = new killOldBuilds()
[...]
stage ''purge''
pipeline.killOldBuilds()
Edición: ¡Dependiendo de la fuerza con la que quiera matar al oldBuild, puede usar doStop (), doTerm () o doKill ()!
Si alguien lo necesita en Jenkins Pipeline Multibranch, puede hacerlo en Jenkinsfile así:
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}")
}
}
}
También compilé una versión de las que se dieron anteriormente con algunos ajustes menores:
- El bucle
while()
generó múltiples salidas para cada compilación - UserInterruption actualmente espera un ID de usuario en lugar de una cadena de razonamiento, y no mostrará una cadena de razonamiento en ningún lugar. Por lo tanto, esto solo proporciona el ID de usuario
def killOldBuilds(userAborting) {
def killedBuilds = []
while(currentBuild.rawBuild.getPreviousBuildInProgress() != null) {
def build = currentBuild.rawBuild.getPreviousBuildInProgress()
def exec = build.getExecutor()
if (build.number != currentBuild.number && exec != null && !killedBuilds.contains(build.number)) {
exec.interrupt(
Result.ABORTED,
// The line below actually requires a userId, and doesn''t output this text anywhere
new CauseOfInterruption.UserInterruption(
"${userAborting}"
)
)
println("Aborted previous running build #${build.number}")
killedBuilds.add(build.number)
}
}
}
habilite la ejecución paralela del trabajo para su proyecto con Execute concurrent builds if necessary
Utilice el execute system groovy script
como primer paso de compilación:
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)
}
}
y en el (los) trabajo (s) interrumpido (s) habrá un registro:
Build was aborted
interrupted by build #12
Finished: ABORTED