pipeline { agent any environment { // Application configuration APP_NAME = 'demo-nginx' NAMESPACE = 'demo-app' // Docker registry (измени на свой registry) DOCKER_REGISTRY = 'docker.io' // Или Harbor: harbor.thedevops.dev DOCKER_REPO = 'vladimiras' // Твой Docker Hub username или Harbor project // Gitea configuration GITEA_URL = 'http://gitea-http.gitea.svc.cluster.local:3000' GITEA_REPO = 'admin/k3s-gitops' GITEA_BRANCH = 'main' // Build info BUILD_TAG = "${env.BUILD_NUMBER}" IMAGE_TAG = "${env.BRANCH_NAME}-${env.BUILD_NUMBER}" } stages { stage('Checkout Source') { steps { echo "Checking out application source code..." // Если у тебя есть отдельный репозиторий с приложением, клонируй его здесь // git branch: 'main', url: 'http://gitea-http.gitea.svc.cluster.local:3000/admin/demo-nginx-app' // Для примера, создадим простой Dockerfile sh ''' cat > Dockerfile << 'EOF' FROM nginx:1.25.3-alpine # Add custom index.html RUN echo "
Environment: Production
Version: ${IMAGE_TAG}
" > /usr/share/nginx/html/index.html # Add custom nginx config (optional) COPY nginx.conf /etc/nginx/nginx.conf EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] EOF ''' sh ''' cat > nginx.conf << 'EOF' user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; server { listen 80; server_name _; location / { root /usr/share/nginx/html; index index.html; } location /health { access_log off; return 200 "healthy\n"; add_header Content-Type text/plain; } } } EOF ''' } } stage('Build Docker Image') { steps { script { echo "Building Docker image: ${DOCKER_REGISTRY}/${DOCKER_REPO}/${APP_NAME}:${IMAGE_TAG}" // Build image sh """ docker build \ --build-arg BUILD_NUMBER=${BUILD_NUMBER} \ --build-arg IMAGE_TAG=${IMAGE_TAG} \ -t ${DOCKER_REGISTRY}/${DOCKER_REPO}/${APP_NAME}:${IMAGE_TAG} \ -t ${DOCKER_REGISTRY}/${DOCKER_REPO}/${APP_NAME}:latest \ . """ } } } stage('Test Image') { steps { script { echo "Testing Docker image..." // Run container for testing sh """ docker run -d --name test-${BUILD_NUMBER} \ -p 8888:80 \ ${DOCKER_REGISTRY}/${DOCKER_REPO}/${APP_NAME}:${IMAGE_TAG} sleep 5 # Test HTTP response curl -f http://localhost:8888/ || exit 1 curl -f http://localhost:8888/health || exit 1 # Cleanup docker stop test-${BUILD_NUMBER} docker rm test-${BUILD_NUMBER} """ echo "✅ Image tests passed!" } } } stage('Push to Registry') { when { branch 'main' } steps { script { echo "Pushing image to registry..." // Login to Docker registry withCredentials([usernamePassword( credentialsId: 'docker-registry-credentials', usernameVariable: 'DOCKER_USER', passwordVariable: 'DOCKER_PASS' )]) { sh """ echo "\${DOCKER_PASS}" | docker login ${DOCKER_REGISTRY} -u "\${DOCKER_USER}" --password-stdin docker push ${DOCKER_REGISTRY}/${DOCKER_REPO}/${APP_NAME}:${IMAGE_TAG} docker push ${DOCKER_REGISTRY}/${DOCKER_REPO}/${APP_NAME}:latest docker logout ${DOCKER_REGISTRY} """ } echo "✅ Image pushed successfully!" } } } stage('Update GitOps Manifests') { when { branch 'main' } steps { script { echo "Updating Kubernetes manifests in Gitea..." withCredentials([usernamePassword( credentialsId: 'gitea-credentials', usernameVariable: 'GIT_USER', passwordVariable: 'GIT_PASS' )]) { sh """ # Clone GitOps repository rm -rf k3s-gitops || true git clone http://\${GIT_USER}:\${GIT_PASS}@gitea-http.gitea.svc.cluster.local:3000/admin/k3s-gitops.git cd k3s-gitops # Configure git git config user.name "Jenkins" git config user.email "jenkins@thedevops.dev" # Update image tag in deployment sed -i 's|image: .*|image: ${DOCKER_REGISTRY}/${DOCKER_REPO}/${APP_NAME}:${IMAGE_TAG}|' apps/demo-nginx/deployment.yaml # Commit and push git add apps/demo-nginx/deployment.yaml git commit -m "chore(demo-nginx): Update image to ${IMAGE_TAG}" || echo "No changes to commit" git push origin main """ } echo "✅ GitOps manifests updated!" } } } stage('Wait for ArgoCD Sync') { when { branch 'main' } steps { script { echo "Waiting for ArgoCD to sync application..." timeout(time: 5, unit: 'MINUTES') { sh """ # Wait for ArgoCD to sync for i in {1..30}; do STATUS=\$(kubectl get application ${APP_NAME} -n argocd -o jsonpath='{.status.sync.status}' 2>/dev/null || echo "Unknown") HEALTH=\$(kubectl get application ${APP_NAME} -n argocd -o jsonpath='{.status.health.status}' 2>/dev/null || echo "Unknown") echo "ArgoCD Sync Status: \${STATUS}, Health: \${HEALTH}" if [ "\${STATUS}" = "Synced" ] && [ "\${HEALTH}" = "Healthy" ]; then echo "✅ Application synced and healthy!" exit 0 fi sleep 10 done echo "⚠️ Timeout waiting for sync, but continuing..." """ } } } } stage('Verify Deployment') { when { branch 'main' } steps { script { echo "Verifying deployment in Kubernetes..." sh """ # Check deployment status kubectl rollout status deployment/${APP_NAME} -n ${NAMESPACE} --timeout=300s # Get pods kubectl get pods -n ${NAMESPACE} -l app=${APP_NAME} # Verify image DEPLOYED_IMAGE=\$(kubectl get deployment ${APP_NAME} -n ${NAMESPACE} -o jsonpath='{.spec.template.spec.containers[0].image}') echo "Deployed image: \${DEPLOYED_IMAGE}" if [[ "\${DEPLOYED_IMAGE}" == *"${IMAGE_TAG}"* ]]; then echo "✅ Correct image version deployed!" else echo "❌ Image version mismatch!" exit 1 fi """ echo "✅ Deployment verified successfully!" } } } } post { success { echo """ ✅ Pipeline completed successfully! Application: ${APP_NAME} Image: ${DOCKER_REGISTRY}/${DOCKER_REPO}/${APP_NAME}:${IMAGE_TAG} Namespace: ${NAMESPACE} URL: https://demo-nginx.thedevops.dev ArgoCD will automatically sync the changes. """ // Optional: Send notification to Slack/Teams/Email // slackSend(color: 'good', message: "Deployment succeeded: ${APP_NAME}:${IMAGE_TAG}") } failure { echo """ ❌ Pipeline failed! Please check the logs above for details. """ // Optional: Send notification // slackSend(color: 'danger', message: "Deployment failed: ${APP_NAME}:${IMAGE_TAG}") } always { // Cleanup sh """ docker rmi ${DOCKER_REGISTRY}/${DOCKER_REPO}/${APP_NAME}:${IMAGE_TAG} || true docker rmi ${DOCKER_REGISTRY}/${DOCKER_REPO}/${APP_NAME}:latest || true docker system prune -f || true """ cleanWs() } } }