Compare commits

..

1 commit
v1.0.2 ... main

Author SHA1 Message Date
0fc3706152 Update Jenkinsfile 2025-10-21 17:30:23 +00:00

268
Jenkinsfile vendored
View file

@ -1,56 +1,67 @@
pipeline { pipeline {
agent any agent {
docker {
image 'docker:27-cli'
args '-v /var/run/docker.sock:/var/run/docker.sock'
}
}
environment { environment {
IMAGE_NAME = 'test-img' IMAGE_NAME = 'core-pim-test'
DOCKERHUB_USER = 'ramonvasquezliesa'
DOCKERHUB_REPO = 'ramonvasquezliesa/test-img'
IMAGE_TAG = 'latest' IMAGE_TAG = 'latest'
IMAGE = "${DOCKERHUB_REPO}:${IMAGE_TAG}" CONTAINER_NAME = "${IMAGE_NAME}-container"
CONTAINER_NAME = 'test-img-container'
PORTS = '8081:80'
VOLUMES = ''
ENV_FILE = ''
REMOVE_DANGLING_IMAGES = 'true' DOCKERHUB_USER = 'ramonvasquezliesa'
USE_DOCKERHUB_LOGIN = 'false' DOCKERHUB_REPO = "${DOCKERHUB_USER}/${IMAGE_NAME}"
DOCKERHUB_IMAGE = "${DOCKERHUB_REPO}:${IMAGE_TAG}"
FORGEJO_URL = 'https://forgejo.test.dev.it.liesa.com.ar' FORGEJO_URL = 'https://forgejo.test.dev.it.liesa.com.ar'
FORGEJO_REPO = 'ramon.vasquez/test-img.git' FORGEJO_OWNER = 'it.dev'
FORGEJO_REPO = 'integrations.core.pim.git'
// Policy REQUIRE_VERSION_TAG = 'true'
REQUIRE_VERSION_TAG = 'true' // Fail if no matching tag exists remotely REMOVE_DANGLING_IMAGES = 'true'
PORTS = '8081:80'
ENV_FILE = ''
VOLUMES = ''
} }
stages { stages {
stage('Checkout (with submodules)') { stage('Checkout (with submodules)') {
steps { steps {
checkout(scmGit( checkout(scmGit(
branches: [[name: '*/main']], // branches: [[name: '*/dev']],
userRemoteConfigs: [[ userRemoteConfigs: [[
url: 'https://forgejo.test.dev.it.liesa.com.ar/ramon.vasquez/pl-1.git', url: "${FORGEJO_URL}/${FORGEJO_OWNER}/${FORGEJO_REPO}",
credentialsId: 'hermes' credentialsId: 'forgejo-token-hermes'
]], ]],
// extensions: [ extensions: [
// [$class: 'SubmoduleOption', [$class: 'SubmoduleOption',
// disableSubmodules: false, disableSubmodules: false,
// recursiveSubmodules: true, recursiveSubmodules: true,
// parentCredentials: true, parentCredentials: true,
// trackingSubmodules: true trackingSubmodules: true
// ] ]
// ] ]
)) ))
} }
} }
stage('Docker Login (optional)') { stage('Login Docker') {
when { steps {
expression { return env.USE_DOCKERHUB_LOGIN?.toBoolean() } sh '''
docker --version
echo "$DOCKERHUB_TOKEN" | docker login -u "$DOCKERHUB_USER" --password-stdin
'''
} }
}
stage('Docker Login') {
steps { steps {
withCredentials([ withCredentials([
usernamePassword( usernamePassword(
credentialsId: 'dockerhub-credentials', credentialsId: 'dockerhub-credentials-hermes',
usernameVariable: 'DOCKERHUB_USER', usernameVariable: 'DOCKERHUB_USER',
passwordVariable: 'DOCKERHUB_PASS' passwordVariable: 'DOCKERHUB_PASS'
) )
@ -63,209 +74,22 @@ pipeline {
} }
} }
// 🔎 Resolve the latest version tag from the Forgejo repo *remotely* (no local clone required) stage('Build Image') {
stage('Resolve Latest Version Tag (Forgejo remote)') {
steps { 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 { script {
def status = readFile('.tag_check_status').trim() docker.build("${DOCKERHUB_REPO}:${TAG}", '-f src/Service/Infrastructure/App/Dockerfile .')
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 : '<none>'
echo '📌 Matching version tags:'
echo matches ? matches : '<none>'
} }
} }
} }
// ⬇️ Clone the Forgejo repo at the *latest version tag* (detached HEAD), or default branch if none stage('Push Image') {
stage('Clone Git Repository') {
steps { 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 { script {
if ((env.REMOVE_DANGLING_IMAGES ?: 'true').toBoolean()) { docker.withRegistry('https://index.docker.io/v1/', 'dockerhub-credentials-hermes') {
sh 'docker image prune -f || true' docker.image("${DOCKERHUB_REPO}:${TAG}").push()
}
} }
} }
sh 'docker logout || true'
} }
} }
} }
//