pipeline { agent any options { timestamps() disableConcurrentBuilds() } parameters { choice(name: 'ENVIRONMENT', choices: ['development', 'main'], description: 'Rama a ejecutar') string(name: 'VERSION_MAYOR', defaultValue: '1', description: 'Componente mayor de versión') } environment { REGISTRY = 'dev.aduanasoft.com' IMAGE_NAMESPACE = 'anexo76' } stages { stage('Checkout') { steps { checkout([ $class: 'GitSCM', branches: [[name: "*/${params.ENVIRONMENT}"]], userRemoteConfigs: [[ url: 'git@gitea.company.com:repo/anexo76.git', credentialsId: 'gitea-ssh' ]], extensions: [[$class: 'CloneOption', depth: 0, shallow: false]] ]) } } stage('Test backend') { environment { TEST_DATABASE_URL = credentials('test-database-url') } steps { sh ''' set -euo pipefail python3 --version VENV="$WORKSPACE/.pytest-venv" python3 -m venv "$VENV" . "$VENV/bin/activate" python -m pip install --upgrade pip pip install -r "$WORKSPACE/backend/requirements.txt" cd "$WORKSPACE/backend" export TEST_DATABASE_URL alembic upgrade head pytest -q tests -v -ra -s ''' } } stage('Generate version') { steps { script { def year = sh(returnStdout: true, script: 'date +%y').trim() def month = sh(returnStdout: true, script: 'date +%m').trim() if (params.ENVIRONMENT == 'development') { def shortHash = sh(returnStdout: true, script: 'git rev-parse --short=8 HEAD').trim() env.APP_VERSION = "${year}.${month}.${params.VERSION_MAYOR}.${shortHash}" } else { def lastTag = sh(returnStdout: true, script: 'git describe --tags --abbrev=0 2>/dev/null || true').trim() def commitCount = lastTag ? sh(returnStdout: true, script: "git rev-list ${lastTag}..HEAD --count").trim() : sh(returnStdout: true, script: 'git rev-list --count HEAD').trim() if (commitCount == '0') { commitCount = '1' } env.APP_VERSION = "${year}.${month}.${params.VERSION_MAYOR}.${commitCount}" } echo "VERSION: ${env.APP_VERSION}" } } } stage('Docker login') { steps { withCredentials([usernamePassword(credentialsId: 'harbor-credentials', usernameVariable: 'HARBOR_USERNAME', passwordVariable: 'HARBOR_PASSWORD')]) { sh ''' set -euo pipefail echo "$HARBOR_PASSWORD" | docker login "$REGISTRY" -u "$HARBOR_USERNAME" --password-stdin ''' } } } 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 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 docker push "${REGISTRY}/${IMAGE_NAMESPACE}/frontend:latest" ''' } } stage('Tag release (main)') { when { expression { params.ENVIRONMENT == 'main' } } steps { sshagent(credentials: ['gitea-ssh']) { sh ''' set -euo pipefail git -c user.name='Jenkins' -c user.email='jenkins@gitea.local' \ tag -a "v${APP_VERSION}" -m "Release version ${APP_VERSION}" git push origin "v${APP_VERSION}" ''' } } } stage('Deploy development') { when { expression { params.ENVIRONMENT == 'development' } } steps { withCredentials([ usernamePassword(credentialsId: 'harbor-credentials', usernameVariable: 'HARBOR_USERNAME', passwordVariable: 'HARBOR_PASSWORD'), string(credentialsId: 'dev-server-user', variable: 'DEV_SERVER_USER'), string(credentialsId: 'dev-server-host', variable: 'DEV_SERVER_HOST') ]) { sshagent(credentials: ['dev-server-ssh']) { sh ''' set -euo pipefail ssh -o StrictHostKeyChecking=accept-new "${DEV_SERVER_USER}@${DEV_SERVER_HOST}" ' cd ~/projects/anexo76 && echo '"'"'"${HARBOR_PASSWORD}"'"'"' | docker login '"${REGISTRY}"' -u '"${HARBOR_USERNAME}"' --password-stdin && docker compose -f docker-compose.prod.yml pull && docker compose -f docker-compose.prod.yml up -d && docker image prune -f ' ''' } } } } } }