template - Cargar Jenkins Pipeline Shared Library desde el mismo repositorio
jenkins pipeline tools (4)
TL; DR ¿Hay alguna forma de importar código en el Jenkinsfile
desde el repositorio local (que no sea el paso de load
)?
¿Por qué?
Experimenté que para las compilaciones complejas, el Jenkinsfile
vuelve un poco voluminoso y no es muy Jenkinsfile
de mantener.
Ahora que el trabajo de compilación es un código, sería maravilloso tener los mismos medios que para otro código. Es decir, me gustaría dividirlo en unidades más pequeñas (más mantenibles) y probarlas por unidad .
Lo que intenté
- bibliotecas compartidas : permite dividir nuestra lógica Jenkins Pipeline en archivos más pequeños en un módulo separado e incluso una prueba de unidad.
Sin embargo, deben estar en un repositorio diferente y (si no está en GitHub) deben configurarse en Jenkins. - Paso de
load
: permitir la carga de guiones geniales desde el repositorio.
Sin embargo, los archivos deben ser secuencias de comandos y no clases "completas", lo que dificulta tener varios archivos o clases que dependan entre sí. Por ejemplo, la herencia es imposible.
Además, estos archivos no se muestran cuando se hace una replay en un trabajo de Jenkins, lo que dificulta su desarrollo y depuración.
Mis preguntas
- ¿Hay alguna forma (o solución alternativa) de crear una biblioteca compartida en el mismo repositorio que el
Jenkinsfile
e importar esta biblioteca alJenkinsfile
? - ¿O hay alguna otra forma que no haya probado todavía?
Ejemplo de estructura de directorio
Similar a la estructura de directorios descrita para las bibliotecas compartidas, me gustaría tener lo siguiente en un solo repositorio .
(root)
+- someModule
| +- ...
+- jenkins # Classes/Scripts used by Jenkins in a separate module
| +- src # Groovy source files
| +- org
| +- foo
| +- Bar.groovy # for org.foo.Bar class
| +- test # Groovy test files
| +- org
| +- foo
| +- BarTest.groovy # Test for org.foo.Bar class
| +- pom.xml or build.groovy # Build for local library
+- Jenkinsfile # Build "someModule", uses classes from "jenkins" module
Puede echar un vistazo al complemento que escribí, que habilita el uso de subdirectorios de repositorio donde su canalización es como bibliotecas compartidas: https://github.com/karolgil/SharedLibrary
Después de construirlo e instalarlo, simplemente puede poner lo siguiente en su canalización:
@SharedLibrary(''dir/in/repo'') _
Para comenzar a usar dir/in/repo
como biblioteca compartida para sus tuberías.
Quería hacer lo mismo y acabé creando esto:
https://github.com/jenkinsci/workflow-cps-global-lib-plugin/pull/37
Y aquí es como lo uso:
https://github.com/syndesisio/syndesis-pipeline-library/blob/master/Jenkinsfile#L3
En mi caso, quería crear un archivo Jenkins que realmente tests
la biblioteca de tuberías que contiene el repositorio.
Déjame saber lo que piensas y siéntete libre de agregar tus comentarios sobre las relaciones públicas también.
Solución:
library identifier: ''shared-library@version'', retriever: legacySCM(scm)
El enfoque que se toma actualmente en PR 37 no funcionará correctamente con los agentes de compilación, y de todos modos solo funcionará para los scripts usando el paso de la library
, no la anotación de @Library
.
Por cierto, los archivos cargados desde el paso de load
aparecen en Replay . Pero es cierto que su script no puede referirse estáticamente a tipos definidos en tales archivos. En otras palabras, podría simular bibliotecas vars/*.groovy
pero no src/**/*.groovy
la misma limitación que la PR 37 actual.
Supongo que la forma correcta de hacerlo es implementar un SCMRetriever
personalizado.
Sin embargo, puedes usar el siguiente hack:
Suponiendo que jenkins/vars/log.groovy
en su repositorio local contiene:
def info(message) {
echo "INFO: ${message}"
}
Su Jenkinsfile
puede cargar esa biblioteca compartida desde el directorio jenkins/
usando el paso de la library
:
node(''node1'') { // load library
checkout scm
// create new git repo inside jenkins subdirectory
sh(''cd jenkins && git init && git add --all . && git commit -m init &> /dev/null'')
def repoPath = sh(returnStdout: true, script: ''pwd'').trim() + "/jenkins"
library identifier: ''local-lib@master'', retriever: modernSCM([$class: ''GitSCMSource'', remote: repoPath])
}
node(''node2'') {
stage(''Build'') {
log.info("called shared lib") // use the loaded library
}
}