{"id":201,"date":"2026-10-30T08:01:27","date_gmt":"2026-10-30T08:01:27","guid":{"rendered":"https:\/\/rezachegini.com\/?post_type=project&#038;p=201"},"modified":"2026-10-30T08:01:27","modified_gmt":"2026-10-30T08:01:27","slug":"node-js-ci-cd-pipeline-with-jenkins-argocd-elk-stack","status":"publish","type":"project","link":"https:\/\/rezachegini.com\/?project=node-js-ci-cd-pipeline-with-jenkins-argocd-elk-stack","title":{"rendered":"Node.js CI\/CD Pipeline with Jenkins, ArgoCD &amp; ELK Stack"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Built a production-style Product Catalog REST API using Node.js and Express, deployed to Kubernetes with a full 8-stage Jenkins CI\/CD pipeline and GitOps workflow.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CI Pipeline (Jenkins):<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>npm install inside node:20-alpine Docker container<\/li>\n\n\n\n<li>Jest tests with mongodb-memory-server (node:20 Debian)<\/li>\n\n\n\n<li>Docker image built and pushed to Docker Hub with Git SHA tag<\/li>\n\n\n\n<li>Helm values.yaml updated with new image tag<\/li>\n\n\n\n<li>Git commit triggers ArgoCD sync<\/li>\n\n\n\n<li>Jenkins polls ArgoCD API and confirms pod is Healthy before marking build green<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">CD &amp; Deployment:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ArgoCD watches GitHub repo and auto-deploys on every merge to master<\/li>\n\n\n\n<li>App deployed to K3s cluster via Helm chart with multi-environment values files<\/li>\n\n\n\n<li>MongoDB running as separate K8s pod, connected by service name<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Observability:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>OpenTelemetry SDK instruments Express and HTTP automatically<\/li>\n\n\n\n<li>Traces exported to OTel Collector \u2192 Jaeger<\/li>\n\n\n\n<li>Winston JSON logs shipped via Filebeat \u2192 Elasticsearch \u2192 Kibana<\/li>\n\n\n\n<li>Every log line includes traceId for Kibana \u2194 Jaeger correlation<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Real bugs fixed during the project:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>mongodb-memory-server fails on Alpine \u2014 switched to node:20 Debian with MONGOMS_VERSION=7.0.14<\/li>\n\n\n\n<li>Groovy parser crashes on bash ${VAR#prefix} syntax \u2014 fixed with sed at runtime<\/li>\n\n\n\n<li>Jenkins when { branch &#8216;master&#8217; } always skips in regular Pipeline jobs \u2014 fixed with GIT_BRANCH expression<\/li>\n\n\n\n<li>OTel MongoDB instrumentation conflicts with mongoose bundled driver \u2014 disabled selectively<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Built a production-style Product Catalog REST API using Node.js and Express, deployed to Kubernetes with a full 8-stage Jenkins CI\/CD pipeline and&hellip;<\/p>\n","protected":false},"featured_media":0,"menu_order":0,"template":"","tech":[128,139,173,172,169,176,179,133,167,125,177,126,121,174,120,175,171,168,170,178],"class_list":["post-201","project","type-project","status-publish","hentry","tech-argocd","tech-docker","tech-elastic-stack-elk","tech-elasticsearch","tech-express-js","tech-filebeat","tech-git","tech-gitops","tech-helm","tech-jaeger","tech-javascript","tech-jenkins","tech-k3s","tech-kibana","tech-kubernetes","tech-logstash","tech-mongodb","tech-node-js","tech-opentelemetry","tech-rest-apis"],"_links":{"self":[{"href":"https:\/\/rezachegini.com\/index.php?rest_route=\/wp\/v2\/project\/201","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rezachegini.com\/index.php?rest_route=\/wp\/v2\/project"}],"about":[{"href":"https:\/\/rezachegini.com\/index.php?rest_route=\/wp\/v2\/types\/project"}],"wp:attachment":[{"href":"https:\/\/rezachegini.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=201"}],"wp:term":[{"taxonomy":"tech","embeddable":true,"href":"https:\/\/rezachegini.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftech&post=201"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}