Jenkins con pylint da una falla de construcción
Pregunta
Agregué un paso de compilación para ejecutar un script de Python.
En este script se llama a Pylint con Lint.run (.. Args) para verificar el código.
El script funciona, pero al final, la compilación falla con el único mensaje de error:
Build step 'Execute Python script' marked build as failure
Alguien tiene una idea de por qué sucede esto?
Solución
Parece que su ejecución de pylint sale con un estado distinto de cero (faltando script, malas opciones ...), tal vez salga del script con una excepción planteada o una sys.exit(something_else_than_zero)
Otros consejos
También puedes simplemente poner un
pylint || Salir 0
En la línea de cmd de shell. El complemento Pylint fallará la compilación de todos modos al verificar el resultado de Pyllint.
Pylint tiene el comportamiento desagradable de devolver un código de salida distinto de cero, incluso solo si se encontró un pequeño problema de advertencia. Solo cuando todo estaba bien, se devuelve 0 (ver página del hombre).
Como generalmente un código distinto de cero denota un error, Jenkins falla la compilación.
Veo dos formas de superar esto:
- Use un pequeño script alrededor de Pylint que siempre regresa 0. Entonces Jenkins no fallará debido a Pylint. Utilizo un pequeño script de Python que llama a Pylint con os.system () y sys.exit (0) después de que. Puede verlo como anular el código de error de Pylint.
- Parche Pylint. Por ejemplo, en mi sistema Linux, la llamada sys.exit () está en el archivo /usr/lib/pymodules/python2.6/pylint/lint.py
Rylint reciente tiene la opción de no llamar a la salida SYS
lint.Run(args, exit=False, **kwargs)
En Pylint 1.9.3, hay un --exit-zero
bandera.
Estoy de acuerdo con @DMeister, pero con el código de tubería (Jenkinsfile) sugiero un intento/captura y luego analizando el error. De esta manera, puede determinar si solo está obteniendo bits de estado de Pylint (vea los documentos de Pylint), si Pylint informa un error de uso o si hubo un fracaso catastrófico:
try {
sh 'pylint --output-format=parseable my_module'
} catch ( pylint_rc ) {
// pylint_rc will be of the form
// "hudson.AbortException: script returned exit code NN"
// where NN is 1-63 and represents bit field;
// bits 0-4 indicate lint-ish issues in analyzed code,
// bit 5 indicates pylint usage error
echo "pylint_rc= \'$pylint_rc\'"
String rc = "$pylint_rc"
String code = rc.split()[5]
echo "Isolated return code string value $code"
int value = code.toInteger()
// catastrophic/crash error returns a 1; else there is a pylint return code
int error_bits_code = value & 0x20
int lint_bits_code = value & 0x1f
echo "pylint error_bits_code=$error_bits_code ; lint_bits_code=$lint_bits_code"
if ( (value == 1) || (error_bits_code != 0) ) {
currentBuild.result = "FAILURE"
throw pylint_rc
}
}
Disculpas a los puristas maravillosos: Groovy no es lo mío, así que estoy seguro de que esto se puede mejorar, hágamelo saber. Hay un agujero conocido: si Pylint solo detecta errores de tipo "fatal" (bit 0) y ningún otro problema de ningún tipo (los bits 1-4 no están configurados), entonces este código lanzará incorrectamente una excepción. Pero mi código marca toneladas de problemas, por lo que eso no es un problema para mí. La solución (? Msg de error de análisis?) Podría ser trivial para alguien con chuletas maravillosas.
Se encontró con esto hoy (aunque no usa Jenkins).
En mi caso, se debió a cómo Pylint codifica la información de uso de la convención-confactor de error fatal en su código de salida: https://docs.pylint.org/en/1.6.0/run.html#exit-codes
Mi solución:
#!/usr/bin/env sh
# Wraps Pylint invocation to produce shell-friendly exit codes
# Because Pylint exit codes are weird:
# https://docs.pylint.org/en/1.6.0/run.html#exit-codes
PYTHON_EXECUTABLE=python
if [ ! -z $PYTHON_ENV ]; then
PYTHON_EXECUTABLE="$PYTHON_ENV/bin/python"
fi
${PYTHON_EXECUTABLE} -m pylint $@
PYLINT_EXIT_CODE=$?
exit $(($PYLINT_EXIT_CODE % 4))
(Esencia: https://gist.github.com/nkashy1/ae59d06d4bf81fb72047fcd390d08903)