pipeline { agent { kubernetes { label 'docker-agent' yaml """ apiVersion: v1 kind: Pod spec: serviceAccountName: jenkins containers: - name: docker image: docker:dind securityContext: privileged: true env: - name: DOCKER_TLS_CERTDIR value: "" - name: HTTP_PROXY value: http://10.0.10.10:3128 - name: HTTPS_PROXY value: http://10.0.10.10:3128 - name: NO_PROXY value: localhost,127.0.0.1,10.0.0.0/8,.cluster.local,.svc,.knapp-world.app.ariki.ai - name: http_proxy value: http://10.0.10.10:3128 - name: https_proxy value: http://10.0.10.10:3128 - name: no_proxy value: localhost,127.0.0.1,10.0.0.0/8,.cluster.local,.svc,.knapp-world.app.ariki.ai volumeMounts: - name: docker-storage mountPath: /var/lib/docker - name: harbor-ca mountPath: /etc/docker/certs.d/harbor.knapp-world.app.ariki.ai/ca.crt subPath: ca.crt - name: tools image: alpine/git:latest command: ['sleep'] args: ['99d'] ttyEnabled: true volumes: - name: docker-storage emptyDir: {} - name: harbor-ca secret: secretName: internal-root-ca """ } } triggers { GenericTrigger( genericVariables: [ [key: 'ref', value: '$.ref'], [key: 'commit_message', value: '$.head_commit.message'] ], token: 'gitea-webhook' ) } environment { HARBOR_HOST = "harbor.knapp-world.app.ariki.ai" HARBOR_PROJECT = "knapp-world" IMAGE_NAME = "${HARBOR_HOST}/${HARBOR_PROJECT}/hello-world" IMAGE_TAG = "${BUILD_NUMBER}" GITEA_HOST = "gitea.knapp-world.app.ariki.ai" GITEA_REPO = "admin/hello-world" } stages { stage('Skip CI commit') { when { expression { return env.commit_message?.contains('[skip ci]') } } steps { script { currentBuild.result = 'NOT_BUILT' error('Skipping Jenkins-generated commit') } } } stage('Build Image') { steps { container('docker') { sh """ # Wait for docker daemon to be ready for i in \$(seq 1 30); do docker info > /dev/null 2>&1 && break echo "Waiting for Docker daemon... \$i" sleep 2 done docker build -t ${IMAGE_NAME}:${IMAGE_TAG} -t ${IMAGE_NAME}:latest . """ } } } stage('Push to Harbor') { steps { container('docker') { withCredentials([usernamePassword( credentialsId: 'harbor-credentials', usernameVariable: 'HARBOR_USER', passwordVariable: 'HARBOR_PASS' )]) { sh """ docker login ${HARBOR_HOST} -u \${HARBOR_USER} -p \${HARBOR_PASS} docker push ${IMAGE_NAME}:${IMAGE_TAG} docker push ${IMAGE_NAME}:latest """ } } } } stage('Update Manifest and Push') { steps { container('tools') { withCredentials([usernamePassword( credentialsId: 'gitea-credentials', usernameVariable: 'GIT_USER', passwordVariable: 'GIT_PASS' )]) { sh """ set -e cd "$WORKSPACE" git config --global --add safe.directory "$WORKSPACE" pwd git status git config user.email "jenkins@local" git config user.name "Jenkins" # Update image tag in deployment manifest sed -i "s|image: ${IMAGE_NAME}:.*|image: ${IMAGE_NAME}:${IMAGE_TAG}|" k8s/deployment.yml git add k8s/deployment.yml git diff --staged --quiet && echo "No changes to commit" && exit 0 git commit -m "ci: update image to build ${IMAGE_TAG} [skip ci]" git push https://\${GIT_USER}:\${GIT_PASS}@${GITEA_HOST}/${GITEA_REPO}.git HEAD:main """ } } } } } post { success { echo "Build ${BUILD_NUMBER} deployed — https://hello-world.knapp-world.app.ariki.ai" } failure { echo "Pipeline failed at: ${env.STAGE_NAME}" } } }