diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 00000000..88280eae --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,175 @@ +pipeline { + agent any + + options { + timestamps() + disableConcurrentBuilds() + } + + parameters { + choice(name: 'ENVIRONMENT', choices: ['development', 'main'], description: 'Rama a ejecutar') + } + + environment { + REGISTRY = 'dev.aduanasoft.com' + IMAGE_NAMESPACE = 'anexo76' + VERSION_MAYOR = credentials('version-mayor') // secret text, ej: 1 + } + + 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}.${env.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}.${env.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 + ' + ''' + } + } + } + } + } + + post { + always { + sh 'docker logout "${REGISTRY}" || true' + } + } +}