From 88ab44a604751944f257ae4c5ba29ceff9771d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C3=B3n=20V=C3=A1squez?= Date: Mon, 13 Oct 2025 16:23:41 -0300 Subject: [PATCH 1/5] Jenkinsfile --- Jenkinsfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Jenkinsfile b/Jenkinsfile index 4ccfecf..55f88fa 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -20,3 +20,4 @@ pipeline { // // // +// From 7d309caea49f1690edaa2b020470ced76973c850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C3=B3n=20V=C3=A1squez?= Date: Mon, 13 Oct 2025 16:31:35 -0300 Subject: [PATCH 2/5] Jenkinsfile --- Jenkinsfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Jenkinsfile b/Jenkinsfile index 55f88fa..ac5144c 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -21,3 +21,4 @@ pipeline { // // // +// From 30529c49388d27cbe62f0f038f845dc567082bd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C3=B3n=20V=C3=A1squez?= Date: Tue, 14 Oct 2025 15:24:45 -0300 Subject: [PATCH 3/5] Jenkinsfile --- Jenkinsfile | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index ac5144c..c35eba2 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -13,12 +13,3 @@ pipeline { } } } -// -// -// -// -// -// -// -// -// From 3301a1a6afe5dda34e650e66cc8fda54b20e8581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C3=B3n=20V=C3=A1squez?= Date: Tue, 14 Oct 2025 15:37:30 -0300 Subject: [PATCH 4/5] Jenkinsfile --- Jenkinsfile | 267 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 261 insertions(+), 6 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index c35eba2..19c7abf 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,15 +1,270 @@ pipeline { agent any + environment { + IMAGE_NAME = 'test-img' + DOCKERHUB_USER = 'ramonvasquezliesa' + DOCKERHUB_REPO = 'ramonvasquezliesa/test-img' + IMAGE_TAG = 'latest' + IMAGE = "${DOCKERHUB_REPO}:${IMAGE_TAG}" + CONTAINER_NAME = 'test-img-container' + PORTS = '8081:80' + VOLUMES = '' + ENV_FILE = '' + + REMOVE_DANGLING_IMAGES = 'true' + USE_DOCKERHUB_LOGIN = 'false' + + FORGEJO_URL = 'https://forgejo.test.dev.it.liesa.com.ar' + FORGEJO_REPO = 'ramon.vasquez/test-img.git' + + // Policy + REQUIRE_VERSION_TAG = 'true' // Fail if no matching tag exists remotely + } + stages { - stage('Stage Test') - { + stage('Checkout (with submodules)') { steps { - echo 'Un día me preguntaron qué es lo que quería...' - echo 'les contesté que Racing el domingo me dé una alegría...' - echo 'para poder festejar con toda la gente...' - echo 'Racing, mi buen amigo...' + checkout(scmGit( + branches: [[name: '*/main']], + userRemoteConfigs: [[ + url: 'https://forgejo.test.dev.it.liesa.com.ar/ramon.vasquez/pl-1.git', + credentialsId: 'hermes' + ]], + // extensions: [ + // [$class: 'SubmoduleOption', + // disableSubmodules: false, + // recursiveSubmodules: true, + // parentCredentials: true, + // trackingSubmodules: true + // ] + // ] + )) + } + } + + stage('Docker Login (optional)') { + when { + expression { return env.USE_DOCKERHUB_LOGIN?.toBoolean() } + } + steps { + withCredentials([ + usernamePassword( + credentialsId: 'dockerhub-credentials', + usernameVariable: 'DOCKERHUB_USER', + passwordVariable: 'DOCKERHUB_PASS' + ) + ]) { + sh ''' + set -eu pipefail + echo "$DOCKERHUB_PASS" | docker login -u "$DOCKERHUB_USER" --password-stdin + ''' + } + } + } + + // 🔎 Resolve the latest version tag from the Forgejo repo *remotely* (no local clone required) + stage('Resolve Latest Version Tag (Forgejo remote)') { + steps { + sh ''' + set -eu pipefail + + : > .latest_version_tag + : > .tag_check_status + : > .all_tags + : > .matching_tags + + # Version pattern: vN, vN.N, vN.N.N (N = digits) + pattern='^[vV][0-9]+(\\.[0-9]+){0,2}$' + + # List all tags from remote (strip refs/tags/ and peeled ^{} suffixes), unique, sorted + git ls-remote --tags "${FORGEJO_URL}/${FORGEJO_REPO}" \ + | awk '{print $2}' \ + | sed -E 's@^refs/tags/@@; s/\\^\\{\\}$//' \ + | sort -u > .all_tags + + # Filter only tags that match the version pattern + matches="$(grep -E "${pattern}" .all_tags || true)" + printf '%s\n' "$matches" > .matching_tags + + if [ -z "$matches" ]; then + echo 'NONE' > .tag_check_status + exit 0 + fi + + # Select numerically highest MAJOR.MINOR.PATCH (missing minor/patch => 0) + latest_line="$( + awk ' + function to_num(x){ return (x == "" ? 0 : x) + 0 } + { + orig=$0 + t=$0 + gsub(/^[vV]/,"",t) + n=split(t, a, ".") + maj=to_num(a[1]); min=to_num(a[2]); pat=to_num(a[3]) + # zero-padded numeric key → stable lexical sort + printf("%09d.%09d.%09d %s\\n", maj, min, pat, orig) + } + ' .matching_tags | sort -t" " -k1,1 | tail -n1 + )" + + latest_tag="$(printf '%s\\n' "$latest_line" | awk '{ $1=""; sub(/^ /,""); print }')" + + printf '%s\n' "$latest_tag" > .latest_version_tag + echo 'OK' > .tag_check_status + ''' + + script { + def status = readFile('.tag_check_status').trim() + def latestTag = readFile('.latest_version_tag').trim() + def requireTag = (env.REQUIRE_VERSION_TAG ?: 'true').toBoolean() + + def PATTERN_DISPLAY = '^[vV][0-9]+(\\.[0-9]+){0,2}$' + def allTags = sh(script: 'cat .all_tags || true', returnStdout: true).trim() + def matches = sh(script: 'cat .matching_tags || true', returnStdout: true).trim() + + if (status == 'NONE') { + if (requireTag) { + error('''❌ No tags in the Forgejo repo match the required version pattern ''' + PATTERN_DISPLAY) + } else { + echo 'ℹ️ No matching version tags found; will clone default branch and keep IMAGE_TAG as-is.' + env.LATEST_TAG = '' + } + } else { + env.LATEST_TAG = latestTag + // Optionally sync Docker tag with Git tag (comment out if you prefer not to) + env.IMAGE_TAG = latestTag + env.IMAGE = "${env.DOCKERHUB_REPO}:${env.IMAGE_TAG}" + echo "✅ Latest Forgejo tag selected: ${env.LATEST_TAG}" + echo "➡️ Docker image will use tag: ${env.IMAGE_TAG}" + } + + echo '📌 All remote tags:' + echo allTags ? allTags : '' + echo '📌 Matching version tags:' + echo matches ? matches : '' + } + } + } + + // ⬇️ Clone the Forgejo repo at the *latest version tag* (detached HEAD), or default branch if none + stage('Clone Git Repository') { + steps { + sh """ + set -eu pipefail + echo "Preparing clone from ${FORGEJO_URL}/${FORGEJO_REPO} ..." + rm -rf test-img || true + if [ -n "\${LATEST_TAG:-}" ]; then + echo "Cloning tag: \${LATEST_TAG}" + git clone --branch "\${LATEST_TAG}" --depth 1 "${FORGEJO_URL}/${FORGEJO_REPO}" test-img + else + echo "Cloning default branch (no version tag selected)" + git clone "${FORGEJO_URL}/${FORGEJO_REPO}" test-img + fi + cd test-img + echo "Repository ready at commit: \$(git rev-parse --short HEAD)" + """ + } + } + + stage('Pull or Build Image') { + steps { + sh ''' + set -eu pipefail + echo "Pulling $IMAGE ..." + docker pull "$IMAGE" + docker image inspect "$IMAGE" >/dev/null + echo "Image ready: $IMAGE" + ''' + } + } + + stage('Deploy (stop old, run new)') { + steps { + sh label: 'Deploy with bash', script: ''' + bash -euo pipefail <<'BASH' + + # Default possibly-unset Jenkins params to empty strings + : "${PORTS:=}" + : "${VOLUMES:=}" + : "${ENV_FILE:=}" + + # Stop & remove existing container (if any) + if docker ps -a --format '{{.Names}}' | grep -w "$CONTAINER_NAME" >/dev/null 2>&1; then + echo "Stopping and removing existing container: $CONTAINER_NAME" + docker rm -f "$CONTAINER_NAME" || true + fi + # Check host-port availability (fail fast if any are busy) + if [ -n "$PORTS" ]; then + IFS=', ' read -r -a PORT_ARR <<< "$PORTS" + BUSY="" + + for map in "${PORT_ARR[@]}"; do + [ -z "$map" ] && continue + IFS=':' read -r p1 p2 p3 <<< "$map" + if [ -n "$p3" ]; then HP="$p2"; else HP="$p1"; fi + HP="${HP%%/*}" # strip /proto + [ -z "$HP" ] && continue + if command -v ss >/dev/null 2>&1; then + if ss -ltnH | awk '{print $4}' | grep -Eq "(:|\\.)${HP}$"; then + BUSY="$BUSY $HP" + fi + elif command -v lsof >/dev/null 2>&1; then + if lsof -iTCP:"$HP" -sTCP:LISTEN -P -n >/dev/null 2>&1; then + BUSY="$BUSY $HP" + fi + fi + done + + if [ -n "$BUSY" ]; then + echo "ERROR: Host port(s) in use:$BUSY" + echo "Hint: Jenkins usually listens on 8081. Change PORTS to something like '8081:80'" + exit 1 + fi + fi + + # Build runtime args dynamically + RUNTIME_ARGS="" + + if [ -n "$PORTS" ]; then + IFS=', ' read -r -a PORT_ARR <<< "$PORTS" + for p in "${PORT_ARR[@]}"; do + [ -n "$p" ] && RUNTIME_ARGS="$RUNTIME_ARGS -p $p" + done + fi + + if [ -n "$VOLUMES" ]; then + IFS=', ' read -r -a VOL_ARR <<< "$VOLUMES" + for v in "${VOL_ARR[@]}"; do + [ -n "$v" ] && RUNTIME_ARGS="$RUNTIME_ARGS -v $v" + done + fi + + if [ -n "$ENV_FILE" ]; then + RUNTIME_ARGS="$RUNTIME_ARGS --env-file \"$ENV_FILE\"" + fi + + echo "Running container: $CONTAINER_NAME from $IMAGE" + set -x + # shellcheck disable=SC2086 + docker run -d --restart on-failure --name "$CONTAINER_NAME" $RUNTIME_ARGS "$IMAGE" + set +x + + echo "Container status:" + docker ps --filter "name=^${CONTAINER_NAME}$" + ''' } } } + + post { + always { + script { + if ((env.REMOVE_DANGLING_IMAGES ?: 'true').toBoolean()) { + sh 'docker image prune -f || true' + } + } + sh 'docker logout || true' + } + } } From 0fc3706152f68f809caa078e85e70218c0e3ccaa Mon Sep 17 00:00:00 2001 From: "ramon.vasquez" Date: Tue, 21 Oct 2025 17:30:23 +0000 Subject: [PATCH 5/5] Update Jenkinsfile --- Jenkinsfile | 279 ++++++++++------------------------------------------ 1 file changed, 52 insertions(+), 227 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 19c7abf..d50e4df 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,56 +1,67 @@ pipeline { - agent any + agent { + docker { + image 'docker:27-cli' + args '-v /var/run/docker.sock:/var/run/docker.sock' + } + } environment { - IMAGE_NAME = 'test-img' - DOCKERHUB_USER = 'ramonvasquezliesa' - DOCKERHUB_REPO = 'ramonvasquezliesa/test-img' - IMAGE_TAG = 'latest' - IMAGE = "${DOCKERHUB_REPO}:${IMAGE_TAG}" - CONTAINER_NAME = 'test-img-container' - PORTS = '8081:80' - VOLUMES = '' - ENV_FILE = '' + IMAGE_NAME = 'core-pim-test' + IMAGE_TAG = 'latest' + CONTAINER_NAME = "${IMAGE_NAME}-container" + DOCKERHUB_USER = 'ramonvasquezliesa' + DOCKERHUB_REPO = "${DOCKERHUB_USER}/${IMAGE_NAME}" + DOCKERHUB_IMAGE = "${DOCKERHUB_REPO}:${IMAGE_TAG}" + + FORGEJO_URL = 'https://forgejo.test.dev.it.liesa.com.ar' + FORGEJO_OWNER = 'it.dev' + FORGEJO_REPO = 'integrations.core.pim.git' + + REQUIRE_VERSION_TAG = 'true' REMOVE_DANGLING_IMAGES = 'true' - USE_DOCKERHUB_LOGIN = 'false' - FORGEJO_URL = 'https://forgejo.test.dev.it.liesa.com.ar' - FORGEJO_REPO = 'ramon.vasquez/test-img.git' - - // Policy - REQUIRE_VERSION_TAG = 'true' // Fail if no matching tag exists remotely + PORTS = '8081:80' + ENV_FILE = '' + VOLUMES = '' } stages { stage('Checkout (with submodules)') { steps { checkout(scmGit( - branches: [[name: '*/main']], + // branches: [[name: '*/dev']], userRemoteConfigs: [[ - url: 'https://forgejo.test.dev.it.liesa.com.ar/ramon.vasquez/pl-1.git', - credentialsId: 'hermes' + url: "${FORGEJO_URL}/${FORGEJO_OWNER}/${FORGEJO_REPO}", + credentialsId: 'forgejo-token-hermes' ]], - // extensions: [ - // [$class: 'SubmoduleOption', - // disableSubmodules: false, - // recursiveSubmodules: true, - // parentCredentials: true, - // trackingSubmodules: true - // ] - // ] + extensions: [ + [$class: 'SubmoduleOption', + disableSubmodules: false, + recursiveSubmodules: true, + parentCredentials: true, + trackingSubmodules: true + ] + ] )) } } - stage('Docker Login (optional)') { - when { - expression { return env.USE_DOCKERHUB_LOGIN?.toBoolean() } + stage('Login Docker') { + steps { + sh ''' + docker --version + echo "$DOCKERHUB_TOKEN" | docker login -u "$DOCKERHUB_USER" --password-stdin + ''' + } } + + stage('Docker Login') { steps { withCredentials([ usernamePassword( - credentialsId: 'dockerhub-credentials', + credentialsId: 'dockerhub-credentials-hermes', usernameVariable: 'DOCKERHUB_USER', passwordVariable: 'DOCKERHUB_PASS' ) @@ -63,208 +74,22 @@ pipeline { } } - // 🔎 Resolve the latest version tag from the Forgejo repo *remotely* (no local clone required) - stage('Resolve Latest Version Tag (Forgejo remote)') { + stage('Build Image') { steps { - sh ''' - set -eu pipefail - - : > .latest_version_tag - : > .tag_check_status - : > .all_tags - : > .matching_tags - - # Version pattern: vN, vN.N, vN.N.N (N = digits) - pattern='^[vV][0-9]+(\\.[0-9]+){0,2}$' - - # List all tags from remote (strip refs/tags/ and peeled ^{} suffixes), unique, sorted - git ls-remote --tags "${FORGEJO_URL}/${FORGEJO_REPO}" \ - | awk '{print $2}' \ - | sed -E 's@^refs/tags/@@; s/\\^\\{\\}$//' \ - | sort -u > .all_tags - - # Filter only tags that match the version pattern - matches="$(grep -E "${pattern}" .all_tags || true)" - printf '%s\n' "$matches" > .matching_tags - - if [ -z "$matches" ]; then - echo 'NONE' > .tag_check_status - exit 0 - fi - - # Select numerically highest MAJOR.MINOR.PATCH (missing minor/patch => 0) - latest_line="$( - awk ' - function to_num(x){ return (x == "" ? 0 : x) + 0 } - { - orig=$0 - t=$0 - gsub(/^[vV]/,"",t) - n=split(t, a, ".") - maj=to_num(a[1]); min=to_num(a[2]); pat=to_num(a[3]) - # zero-padded numeric key → stable lexical sort - printf("%09d.%09d.%09d %s\\n", maj, min, pat, orig) - } - ' .matching_tags | sort -t" " -k1,1 | tail -n1 - )" - - latest_tag="$(printf '%s\\n' "$latest_line" | awk '{ $1=""; sub(/^ /,""); print }')" - - printf '%s\n' "$latest_tag" > .latest_version_tag - echo 'OK' > .tag_check_status - ''' - script { - def status = readFile('.tag_check_status').trim() - def latestTag = readFile('.latest_version_tag').trim() - def requireTag = (env.REQUIRE_VERSION_TAG ?: 'true').toBoolean() + docker.build("${DOCKERHUB_REPO}:${TAG}", '-f src/Service/Infrastructure/App/Dockerfile .') + } + } + } - def PATTERN_DISPLAY = '^[vV][0-9]+(\\.[0-9]+){0,2}$' - def allTags = sh(script: 'cat .all_tags || true', returnStdout: true).trim() - def matches = sh(script: 'cat .matching_tags || true', returnStdout: true).trim() - - if (status == 'NONE') { - if (requireTag) { - error('''❌ No tags in the Forgejo repo match the required version pattern ''' + PATTERN_DISPLAY) - } else { - echo 'ℹ️ No matching version tags found; will clone default branch and keep IMAGE_TAG as-is.' - env.LATEST_TAG = '' - } - } else { - env.LATEST_TAG = latestTag - // Optionally sync Docker tag with Git tag (comment out if you prefer not to) - env.IMAGE_TAG = latestTag - env.IMAGE = "${env.DOCKERHUB_REPO}:${env.IMAGE_TAG}" - echo "✅ Latest Forgejo tag selected: ${env.LATEST_TAG}" - echo "➡️ Docker image will use tag: ${env.IMAGE_TAG}" + stage('Push Image') { + steps { + script { + docker.withRegistry('https://index.docker.io/v1/', 'dockerhub-credentials-hermes') { + docker.image("${DOCKERHUB_REPO}:${TAG}").push() } - - echo '📌 All remote tags:' - echo allTags ? allTags : '' - echo '📌 Matching version tags:' - echo matches ? matches : '' } } } - - // ⬇️ Clone the Forgejo repo at the *latest version tag* (detached HEAD), or default branch if none - stage('Clone Git Repository') { - steps { - sh """ - set -eu pipefail - echo "Preparing clone from ${FORGEJO_URL}/${FORGEJO_REPO} ..." - rm -rf test-img || true - if [ -n "\${LATEST_TAG:-}" ]; then - echo "Cloning tag: \${LATEST_TAG}" - git clone --branch "\${LATEST_TAG}" --depth 1 "${FORGEJO_URL}/${FORGEJO_REPO}" test-img - else - echo "Cloning default branch (no version tag selected)" - git clone "${FORGEJO_URL}/${FORGEJO_REPO}" test-img - fi - cd test-img - echo "Repository ready at commit: \$(git rev-parse --short HEAD)" - """ - } - } - - stage('Pull or Build Image') { - steps { - sh ''' - set -eu pipefail - echo "Pulling $IMAGE ..." - docker pull "$IMAGE" - docker image inspect "$IMAGE" >/dev/null - echo "Image ready: $IMAGE" - ''' - } - } - - stage('Deploy (stop old, run new)') { - steps { - sh label: 'Deploy with bash', script: ''' - bash -euo pipefail <<'BASH' - - # Default possibly-unset Jenkins params to empty strings - : "${PORTS:=}" - : "${VOLUMES:=}" - : "${ENV_FILE:=}" - - # Stop & remove existing container (if any) - if docker ps -a --format '{{.Names}}' | grep -w "$CONTAINER_NAME" >/dev/null 2>&1; then - echo "Stopping and removing existing container: $CONTAINER_NAME" - docker rm -f "$CONTAINER_NAME" || true - fi - # Check host-port availability (fail fast if any are busy) - if [ -n "$PORTS" ]; then - IFS=', ' read -r -a PORT_ARR <<< "$PORTS" - BUSY="" - - for map in "${PORT_ARR[@]}"; do - [ -z "$map" ] && continue - IFS=':' read -r p1 p2 p3 <<< "$map" - if [ -n "$p3" ]; then HP="$p2"; else HP="$p1"; fi - HP="${HP%%/*}" # strip /proto - [ -z "$HP" ] && continue - if command -v ss >/dev/null 2>&1; then - if ss -ltnH | awk '{print $4}' | grep -Eq "(:|\\.)${HP}$"; then - BUSY="$BUSY $HP" - fi - elif command -v lsof >/dev/null 2>&1; then - if lsof -iTCP:"$HP" -sTCP:LISTEN -P -n >/dev/null 2>&1; then - BUSY="$BUSY $HP" - fi - fi - done - - if [ -n "$BUSY" ]; then - echo "ERROR: Host port(s) in use:$BUSY" - echo "Hint: Jenkins usually listens on 8081. Change PORTS to something like '8081:80'" - exit 1 - fi - fi - - # Build runtime args dynamically - RUNTIME_ARGS="" - - if [ -n "$PORTS" ]; then - IFS=', ' read -r -a PORT_ARR <<< "$PORTS" - for p in "${PORT_ARR[@]}"; do - [ -n "$p" ] && RUNTIME_ARGS="$RUNTIME_ARGS -p $p" - done - fi - - if [ -n "$VOLUMES" ]; then - IFS=', ' read -r -a VOL_ARR <<< "$VOLUMES" - for v in "${VOL_ARR[@]}"; do - [ -n "$v" ] && RUNTIME_ARGS="$RUNTIME_ARGS -v $v" - done - fi - - if [ -n "$ENV_FILE" ]; then - RUNTIME_ARGS="$RUNTIME_ARGS --env-file \"$ENV_FILE\"" - fi - - echo "Running container: $CONTAINER_NAME from $IMAGE" - set -x - # shellcheck disable=SC2086 - docker run -d --restart on-failure --name "$CONTAINER_NAME" $RUNTIME_ARGS "$IMAGE" - set +x - - echo "Container status:" - docker ps --filter "name=^${CONTAINER_NAME}$" - ''' - } - } - } - - post { - always { - script { - if ((env.REMOVE_DANGLING_IMAGES ?: 'true').toBoolean()) { - sh 'docker image prune -f || true' - } - } - sh 'docker logout || true' - } } }