Refactor Jenkinsfile to enhance build and deployment processes. Updated agent configuration to use a specific Docker label, improved database readiness checks with error handling, and implemented retry logic for Docker builds and pushes. Additionally, refined SSH key handling and ensured proper tagging for Docker images during the build process.

This commit is contained in:
2026-04-02 11:18:18 -05:00
parent 36424a2e04
commit b784ea1cd5

76
Jenkinsfile vendored
View File

@@ -1,5 +1,7 @@
pipeline {
agent any
agent {
label 'docker'
}
options {
timestamps()
disableConcurrentBuilds()
@@ -57,7 +59,6 @@ pipeline {
DB_NAME="anexo76_test"
DB_USER="anexo76"
DB_PASS="anexo76"
DB_PORT="55432"
export TEST_DATABASE_URL="postgresql://${DB_USER}:${DB_PASS}@${DB_CONTAINER}:5432/${DB_NAME}"
PY_CONTAINER="anexo76-test-py-${BUILD_NUMBER}"
TEST_NETWORK="anexo76-test-net-${BUILD_NUMBER}"
@@ -80,13 +81,19 @@ pipeline {
-e POSTGRES_PASSWORD="$DB_PASS" \
postgres:16-alpine
# Espera a que Postgres acepte conexiones
# Espera a que Postgres acepte conexiones (hasta ~60s)
READY=0
for i in $(seq 1 30); do
if docker exec "$DB_CONTAINER" pg_isready -U "$DB_USER" -d "$DB_NAME" >/dev/null 2>&1; then
READY=1
break
fi
sleep 2
done
if [ "$READY" != "1" ]; then
echo "ERROR: Postgres no quedó listo a tiempo (30 intentos × 2s)."
exit 1
fi
docker exec "$DB_CONTAINER" pg_isready -U "$DB_USER" -d "$DB_NAME"
docker exec "$DB_CONTAINER" psql -U "$DB_USER" -d "$DB_NAME" -v ON_ERROR_STOP=1 -c "
CREATE SCHEMA IF NOT EXISTS core;
@@ -165,33 +172,47 @@ pipeline {
stage('Build + push backend') {
steps {
sh '''
set -euo pipefail
docker build \
--build-arg APP_VERSION="${APP_VERSION}" \
-t "${REGISTRY}/${IMAGE_NAMESPACE}/backend:latest" \
-f ./backend/Dockerfile \
./backend
script {
retry(3) {
sh '''
set -euo pipefail
export DOCKER_BUILDKIT=1
docker build \
--build-arg APP_VERSION="${APP_VERSION}" \
-t "${REGISTRY}/${IMAGE_NAMESPACE}/backend:${APP_VERSION}" \
-t "${REGISTRY}/${IMAGE_NAMESPACE}/backend:latest" \
-f ./backend/Dockerfile \
./backend
docker push "${REGISTRY}/${IMAGE_NAMESPACE}/backend:latest"
'''
docker push "${REGISTRY}/${IMAGE_NAMESPACE}/backend:${APP_VERSION}"
docker push "${REGISTRY}/${IMAGE_NAMESPACE}/backend:latest"
'''
}
}
}
}
stage('Build + push frontend') {
steps {
sh '''
set -euo pipefail
docker build \
--build-arg VITE_API_URL=https://anexo76-dev.aduanasoft.com/api/ \
--build-arg VITE_KEYCLOAK_URL=https://anexo76-dev.aduanasoft.com/kcauth/ \
--build-arg INTERNAL_API_URL=http://backend:3467/api/ \
-t "${REGISTRY}/${IMAGE_NAMESPACE}/frontend:latest" \
-f ./frontend/Dockerfile.prod \
./frontend
script {
retry(3) {
sh '''
set -euo pipefail
export DOCKER_BUILDKIT=1
docker build \
--build-arg VITE_API_URL=https://anexo76-dev.aduanasoft.com/api/ \
--build-arg VITE_KEYCLOAK_URL=https://anexo76-dev.aduanasoft.com/kcauth/ \
--build-arg INTERNAL_API_URL=http://backend:3467/api/ \
-t "${REGISTRY}/${IMAGE_NAMESPACE}/frontend:${APP_VERSION}" \
-t "${REGISTRY}/${IMAGE_NAMESPACE}/frontend:latest" \
-f ./frontend/Dockerfile.prod \
./frontend
docker push "${REGISTRY}/${IMAGE_NAMESPACE}/frontend:latest"
'''
docker push "${REGISTRY}/${IMAGE_NAMESPACE}/frontend:${APP_VERSION}"
docker push "${REGISTRY}/${IMAGE_NAMESPACE}/frontend:latest"
'''
}
}
}
}
@@ -229,13 +250,19 @@ pipeline {
)
]) {
script {
sh """
set -euo pipefail
mkdir -p ~/.ssh
chmod 700 ~/.ssh
ssh-keyscan -T 15 -H '${env.DEV_SERVER_HOST}' >> ~/.ssh/known_hosts
"""
def remote = [
name: 'dev-server',
host: env.DEV_SERVER_HOST,
user: env.DEV_SERVER_USER ?: env.DEV_SERVER_SSH_USER,
identityFile: env.DEV_SERVER_KEY,
passphrase: env.DEV_SERVER_KEY_PASSPHRASE,
allowAnyHosts: true
allowAnyHosts: false
]
sshCommand remote: remote, command: '''
set -euo pipefail
@@ -243,6 +270,7 @@ pipeline {
# Asume docker login ya configurado en el host destino para evitar exponer secretos por interpolación.
docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d
# Solo imágenes colgantes (sin tag); no borra imágenes en uso por otros contenedores.
docker image prune -f
'''
}