From 655eb4a1997de0b0c978c4b7df7e37e37c92bde6 Mon Sep 17 00:00:00 2001 From: devops Date: Wed, 16 Sep 2026 16:16:46 +0000 Subject: [PATCH] gitops promotion stage: pipeline image tag commit karti hai, ArgoCD deploy karta hai --- vars/devopsPipeline.groovy | 33 ++++++++++++++++++------- vars/gitopsPromote.groovy | 49 ++++++++++++++++++++++++++++++++++++++ vars/waitForRollout.groovy | 20 ++++++++++++++++ 3 files changed, 94 insertions(+), 8 deletions(-) create mode 100644 vars/gitopsPromote.groovy create mode 100644 vars/waitForRollout.groovy diff --git a/vars/devopsPipeline.groovy b/vars/devopsPipeline.groovy index 3af41fa..d0926f4 100644 --- a/vars/devopsPipeline.groovy +++ b/vars/devopsPipeline.groovy @@ -28,6 +28,13 @@ def call(Map cfg = [:]) { cfg.runSonar = cfg.containsKey('runSonar') ? cfg.runSonar : true cfg.runDeploy = cfg.containsKey('runDeploy') ? cfg.runDeploy : true cfg.approval = cfg.containsKey('approval') ? cfg.approval : true + // GitOps lane: k8s cluster me deploy ArgoCD karta hai, Jenkins sirf tag commit karta hai. + cfg.gitops = cfg.containsKey('gitops') ? cfg.gitops : false + cfg.gitopsRepo = cfg.gitopsRepo ?: 'https://ns31240276.ip-51-195-4.eu/devops/gitops.git' + cfg.gitopsPath = cfg.gitopsPath ?: "manifests/${cfg.module}" + cfg.k8sVerifyUrl = cfg.k8sVerifyUrl ?: '' + // VM lane: ansible se app-vm/staging-vm par deploy. + cfg.deployVM = cfg.containsKey('deployVM') ? cfg.deployVM : true properties([ parameters([ @@ -219,12 +226,20 @@ assert r['version'] == '${IMAGE_TAG}', 'version mismatch' node(P.deployLabel) { withEnv(commonEnv) { stage('Verify signature') { cosignVerify() } - stage('Deploy STAGING') { ansibleDeploy('staging') } - stage('Verify STAGING') { verifyEnv('staging') } + if (cfg.gitops) { + stage('Promote to GitOps') { gitopsPromote(cfg) } + if (cfg.k8sVerifyUrl) { + stage('Verify k8s (ArgoCD)') { waitForRollout(cfg.k8sVerifyUrl, imageTag) } + } + } + if (cfg.deployVM) { + stage('Deploy STAGING') { ansibleDeploy('staging') } + stage('Verify STAGING') { verifyEnv('staging') } + } } } - if (cfg.approval) { + if (cfg.approval && cfg.deployVM) { stage('Production approval') { // Node ke bahar hai - intezaar me koi executor block nahi hota. timeout(time: 30, unit: 'MINUTES') { @@ -234,11 +249,13 @@ assert r['version'] == '${IMAGE_TAG}', 'version mismatch' } } - node(P.deployLabel) { - withEnv(commonEnv) { - stage('Deploy PRODUCTION') { ansibleDeploy('production') } - stage('Verify PRODUCTION') { verifyEnv('production') } - } + if (cfg.deployVM) { + node(P.deployLabel) { + withEnv(commonEnv) { + stage('Deploy PRODUCTION') { ansibleDeploy('production') } + stage('Verify PRODUCTION') { verifyEnv('production') } + } + } } currentBuild.description = "${cfg.module}:${imageTag}${isRollback ? ' (rollback)' : ''}" diff --git a/vars/gitopsPromote.groovy b/vars/gitopsPromote.groovy new file mode 100644 index 0000000..d81697b --- /dev/null +++ b/vars/gitopsPromote.groovy @@ -0,0 +1,49 @@ +// CI yahan khatam: image ka naya tag gitops repo me commit ho jaata hai. +// Aage ka kaam ArgoCD ka hai - wahi cluster ko git wali state par le jaata hai. +// Jenkins ke paas cluster ka koi access nahi chahiye. Yahi GitOps ka asli fayda. +def call(Map cfg) { + withCredentials([usernamePassword(credentialsId: 'gitea-user', + usernameVariable: 'GIT_USER', + passwordVariable: 'GIT_PASS')]) { + withEnv(["GITOPS_REPO=${cfg.gitopsRepo}", "GITOPS_PATH=${cfg.gitopsPath}"]) { + sh ''' + set +x + WORK=$(mktemp -d); trap "rm -rf $WORK" EXIT + AUTH_URL=$(printf '%s' "$GITOPS_REPO" | sed "s|https://|https://$GIT_USER:$GIT_PASS@|") + git clone -q --depth 1 "$AUTH_URL" "$WORK/repo" + cd "$WORK/repo" + + python3 - "$GITOPS_PATH" "$REGISTRY/$IMAGE_NAME" "$IMAGE_TAG" <<'PY' +import sys, pathlib +path, image, tag = sys.argv[1], sys.argv[2], sys.argv[3] +changed = [] +for f in sorted(pathlib.Path(path).rglob("*.yaml")): + lines = f.read_text().splitlines(True) + out, hit = [], False + for ln in lines: + if ln.strip().startswith("image:") and (image + ":") in ln: + indent = ln[: len(ln) - len(ln.lstrip())] + out.append(indent + "image: " + image + ":" + tag + "\n") + hit = True + else: + out.append(ln) + if hit: + f.write_text("".join(out)) + changed.append(str(f)) +print(" updated:", ", ".join(changed) if changed else "kuch nahi mila") +PY + + git config user.email "jenkins@platform.local" + git config user.name "jenkins" + git add -A + if git diff --cached --quiet; then + echo " tag pehle se wahi hai, commit ki zarurat nahi" + exit 0 + fi + git commit -q -m "$MODULE: image -> $IMAGE_TAG (jenkins build $BUILD_NUMBER)" + git push -q "$AUTH_URL" HEAD:main + echo " gitops repo commit ho gaya - ArgoCD sync karega" + ''' + } + } +} diff --git a/vars/waitForRollout.groovy b/vars/waitForRollout.groovy new file mode 100644 index 0000000..3add456 --- /dev/null +++ b/vars/waitForRollout.groovy @@ -0,0 +1,20 @@ +// Deploy ke baad sach me naya version live hua ya nahi - HTTP se check. +// ArgoCD apne aap sync karta hai, isliye thoda intezaar karna padta hai. +def call(String url, String expectedVersion, int tries = 30) { + withEnv(["CHECK_URL=${url}", "EXPECT=${expectedVersion}", "TRIES=${tries}"]) { + sh ''' + i=0 + while [ $i -lt "$TRIES" ]; do + GOT=$(curl -sf --max-time 5 "$CHECK_URL" 2>/dev/null \ + | python3 -c "import sys,json;print(json.load(sys.stdin)['version'])" 2>/dev/null || echo "") + if [ "$GOT" = "$EXPECT" ]; then + echo " live version = $GOT (OK)" + exit 0 + fi + i=$((i+1)); sleep 10 + done + echo " $CHECK_URL par $EXPECT nahi aaya (aakhri: ${GOT:-kuch nahi})" + exit 1 + ''' + } +}