Wiki source code of Libertya CI/CD

Last modified by admin on 2026/07/18 17:44

Show last authors
1 = Pestaña 1 {{id name="pestaña-1" /}}=
2
3 **Libertya CI/CD**
4
5 Análisis e implementación de mejoras en la metodología de desarrollo Libertya mediante CI/CD y testing automation.
6
7 [[image:image1.png]]\\[[image:image2.png]]
8
9 = **Índice** {{id name="índice" /}}=
10
11 {{toc/}}
12
13 = **Objetivo** {{id name="objetivo" /}}=
14
15 El objetivo de este documento es detallar el análisis, tareas realizadas y proporcionar información útil acerca de la implementación de automatización en la metodología de desarrollo de Libertya. La idea es apuntar a un pipeline CI/CD que ayude a automatizar diferentes etapas del proceso, así como también incorporar el uso de tests. Para lograr llevar adelante estas mejoras, se propone la utilización de Jenkins https://www.jenkins.io/
16
17 = **Acceso a Jenkins** {{id name="acceso-a-jenkins" /}}=
18
19 Se configuró Jenkins para acceder por medio de tunel ssh en el puerto 9090.
20
21 Conectarse de esta forma:
22
23 |=ssh -p 4565 usuario@138.219.43.229 -L 9090:localhost:9090
24
25 Luego acceder desde el navegador con **localhost:9090**
26
27 *. **Username:** jenkins\\
28 *. **Password:** Bangla…
29
30 **[[image:image3.png]]**
31
32 = **Acceso a SonarQube (deshabilitado)** {{id name="acceso-a-sonarqube-deshabilitado" /}}=
33
34 Se configuró SonarQube para acceder por medio de tunel ssh en el puerto 9000.
35
36 Acceder desde el navegador con **localhost:9000**
37
38 *. **Username:** admin\\
39 *. **Password:** Putra… 424 (con espacio)
40
41 **token (utilizado por jenkins):** squ_6999e9c29d865ed3233d47cb2ec31fb9904f06f2
42
43 [[image:image4.png]]
44
45 = **Información de la instancia** {{id name="información-de-la-instancia" /}}=
46
47 == Nociones generales {{id name="nociones-generales" /}}==
48
49 Todo lo relacionado a Jenkins se encuentra ubicado en el servidor de desarrollo en el directorio /home/jenkins.
50
51 Se encuentra archivo el **docker-compose.yml**
52
53
54 {{code language="bash"}}
55 version: '3.8' services: jenkins: image~: jenkins/jenkins-custom:latest container_name: jenkins restart: unless-stopped user: root privileged: true network_mode: host volumes: - jenkins_home:/var/jenkins_home - /var/run/docker.sock:/var/run/docker.sock - /home/jenkins/reportes:/var/reportes environment: - JAVA_OPTS=-Djenkins.install.runSetupWizard=true - JENKINS_OPTS=--httpPort=9090 postgres: image~: postgres:10.10 container_name: libertya-postgres restart: unless-stopped network_mode: host environment: POSTGRES_DB: libertya_test POSTGRES_USER: libertya POSTGRES_PASSWORD: libertya PGPORT: 5434 volumes: -
56 ./init-db:/docker-entrypoint-initdb.d -
57 ./pgdata:/var/lib/postgresql/data
58 # sonarqube:
59 # image~: sonarqube:latest
60 # container_name: sonarqube
61 # restart: unless-stopped
62 # network_mode: host
63 # ports:
64 # - "9000:9000"
65 # volumes:
66 # - sonarqube_data:/opt/sonarqube/data
67 # - sonarqube_extensions:/opt/sonarqube/extensions
68 # - sonarqube_logs:/opt/sonarqube/logs volumes: jenkins_home:
69 # sonarqube_data:
70 # sonarqube_extensions:
71 # sonarqube_logs:
72 {{/code}}
73
74 Existen 2 contenedores principales, el de jenkins y el de postgres utilizado para almacenar las bases de test de los pipelines.
75
76 Notar que se creó una **imagen custom de jenkins** como solución, ya que fue necesario instalar ciertas herramientas y al reiniciar el contenedor esos cambios se perderían. Actualmente esas herramientas son las siguientes:
77
78 **Instalar jdk11 y zip**
79
80 |=echo “deb http:~/~/deb.debian.org/debian bullseye main” >> /etc/apt/sources.list apt update apt install -y openjdk-11-jdk apt install -y zip
81
82 **Instalar jdk8 (desde servidor)**
83
84
85 {{code language="bash"}}
86 cd /home/jenkins docker
87 cp jdk1.8.0_121.zip jenkins:/opt docker exec -it jenkins bash
88 cd /opt
89 unzip jdk1.8.0_121.zip
90 {{/code}}
91
92 == Cómo reiniciar el servicio? {{id name="cómo-reiniciar-el-servicio" /}}==
93
94 Para reiniciar tanto Jenkins como el Postgres asociado, acceder como root y luego ejecutar lo siguiente:
95
96
97 {{code language="bash"}}
98 #Acceder a la ubicación
99 cd /home/jenkins #Detener los contenedores docker compose down #Levantar los contenedores en modo detach docker compose up -d
100 {{/code}}
101
102 = **Pipelines** {{id name="pipelines" /}}=
103
104 Actualmente existen 2 pipelines principales.
105
106 **Libertya-Core** es el pipeline productivo para Libertya Core. Clona los repositorios de Libertya y lyrestapi, compila, configura y ejecuta el test-set. Finalmente envía un mail con los reportes generados con los tests automáticos.
107
108 **Libertya-Core-Sandbox** es un pipeline copia de Libertya-Core pensado para implementar nuevas funcionalidades y hacer pruebas en el pipeline antes de pisar el pipeline productivo. Es un pipeline de “juguete” que en principio se comporta igual que el productivo pero no envía mails, no pisa los reportes ni ninguna otra acción que pueda repercutir.
109
110 [[image:image5.png]]
111
112 = **Diseño de pipelines** {{id name="diseño-de-pipelines" /}}=
113
114 == Pipeline exploratorio para Libertya-Core {{id name="pipeline-exploratorio-para-libertya-core" /}}==
115
116 🚀 **Desencadenante**
117
118 *. Se realiza un **push a {{code}}master{{/code}}** del repo de **Libertya Core** en GitHub.\\
119 *. Jenkins detecta el cambio y **dispara el pipeline automáticamente**.
120
121 🏗️ **Flujo completo**
122
123 **1. Preparación del entorno**
124
125 *. Se configura el entorno con {{code}}JAVA 11{{/code}}, paths internos ({{code}}OXP_HOME{{/code}}, {{code}}WORKDIR{{/code}}, {{code}}REPORTS_DIR{{/code}}, etc.), y credenciales de DB.\\
126 *. Se definen variables de entorno necesarias para compilar Libertya y ejecutar los tests.
127
128 **2. Clonar y compilar Libertya Core**
129
130 *. Se clona el repo de **Libertya** desde GitHub ({{code}}branch: master{{/code}}).\\
131 *. Se obtiene el **commit hash** actual ({{code}}LIBERTYA_COMMIT{{/code}}).\\
132 *. Se le dan permisos de ejecución a los scripts {{code}}.sh{{/code}}.\\
133 *. Se ejecuta el script {{code}}utils_dev/Compilar.sh{{/code}} para compilar el sistema.
134
135 **3. Generación de Keystore**
136
137 *. Se genera un **keystore Java ({{code}}myKeystore{{/code}})** si no existe, necesario para la ejecución de ConfigurarAuto.sh
138
139 **4. Configuración de Libertya**
140
141 *. Se copia el archivo {{code}}LibertyaEnv.properties{{/code}} desde el **Config File Provider** de Jenkins.\\
142 *. Se le da permiso de ejecución a todos los scripts.\\
143 *. Se ejecuta {{code}}ConfigurarAuto.sh{{/code}} para inicializar la instalación.
144
145 **5. Limpieza del jar OXPXLib**
146
147 *. Se eliminan clases conflictivas ({{code}}org.slf4j.impl.*{{/code}}) y metainformación innecesaria del {{code}}.jar{{/code}} ({{code}}META-INF/INDEX.LIST{{/code}}).
148
149 **6. Clonar LYRestAPI**
150
151 *. Se clona el repo de **lyrestapi** desde GitHub ({{code}}branch: main{{/code}}).\\
152 *. Se guarda el **commit hash** ({{code}}LYRESTAPI_COMMIT{{/code}}).
153
154 **7. Ejecución de Tests**
155
156 *. Se usa **Java 8** (temporal downgrade) para ejecutar los tests.\\
157 *. Se corre {{code}}./gradlew clean test --info{{/code}} desde el directorio {{code}}lyrestapi{{/code}}.
158
159 🧾 **Post build (siempre se ejecuta)**
160
161 ✅ **Si los tests pasan o fallan:**
162
163 *. Se copian los reportes HTML de los tests al directorio {{code}}/var/reportes{{/code}}.\\
164 *. Se ajustan permisos para que estén disponibles públicamente en http://lycore-tests.libertya.office-on-the.net/
165
166 📧 **Se envía un email HTML con:**
167
168 *. Estado del build ({{code}}SUCCESS{{/code}} o {{code}}FAILURE{{/code}})\\
169 *. Fecha y hora\\
170 *. Commit de Libertya\\
171 *. Commit de LYRestAPI\\
172 *. Link al reporte de tests
173
174 == Pipelines para ramas dev y master {{id name="pipelines-para-ramas-dev-y-master" /}}==
175
176 ✅ 2 Pipelines separados en Jenkins: uno para {{code}}dev{{/code}} y otro para {{code}}master{{/code}}
177
178 1. 🛠️ Pipeline {{code}}dev{{/code}} (Integración continua)
179
180 *. **Trigger**: push en {{code}}dev{{/code}}\\
181 *. **Qué hace**:
182 **. Compila\\
183 **. Ejecuta tests automáticos\\
184 **. despliega en entorno //de testing manual//\\
185 *. **Resultado esperado**: Confirmar que lo nuevo no rompe nada. Si falla, no se hace el PR a {{code}}master{{/code}}.
186
187 🎯 Este es el filtro de calidad previo.
188
189
190 ----
191
192 1. 🚀 Pipeline {{code}}master{{/code}} (Despliegue continuo)
193
194 *. **Trigger**: merge a {{code}}master{{/code}} (después del PR aprobado desde {{code}}dev{{/code}})\\
195 *. **Qué hace**:
196 **. Repite la build\\
197 **. Corre los tests automáticos nuevamente\\
198 **. Hace deploy del release (//release server//, //prod//, etc.)\\
199 **. (Opcional) versiona, taguea, sube binarios, etc.
200
201 🎯 Este pipeline representa la versión oficial y estable.
202
203
204 ----
205
206 🧠 ¿Por qué dos pipelines?
207
208 Porque **la intención y los riesgos de cada rama son distintos**:
209
210 |=Rama |=Pipeline |=Objetivo |=Despliegue
211 |{{code}}dev{{/code}} |CI |Validar cambios antes del merge |Staging (opcional)
212 |{{code}}master{{/code}} |CD |Versión estable para producción |Producción
213
214 == Automatización de otros proyectos y consideración de metadata {{id name="automatización-de-otros-proyectos-y-consideración-de-metadata" /}}==
215
216 Otros proyectos van a requerir sus propios pipelines, como LYEI o LocaleAR. Estos a su vez deberían ser tenidos en cuenta para integrarse en el deploy automático a la instancia de testing manual. En caso de exportar un release de estos proyectos, se incluiría tanto binarios como metadata completa, pero para exportar a la instancia de testing manual, se tienen que ajustar algunos parámetros ya que la metadata se instala de forma incremental. Esto impacta directamente en los ID de changelogs a considerar en cada incremento.
217
218 **Opcion 1:** parametrizar el archivo devinfo.properties dentro del pipeline.
219
220 Se podría utilizar sed, awk, envsubst o alguna herramienta similar que pise valores específicos, por ejemplo, el {{code}}ExportChangelogFromID{{/code}} Para ajustar la versión a instalar en el entorno de pruebas. Al ser incremental, la base de datos de test ya tendría la metadata previa, entonces habría que parametrizar los changelogs a incluir.
221
222 **IMPORTANTE:** Para realizar esto, es necesario sanitizar el preinstall de LYEI. Actualmente tiene instrucciones del tipo “CREATE TABLE” que dan error en la instalación si esas tablas ya fueron creadas.
223
224 **Opcion 2:** Modificar clases de Libertya para lograr cierta flexibilidad a la hora de realizar un export o install. Por ejemplo, modificar la clase ExportPlugin para que permita tomar variables de entorno con prioridad en lugar de tomar únicamente los valores por defecto de devinfo.properties. También se podría investigar si es posible modificar el [[PluginInstaller.sh>>http://PluginInstaller.sh]] (y clases java asociadas) para instalar un componente de forma más flexible. Por ejemplo instalar los changelogs faltantes de la versión actual e ignorar los que ya fueron instalados, en lugar de tener que exportar el rango exacto a instalar.
225
226 = **Cambios en metodología de Desarrollo – Flujo de ramas y automatización** {{id name="cambios-en-metodología-de-desarrollo-flujo-de-ramas-y-automatización" /}}=
227
228 == Ramas {{id name="ramas" /}}==
229
230 **dev**
231
232 *. **Rama libre** de trabajo diario
233 *. Todos los desarrolladores pueden hacer **push directo** a esta rama
234 *. Cada push dispara el pipeline CI/CD (build + tests automáticos).
235
236 **master**
237
238 *. Rama estable y protegida.
239 *. **No se puede pushear directamente**.
240 *. Solo se actualiza vía Pull Request (PR) desde {{code}}dev{{/code}}.
241 *. Representa siempre el estado listo para producción/release.
242
243 == Flujo de trabajo {{id name="flujo-de-trabajo" /}}==
244
245 **1. Trabajo diario**
246
247 *. Cada dev hace sus cambios y pushea a la rama dev (directamente o mediante branches personales, si lo prefiere).
248 *. El pipeline de Jenkins corre automáticamente con cada cambio en {{code}}dev{{/code}}:
249
250 **. Compila el proyecto.
251 **. Ejecuta todos los tests automáticos.
252 **. Al finalizar, **envía un email** a todos los desarrolladores con los resultados (éxito o errores de los tests).
253
254 Ejemplo de notificación implementada:
255
256 [[image:image6.png]]
257
258 **2. Preparación para nuevo release**
259
260 Cuando {{code}}dev{{/code}} está estable y **todos los tests pasan**, cualquier integrante puede proponer un **Pull Request (PR)** de {{code}}dev{{/code}} hacia {{code}}master{{/code}} desde la web de GitHub.
261
262 El pipeline podría volverse a ejecutar sobre {{code}}master{{/code}} después del merge para asegurar estabilidad final.
263
264 **3. Generación y distribución del release**
265
266 *. Una vez que el PR se aprueba y mergea en {{code}}master{{/code}}, Jenkins dispara automáticamente el pipeline de release:
267
268 **. Se asigna un nuevo **número de versión** (versionado automático).
269 **. Se genera el ejecutable/distribuible.
270 **. Se publica o distribuye en el servidor de releases.
271
272 = **Bitácora de implementación** {{id name="bitácora-de-implementación" /}}=
273
274 Se detallan a continuación las tareas realizadas en función de avanzar con la implementación del entorno y pipelines.
275
276 Se instaló Jenkins mediante docker en el servidor de desarrollo. Se creó el directorio /home/jenkins para centralizar todo lo relacionado a la herramienta.
277
278 Se configuró la red en modo host y el puerto de Jenkins 9090.
279
280 El archivo docker-compose.yml utilizado al momento de redactar este documento es el siguiente:
281
282
283 {{code language="bash"}}
284 version: '3.8' services: jenkins: image~: jenkins/jenkins:lts container_name: jenkins restart: unless-stopped user: root privileged: true network_mode: host volumes: - jenkins_home:/var/jenkins_home - /var/run/docker.sock:/var/run/docker.sock environment: - JAVA_OPTS=-Djenkins.install.runSetupWizard=true - JENKINS_OPTS=--httpPort=9090 postgres: image~: postgres:10.10 container_name: libertya-postgres restart: unless-stopped network_mode: host environment: POSTGRES_DB: libertya_test POSTGRES_USER: libertya POSTGRES_PASSWORD: libertya PGPORT: 5434 volumes: -
285 ./init-db:/docker-entrypoint-initdb.d volumes: jenkins_home:
286 {{/code}}
287
288 Se configuraron las credenciales para Github y SVN. Estas son necesarias para interactuar con los repositorios y poder clonar los proyectos.
289
290 Se creó un pipeline inicial para probar las funcionalidades básicas como clonación de repositorios, ejecución de scripts, etc… Se probaron también diferentes formas de ejecutar el pipeline, mediante el uso de Jenkinsfile en el repositorio y mediante un script dentro del propio Jenkins.
291
292 Se configuró un contenedor para postgres (ya especificado en el docker-compose.yml) que se levanta junto a Jenkins para instanciar la base de datos de test. Al crear el contenedor se toma el dump ubicado en el directorio init-db que es una base de datos preparada para testing actualmente basada en Libertya 22.
293
294 Se mejoró iterativamente el pipeline, probando diferentes ejecuciones y actualmente se pueden clonar los repositorios de Libertya y lyrestapi, disparar la compilación de Libertya, etc…
295
296 La compilación de Libertya falla con el script ./[[Compilar.sh>>http://Compilar.sh]] debido a que intenta utilizar el jdk17 que está por defecto en la instancia. Se configuró el openjdk-11 desde el contenedor para utilizar en el pipeline.
297
298 == Configuración de JDK para pipeline {{id name="configuración-de-jdk-para-pipeline" /}}==
299
300 Por defecto, el contenedor de Jenkins tenía configurado Java 17. Para instalar Java 11, se siguieron los siguientes pasos:
301
302 **1. Actualizar las fuentes del sistema operativo (Debian):**\\El paquete {{code}}openjdk-11-jdk{{/code}} no estaba disponible inicialmente. Para solucionarlo se agregó el repositorio adecuado:
303
304 |=echo “deb http:~/~/deb.debian.org/debian bullseye main” >> /etc/apt/sources.list apt update apt install -y openjdk-11-jdk
305
306 **2. Configuración de la instalación del JDK en Jenkins**
307
308 Una vez instalado el JDK, se registró manualmente en Jenkins:
309
310 1. Ir a: **Jenkins > Administrar Jenkins > Global Tool Configuration**
311 1. Buscar la sección **JDK**
312 1. Añadir una nueva entrada con los siguientes valores:
313
314 1*. **Nombre**: {{code}}java-11-openjdk-amd64{{/code}}
315 1*. **JAVA_HOME**: {{code}}/usr/lib/jvm/java-11-openjdk-amd64{{/code}}
316 1*. Desmarcar la opción **“Instalar automáticamente”** (ya que ya está instalado en el sistema).
317
318 **3. Uso del JDK desde un Jenkinsfile**
319
320 Para utilizar este JDK en un pipeline declarativo, se incluyó la configuración del JDK en la sección {{code}}tools{{/code}}, y luego se actualizó el {{code}}PATH{{/code}}:
321
322
323 {{code language="bash"}}
324 tools { jdk 'java-11-openjdk-amd64' } environment { JAVA_HOME = "${tool 'java-11-openjdk-amd64'}" PATH = "${env.JAVA_HOME}/bin:${env.PATH}" }
325 {{/code}}
326
327 **Nota**: Para la ejecución de lyrestapi se configuró java-8-temurin de manera similar en /opt/jdk8u452-b09
328
329 [[image:image7.png]]
330
331 El error persiste:
332
333 [mkdir] Created dir: /var/jenkins_home/workspace/Libertya-Core/libertya/install/compilacion/ServidorOXP/jboss/server\\[copy] Copying 284 files to /var/jenkins_home/workspace/Libertya-Core/libertya/install/compilacion/ServidorOXP/jboss/server\\[zip] Building zip: /var/jenkins_home/workspace/Libertya-Core/install/ServidorOXP_V22.0.zip
334
335 **BUILD FAILED**\\/var/jenkins_home/workspace/Libertya-Core/libertya/utils_dev/build.xml:32: The following error occurred while executing this line:\\/var/jenkins_home/workspace/Libertya-Core/libertya/install/build.xml:218: Problem creating zip: /var/jenkins_home/workspace/Libertya-Core/install/ServidorOXP_V22.0.zip (No such file or directory) (and the archive is probably corrupt but I could not delete it)Total time: 1 minute 31 seconds\\Se intentó modificar los scripts y/o pipeline para poder alterar los directorios donde se exporta Libertya ([[Compilar.sh>>http://Compilar.sh]], build.xml, [[VariablesCompilacion.sh>>http://VariablesCompilacion.sh]], etc..)
336
337 Se logró realizar la compilación. Da errores al descomprimir el zip pero se probó realizar la descompresión manualmente dentro del pipeline:
338
339 Env.
340
341
342 {{code language="bash"}}
343 environment { WORKDIR = '/var/jenkins_home/workspace/Libertya-Core' JAVA_HOME = "${tool 'java-11-openjdk-amd64'}" PATH = "${env.JAVA_HOME}/bin:${env.PATH}" OXP_ROOT = '$(pwd)' DB_NAME = 'libertya_test' DB_USER = 'libertya' DB_PASS = 'libertya' DB_PORT = '5434' }
344 {{/code}}
345
346 Stage “Clonar y Compilar Libertya”
347
348
349 {{code language="bash"}}
350 stage('Clonar y Compilar Libertya') { steps { dir('libertya'){ git branch: 'master', url: 'https://github.com/Disytel-Consulting-SA/libertya.git' sh ''' echo "==> Listando directorios y archivos" ls -lhst INSTALL_DIR="${WORKDIR}/install"
351 mkdir -p ${INSTALL_DIR}
352 chmod -R u+w ${INSTALL_DIR} echo "==> Habilitando permisos de ejecución..." find . -type f -name "*.sh" -exec
353 chmod \+x {} \\; echo "==> Ejecutando script de compilación..."
354 cd utils_dev &&
355 ./Compilar.sh #echo "==> Descomprimiendo..." OXP_HOME="${WORKDIR}/ServidorOXP"
356 unzip ${INSTALL_DIR}/ServidorOXP_V22.0.zip -d ${WORKDIR} ''' } } }
357 {{/code}}
358
359 Consiguiendo que Libertya quede en el workspace dentro de ServidorOXP.\\[[image:image8.png]]\\Lógicamente esto se buscó para no utilizar las rutas por defecto como /ServidorOXP o /install ya que se escapan del contexto del pipeline (workdir). La idea es que todo quede contenido en el propio workdir del pipeline para no correr el riesgo de mezclar datos con otros pipelines.
360
361 Para tener una versión preparada de LibertyaEnv.properties se configuró el plugin Config File Provider que permite administrar archivos de configuración (como {{code}}.properties{{/code}}, {{code}}.xml{{/code}}, etc.) directamente desde Jenkins y usarlos en los pipelines o jobs.
362
363 Se puede acceder desde **Administrar Jenkins > Managed files**
364
365 [[image:image9.png]]
366
367 Ejecución de [[ConfigurarAuto.sh>>http://ConfigurarAuto.sh]]
368
369 + ./ConfigurarAuto.sh\\=======================================\\Comenzando Configuraci�n …\\=======================================\\Validando existencia de clases duplicadas en ./lib/plugins\\Sin archivos para procesar.
370
371 …\\…\\…
372
373 [delete] Deleting directory /var/jenkins_home/workspace/Libertya-Core/ServidorOXP/nuevosComponents\\[delete] Deleting directory /var/jenkins_home/workspace/Libertya-Core/ServidorOXP/backupOXP\\[echo] KeyStore=/var/jenkins_home/workspace/Libertya-Core/ServidorOXP/keystore/myKeystore - Alias=libertya\\[signjar] Signing JAR: /var/jenkins_home/workspace/Libertya-Core/ServidorOXP/lib/OXPXLib.jar\\**[signjar] jarsigner error: java.lang.RuntimeException: keystore load: /var/jenkins_home/workspace/Libertya-Core/ServidorOXP/keystore/myKeystore (No such file or directory)**
374
375 **BUILD FAILED**\\**/var/jenkins_home/workspace/Libertya-Core/ServidorOXP/build.xml:414: exec returned: 1**
376
377 Total time: 26 seconds
378
379 Luego de revisar la ejecución y hacer pruebas locales, se observó que no fue creado **ServidorOXP/keystore/myKeystore** en jenkins. Probablemente por algo ocurrido en el proceso de compilación.
380
381 Se modificó [[**VariablesCompilacion.sh**>>http://VariablesCompilacion.sh]] desde Github para hacer mas flexible la toma de variables para compilacion, ahora seteando un OXP_HOME adaptado a jenkins se debería poder compilar correctamente.
382
383 Se realizaron modificaciones en Libertya CORE pero aun así se tiene el problema de la keystore. Se va a configurar manualmente para que permita firmar los Jars a la hora de ejecutar el [[ConfigurarAuto.sh>>http://ConfigurarAuto.sh]]
384
385 Se optó por incluir la configuración de keystore desde el propio pipeline:
386
387
388 {{code language="bash"}}
389 stage('Preparar keystore') { steps { sh '''
390 mkdir -p ${OXP_HOME}/keystore if [ ! -f ${OXP_HOME}/keystore/myKeystore ]; then keytool -genkey -keyalg RSA \ -alias libertya \ -dname "CN=Jenkins, OU=CI, O=TuEmpresa, L=Ciudad, ST=Provincia, C=AR" \ -keypass libertya \ -storepass libertya \ -validity 365 \ -keystore ${OXP_HOME}/keystore/myKeystore fi ''' } }
391 {{/code}}
392
393 La ejecución final funcionó correctamente.
394
395 BUILD SUCCESSFUL\\Total time: 1 minute 8 seconds
396
397 ~*~** 2025-06-12 02:01:46.38 OpenXpertya Log (CLogConsole) ~*~**
398
399 Si se examina el workspace se puede observar como quedó compilado Libertya:\\[[image:image10.png]]
400
401 Se configuró el pipeline para tomar lyrestapi y ejecutar los tests. Actualmente falla porque lyrestapi aun no es compatible con jdk11. Se va a configurar un jdk8 para poder hacer esta ejecución.
402
403 > Task :compileJava FAILED\\/var/jenkins_home/workspace/Libertya-Core/lyrestapi/src/main/java/org/libertya/api/controller/AbstractController.java:16: error: package javax.rmi.CORBA does not exist\\import javax.rmi.CORBA.Util;\\^\\Note: /var/jenkins_home/workspace/Libertya-Core/lyrestapi/src/main/java/org/libertya/api/security/WebSecurityConfig.java uses or overrides a deprecated API.\\Note: Recompile with -Xlint:deprecation for details.\\1 error
404
405 FAILURE: Build failed with an exception.
406
407 Se configuró jdk-8-temurin y se volvió a ejecutar:
408
409 java -version\\openjdk version “1.8.0_452”\\OpenJDK Runtime Environment (Temurin)(build 1.8.0_452-b09)\\OpenJDK 64-Bit Server VM (Temurin)(build 25.452-b09, mixed mode)\\[Pipeline] sh\\+ chmod +x ./gradlew\\[Pipeline] sh
410
411 + ./gradlew clean test\\Starting a Gradle Daemon (subsequent builds will be faster)
412
413 > Task :clean UP-TO-DATE
414
415 > Task :compileJava\\Note: /var/jenkins_home/workspace/Libertya-Core/lyrestapi/src/main/java/org/libertya/api/security/WebSecurityConfig.java uses or overrides a deprecated API.\\Note: Recompile with -Xlint:deprecation for details.\\Note: Some input files use unchecked or unsafe operations.\\Note: Recompile with -Xlint:unchecked for details.
416
417 > Task :processResources\\> Task :classes
418
419 > Task :compileTestJava\\> Task :processTestResources NO-SOURCE\\> Task :testClasses
420
421 > Task :test
422
423 AllocationIntegrationTests > initializationError FAILED\\java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:98\\Caused by: java.lang.IllegalArgumentException at Assert.java:702
424
425 BPartnerIntegrationTests > initializationError FAILED\\java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:98\\Caused by: java.lang.IllegalArgumentException at Assert.java:702
426
427 BPartnerLocationIntegrationTests > initializationError FAILED\\java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:98\\Caused by: java.lang.IllegalArgumentException at Assert.java:702
428
429 BanksAccountsIntegrationTests > initializationError FAILED\\java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:98\\Caused by: java.lang.IllegalArgumentException at Assert.java:702
430
431 BanksIntegrationTests > initializationError FAILED\\java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:98\\Caused by: java.lang.IllegalArgumentException at Assert.java:702
432
433 CashBooksIntegrationTests > initializationError FAILED\\java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:98\\Caused by: java.lang.IllegalArgumentException at Assert.java:702
434
435 Se obtuvieron varios errores que en local no ocurren. Se procede a cambiar el jdk por una version de oracle.
436
437 AllocationIntegrationTests > initializationError FAILED java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:98 Caused by: java.lang.IllegalArgumentException at Assert.java:702
438
439 Se sigue obteniendo el mismo error. Se ejecutó gradlew clean test –info
440
441 Successfully started process ‘Gradle Test Executor 1’
442
443 Gradle Test Executor 1 started executing tests.
444
445 > Task :test
446
447 AllocationIntegrationTests STANDARD_OUT\\- Neither @ContextConfiguration nor @ContextHierarchy found for test class [org.libertya.api.AllocationIntegrationTests], using SpringBootContextLoader\\- Could not detect default resource locations for test class [org.libertya.api.AllocationIntegrationTests]: no resource found for suffixes {-context.xml, Context.groovy}.\\- Could not detect default configuration classes for test class [org.libertya.api.AllocationIntegrationTests]: AllocationIntegrationTests does not declare any static, non-private, non-final, nested classes annotated with @Configuration.\\- Found @SpringBootConfiguration org.libertya.api.LYRestAPI for test class org.libertya.api.AllocationIntegrationTests\\- Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener, org.springframework.boot.test.autoconfigure.webservices.client.MockWebServiceServerTestExecutionListener, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener, org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.event.ApplicationEventsTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener, org.springframework.test.context.event.EventPublishingTestExecutionListener]\\- Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@75390459, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@7756c3cd, org.springframework.test.context.event.ApplicationEventsTestExecutionListener@2313052e, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener@2bd2b28e, org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@16746061, org.springframework.test.context.support.DirtiesContextTestExecutionListener@57fd91c9, org.springframework.test.context.event.EventPublishingTestExecutionListener@6cfcd46d, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener@52045dbe, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener@674658f7, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener@5c8eee0f, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener@565b064f, org.springframework.boot.test.autoconfigure.webservices.client.MockWebServiceServerTestExecutionListener@26425897, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener@73163d48]
448
449 *. Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@16746061] to prepare test instance [org.libertya.api.AllocationIntegrationTests@419a20a6]\\java.lang.IllegalStateException: Failed to load ApplicationContext\\at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:98)\\at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124)\\at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)\\at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)\\at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:43)\\at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:248)\\at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:138)\\at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda~$invokeTestInstancePostProcessors~$8(ClassBasedTestDescriptor.java:363)\\at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:368)\\at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda~$invokeTestInstancePostProcessors~$9(ClassBasedTestDescriptor.java:363)\\at java.util.stream.ReferencePipeline~$3~$1.accept(ReferencePipeline.java:193)\\at java.util.stream.ReferencePipeline~$2~$1.accept(ReferencePipeline.java:175)\\at java.util.ArrayList~$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)\\at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)\\at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)\\at java.util.stream.StreamSpliterators~$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312)\\at java.util.stream.Streams~$ConcatSpliterator.forEachRemaining(Streams.java:743)\\at java.util.stream.ReferencePipeline~$Head.forEach(ReferencePipeline.java:580)\\at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:362)\\at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda~$instantiateAndPostProcessTestInstance~$6(ClassBasedTestDescriptor.java:283)\\at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)\\at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:282)\\at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda~$testInstancesProvider~$4(ClassBasedTestDescriptor.java:272)\\at java.util.Optional.orElseGet(Optional.java:267)\\at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda~$testInstancesProvider~$5(ClassBasedTestDescriptor.java:271)\\at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31)\\at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda~$before~$2(ClassBasedTestDescriptor.java:197)\\at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)\\at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:196)\\at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:80)\\at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda~$executeRecursively~$6(NodeTestTask.java:148)\\at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)\\at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda~$executeRecursively~$8(NodeTestTask.java:141)\\at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)\\at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda~$executeRecursively~$9(NodeTestTask.java:139)\\at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)\\at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)\\at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)\\at java.util.ArrayList.forEach(ArrayList.java:1249)\\at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)\\at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda~$executeRecursively~$6(NodeTestTask.java:155)\\at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)\\at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda~$executeRecursively~$8(NodeTestTask.java:141)\\at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)\\at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda~$executeRecursively~$9(NodeTestTask.java:139)\\at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)\\at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)\\at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)\\at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)\\at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)\\at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)\\at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)\\at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)\\at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda~$execute~$0(EngineExecutionOrchestrator.java:54)\\at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)\\at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)\\at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)\\at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)\\at org.junit.platform.launcher.core.DefaultLauncherSession~$DelegatingLauncher.execute(DefaultLauncherSession.java:86)\\at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)\\at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor~$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)\\at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor~$CollectAllTestClassesExecutor.access~$000(JUnitPlatformTestClassProcessor.java:79)\\at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)\\at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)\\at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\\at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\\at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\\at java.lang.reflect.Method.invoke(Method.java:498)\\at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)\\at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)\\at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)\\at org.gradle.internal.dispatch.ProxyDispatchAdapter~$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)\\at com.sun.proxy.~$Proxy2.stop(Unknown Source)\\at org.gradle.api.internal.tasks.testing.worker.TestWorker~$3.run(TestWorker.java:193)\\at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)\\at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)\\at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)\\at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)\\at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)\\at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)\\at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)\\at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)\\Caused by: java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. Either remove Logback or the competing implementation (class org.slf4j.impl.JDK14LoggerFactory loaded from file:/var/jenkins_home/workspace/Libertya-Core/ServidorOXP/lib/OXPXLib.jar). If you are using WebLogic you will need to add ‘org.slf4j’ to prefer-application-packages in WEB-INF/weblogic.xml: org.slf4j.impl.JDK14LoggerFactory\\at org.springframework.util.Assert.instanceCheckFailed(Assert.java:702)\\at org.springframework.util.Assert.isInstanceOf(Assert.java:621)\\at org.springframework.boot.logging.logback.LogbackLoggingSystem.getLoggerContext(LogbackLoggingSystem.java:294)\\at org.springframework.boot.logging.logback.LogbackLoggingSystem.beforeInitialize(LogbackLoggingSystem.java:118)\\at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationStartingEvent(LoggingApplicationListener.java:238)\\at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:220)\\at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)\\at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)\\at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)\\at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:131)\\at org.springframework.boot.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:79)\\at org.springframework.boot.SpringApplicationRunListeners.lambda~$starting~$0(SpringApplicationRunListeners.java:56)\\at java.util.ArrayList.forEach(ArrayList.java:1249)\\at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:120)\\at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:56)\\at org.springframework.boot.SpringApplication.run(SpringApplication.java:298)\\at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:136)\\at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:141)\\at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:90)\\… 81 more
450
451 Luego de análisis y consultas, se modificó el pipeline para eliminar org/slf4j/impl y el index
452
453 zip -d OXPXLib.jar “org/slf4j/impl/*”\\zip -d OXPXLib.jar “META-INF/INDEX.LIST”
454
455 Para esto fue necesario instalar ZIP en el contenedor de jenkins.
456
457 Se configuraron las notificaciones por email mediante Extended email plugin.
458
459 [[image:image11.png]]
460
461 Node 22 y pnpm
462
463 Se instaló Node 22 y pnpm 9.6.0 para el deploy del pos-web y productos afines
464
465 curl -fsSL https:~/~/deb.nodesource.com/setup_22.x | bash -\\apt-get install -y nodejs\\npm install -g pnpm@9.6.0
466
467 == SonarQube {{id name="sonarqube" /}}==
468
469 Se realizaron pruebas a nivel local con SonarQube para el análisis de código, con la posibilidad de integrarlo en el pipeline junto con los tests automáticos.
470
471 |=services: sonarqube: image~: sonarqube:latest ports: - “9000:9000” volumes: - sonarqube_data:/opt/sonarqube/data - sonarqube_extensions:/opt/sonarqube/extensions - sonarqube_logs:/opt/sonarqube/logs volumes: sonarqube_data: sonarqube_extensions: sonarqube_logs:
472
473 [[image:image12.png]][[image:image13.png]]
474
475 Se ejecutó sonar-scanner desde CLI (docker). Para eso fue necesario generar un token desde el servidor de SonarQube para el usuario admin. Después es necesario especificar el directorio donde se encuentra Libertya **compilado**. En este caso se configuró /libertya_export
476
477 |=docker run \ –rm \ -e SONAR_HOST_URL=“http:~/~/172.17.0.1:9000” \ -e SONAR_TOKEN=“squ_69d3653bc7494955e0187e4dee003fef14231bd0” \ -v “/libertya_export:/usr/src” \ sonarsource/sonar-scanner-cli
478
479 Para ejecutar el CLI se tiene que configurar un archivo **sonar-project.properties** en el directorio raiz del proyecto, en este caso directamente en /libertya_export
480
481 |=sonar.projectKey=libertya sonar.projectName=Libertya ERP sonar.projectVersion=1.0 sonar.sources=base/src,client/Src sonar.java.binaries=base/compilacion,client/compilacion sonar.sourceEncoding=UTF-8
482
483 Uno de los errores que surgieron en la ejecución fue:\\22:39:23.573 INFO Sensor JavaSensor [java]\\22:39:23.593 ERROR Error during SonarScanner Engine execution\\org.sonar.java.AnalysisException: Your project contains .java files, please provide compiled classes with sonar.java.binaries property, or exclude them from the analysis with sonar.exclusions property.\\at org.sonar.java.classpath.ClasspathForMain.init(ClasspathForMain.java:70)\\at org.sonar.java.classpath.AbstractClasspath.getElements(AbstractClasspath.java:316)\\at org.sonar.java.SonarComponents.getJavaClasspath(SonarComponents.java:250)\\at org.sonar.java.JavaFrontend.<init>(JavaFrontend.java:92)
484
485 Esto se debe a que la CLI no encuentra los .class del proyecto. Se debe configurar explicitamente donde encontrarlos en el archivo **sonar-project.properties.** Para eso se utiliza la línea **sonar.java.binaries=base/compilacion,client/compilacion.** En este caso se incluyeron solamente los .class de esos directorios. Lógicamente no hay que tener en cuenta directorios relacionados a librerías como tools/ etc..
486
487 Una vez ejecutado, va a aparecer el reporte en el servidor de sonarqube:\\[[image:image14.png]]
488
489 [[image:image15.png]]
490
491 Dentro de Jenkins se instaló el plugin SonarQube Scanner, luego en Tools se configuró:\\[[image:image16.png]]
492
493 y luego en administrar jenkins -> system se agrega el server
494
495 [[image:image17.png]]
496
497 Se configuró un pipeline de pruebas para la ejecución de SonarQube, los stages relevantes son los siguientes:
498
499
500 {{code language="bash"}}
501 stage('Analizar con SonarQube') { tools { jdk 'jdk-17' } steps { dir('libertya') { script { def scannerHome = tool 'SonarQube-Scanner' withSonarQubeEnv("${SONARQUBE_SERVER}") { sh """ ${scannerHome}/bin/sonar-scanner \ -Dsonar.projectKey=libertya \ -Dsonar.projectName="Libertya ERP" \ -Dsonar.projectVersion=1.0 \ -Dsonar.sources=base/src,client/Src \ -Dsonar.java.binaries=base/compilacion,client/compilacion \ -Dsonar.sourceEncoding=UTF-8 \ -Dsonar.token=${SONARQUBE_TOKEN} """ } } } } } stage('Esperar Quality Gate') { steps { timeout(time: 10, unit: 'MINUTES') { waitForQualityGate abortPipeline: true } } }
502 {{/code}}
503
504 Aún así, se presentaron errores en la ejecución:
505
506 02:29:41.092 **WARN Invalid character encountered in file /var/jenkins_home/workspace/test/libertya/base/src/org/openXpertya/model/MRole.java at line 2 for encoding UTF-8. Please fix file content or configure the encoding to be used using property ‘sonar.sourceEncoding’.**\\02:29:46.206 **WARN** Invalid character encountered in file /var/jenkins_home/workspace/test/libertya/base/src/org/openXpertya/model/MAttributeSet.java at line 173 for encoding UTF-8. Please fix file content or configure the encoding to be used using property ‘sonar.sourceEncoding’.\\02:29:49.441 **WARN** Invalid character encountered in file /var/jenkins_home/workspace/test/libertya/base/src/org/openXpertya/model/MOrder.java at line 3550 for encoding UTF-8. Please fix file content or configure the encoding to be used using property ‘sonar.sourceEncoding’.\\02:30:10.808 **WARN** Invalid character encountered in file /var/jenkins_home/workspace/test/libertya/base/src/org/openXpertya/print/ArchiveEngine.java at line 125 for encoding UTF-8. Please fix file content or configure the encoding to be used using property ‘sonar.sourceEncoding’.\\02:30:21.575 INFO 42% analyzed\\02:30:37.897 INFO 43% analyzed\\02:30:42.794 **WARN** Invalid character encountered in file /var/jenkins_home/workspace/test/libertya/client/Src/org/openXpertya/grid/ed/VPAttributeDialog.java at line 1134 for encoding UTF-8. Please fix file content or configure the encoding to be used using property ‘sonar.sourceEncoding’.\\02:30:42.847 **WARN** Invalid character encountered in file /var/jenkins_home/workspace/test/libertya/base/src/org/openXpertya/model/MQuarter.java at line 251 for encoding UTF-8. Please fix file content or configure the encoding to be used using property ‘sonar.sourceEncoding’.\\**02:30:56.626 ERROR [stderr] OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000c5200000, 378535936, 0) failed; error=‘Not enough space’ (errno=12)**\\**02:30:56.681 INFO [stdout] #**\\**02:30:56.681 INFO [stdout] # There is insufficient memory for the Java Runtime Environment to continue.**\\**02:30:56.681 INFO [stdout] # Native memory allocation (mmap) failed to map 378535936 bytes. Error detail: committing reserved memory.**\\**02:30:56.682 INFO [stdout] # An error report file with more information is saved as:**\\**02:30:56.682 INFO [stdout] # /var/jenkins_home/workspace/test/libertya/hs_err_pid10107.log**\\**02:30:57.682 INFO EXECUTION FAILURE**\\**02:30:58.539 INFO Total time: 5:32.863s**
507
508 El servidor llegó al límite de memoria, usar Jenkins, SonarQube, Postgres, etc.. es demasiada carga para la memoria actual.
509
510 Se deshabilitó temporalmente la utilización de SonarQUbe por sobrecarga en el servidor.
511
512 Se creó el pipeline Libertya-Core-Sandbox para pruebas que no afecten el pipeline “productivo”.
513
514 Se configuraron credenciales y secrets para transferir builds al server de desarrollo
515
516 = **Referencias** {{id name="referencias" /}}=
517
518 https://www.jenkins.io/doc/book/installing/