From c6e9ec049e26015d1b9a85e8f9cdc251b4de646d Mon Sep 17 00:00:00 2001 From: satyamsingh_8888 Date: Mon, 14 Sep 2026 13:36:38 +0530 Subject: [PATCH 1/7] Add Drone CI pipeline and static-only nginx serving for dev deploy --- .drone.yml | 281 +++++++++++++++++++++++++++++++++++++++++++++++++ Dockerfile | 8 ++ nginx.spa.conf | 45 ++++++++ 3 files changed, 334 insertions(+) create mode 100644 .drone.yml create mode 100644 nginx.spa.conf diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 000000000..ced085354 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,281 @@ +kind: pipeline +type: docker +name: auto-deploy + +steps: + + # ============================================================ + # DOCKER BUILD & PUSH + # + # Angular build (npm ci + ng build) Dockerfile ke andar + # multi-stage me hota hai, isliye alag build step nahi chahiye. + # ============================================================ + - name: docker-build-push + image: docker + + volumes: + - name: dockersock + path: /var/run/docker.sock + + commands: + - | + set -e + + # -------------------------------------------------------- + # Repository name comes from Drone + # -------------------------------------------------------- + REPO="$${DRONE_REPO_NAME}" + REPO="$$(echo "$$REPO" | tr '[:upper:]' '[:lower:]')" + + IMAGE="harbor.lincpay:8082/lincpay/$$REPO:$${DRONE_BUILD_NUMBER}" + + echo "==========================================" + echo "DOCKER BUILD & PUSH" + echo "==========================================" + echo "Repository : $$REPO" + echo "Build : $${DRONE_BUILD_NUMBER}" + echo "Image : $$IMAGE" + echo "==========================================" + + # -------------------------------------------------------- + # Harbor login + # -------------------------------------------------------- + echo 'QVgW5QbqlKKtBU2dYApTY28Dd6J36GK3' | \ + docker login harbor.lincpay:8082 \ + -u 'robot$lincpay+drone' \ + --password-stdin + + # -------------------------------------------------------- + # Build + # -------------------------------------------------------- + echo "Building Docker image..." + + docker build \ + -t "$$IMAGE" \ + . + + # -------------------------------------------------------- + # Push + # -------------------------------------------------------- + echo "Pushing Docker image..." + + docker push "$$IMAGE" + + echo "Docker image pushed successfully." + + + # ============================================================ + # DEPLOY + # ============================================================ + - name: deploy + image: docker + + volumes: + - name: dockersock + path: /var/run/docker.sock + + - name: envfiles + path: /platform-env + + commands: + - | + set -e + + # ======================================================== + # REPOSITORY / SERVICE / IMAGE + # ======================================================== + + REPO="$${DRONE_REPO_NAME}" + REPO="$$(echo "$$REPO" | tr '[:upper:]' '[:lower:]')" + + SERVICE_NAME="$${REPO}_app" + + IMAGE="harbor.lincpay:8082/lincpay/$$REPO:$${DRONE_BUILD_NUMBER}" + + echo "==========================================" + echo "DEPLOYMENT" + echo "==========================================" + echo "Repository : $$REPO" + echo "Service : $$SERVICE_NAME" + echo "Image : $$IMAGE" + echo "Placement : node.labels.environment == dev" + echo "==========================================" + + + # ======================================================== + # VALIDATION + # ======================================================== + + if [ -z "$$REPO" ]; then + echo "ERROR: DRONE_REPO_NAME is empty." + exit 1 + fi + + if [ -z "$$SERVICE_NAME" ]; then + echo "ERROR: Service name is empty." + exit 1 + fi + + if [ -z "$$IMAGE" ]; then + echo "ERROR: Docker image is empty." + exit 1 + fi + + echo "Repository verified : $$REPO" + echo "Service verified : $$SERVICE_NAME" + echo "Image verified : $$IMAGE" + + + # ======================================================== + # EXISTING SERVICE + # ======================================================== + + if docker service ls --format '{{.Name}}' | grep -Fxq "$$SERVICE_NAME"; then + + echo "" + echo "==========================================" + echo "EXISTING SERVICE" + echo "==========================================" + echo "Service: $$SERVICE_NAME" + + + # ------------------------------------------------------ + # Check whether dev constraint already exists + # ------------------------------------------------------ + + CONSTRAINT_EXISTS=$$(docker service inspect "$$SERVICE_NAME" \ + --format '{{range .Spec.TaskTemplate.Placement.Constraints}}{{println .}}{{end}}' \ + | grep -Fx 'node.labels.environment == dev' || true) + + + # ------------------------------------------------------ + # Add constraint if missing + # ------------------------------------------------------ + + if [ -z "$$CONSTRAINT_EXISTS" ]; then + + echo "Constraint missing." + echo "Adding: node.labels.environment == dev" + + docker service update \ + --constraint-add 'node.labels.environment == dev' \ + "$$SERVICE_NAME" + + else + + echo "Constraint already exists." + + fi + + + # ------------------------------------------------------ + # Update image + # ------------------------------------------------------ + + echo "Updating service image..." + + docker service update \ + --image "$$IMAGE" \ + --replicas 1 \ + --with-registry-auth \ + "$$SERVICE_NAME" + + + # ======================================================== + # NEW SERVICE + # ======================================================== + + else + + echo "" + echo "==========================================" + echo "NEW SERVICE" + echo "==========================================" + echo "Creating: $$SERVICE_NAME" + + + # ------------------------------------------------------ + # Traefik rule + # + # Construct it without allowing Drone to consume + # the shell backticks. + # ------------------------------------------------------ + + TRAEFIK_RULE='Host(`'$$REPO'.lincpay`)' + + echo "Traefik rule: $$TRAEFIK_RULE" + + + # ------------------------------------------------------ + # Create service + # ------------------------------------------------------ + + docker service create \ + --name "$$SERVICE_NAME" \ + --network edge-network \ + --replicas 1 \ + --constraint 'node.labels.environment == dev' \ + --with-registry-auth \ + --env-file /platform-env/global.env \ + --env-file /platform-env/dev.env \ + --label traefik.enable=true \ + --label "traefik.docker.network=edge-network" \ + --label "traefik.http.routers.$$REPO.rule=$$TRAEFIK_RULE" \ + --label "traefik.http.services.$$REPO.loadbalancer.server.port=80" \ + "$$IMAGE" + + fi + + + # ======================================================== + # FINAL STATUS + # ======================================================== + + echo "" + echo "==========================================" + echo "FINAL SERVICE STATUS" + echo "==========================================" + + docker service ls \ + --filter "name=$$SERVICE_NAME" + + + echo "" + echo "==========================================" + echo "PLACEMENT CONSTRAINT" + echo "==========================================" + + docker service inspect "$$SERVICE_NAME" \ + --format '{{json .Spec.TaskTemplate.Placement}}' + + + echo "" + echo "==========================================" + echo "SERVICE TASKS" + echo "==========================================" + + docker service ps "$$SERVICE_NAME" --no-trunc + + + echo "" + echo "==========================================" + echo "DEPLOYMENT COMPLETE" + echo "==========================================" + + +volumes: + + # ============================================================ + # DOCKER SOCKET + # ============================================================ + - name: dockersock + host: + path: /var/run/docker.sock + + + # ============================================================ + # ENVIRONMENT FILES + # ============================================================ + - name: envfiles + host: + path: /opt/platform/env diff --git a/Dockerfile b/Dockerfile index 5e5750925..f7fd4c7da 100644 --- a/Dockerfile +++ b/Dockerfile @@ -41,6 +41,14 @@ RUN sh -c "ng build --output-path=/dist $BUILD_ENVIRONMENT_OPTIONS" ############### FROM $NGINX_IMAGE +# envsubst (gettext) alpine-slim me nahi hota — runtime env.js generation ke +# liye zaroori hai, isliye explicitly install kar rahe hain. +RUN apk add --no-cache gettext + +# Static-only nginx config (SPA fallback, no API proxy). Stock default.conf +# ko replace karta hai taaki deep-link refresh par 404 na aaye. +COPY nginx.spa.conf /etc/nginx/conf.d/default.conf + COPY --from=builder /dist/browser /usr/share/nginx/html EXPOSE 80 diff --git a/nginx.spa.conf b/nginx.spa.conf new file mode 100644 index 000000000..86dae6530 --- /dev/null +++ b/nginx.spa.conf @@ -0,0 +1,45 @@ +# Static-only nginx config for the CBSNexora Angular UI. +# NOTE: No API reverse-proxy here by design — the browser calls the Fineract +# backend directly via FINERACT_API_URL (env.js). nginx sirf static files +# serve karta hai + Angular SPA routing handle karta hai. + +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + # ---- Compression ---- + gzip on; + gzip_comp_level 6; + gzip_min_length 1024; + gzip_proxied any; + gzip_types text/plain text/css application/javascript application/json + application/xml image/svg+xml font/woff font/woff2; + + # ---- Runtime env: env.js aur index.html kabhi cache na ho ---- + # (env.js har container start par envsubst se regenerate hoti hai; + # index.html hashed asset filenames point karti hai) + location = /assets/env.js { + add_header Cache-Control "no-store, no-cache, must-revalidate"; + expires -1; + } + + location = /index.html { + add_header Cache-Control "no-store, no-cache, must-revalidate"; + expires -1; + } + + # ---- Hashed static assets: lambe time cache ---- + location ~* \.(?:js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + expires 7d; + add_header Cache-Control "public"; + try_files $uri =404; + } + + # ---- Angular SPA fallback: har route index.html par ---- + location / { + try_files $uri $uri/ /index.html; + } +} From 8db857dbfe176ee519e3a9f70c20390b1c6f7076 Mon Sep 17 00:00:00 2001 From: LincPay Admin Date: Mon, 14 Sep 2026 08:12:28 +0000 Subject: [PATCH 2/7] Update .drone.yml --- .drone.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.drone.yml b/.drone.yml index ced085354..5afc4bcda 100644 --- a/.drone.yml +++ b/.drone.yml @@ -2,6 +2,10 @@ kind: pipeline type: docker name: auto-deploy +trigger: + branch: + - dev + steps: # ============================================================ From f4e596f64130422ead69c165430478cb1aa2cc9f Mon Sep 17 00:00:00 2001 From: satyamsingh_8888 Date: Mon, 14 Sep 2026 13:50:11 +0530 Subject: [PATCH 3/7] Restrict Drone trigger to push events on dev (covers PR merges) --- .drone.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.drone.yml b/.drone.yml index 5afc4bcda..692858be7 100644 --- a/.drone.yml +++ b/.drone.yml @@ -5,6 +5,8 @@ name: auto-deploy trigger: branch: - dev + event: + - push steps: From ffcf9f4d4139a3ce3806606e839fc5aab9cf4b27 Mon Sep 17 00:00:00 2001 From: satyamsingh_8888 Date: Mon, 14 Sep 2026 13:51:42 +0530 Subject: [PATCH 4/7] Raise Node heap to 8g for Angular production build --- Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index f7fd4c7da..eb90d8958 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,9 @@ ARG PUPPETEER_CHROMIUM_REVISION_ARG=1011831 ARG PUPPETEER_SKIP_DOWNLOAD_ARG # Set the environment variable to increase Node.js memory limit -ENV NODE_OPTIONS="--max-old-space-size=4096" +# (Mifos web-app ka production build memory-heavy hai; upstream build:prod +# 16384 use karta hai. 4096 par 'ng build' OOM ho jata hai.) +ENV NODE_OPTIONS="--max-old-space-size=8192" RUN apk add --no-cache git From 170a8a3f975bd2a4f881df659eaf895f0ef5c339 Mon Sep 17 00:00:00 2001 From: LincPay Admin Date: Mon, 14 Sep 2026 09:55:43 +0000 Subject: [PATCH 5/7] Update .drone.yml --- .drone.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.drone.yml b/.drone.yml index 692858be7..565892284 100644 --- a/.drone.yml +++ b/.drone.yml @@ -285,3 +285,4 @@ volumes: - name: envfiles host: path: /opt/platform/env + From b0d72d16f38c9a8be2dc62f944438cdf5b5b2931 Mon Sep 17 00:00:00 2001 From: satyamsingh_8888 Date: Mon, 14 Sep 2026 16:05:28 +0530 Subject: [PATCH 6/7] Skip Cypress/Puppeteer/Playwright binary downloads in build (unstick npm ci) --- Dockerfile | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index eb90d8958..7b4c5c0cf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,8 @@ ARG NPM_REGISTRY_URL=https://registry.npmjs.org/ ARG BUILD_ENVIRONMENT_OPTIONS="--configuration production" ARG PUPPETEER_DOWNLOAD_HOST_ARG=https://storage.googleapis.com ARG PUPPETEER_CHROMIUM_REVISION_ARG=1011831 -ARG PUPPETEER_SKIP_DOWNLOAD_ARG +# Build ko Chromium nahi chahiye — skip (warna npm ci Chromium download par atak jata hai). +ARG PUPPETEER_SKIP_DOWNLOAD_ARG=true # Set the environment variable to increase Node.js memory limit # (Mifos web-app ka production build memory-heavy hai; upstream build:prod @@ -27,6 +28,13 @@ ENV PUPPETEER_DOWNLOAD_HOST=$PUPPETEER_DOWNLOAD_HOST_ARG ENV PUPPETEER_CHROMIUM_REVISION=$PUPPETEER_CHROMIUM_REVISION_ARG ENV PUPPETEER_SKIP_DOWNLOAD=$PUPPETEER_SKIP_DOWNLOAD_ARG +# Test/e2e tooling ke bhaari binary downloads skip karo — build inhe use nahi +# karta, aur inke bina npm ci turant complete ho jata hai. +# Cypress -> ~250MB binary (CI me sabse zyada atakta hai) +# Playwright-> browser binaries +ENV CYPRESS_INSTALL_BINARY=0 +ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 + COPY ./ /usr/src/app/ RUN npm cache clear --force From c0f96e401f187872044c20106bc4002760237fa2 Mon Sep 17 00:00:00 2001 From: satyamsingh_8888 Date: Mon, 14 Sep 2026 16:16:54 +0530 Subject: [PATCH 7/7] Cache npm downloads via BuildKit mount, drop cache-clear (faster npm ci) --- Dockerfile | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7b4c5c0cf..26bedcd4b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,4 @@ +# syntax=docker/dockerfile:1 ############### ### STAGE 1: Build app ############### @@ -37,12 +38,13 @@ ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 COPY ./ /usr/src/app/ -RUN npm cache clear --force +RUN npm config set fetch-retry-maxtimeout 120000 \ + && npm config set registry $NPM_REGISTRY_URL --location=global -RUN npm config set fetch-retry-maxtimeout 120000 -RUN npm config set registry $NPM_REGISTRY_URL --location=global - -RUN npm ci +# BuildKit cache mount: npm ka download cache builds ke beech persist hota hai, +# isliye har build par saare packages dobara download nahi hote (bahut fast). +# 'npm cache clear --force' hata diya — wo har build par cache wipe kar deta tha. +RUN --mount=type=cache,target=/root/.npm npm ci --no-audit --no-fund RUN sh -c "ng build --output-path=/dist $BUILD_ENVIRONMENT_OPTIONS"