From 3597ba89e57ee827ae3a05b5ca353bc68ccf65d1 Mon Sep 17 00:00:00 2001 From: "Amelia (Dev Agent)" Date: Thu, 16 Apr 2026 15:26:59 -0600 Subject: [PATCH] fix(pipeline): hacer pasos de build y deploy condicionales MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit El repositorio proyectosacc actualmente solo contiene infraestructura (Terraform, scripts, nginx). El código de la aplicación se agregará en el futuro. Este cambio hace que los pasos 04_build, 05_publish, 06_install y 07_deploy verifiquen la existencia de archivos de aplicación antes de ejecutar npm/gradle/aws s3/ssh, evitando fallos del pipeline cuando no hay código que compilar o desplegar. --- bitbucket-pipelines.yml | 157 +++++++++++++++++++++++++++++++--------- 1 file changed, 123 insertions(+), 34 deletions(-) diff --git a/bitbucket-pipelines.yml b/bitbucket-pipelines.yml index 22b9fe9..9c9eb67 100644 --- a/bitbucket-pipelines.yml +++ b/bitbucket-pipelines.yml @@ -38,9 +38,20 @@ pipelines: script: - set -euo pipefail - echo "=== Build de proyectosacc (sin deploy) ===" - - npm ci - - npm run build - - ./gradlew clean bootJar + - | + if [ -f package.json ]; then + npm ci + npm run build + else + echo "INFO: No se encontró package.json. Saltando build npm." + fi + - | + if [ -f gradlew ] || [ -f build.gradle ]; then + ./gradlew clean bootJar + else + echo "INFO: No se encontró gradlew ni build.gradle. Saltando build Gradle." + fi + - echo "Build condicional completado." branches: developer: @@ -85,9 +96,20 @@ pipelines: name: 04_build script: - set -euo pipefail - - npm ci - - npm run build - - ./gradlew clean bootJar + - | + if [ -f package.json ]; then + npm ci + npm run build + else + echo "INFO: No se encontró package.json. Saltando build npm." + fi + - | + if [ -f gradlew ] || [ -f build.gradle ]; then + ./gradlew clean bootJar + else + echo "INFO: No se encontró gradlew ni build.gradle. Saltando build Gradle." + fi + - echo "Build condicional completado." artifacts: - build/** - build/libs/*.jar @@ -98,21 +120,44 @@ pipelines: script: - set -euo pipefail - source scripts/aws-oidc-setup.sh dev - - aws s3 sync build/ "s3://${DEV_S3_FRONTEND_BUCKET}/" --delete - - aws s3 cp build/libs/*.jar "s3://${DEV_S3_ARTIFACTS_BUCKET}/develop/proyectosacc-app.jar" + - | + if [ -d build/ ] && [ "$(ls -A build/ 2>/dev/null)" ]; then + aws s3 sync build/ "s3://${DEV_S3_FRONTEND_BUCKET}/" --delete + else + echo "INFO: No se encontró directorio build/ con contenido. Saltando sync a S3." + fi + - | + if ls build/libs/*.jar >/dev/null 2>&1; then + aws s3 cp build/libs/*.jar "s3://${DEV_S3_ARTIFACTS_BUCKET}/develop/proyectosacc-app.jar" + else + echo "INFO: No se encontró JAR en build/libs/. Saltando copia a S3." + fi + - echo "Publish condicional completado." - step: name: 06_install script: - set -euo pipefail - - echo "${DEV_SSH_PRIVATE_KEY_THOTH_PROYECTOSACC}" | base64 -d > ~/.ssh/sacc4_key - - chmod 600 ~/.ssh/sacc4_key - | - ssh -p "${DEV_SSH_PORT_PROYECTOSACC:-22}" \ - -i ~/.ssh/sacc4_key \ - -o StrictHostKeyChecking=no \ - "${DEV_SERVER_USER_PROYECTOSACC:-thoth}@${DEV_SERVER_IP_PROYECTOSACC}" \ - "bash -c 'mkdir -p /home/thoth/deploy/artifacts/current && aws s3 cp s3://${DEV_S3_ARTIFACTS_BUCKET}/develop/proyectosacc-app.jar /home/thoth/deploy/artifacts/current/proyectosacc-app.jar && chown osiris:osiris /home/thoth/deploy/artifacts/current/proyectosacc-app.jar'" + JAR_LOCAL_PATTERN="build/libs/*.jar" + JAR_S3_URI="s3://${DEV_S3_ARTIFACTS_BUCKET}/develop/proyectosacc-app.jar" + HAS_LOCAL_JAR=false + if ls ${JAR_LOCAL_PATTERN} >/dev/null 2>&1; then + HAS_LOCAL_JAR=true + fi + if [ "${HAS_LOCAL_JAR}" = "true" ]; then + echo "INFO: Artefacto JAR encontrado localmente. Procediendo con instalación en servidor." + echo "${DEV_SSH_PRIVATE_KEY_THOTH_PROYECTOSACC}" | base64 -d > ~/.ssh/sacc4_key + chmod 600 ~/.ssh/sacc4_key + ssh -p "${DEV_SSH_PORT_PROYECTOSACC:-22}" \ + -i ~/.ssh/sacc4_key \ + -o StrictHostKeyChecking=no \ + "${DEV_SERVER_USER_PROYECTOSACC:-thoth}@${DEV_SERVER_IP_PROYECTOSACC}" \ + "bash -c 'mkdir -p /home/thoth/deploy/artifacts/current && aws s3 cp ${JAR_S3_URI} /home/thoth/deploy/artifacts/current/proyectosacc-app.jar && chown osiris:osiris /home/thoth/deploy/artifacts/current/proyectosacc-app.jar'" + else + echo "INFO: No se encontró artefacto JAR localmente. Saltando instalación." + fi + - echo "Install condicional completado." - step: name: 07_deploy @@ -127,12 +172,17 @@ pipelines: -i ~/.ssh/sacc4_key \ -o StrictHostKeyChecking=no \ "${DEV_SERVER_USER_PROYECTOSACC:-thoth}@${DEV_SERVER_IP_PROYECTOSACC}" \ - "bash /home/thoth/deploy/setup/deploy.sh" - - export CLOUDFRONT_DISTRIBUTION_ID=$(python3 -c "import json; print(json.load(open('terraform/terraform-outputs.json'))['cloudfront_distribution_id']['value'])") - - aws cloudfront create-invalidation --distribution-id "${CLOUDFRONT_DISTRIBUTION_ID}" --paths "/*" + "bash -c 'if [ -f /home/thoth/deploy/setup/deploy.sh ]; then bash /home/thoth/deploy/setup/deploy.sh; else echo \"INFO: No se encontró script de deploy. Saltando deploy backend.\"; fi'" + - | + if [ -f terraform/terraform-outputs.json ]; then + export CLOUDFRONT_DISTRIBUTION_ID=$(python3 -c "import json; print(json.load(open('terraform/terraform-outputs.json'))['cloudfront_distribution_id']['value'])") + aws cloudfront create-invalidation --distribution-id "${CLOUDFRONT_DISTRIBUTION_ID}" --paths "/*" + else + echo "INFO: No se encontró terraform-outputs.json. Saltando invalidación de CloudFront." + fi - export TELEGRAM_BOT_TOKEN="${DEV_TELEGRAM_BOT_TOKEN}" - export TELEGRAM_CHAT_ID="${DEV_TELEGRAM_CHAT_ID}" - - bash scripts/telegram-pipeline-notify.sh success "CloudFront invalidado" + - bash scripts/telegram-pipeline-notify.sh success "Deploy condicional completado" master: - step: @@ -176,9 +226,20 @@ pipelines: name: 04_build script: - set -euo pipefail - - npm ci - - npm run build - - ./gradlew clean bootJar + - | + if [ -f package.json ]; then + npm ci + npm run build + else + echo "INFO: No se encontró package.json. Saltando build npm." + fi + - | + if [ -f gradlew ] || [ -f build.gradle ]; then + ./gradlew clean bootJar + else + echo "INFO: No se encontró gradlew ni build.gradle. Saltando build Gradle." + fi + - echo "Build condicional completado." artifacts: - build/** - build/libs/*.jar @@ -189,21 +250,44 @@ pipelines: script: - set -euo pipefail - source scripts/aws-oidc-setup.sh prod - - aws s3 sync build/ "s3://${PROD_S3_FRONTEND_BUCKET}/" --delete - - aws s3 cp build/libs/*.jar "s3://${PROD_S3_ARTIFACTS_BUCKET}/main/proyectosacc-app.jar" + - | + if [ -d build/ ] && [ "$(ls -A build/ 2>/dev/null)" ]; then + aws s3 sync build/ "s3://${PROD_S3_FRONTEND_BUCKET}/" --delete + else + echo "INFO: No se encontró directorio build/ con contenido. Saltando sync a S3." + fi + - | + if ls build/libs/*.jar >/dev/null 2>&1; then + aws s3 cp build/libs/*.jar "s3://${PROD_S3_ARTIFACTS_BUCKET}/main/proyectosacc-app.jar" + else + echo "INFO: No se encontró JAR en build/libs/. Saltando copia a S3." + fi + - echo "Publish condicional completado." - step: name: 06_install script: - set -euo pipefail - - echo "${PROD_SSH_PRIVATE_KEY_THOTH_PROYECTOSACC}" | base64 -d > ~/.ssh/sacc4_key - - chmod 600 ~/.ssh/sacc4_key - | - ssh -p "${PROD_SSH_PORT_PROYECTOSACC:-22}" \ - -i ~/.ssh/sacc4_key \ - -o StrictHostKeyChecking=no \ - "${PROD_SERVER_USER_PROYECTOSACC:-thoth}@${PROD_SERVER_IP_PROYECTOSACC}" \ - "bash -c 'mkdir -p /home/thoth/deploy/artifacts/current && aws s3 cp s3://${PROD_S3_ARTIFACTS_BUCKET}/main/proyectosacc-app.jar /home/thoth/deploy/artifacts/current/proyectosacc-app.jar && chown osiris:osiris /home/thoth/deploy/artifacts/current/proyectosacc-app.jar'" + JAR_LOCAL_PATTERN="build/libs/*.jar" + JAR_S3_URI="s3://${PROD_S3_ARTIFACTS_BUCKET}/main/proyectosacc-app.jar" + HAS_LOCAL_JAR=false + if ls ${JAR_LOCAL_PATTERN} >/dev/null 2>&1; then + HAS_LOCAL_JAR=true + fi + if [ "${HAS_LOCAL_JAR}" = "true" ]; then + echo "INFO: Artefacto JAR encontrado localmente. Procediendo con instalación en servidor." + echo "${PROD_SSH_PRIVATE_KEY_THOTH_PROYECTOSACC}" | base64 -d > ~/.ssh/sacc4_key + chmod 600 ~/.ssh/sacc4_key + ssh -p "${PROD_SSH_PORT_PROYECTOSACC:-22}" \ + -i ~/.ssh/sacc4_key \ + -o StrictHostKeyChecking=no \ + "${PROD_SERVER_USER_PROYECTOSACC:-thoth}@${PROD_SERVER_IP_PROYECTOSACC}" \ + "bash -c 'mkdir -p /home/thoth/deploy/artifacts/current && aws s3 cp ${JAR_S3_URI} /home/thoth/deploy/artifacts/current/proyectosacc-app.jar && chown osiris:osiris /home/thoth/deploy/artifacts/current/proyectosacc-app.jar'" + else + echo "INFO: No se encontró artefacto JAR localmente. Saltando instalación." + fi + - echo "Install condicional completado." - step: name: 06b_notify_approval @@ -229,9 +313,14 @@ pipelines: -i ~/.ssh/sacc4_key \ -o StrictHostKeyChecking=no \ "${PROD_SERVER_USER_PROYECTOSACC:-thoth}@${PROD_SERVER_IP_PROYECTOSACC}" \ - "bash /home/thoth/deploy/setup/deploy.sh" - - export CLOUDFRONT_DISTRIBUTION_ID=$(python3 -c "import json; print(json.load(open('terraform/terraform-outputs.json'))['cloudfront_distribution_id']['value'])") - - aws cloudfront create-invalidation --distribution-id "${CLOUDFRONT_DISTRIBUTION_ID}" --paths "/*" + "bash -c 'if [ -f /home/thoth/deploy/setup/deploy.sh ]; then bash /home/thoth/deploy/setup/deploy.sh; else echo \"INFO: No se encontró script de deploy. Saltando deploy backend.\"; fi'" + - | + if [ -f terraform/terraform-outputs.json ]; then + export CLOUDFRONT_DISTRIBUTION_ID=$(python3 -c "import json; print(json.load(open('terraform/terraform-outputs.json'))['cloudfront_distribution_id']['value'])") + aws cloudfront create-invalidation --distribution-id "${CLOUDFRONT_DISTRIBUTION_ID}" --paths "/*" + else + echo "INFO: No se encontró terraform-outputs.json. Saltando invalidación de CloudFront." + fi - export TELEGRAM_BOT_TOKEN="${PROD_TELEGRAM_BOT_TOKEN}" - export TELEGRAM_CHAT_ID="${PROD_TELEGRAM_CHAT_ID}" - bash scripts/telegram-pipeline-notify.sh success "CloudFront invalidado | Deploy a PROD aprobado y completado"