Compare commits
No commits in common. "main" and "v1.0.1" have entirely different histories.
1 changed files with 225 additions and 50 deletions
273
Jenkinsfile
vendored
273
Jenkinsfile
vendored
|
|
@ -1,67 +1,56 @@
|
||||||
pipeline {
|
pipeline {
|
||||||
agent {
|
agent any
|
||||||
docker {
|
|
||||||
image 'docker:27-cli'
|
|
||||||
args '-v /var/run/docker.sock:/var/run/docker.sock'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
environment {
|
environment {
|
||||||
IMAGE_NAME = 'core-pim-test'
|
IMAGE_NAME = 'test-img'
|
||||||
IMAGE_TAG = 'latest'
|
|
||||||
CONTAINER_NAME = "${IMAGE_NAME}-container"
|
|
||||||
|
|
||||||
DOCKERHUB_USER = 'ramonvasquezliesa'
|
DOCKERHUB_USER = 'ramonvasquezliesa'
|
||||||
DOCKERHUB_REPO = "${DOCKERHUB_USER}/${IMAGE_NAME}"
|
DOCKERHUB_REPO = 'ramonvasquezliesa/test-img'
|
||||||
DOCKERHUB_IMAGE = "${DOCKERHUB_REPO}:${IMAGE_TAG}"
|
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_URL = 'https://forgejo.test.dev.it.liesa.com.ar'
|
||||||
FORGEJO_OWNER = 'it.dev'
|
FORGEJO_REPO = 'ramon.vasquez/test-img.git'
|
||||||
FORGEJO_REPO = 'integrations.core.pim.git'
|
|
||||||
|
|
||||||
REQUIRE_VERSION_TAG = 'true'
|
// Policy
|
||||||
REMOVE_DANGLING_IMAGES = 'true'
|
REQUIRE_VERSION_TAG = 'true' // Fail if no matching tag exists remotely
|
||||||
|
|
||||||
PORTS = '8081:80'
|
|
||||||
ENV_FILE = ''
|
|
||||||
VOLUMES = ''
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stages {
|
stages {
|
||||||
stage('Checkout (with submodules)') {
|
stage('Checkout (with submodules)') {
|
||||||
steps {
|
steps {
|
||||||
checkout(scmGit(
|
checkout(scmGit(
|
||||||
// branches: [[name: '*/dev']],
|
branches: [[name: '*/main']],
|
||||||
userRemoteConfigs: [[
|
userRemoteConfigs: [[
|
||||||
url: "${FORGEJO_URL}/${FORGEJO_OWNER}/${FORGEJO_REPO}",
|
url: 'https://forgejo.test.dev.it.liesa.com.ar/ramon.vasquez/pl-1.git',
|
||||||
credentialsId: 'forgejo-token-hermes'
|
credentialsId: 'hermes'
|
||||||
]],
|
]],
|
||||||
extensions: [
|
// extensions: [
|
||||||
[$class: 'SubmoduleOption',
|
// [$class: 'SubmoduleOption',
|
||||||
disableSubmodules: false,
|
// disableSubmodules: false,
|
||||||
recursiveSubmodules: true,
|
// recursiveSubmodules: true,
|
||||||
parentCredentials: true,
|
// parentCredentials: true,
|
||||||
trackingSubmodules: true
|
// trackingSubmodules: true
|
||||||
]
|
// ]
|
||||||
]
|
// ]
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stage('Login Docker') {
|
stage('Docker Login (optional)') {
|
||||||
steps {
|
when {
|
||||||
sh '''
|
expression { return env.USE_DOCKERHUB_LOGIN?.toBoolean() }
|
||||||
docker --version
|
|
||||||
echo "$DOCKERHUB_TOKEN" | docker login -u "$DOCKERHUB_USER" --password-stdin
|
|
||||||
'''
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
stage('Docker Login') {
|
|
||||||
steps {
|
steps {
|
||||||
withCredentials([
|
withCredentials([
|
||||||
usernamePassword(
|
usernamePassword(
|
||||||
credentialsId: 'dockerhub-credentials-hermes',
|
credentialsId: 'dockerhub-credentials',
|
||||||
usernameVariable: 'DOCKERHUB_USER',
|
usernameVariable: 'DOCKERHUB_USER',
|
||||||
passwordVariable: 'DOCKERHUB_PASS'
|
passwordVariable: 'DOCKERHUB_PASS'
|
||||||
)
|
)
|
||||||
|
|
@ -74,22 +63,208 @@ pipeline {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stage('Build Image') {
|
// 🔎 Resolve the latest version tag from the Forgejo repo *remotely* (no local clone required)
|
||||||
|
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 {
|
||||||
docker.build("${DOCKERHUB_REPO}:${TAG}", '-f src/Service/Infrastructure/App/Dockerfile .')
|
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 : '<none>'
|
||||||
|
echo '📌 Matching version tags:'
|
||||||
|
echo matches ? matches : '<none>'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stage('Push Image') {
|
// ⬇️ Clone the Forgejo repo at the *latest version tag* (detached HEAD), or default branch if none
|
||||||
|
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 {
|
||||||
docker.withRegistry('https://index.docker.io/v1/', 'dockerhub-credentials-hermes') {
|
if ((env.REMOVE_DANGLING_IMAGES ?: 'true').toBoolean()) {
|
||||||
docker.image("${DOCKERHUB_REPO}:${TAG}").push()
|
sh 'docker image prune -f || true'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
sh 'docker logout || true'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue