Repository: one-acre-fund/fineract-frontend-v2
Pull request #240: Merge in develop
Author: login: shejasabin
Labels: name: size/XL
Created: 2025-04-23T13:15:22Z | Merged: 2025-04-23T13:24:03Z

## Description
Merge in develop


Diff:
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000000..09d0da0ef8
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1 @@
+.github/ @one-acre-fund/devops
\ No newline at end of file
diff --git a/.github/actions/helm_fineract_frontend/action.yml b/.github/actions/helm_fineract_frontend/action.yml
index ee4a46c86a..5dcebd5160 100644
--- a/.github/actions/helm_fineract_frontend/action.yml
+++ b/.github/actions/helm_fineract_frontend/action.yml
@@ -1,13 +1,19 @@
----
 name: Helm Fineract Frontend
 description: GitHub Action for deploying ingresses.
+
 inputs:
+  ACR_REGISTRY:
+    description: The Azure Container Registry.
+    required: true
   ACR_PULL_PASSWORD:
     description: The password for the Azure Container Registry.
     required: true
   ACR_PULL_USERNAME:
     description: The username for the Azure Container Registry.
     required: true
+  ARTIFACT_NAME:
+    description: The name of the artifact.
+    required: true
   NAMESPACE:
     description: The namespace to deploy the ingresses.
     required: true
@@ -33,7 +39,7 @@ inputs:
     description: The client ID of the Keycloak client.
     required: true
   FINERACT_KEYCLOAK_TOKEN_URL:
-    description: The client ID of the Keycloak client.
+    description: The Token URL of the Keycloak client.
     required: true
   FINERACT_KEYCLOAK_REALM:
     description: The realm of the Keycloak client.
@@ -62,53 +68,47 @@ inputs:
   SENTRY_DSN:
     description: The Sentry DSN.
     required: true
+
 runs:
   using: composite
   steps:
     - name: Create Values File
       run: |
-        mkdir -p "${{ github.workspace }}/deployment"
-        touch "${{ github.workspace }}/deployment/my-values.yaml"
+        cat <<EOF > "${{ github.workspace }}/fineract-values.yaml"
+        commonconfig:
+          FINERACT_KEYCLOAK_REALM: "${{ inputs.FINERACT_KEYCLOAK_REALM }}"
+          FINERACT_KEYCLOAK_AUTH_SERVER_URL: "${{ inputs.FINERACT_KEYCLOAK_AUTH_SERVER_URL }}"
+          FINERACT_PROXY_URL: "https://${{ inputs.FINERACT_PROXY_URL }}:${{ inputs.FINERACT_PROXY_HTTPS_PORT }}"
+          FINERACT_KEYCLOAK_CLIENT_ID: "${{ inputs.FINERACT_KEYCLOAK_CLIENT_ID }}"
+          FINERACT_KEYCLOAK_TOKEN_URL: "${{ inputs.FINERACT_KEYCLOAK_TOKEN_URL }}"
+          FINERACT_KEYCLOAK_PUBLIC_CLIENT: true
+          FINERACT_KEYCLOAK_API_URL: "${{ inputs.FINERACT_KEYCLOAK_API_URL }}"
+          AUTH_SERVER_URL: "${{ inputs.FINERACT_AUTH_URL }}"
+          FINERACT_API_URL: "${{ inputs.FINERACT_API_URL }}"
+          HOST_HOME_URL: "${{ inputs.FINERACT_HOST_HOME_URL }}"
+          MATOMO_SITE_URL: "${{ inputs.MATOMO_SITE_URL }}"
+          MATOMO_SITE_ID: "${{ inputs.MATOMO_SITE_ID }}"
+          SENTRY_DSN: "${{ inputs.SENTRY_DSN }}"
 
-        echo "
-          commonconfig:
-            FINERACT_KEYCLOAK_REALM: "${{ inputs.FINERACT_KEYCLOAK_REALM }}"
-            FINERACT_KEYCLOAK_AUTH_SERVER_URL: "${{ inputs.FINERACT_KEYCLOAK_AUTH_SERVER_URL }}"
-            FINERACT_PROXY_URL: "https://${{ inputs.FINERACT_PROXY_URL }}:${{ inputs.FINERACT_PROXY_HTTPS_PORT }}"
-            FINERACT_KEYCLOAK_CLIENT_ID: "${{ inputs.FINERACT_KEYCLOAK_CLIENT_ID }}"
-            FINERACT_KEYCLOAK_TOKEN_URL: "${{ inputs.FINERACT_KEYCLOAK_TOKEN_URL }}"
-            FINERACT_KEYCLOAK_PUBLIC_CLIENT: true
-            FINERACT_KEYCLOAK_API_URL: "${{ inputs.FINERACT_KEYCLOAK_API_URL }}"
-            AUTH_SERVER_URL : "${{ inputs.FINERACT_AUTH_URL }}"
-            FINERACT_API_URL : "${{ inputs.FINERACT_API_URL }}"
-            HOST_HOME_URL : "${{ inputs.FINERACT_HOST_HOME_URL }}"
-            MATOMO_SITE_URL : "${{ inputs.MATOMO_SITE_URL }}"
-            MATOMO_SITE_ID : "${{ inputs.MATOMO_SITE_ID }}"
-            SENTRY_DSN : "${{ inputs.SENTRY_DSN }}"
+        initContainers:
+          - name: wait-for-fineract-backend
+            image: busybox
+            command: ['sh', '-c', 'until wget -q -O- http://${{ inputs.FINERACT_PROXY_URL }}:${{ inputs.FINERACT_PROXY_HTTP_PORT }}/fineract-provider/actuator/health; do echo waiting for fineract backend; sleep 2; done;']
 
-          initContainers:
-            - name: wait-for-fineract-backend
-              image: busybox
-              command: ['sh', '-c', 'until wget -q -O- http://${{ inputs.FINERACT_PROXY_URL }}:${{ inputs.FINERACT_PROXY_HTTP_PORT }}/fineract-provider/actuator/health; do echo waiting for fineract backend; sleep 2; done;']
-              restartPolicy: Never
-
-          replicaCount: ${{ inputs.REPLICAS }} " > "${{ github.workspace }}/deployment/my-values.yaml"
+        replicaCount: ${{ inputs.REPLICAS }}
+        EOF
       shell: bash
-    - name: Helm Install fineract frontend
-      run: |-
-        export HELM_EXPERIMENTAL_OCI=1
-
-        echo ${{ inputs.ACR_PULL_PASSWORD }} | helm registry login oaftech.azurecr.io --username ${{ inputs.ACR_PULL_USERNAME }} --password-stdin
 
-        echo "Downloading chart to cache..."
-        helm pull oci://oaftech.azurecr.io/helm/fineract-frontend --untar
+    - name: Helm Install Fineract Frontend
+      run: |
+        export HELM_EXPERIMENTAL_OCI=1
+        echo "${{ inputs.ACR_PULL_PASSWORD }}" | helm registry login ${{ inputs.ACR_REGISTRY }} --username "${{ inputs.ACR_PULL_USERNAME }}" --password-stdin
 
         helm upgrade --install \
-          ${{ inputs.RELEASE_NAME }} \
-          --values ${{ github.workspace }}/fineract-frontend-v2/values.yaml \
-          --values my-values.yaml \
-          --namespace=${{ inputs.NAMESPACE }} \
-          --debug \
-          fineract-frontend
+          "${{ inputs.RELEASE_NAME }}" \
+          --values "${{ github.workspace }}/fineract-values.yaml" \
+          --values "${{ github.workspace }}/${{ inputs.ARTIFACT_NAME }}/values.yaml" \
+          --namespace "${{ inputs.NAMESPACE }}" \
+          --debug --wait \
+          oci://${{ inputs.ACR_REGISTRY }}/helm/fineract-frontend
       shell: bash
-      working-directory: "${{ github.workspace }}/deployment"
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 7b72b66126..bfb6b44d00 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,5 +1,5 @@
----
-name: build pipeline
+name: fineract-frontend-v2
+run-name: fineract-frontend-v2-${{ github.ref_name }}-${{ github.run_number }}
 
 on:
   push:
@@ -13,38 +13,35 @@ on:
       - master
       - main
       - develop
-      - 'release/*'
+      - release/*
 
 env:
   SHOULD_PUBLISH: ${{ github.ref  == 'refs/heads/master' ||  github.ref == 'refs/heads/develop' || startsWith(github.ref , 'refs/heads/release') }}
   IS_RELEASE: ${{ github.ref  == 'refs/heads/master' }}
   ARTIFACT_NAME: fineract-frontend-v2
 
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
 jobs:
-  # This workflow contains a single job called "build"
-  build:
-    # The type of runner that the job will run on
-    name: Build and Deploy
+  Build:
+    name: Build
     runs-on: ubuntu-latest
-
-    # Steps represent a sequence of tasks that will be executed as part of the job
     steps:
-      - name: Checkout Repository
-        uses: actions/checkout@v4
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
         with:
           fetch-depth: 0
           fetch-tags: true
           show-progress: false
 
-      - name: Setup Node.js to use
-        uses: actions/setup-node@v4
+      - name: Setup Node.js
+        uses: actions/setup-node@v4.2.0
         with:
           node-version: 18
+
       - name: Angular CLI install
         run: npm install -g --silent @angular/cli@13.3.10
 
       - name: Set image tag & other env variables
+        id: set-env
         run: |
           VERSION_TAG=$(sed 's/.*"version": "\(.*\)".*/\1/;t;d' ./package.json)
           echo "VERSION_TAG=$VERSION_TAG"
@@ -60,113 +57,269 @@ jobs:
           fi
           echo "Tags: $IMAGE_TAGS"
 
-          echo "VERSION_TAG=$VERSION_TAG" >> $GITHUB_ENV
-          echo "IMAGE_TAGS=$IMAGE_TAGS" >> $GITHUB_ENV
+          echo "VERSION_TAG=$VERSION_TAG" >> $GITHUB_OUTPUT
+          echo "IMAGE_TAGS=$IMAGE_TAGS" >> $GITHUB_OUTPUT
 
       - name: Install Node Packages
         run: npm install
 
-      - name: Docker build
-        uses: docker/build-push-action@v5.1.0
-        with:
-          push: false
-          tags: oaftech.azurecr.io/oneacrefund/fineract-frontend-v2:${{ env.IMAGE_TAGS }}
-          context: ${{ github.workspace }}
-
       - name: Login to Azure registry
-        uses: docker/login-action@v3.0.0
+        uses: docker/login-action@v3.3.0
         if: ${{ env.SHOULD_PUBLISH == 'true'}}
         with:
-          registry: oaftech.azurecr.io
+          registry: ${{ vars.ACR_REGISTRY }}
           username: ${{ vars.ACR_PULL_USERNAME }}
           password: ${{ secrets.ACR_PULL_PASSWORD }}
 
-      - name: Push an image to container registry
-        if: ${{ env.SHOULD_PUBLISH == 'true'}}
-        run: docker push oaftech.azurecr.io/oneacrefund/fineract-frontend-v2:${{ env.IMAGE_TAGS }}
+      - name: Docker Build & Push
+        uses: docker/Build-push-action@v6.13.0
+        with:
+          push: ${{ env.SHOULD_PUBLISH == 'true'}}
+          tags: ${{ vars.ACR_REGISTRY }}/oneacrefund/fineract-frontend-v2:${{ steps.set-env.outputs.IMAGE_TAGS }}
+          context: ${{ github.workspace }}
 
       - name: Use latest image tag
-        run: yq -i '.image.tag = "${{ env.IMAGE_TAGS }}"' ${{ github.workspace }}/deployment/values.yaml
+        run: yq -i '.image.tag = "${{ steps.set-env.outputs.IMAGE_TAGS }}"' ${{ github.workspace }}/deployment/values.yaml
 
       - name: Publish configuration package
-        uses: actions/upload-artifact@v4.3.1
+        uses: actions/upload-artifact@v4.6.0
         if: ${{ env.SHOULD_PUBLISH == 'true'}}
         with:
-          name: fineract-frontend-v2
+          name: ${{ env.ARTIFACT_NAME }}
           path: ${{ github.workspace }}/deployment
-  sonarcloud:
-    name: Sonarcloud analyze
+
+  QualityCheck:
+    name: Quality Check
     runs-on: ubuntu-latest
-    environment: dev
     steps:
-      - name: Checkout Repository
-        uses: actions/checkout@v4
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
         with:
           fetch-depth: 0
           fetch-tags: true
           show-progress: false
-      - uses: actions/setup-node@v4
+
+      - name: Setup Node.js
+        uses: actions/setup-node@v4.2.0
         with:
-          fetch-depth: 0
-      - name: Install dependencies
+          node-version: 18
+
+      - name: Install Dependencies
         run: npm install
+
       - name: Run Lint and Unit Tests
         continue-on-error: true
         run: npm run test:ci
-      - name: Test and coverage
+
+      - name: Test Coverage
         continue-on-error: true
         run: npm run test:cov
+
       - name: SonarCloud Scan
-        uses: SonarSource/sonarcloud-github-action@master
+        uses: SonarSource/sonarqube-scan-action@v5.0.0
         env:
-          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
           SONAR_TOKEN: "${{ secrets.SONAR_TOKEN }}"
 
-  ## Deploy to the various clusters
-  Integration-k8s:
+  Integration:
     if: github.event.ref == 'refs/heads/develop'
-    needs: [build, sonarcloud]
-    uses: ./.github/workflows/deploy.yml
-    with:
-      environment: "Integration"
-    secrets:
-      k8s_url: ${{ secrets.K8S_TEST_URL }}
-      k8s_secret: ${{ secrets.K8S_TEST_DEFAULT }}
-      DEPLOYMENT_ACR_PULL_PASSWORD: ${{ secrets.ACR_PULL_PASSWORD }}
-      DEPLOYMENT_SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
-
-  QA-k8s:
-    needs: Integration-k8s
+    runs-on: ubuntu-latest
+    needs: [Build, QualityCheck]
+    environment:
+      name: Integration
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
+
+      - name: Setup Helm
+        uses: one-acre-fund/oaf-actions/helm_setup@1.0.0
+        with:
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+          RUN_ID: "${{ github.run_id }}"
+          CI_REPOSITORY: "${{ github.repository }}"
+          K8S_URL: "${{ secrets.K8S_TEST_URL }}"
+          K8S_SECRET: "${{ secrets.K8S_TEST_DEFAULT }}"
+
+      - name: Deploy using Helm
+        uses: "./.github/actions/helm_fineract_frontend"
+        with:
+          NAMESPACE: "${{ vars.NAMESPACE }}"
+          ACR_REGISTRY: "${{ vars.ACR_REGISTRY }}"
+          ACR_PULL_PASSWORD: "${{ secrets.ACR_PULL_PASSWORD }}"
+          ACR_PULL_USERNAME: "${{ vars.ACR_PULL_USERNAME }}"
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          REPLICAS: "${{ vars.REPLICAS }}"
+          RELEASE_NAME: "${{ vars.RELEASE_NAME }}"
+          FINERACT_PROXY_URL: "${{ vars.FINERACT_PROXY_URL }}"
+          FINERACT_PROXY_HTTPS_PORT: "${{ vars.FINERACT_PROXY_HTTPS_PORT }}"
+          FINERACT_PROXY_HTTP_PORT: "${{ vars.FINERACT_PROXY_HTTP_PORT }}"
+          FINERACT_KEYCLOAK_REALM: "${{ vars.FINERACT_KEYCLOAK_REALM }}"
+          FINERACT_KEYCLOAK_CLIENT_ID: "${{ vars.FINERACT_KEYCLOAK_CLIENT_ID }}"
+          FINERACT_KEYCLOAK_TOKEN_URL: "${{ vars.FINERACT_KEYCLOAK_TOKEN_URL }}"
+          FINERACT_KEYCLOAK_AUTH_SERVER_URL: "${{ vars.FINERACT_KEYCLOAK_AUTH_SERVER_URL }}"
+          FINERACT_KEYCLOAK_API_URL: "${{ vars.FINERACT_KEYCLOAK_API_URL }}"
+          FINERACT_HOST_HOME_URL: "${{ vars.FINERACT_HOST_HOME_URL }}"
+          FINERACT_BASE_URL: "${{ vars.FINERACT_BASE_URL }}"
+          FINERACT_AUTH_URL: "${{ vars.FINERACT_AUTH_URL }}"
+          FINERACT_API_URL: "${{ vars.FINERACT_API_URL }}"
+          MATOMO_SITE_ID: "${{ vars.MATOMO_SITE_ID }}"
+          MATOMO_SITE_URL: "${{ vars.MATOMO_SITE_URL }}"
+          SENTRY_DSN: "${{ secrets.SENTRY_DSN }}"
+
+  QA:
+    runs-on: ubuntu-latest
+    needs: Integration
     if: github.event.ref == 'refs/heads/develop'
-    uses: ./.github/workflows/deploy.yml
-    with:
-      environment: "QA"
-    secrets:
-      k8s_url: ${{ secrets.K8S_QA_URL }}
-      k8s_secret: ${{ secrets.K8S_QA_DEFAULT }}
-      DEPLOYMENT_ACR_PULL_PASSWORD: ${{ secrets.ACR_PULL_PASSWORD }}
-      DEPLOYMENT_SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
-
-  UAT-k8s:
+    environment:
+      name: QA
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
+
+      - name: Setup Helm
+        uses: one-acre-fund/oaf-actions/helm_setup@1.0.0
+        with:
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+          RUN_ID: "${{ github.run_id }}"
+          CI_REPOSITORY: "${{ github.repository }}"
+          K8S_URL: "${{ secrets.K8S_QA_URL }}"
+          K8S_SECRET: "${{ secrets.K8S_QA_DEFAULT }}"
+
+      - name: Deploy using Helm
+        uses: "./.github/actions/helm_fineract_frontend"
+        with:
+          NAMESPACE: "${{ vars.NAMESPACE }}"
+          ACR_REGISTRY: "${{ vars.ACR_REGISTRY }}"
+          ACR_PULL_PASSWORD: "${{ secrets.ACR_PULL_PASSWORD }}"
+          ACR_PULL_USERNAME: "${{ vars.ACR_PULL_USERNAME }}"
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          REPLICAS: "${{ vars.REPLICAS }}"
+          RELEASE_NAME: "${{ vars.RELEASE_NAME }}"
+          FINERACT_PROXY_URL: "${{ vars.FINERACT_PROXY_URL }}"
+          FINERACT_PROXY_HTTPS_PORT: "${{ vars.FINERACT_PROXY_HTTPS_PORT }}"
+          FINERACT_PROXY_HTTP_PORT: "${{ vars.FINERACT_PROXY_HTTP_PORT }}"
+          FINERACT_KEYCLOAK_REALM: "${{ vars.FINERACT_KEYCLOAK_REALM }}"
+          FINERACT_KEYCLOAK_CLIENT_ID: "${{ vars.FINERACT_KEYCLOAK_CLIENT_ID }}"
+          FINERACT_KEYCLOAK_TOKEN_URL: "${{ vars.FINERACT_KEYCLOAK_TOKEN_URL }}"
+          FINERACT_KEYCLOAK_AUTH_SERVER_URL: "${{ vars.FINERACT_KEYCLOAK_AUTH_SERVER_URL }}"
+          FINERACT_KEYCLOAK_API_URL: "${{ vars.FINERACT_KEYCLOAK_API_URL }}"
+          FINERACT_HOST_HOME_URL: "${{ vars.FINERACT_HOST_HOME_URL }}"
+          FINERACT_BASE_URL: "${{ vars.FINERACT_BASE_URL }}"
+          FINERACT_AUTH_URL: "${{ vars.FINERACT_AUTH_URL }}"
+          FINERACT_API_URL: "${{ vars.FINERACT_API_URL }}"
+          MATOMO_SITE_ID: "${{ vars.MATOMO_SITE_ID }}"
+          MATOMO_SITE_URL: "${{ vars.MATOMO_SITE_URL }}"
+          SENTRY_DSN: "${{ secrets.SENTRY_DSN }}"
+
+  UAT:
+    runs-on: ubuntu-latest
     if: github.event.ref == 'refs/heads/main' || contains(github.event.ref, 'refs/heads/hotfix/') || contains(github.event.ref, 'refs/heads/release/')
-    needs: [build, sonarcloud]
-    uses: ./.github/workflows/deploy.yml
-    with:
-      environment: "UAT"
-    secrets:
-      k8s_url: ${{ secrets.K8S_UAT_URL }}
-      k8s_secret: ${{ secrets.K8S_UAT_DEFAULT }}
-      DEPLOYMENT_ACR_PULL_PASSWORD: ${{ secrets.ACR_PULL_PASSWORD }}
-      DEPLOYMENT_SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
-
-  Prod-k8s:
-    needs: UAT-k8s
+    needs: [Build, QualityCheck]
+    environment:
+      name: UAT
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
+
+      - name: Setup Helm
+        uses: one-acre-fund/oaf-actions/helm_setup@1.0.0
+        with:
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+          RUN_ID: "${{ github.run_id }}"
+          CI_REPOSITORY: "${{ github.repository }}"
+          K8S_URL: "${{ secrets.K8S_UAT_URL }}"
+          K8S_SECRET: "${{ secrets.K8S_UAT_DEFAULT }}"
+
+      - name: Deploy using Helm
+        uses: "./.github/actions/helm_fineract_frontend"
+        with:
+          NAMESPACE: "${{ vars.NAMESPACE }}"
+          ACR_REGISTRY: "${{ vars.ACR_REGISTRY }}"
+          ACR_PULL_PASSWORD: "${{ secrets.ACR_PULL_PASSWORD }}"
+          ACR_PULL_USERNAME: "${{ vars.ACR_PULL_USERNAME }}"
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          REPLICAS: "${{ vars.REPLICAS }}"
+          RELEASE_NAME: "${{ vars.RELEASE_NAME }}"
+          FINERACT_PROXY_URL: "${{ vars.FINERACT_PROXY_URL }}"
+          FINERACT_PROXY_HTTPS_PORT: "${{ vars.FINERACT_PROXY_HTTPS_PORT }}"
+          FINERACT_PROXY_HTTP_PORT: "${{ vars.FINERACT_PROXY_HTTP_PORT }}"
+          FINERACT_KEYCLOAK_REALM: "${{ vars.FINERACT_KEYCLOAK_REALM }}"
+          FINERACT_KEYCLOAK_CLIENT_ID: "${{ vars.FINERACT_KEYCLOAK_CLIENT_ID }}"
+          FINERACT_KEYCLOAK_TOKEN_URL: "${{ vars.FINERACT_KEYCLOAK_TOKEN_URL }}"
+          FINERACT_KEYCLOAK_AUTH_SERVER_URL: "${{ vars.FINERACT_KEYCLOAK_AUTH_SERVER_URL }}"
+          FINERACT_KEYCLOAK_API_URL: "${{ vars.FINERACT_KEYCLOAK_API_URL }}"
+          FINERACT_HOST_HOME_URL: "${{ vars.FINERACT_HOST_HOME_URL }}"
+          FINERACT_BASE_URL: "${{ vars.FINERACT_BASE_URL }}"
+          FINERACT_AUTH_URL: "${{ vars.FINERACT_AUTH_URL }}"
+          FINERACT_API_URL: "${{ vars.FINERACT_API_URL }}"
+          MATOMO_SITE_ID: "${{ vars.MATOMO_SITE_ID }}"
+          MATOMO_SITE_URL: "${{ vars.MATOMO_SITE_URL }}"
+          SENTRY_DSN: "${{ secrets.SENTRY_DSN }}"
+
+  Production:
+    runs-on: ubuntu-latest
+    needs: UAT
     if: github.event.ref == 'refs/heads/main' || contains(github.event.ref, 'refs/heads/hotfix/') || contains(github.event.ref, 'refs/heads/release/')
-    uses: ./.github/workflows/deploy.yml
-    with:
-      environment: "Production"
-    secrets:
-      k8s_url: ${{ secrets.K8S_PROD_URL }}
-      k8s_secret: ${{ secrets.K8S_PROD_DEFAULT }}
-      DEPLOYMENT_ACR_PULL_PASSWORD: ${{ secrets.ACR_PULL_PASSWORD }}
-      DEPLOYMENT_SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
+    environment:
+      name: Production
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
+
+      - name: Setup Helm
+        uses: one-acre-fund/oaf-actions/helm_setup@1.0.0
+        with:
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+          RUN_ID: "${{ github.run_id }}"
+          CI_REPOSITORY: "${{ github.repository }}"
+          K8S_URL: "${{ secrets.K8S_PROD_URL }}"
+          K8S_SECRET: "${{ secrets.K8S_PROD_DEFAULT }}"
+
+      - name: Start Maintenance Window
+        id: start_maintenance
+        uses: one-acre-fund/uptime-kuma-create-maintenance@1.0.0
+        with:
+          UPTIME_USERNAME: ${{ secrets.UPTIME_USERNAME }}
+          UPTIME_PASSWORD: ${{ secrets.UPTIME_PASSWORD }}
+          UPTIME_API_URL: ${{ vars.UPTIME_API_URL }}
+          MAINTENANCE_TITLE: "Service Deployment"
+          MONITOR_ID: ${{ vars.MONITOR_ID }}
+          MONITOR_NAME: ${{ vars.MONITOR_NAME }}
+
+      - name: Deploy using Helm
+        uses: "./.github/actions/helm_fineract_frontend"
+        with:
+          NAMESPACE: "${{ vars.NAMESPACE }}"
+          ACR_REGISTRY: "${{ vars.ACR_REGISTRY }}"
+          ACR_PULL_PASSWORD: "${{ secrets.ACR_PULL_PASSWORD }}"
+          ACR_PULL_USERNAME: "${{ vars.ACR_PULL_USERNAME }}"
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          REPLICAS: "${{ vars.REPLICAS }}"
+          RELEASE_NAME: "${{ vars.RELEASE_NAME }}"
+          FINERACT_PROXY_URL: "${{ vars.FINERACT_PROXY_URL }}"
+          FINERACT_PROXY_HTTPS_PORT: "${{ vars.FINERACT_PROXY_HTTPS_PORT }}"
+          FINERACT_PROXY_HTTP_PORT: "${{ vars.FINERACT_PROXY_HTTP_PORT }}"
+          FINERACT_KEYCLOAK_REALM: "${{ vars.FINERACT_KEYCLOAK_REALM }}"
+          FINERACT_KEYCLOAK_CLIENT_ID: "${{ vars.FINERACT_KEYCLOAK_CLIENT_ID }}"
+          FINERACT_KEYCLOAK_TOKEN_URL: "${{ vars.FINERACT_KEYCLOAK_TOKEN_URL }}"
+          FINERACT_KEYCLOAK_AUTH_SERVER_URL: "${{ vars.FINERACT_KEYCLOAK_AUTH_SERVER_URL }}"
+          FINERACT_KEYCLOAK_API_URL: "${{ vars.FINERACT_KEYCLOAK_API_URL }}"
+          FINERACT_HOST_HOME_URL: "${{ vars.FINERACT_HOST_HOME_URL }}"
+          FINERACT_BASE_URL: "${{ vars.FINERACT_BASE_URL }}"
+          FINERACT_AUTH_URL: "${{ vars.FINERACT_AUTH_URL }}"
+          FINERACT_API_URL: "${{ vars.FINERACT_API_URL }}"
+          MATOMO_SITE_ID: "${{ vars.MATOMO_SITE_ID }}"
+          MATOMO_SITE_URL: "${{ vars.MATOMO_SITE_URL }}"
+          SENTRY_DSN: "${{ secrets.SENTRY_DSN }}"
+
+      - name: Delete Maintenance Window
+        if: always()
+        uses: one-acre-fund/uptime-kuma-delete-maintenance@1.0.0
+        with:
+          UPTIME_USERNAME: ${{ secrets.UPTIME_USERNAME }}
+          UPTIME_PASSWORD: ${{ secrets.UPTIME_PASSWORD }}
+          UPTIME_API_URL: ${{ vars.UPTIME_API_URL }}
+          MAINTENANCE_ID: ${{ steps.start_maintenance.outputs.maintenance_id }}
diff --git a/.github/workflows/create-docker-hub-image.yml b/.github/workflows/create-docker-hub-image.yml
deleted file mode 100644
index 6c13a61e2c..0000000000
--- a/.github/workflows/create-docker-hub-image.yml
+++ /dev/null
@@ -1,35 +0,0 @@
----
-name: Publish Image in Docker Hub
-
-on:
-  push:
-    branches: [master]
-  pull_request:
-    branches: [master]
-
-jobs:
-
-  build:
-    runs-on: ubuntu-latest
-    env:
-      DOCKER_ORGANIZATION: ${{secrets.DOCKER_ORGANIZATION}}
-      WEB_APP_VERSION: ${{secrets.WEB_APP_LATEST_STABLE_VERSION}}
-
-    steps:
-      - uses: actions/checkout@v2
-
-      - name: Docker Hub Login
-        env:
-          DOCKER_USER: ${{secrets.DOCKER_USER}}
-          DOCKER_PASSWORD: ${{secrets.DOCKER_PASSWORD}}
-        run: |
-          echo $DOCKER_PASSWORD | docker login -u $DOCKER_USER --password-stdin
-
-      - name: Build the Docker image
-        run: docker build -t web-app:latest .
-
-      - name: Docker Hub Prepare
-        run: docker image tag web-app $DOCKER_ORGANIZATION/web-app:$WEB_APP_VERSION
-
-      - name: Docker Hub Push
-        run: docker image push $DOCKER_ORGANIZATION/web-app:$WEB_APP_VERSION
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
deleted file mode 100644
index e11b481843..0000000000
--- a/.github/workflows/deploy.yml
+++ /dev/null
@@ -1,76 +0,0 @@
-name: Deploy Workflow
-
-on:
-  workflow_call:
-    inputs:
-      environment:
-        required: true
-        type: string
-    secrets:
-      k8s_url:
-        required: true
-      k8s_secret:
-        required: true
-      DEPLOYMENT_ACR_PULL_PASSWORD:
-        required: true
-      DEPLOYMENT_SENTRY_DSN:
-        required: false
-
-jobs:
-  deploy:
-    runs-on: ubuntu-latest
-    environment:
-      name: ${{ inputs.environment }}
-    steps:
-      - uses: actions/checkout@v4
-
-      - uses: one-acre-fund/oaf-actions/helm_setup@main
-        with:
-          ARTIFACT_NAME: "fineract-frontend-v2"
-          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
-          RUN_ID: "${{ github.run_id }}"
-          CI_REPOSITORY: "${{ github.repository }}"
-          K8S_URL: "${{ secrets.k8s_url }}"
-          K8S_SECRET: "${{ secrets.k8s_secret }}"
-
-      # - name: Start Maintenance Window
-      #   id: start_maintenance
-      #   uses: one-acre-fund/uptime-kuma-create-maintenance@1.0.0
-      #   with:
-      #     UPTIME_USERNAME: ${{ secrets.UPTIME_USERNAME }}
-      #     UPTIME_PASSWORD: ${{ secrets.UPTIME_PASSWORD }}
-      #     UPTIME_API_URL: ${{ vars.UPTIME_API_URL }}
-      #     MAINTENANCE_TITLE: "Service Deployment"
-      #     MONITOR_ID: ${{ vars.MONITOR_ID }}
-      #     MONITOR_NAME: ${{ vars.MONITOR_NAME }}
-
-      - uses: "./.github/actions/helm_fineract_frontend"
-        with:
-          NAMESPACE: "${{ vars.NAMESPACE }}"
-          ACR_PULL_PASSWORD: "${{ secrets.DEPLOYMENT_ACR_PULL_PASSWORD }}"
-          ACR_PULL_USERNAME: "${{ vars.ACR_PULL_USERNAME }}"
-          REPLICAS: "${{ vars.REPLICAS }}"
-          RELEASE_NAME: "${{ vars.RELEASE_NAME }}"
-          FINERACT_PROXY_URL: "${{ vars.FINERACT_PROXY_URL }}"
-          FINERACT_PROXY_HTTPS_PORT: "${{ vars.FINERACT_PROXY_HTTPS_PORT }}"
-          FINERACT_PROXY_HTTP_PORT: "${{ vars.FINERACT_PROXY_HTTP_PORT }}"
-          FINERACT_KEYCLOAK_REALM: "${{ vars.FINERACT_KEYCLOAK_REALM }}"
-          FINERACT_KEYCLOAK_CLIENT_ID: "${{ vars.FINERACT_KEYCLOAK_CLIENT_ID }}"
-          FINERACT_KEYCLOAK_TOKEN_URL: "${{ vars.FINERACT_KEYCLOAK_TOKEN_URL }}"
-          FINERACT_KEYCLOAK_AUTH_SERVER_URL: "${{ vars.FINERACT_KEYCLOAK_AUTH_SERVER_URL }}"
-          FINERACT_KEYCLOAK_API_URL: "${{ vars.FINERACT_KEYCLOAK_API_URL }}"
-          FINERACT_HOST_HOME_URL: "${{ vars.FINERACT_HOST_HOME_URL }}"
-          FINERACT_BASE_URL: "${{ vars.FINERACT_BASE_URL }}"
-          FINERACT_AUTH_URL: "${{ vars.FINERACT_AUTH_URL }}"
-          FINERACT_API_URL: "${{ vars.FINERACT_API_URL }}"
-          MATOMO_SITE_ID: "${{ vars.MATOMO_SITE_ID }}"
-          MATOMO_SITE_URL: "${{ vars.MATOMO_SITE_URL }}"
-          SENTRY_DSN: "${{ secrets.DEPLOYMENT_SENTRY_DSN }}"
-
-      # - name: Delete Maintenance Window
-      #   uses: one-acre-fund/uptime-kuma-delete-maintenance@1.0.0
-      #   with:
-      #      UPTIME_USERNAME: ${{ secrets.UPTIME_USERNAME }}
-      #      UPTIME_PASSWORD: ${{ secrets.UPTIME_PASSWORD }}
-      #      UPTIME_API_URL: ${{ vars.UPTIME_API_URL }}
-      #      MAINTENANCE_ID: ${{ steps.start_maintenance.outputs.maintenance_id }}
diff --git a/.github/workflows/megalinter.yml b/.github/workflows/megalinter.yml
index 5a6552995a..51fa6c4386 100644
--- a/.github/workflows/megalinter.yml
+++ b/.github/workflows/megalinter.yml
@@ -1,4 +1,3 @@
----
 name: MegaLinter
 
 on:
@@ -8,74 +7,69 @@ on:
     branches: [main, develop, master]
 
 env:
-  APPLY_FIXES: all # When active, APPLY_FIXES must also be defined as environment variable (in github/workflows/mega-linter.yml or other CI tool)
-  APPLY_FIXES_EVENT: pull_request # Decide which event triggers application of fixes in a commit or a PR (pull_request, push, all)
-  APPLY_FIXES_MODE: commit # If APPLY_FIXES is used, defines if the fixes are directly committed (commit) or posted in a PR (pull_request)
+  APPLY_FIXES: all
+  APPLY_FIXES_EVENT: pull_request
+  APPLY_FIXES_MODE: commit
 
 concurrency:
   group: ${{ github.ref }}-${{ github.workflow }}
   cancel-in-progress: true
 
 jobs:
-  megalinter:
+  MegaLinter:
     name: MegaLinter
     runs-on: ubuntu-latest
     permissions:
-      # Give the default GITHUB_TOKEN write permission to commit and push, comment issues & post new PR
       contents: write
       issues: write
       pull-requests: write
+
     steps:
       - name: Checkout Code
-        uses: actions/checkout@v4
+        uses: actions/checkout@v4.2.2
         with:
-          token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }}
-          fetch-depth: 0 # If you use VALIDATE_ALL_CODEBASE = true, you can remove this line to improve performances
+          token: ${{ secrets.GITHUB_TOKEN }}
+          fetch-depth: 0
 
-      # MegaLinter
       - name: MegaLinter
         id: ml
-        uses: oxsecurity/megalinter/flavors/cupcake@v7
+        uses: oxsecurity/megalinter/flavors/cupcake@v8.4.2
         env:
           VALIDATE_ALL_CODEBASE: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master') }} # Validates all source when push on main, else just the git diff with main. Override with true if you always want to lint all sources
           DEFAULT_BRANCH: ${{ github.base_ref || 'develop' }}
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-          # Override the local value
-          # KOTLIN_KTLINT_CLI_LINT_MODE: list_of_files
 
-      # Upload MegaLinter artifacts
       - name: Archive production artifacts
         if: success() || failure()
-        uses: actions/upload-artifact@v4
+        uses: actions/upload-artifact@v4.6.0
         with:
           name: MegaLinter reports
           path: |
             megalinter-reports
             mega-linter.log
 
-      # Create pull request if applicable (for now works only on PR from same repository, not from forks)
       - name: Create Pull Request with applied fixes
         id: cpr
         if: steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == 'all' || env.APPLY_FIXES_EVENT == github.event_name) && env.APPLY_FIXES_MODE == 'pull_request' && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository) && !contains(github.event.head_commit.message, 'skip fix')
-        uses: peter-evans/create-pull-request@v6
+        uses: peter-evans/create-pull-request@v7.0.6
         with:
-          token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }}
+          token: ${{ secrets.GITHUB_TOKEN }}
           commit-message: "[MegaLinter] Apply linters automatic fixes"
           title: "[MegaLinter] Apply linters automatic fixes"
           labels: bot
+
       - name: Create PR output
         if: steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == 'all' || env.APPLY_FIXES_EVENT == github.event_name) && env.APPLY_FIXES_MODE == 'pull_request' && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository) && !contains(github.event.head_commit.message, 'skip fix')
         run: |
           echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
           echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}"
 
-      # Push new commit if applicable (for now works only on PR from same repository, not from forks)
       - name: Prepare commit
         if: steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == 'all' || env.APPLY_FIXES_EVENT == github.event_name) && env.APPLY_FIXES_MODE == 'commit' && github.ref != 'refs/heads/main' && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository) && !contains(github.event.head_commit.message, 'skip fix')
         run: sudo chown -Rc $UID .git/
       - name: Commit and push applied linter fixes
         if: steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == 'all' || env.APPLY_FIXES_EVENT == github.event_name) && env.APPLY_FIXES_MODE == 'commit' && github.ref != 'refs/heads/main' && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository) && !contains(github.event.head_commit.message, 'skip fix')
-        uses: stefanzweifel/git-auto-commit-action@v4
+        uses: stefanzweifel/git-auto-commit-action@v5.1.0
         with:
           branch: ${{ github.event.pull_request.head.ref || github.head_ref || github.ref }}
           commit_message: "[MegaLinter] Apply linters fixes"
diff --git a/.mega-linter.yml b/.mega-linter.yml
index f86f7a05db..c210e0568b 100644
--- a/.mega-linter.yml
+++ b/.mega-linter.yml
@@ -1,4 +1,3 @@
----
 # Configuration file for Mega-Linter
 # See all available variables at https://megalinter.github.io/latest/configuration/ and in linters documentation
 
diff --git a/yamllint.yml b/.yamllint.yml
similarity index 91%
rename from yamllint.yml
rename to .yamllint.yml
index 30a189e15a..bede37e835 100644
--- a/yamllint.yml
+++ b/.yamllint.yml
@@ -1,6 +1,6 @@
 rules:
   line-length:
-    max: 128
+    max: 400
     allow-non-breakable-words: true
     allow-non-breakable-inline-mappings: false
   document-start:
diff --git a/Dockerfile b/Dockerfile
index 79a91b663c..6bb776492e 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -11,14 +11,10 @@ ENV PATH /usr/src/app/node_modules/.bin:$PATH
 
 COPY ./ /usr/src/app/
 
-RUN npm cache clear --force &&\
-
-  npm config set fetch-retry-maxtimeout 120000 &&\
-
-  npm install --location=global @angular/cli@14.2.13 &&\
-
-  npm install &&\
-
+RUN npm cache clear --force && \
+  npm config set fetch-retry-maxtimeout 120000 && \
+  npm install --location=global @angular/cli@14.2.13 && \
+  npm install && \
   ng build --configuration production --output-path=/dist
 
 ###############
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index cbc87e81bc..9b2d4e4b9b 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -5,6 +5,7 @@
     * [SER-3363] - Implement label translation in Client related UIs
     * [SER-3259] - External Service: Add new page for payment provider configuration
     * [SER-3364] - Implement label translation in Groups and Loans related UIs
+    * [SER-3313] - Add bulk account transaction transfer
 
 ## Version 1.3.5 - Community 1.0.0
 
diff --git a/docker-compose.yml b/docker-compose.yml
index 6ad93719ac..6214b5ce21 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,4 +1,3 @@
----
 version: '3.5'
 
 services:
diff --git a/src/app/organization/bulk-import/bulk-import.component.html b/src/app/organization/bulk-import/bulk-import.component.html
index 34069b9e5d..2e8c03865c 100644
--- a/src/app/organization/bulk-import/bulk-import.component.html
+++ b/src/app/organization/bulk-import/bulk-import.component.html
@@ -140,6 +140,13 @@ <h4 matLine>Guarantors</h4>
             </mat-icon>
             <h4 matLine>Healthy Path</h4>
           </mat-list-item>
+
+          <mat-list-item [routerLink]="['Account Transfer Transaction']" *mifosxHasPermission="'READ_CLIENT'">
+            <mat-icon matListIcon>
+              <fa-icon icon="chevron-right" size="sm"></fa-icon>
+            </mat-icon>
+            <h4 matLine>Account Transfer Transaction</h4>
+          </mat-list-item>
         </mat-nav-list>
       </div>
     </div>
diff --git a/src/app/organization/bulk-import/view-bulk-import/bulk-imports.ts b/src/app/organization/bulk-import/view-bulk-import/bulk-imports.ts
index af40a42645..bc6e49155e 100644
--- a/src/app/organization/bulk-import/view-bulk-import/bulk-imports.ts
+++ b/src/app/organization/bulk-import/view-bulk-import/bulk-imports.ts
@@ -133,4 +133,11 @@ export const BulkImports = [
       permission: 'READ_CLIENT',
       formFields: 1
     },
+    {
+      name: 'Account Transfer Transaction',
+      entityType: 'accounttransferstransaction',
+      urlSuffix: '/accounttransfers',
+      permission: 'READ_CLIENT',
+      formFields: 1
+    },
   ];


Reviews:
user: login: github-advanced-security[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-23T13:15:30Z
user: login: amydoxym
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-23T13:19:07Z
user: login: gilclefes
body: looks good to me
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-23T13:23:39Z

Review comments:
diff_hunk: @@ -13,160 +13,313 @@
       - master
       - main
       - develop
-      - 'release/*'
+      - release/*
 
 env:
   SHOULD_PUBLISH: ${{ github.ref  == 'refs/heads/master' ||  github.ref == 'refs/heads/develop' || startsWith(github.ref , 'refs/heads/release') }}
   IS_RELEASE: ${{ github.ref  == 'refs/heads/master' }}
   ARTIFACT_NAME: fineract-frontend-v2
 
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
 jobs:
-  # This workflow contains a single job called "build"
-  build:
-    # The type of runner that the job will run on
-    name: Build and Deploy
+  Build:
+    name: Build
     runs-on: ubuntu-latest
-
-    # Steps represent a sequence of tasks that will be executed as part of the job
     steps:
-      - name: Checkout Repository
-        uses: actions/checkout@v4
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
         with:
           fetch-depth: 0
           fetch-tags: true
           show-progress: false
 
-      - name: Setup Node.js to use
-        uses: actions/setup-node@v4
+      - name: Setup Node.js
+        uses: actions/setup-node@v4.2.0
         with:
           node-version: 18
+
       - name: Angular CLI install
         run: npm install -g --silent @angular/cli@13.3.10
 
       - name: Set image tag & other env variables
+        id: set-env
         run: |
           VERSION_TAG=$(sed 's/.*"version": "\(.*\)".*/\1/;t;d' ./package.json)
           echo "VERSION_TAG=$VERSION_TAG"
~
~          echo "Is Release=$IS_RELEASE"
~
~          if [ $IS_RELEASE == 'true' ]; then
~            echo "This is a release"
~            IMAGE_TAGS=$VERSION_TAG
~          else
~            echo "This is a normal build"
~            IMAGE_TAGS="${VERSION_TAG}.$(date '+%Y.%m.%d').${{ github.run_number }}"
           fi
           echo "Tags: $IMAGE_TAGS"
 
-          echo "VERSION_TAG=$VERSION_TAG" >> $GITHUB_ENV
-          echo "IMAGE_TAGS=$IMAGE_TAGS" >> $GITHUB_ENV
+          echo "VERSION_TAG=$VERSION_TAG" >> $GITHUB_OUTPUT
+          echo "IMAGE_TAGS=$IMAGE_TAGS" >> $GITHUB_OUTPUT
 
       - name: Install Node Packages
         run: npm install
 
-      - name: Docker build
-        uses: docker/build-push-action@v5.1.0
-        with:
-          push: false
-          tags: oaftech.azurecr.io/oneacrefund/fineract-frontend-v2:${{ env.IMAGE_TAGS }}
-          context: ${{ github.workspace }}
-
       - name: Login to Azure registry
-        uses: docker/login-action@v3.0.0
+        uses: docker/login-action@v3.3.0
         if: ${{ env.SHOULD_PUBLISH == 'true'}}
         with:
-          registry: oaftech.azurecr.io
+          registry: ${{ vars.ACR_REGISTRY }}
           username: ${{ vars.ACR_PULL_USERNAME }}
           password: ${{ secrets.ACR_PULL_PASSWORD }}
 
-      - name: Push an image to container registry
-        if: ${{ env.SHOULD_PUBLISH == 'true'}}
-        run: docker push oaftech.azurecr.io/oneacrefund/fineract-frontend-v2:${{ env.IMAGE_TAGS }}
+      - name: Docker Build & Push
+        uses: docker/Build-push-action@v6.13.0
+        with:
+          push: ${{ env.SHOULD_PUBLISH == 'true'}}
+          tags: ${{ vars.ACR_REGISTRY }}/oneacrefund/fineract-frontend-v2:${{ steps.set-env.outputs.IMAGE_TAGS }}
+          context: ${{ github.workspace }}
 
       - name: Use latest image tag
-        run: yq -i '.image.tag = "${{ env.IMAGE_TAGS }}"' ${{ github.workspace }}/deployment/values.yaml
+        run: yq -i '.image.tag = "${{ steps.set-env.outputs.IMAGE_TAGS }}"' ${{ github.workspace }}/deployment/values.yaml
 
       - name: Publish configuration package
-        uses: actions/upload-artifact@v4.3.1
+        uses: actions/upload-artifact@v4.6.0
         if: ${{ env.SHOULD_PUBLISH == 'true'}}
         with:
-          name: fineract-frontend-v2
+          name: ${{ env.ARTIFACT_NAME }}
           path: ${{ github.workspace }}/deployment
-  sonarcloud:
-    name: Sonarcloud analyze
+
+  QualityCheck:
path: .github/workflows/build.yml
user: login: github-advanced-security[bot]
body: ## Workflow does not contain permissions

Actions Job or Workflow does not set permissions

[Show more details](https://github.com/one-acre-fund/fineract-frontend-v2/security/code-scanning/20)
created_at: 2025-04-23T13:15:30Z
author_association: NONE
diff_hunk: @@ -13,160 +13,313 @@
       - master
       - main
       - develop
-      - 'release/*'
+      - release/*
 
 env:
   SHOULD_PUBLISH: ${{ github.ref  == 'refs/heads/master' ||  github.ref == 'refs/heads/develop' || startsWith(github.ref , 'refs/heads/release') }}
   IS_RELEASE: ${{ github.ref  == 'refs/heads/master' }}
   ARTIFACT_NAME: fineract-frontend-v2
 
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
 jobs:
-  # This workflow contains a single job called "build"
-  build:
-    # The type of runner that the job will run on
-    name: Build and Deploy
+  Build:
+    name: Build
     runs-on: ubuntu-latest
-
-    # Steps represent a sequence of tasks that will be executed as part of the job
     steps:
-      - name: Checkout Repository
-        uses: actions/checkout@v4
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
         with:
           fetch-depth: 0
           fetch-tags: true
           show-progress: false
 
-      - name: Setup Node.js to use
-        uses: actions/setup-node@v4
+      - name: Setup Node.js
+        uses: actions/setup-node@v4.2.0
         with:
           node-version: 18
+
       - name: Angular CLI install
         run: npm install -g --silent @angular/cli@13.3.10
 
       - name: Set image tag & other env variables
+        id: set-env
         run: |
           VERSION_TAG=$(sed 's/.*"version": "\(.*\)".*/\1/;t;d' ./package.json)
           echo "VERSION_TAG=$VERSION_TAG"
~
~          echo "Is Release=$IS_RELEASE"
~
~          if [ $IS_RELEASE == 'true' ]; then
~            echo "This is a release"
~            IMAGE_TAGS=$VERSION_TAG
~          else
~            echo "This is a normal build"
~            IMAGE_TAGS="${VERSION_TAG}.$(date '+%Y.%m.%d').${{ github.run_number }}"
           fi
           echo "Tags: $IMAGE_TAGS"
 
-          echo "VERSION_TAG=$VERSION_TAG" >> $GITHUB_ENV
-          echo "IMAGE_TAGS=$IMAGE_TAGS" >> $GITHUB_ENV
+          echo "VERSION_TAG=$VERSION_TAG" >> $GITHUB_OUTPUT
+          echo "IMAGE_TAGS=$IMAGE_TAGS" >> $GITHUB_OUTPUT
 
       - name: Install Node Packages
         run: npm install
 
-      - name: Docker build
-        uses: docker/build-push-action@v5.1.0
-        with:
-          push: false
-          tags: oaftech.azurecr.io/oneacrefund/fineract-frontend-v2:${{ env.IMAGE_TAGS }}
-          context: ${{ github.workspace }}
-
       - name: Login to Azure registry
-        uses: docker/login-action@v3.0.0
+        uses: docker/login-action@v3.3.0
         if: ${{ env.SHOULD_PUBLISH == 'true'}}
         with:
-          registry: oaftech.azurecr.io
+          registry: ${{ vars.ACR_REGISTRY }}
           username: ${{ vars.ACR_PULL_USERNAME }}
           password: ${{ secrets.ACR_PULL_PASSWORD }}
 
-      - name: Push an image to container registry
-        if: ${{ env.SHOULD_PUBLISH == 'true'}}
-        run: docker push oaftech.azurecr.io/oneacrefund/fineract-frontend-v2:${{ env.IMAGE_TAGS }}
+      - name: Docker Build & Push
+        uses: docker/Build-push-action@v6.13.0
+        with:
+          push: ${{ env.SHOULD_PUBLISH == 'true'}}
+          tags: ${{ vars.ACR_REGISTRY }}/oneacrefund/fineract-frontend-v2:${{ steps.set-env.outputs.IMAGE_TAGS }}
+          context: ${{ github.workspace }}
 
       - name: Use latest image tag
-        run: yq -i '.image.tag = "${{ env.IMAGE_TAGS }}"' ${{ github.workspace }}/deployment/values.yaml
+        run: yq -i '.image.tag = "${{ steps.set-env.outputs.IMAGE_TAGS }}"' ${{ github.workspace }}/deployment/values.yaml
 
       - name: Publish configuration package
-        uses: actions/upload-artifact@v4.3.1
+        uses: actions/upload-artifact@v4.6.0
         if: ${{ env.SHOULD_PUBLISH == 'true'}}
         with:
-          name: fineract-frontend-v2
+          name: ${{ env.ARTIFACT_NAME }}
           path: ${{ github.workspace }}/deployment
-  sonarcloud:
-    name: Sonarcloud analyze
+
+  QualityCheck:
+    name: Quality Check
     runs-on: ubuntu-latest
-    environment: dev
     steps:
-      - name: Checkout Repository
-        uses: actions/checkout@v4
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
         with:
           fetch-depth: 0
           fetch-tags: true
           show-progress: false
-      - uses: actions/setup-node@v4
+
+      - name: Setup Node.js
+        uses: actions/setup-node@v4.2.0
         with:
-          fetch-depth: 0
-      - name: Install dependencies
+          node-version: 18
+
+      - name: Install Dependencies
         run: npm install
+
       - name: Run Lint and Unit Tests
         continue-on-error: true
         run: npm run test:ci
-      - name: Test and coverage
+
+      - name: Test Coverage
         continue-on-error: true
         run: npm run test:cov
+
       - name: SonarCloud Scan
-        uses: SonarSource/sonarcloud-github-action@master
+        uses: SonarSource/sonarqube-scan-action@v5.0.0
         env:
-          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
           SONAR_TOKEN: "${{ secrets.SONAR_TOKEN }}"
 
-  ## Deploy to the various clusters
-  Integration-k8s:
+  Integration:
     if: github.event.ref == 'refs/heads/develop'
-    needs: [build, sonarcloud]
-    uses: ./.github/workflows/deploy.yml
-    with:
-      environment: "Integration"
-    secrets:
-      k8s_url: ${{ secrets.K8S_TEST_URL }}
-      k8s_secret: ${{ secrets.K8S_TEST_DEFAULT }}
-      DEPLOYMENT_ACR_PULL_PASSWORD: ${{ secrets.ACR_PULL_PASSWORD }}
-      DEPLOYMENT_SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
-
-  QA-k8s:
-    needs: Integration-k8s
+    runs-on: ubuntu-latest
+    needs: [Build, QualityCheck]
+    environment:
+      name: Integration
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
+
+      - name: Setup Helm
+        uses: one-acre-fund/oaf-actions/helm_setup@1.0.0
+        with:
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+          RUN_ID: "${{ github.run_id }}"
+          CI_REPOSITORY: "${{ github.repository }}"
+          K8S_URL: "${{ secrets.K8S_TEST_URL }}"
+          K8S_SECRET: "${{ secrets.K8S_TEST_DEFAULT }}"
+
+      - name: Deploy using Helm
+        uses: "./.github/actions/helm_fineract_frontend"
+        with:
+          NAMESPACE: "${{ vars.NAMESPACE }}"
+          ACR_REGISTRY: "${{ vars.ACR_REGISTRY }}"
+          ACR_PULL_PASSWORD: "${{ secrets.ACR_PULL_PASSWORD }}"
+          ACR_PULL_USERNAME: "${{ vars.ACR_PULL_USERNAME }}"
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          REPLICAS: "${{ vars.REPLICAS }}"
+          RELEASE_NAME: "${{ vars.RELEASE_NAME }}"
+          FINERACT_PROXY_URL: "${{ vars.FINERACT_PROXY_URL }}"
+          FINERACT_PROXY_HTTPS_PORT: "${{ vars.FINERACT_PROXY_HTTPS_PORT }}"
+          FINERACT_PROXY_HTTP_PORT: "${{ vars.FINERACT_PROXY_HTTP_PORT }}"
+          FINERACT_KEYCLOAK_REALM: "${{ vars.FINERACT_KEYCLOAK_REALM }}"
+          FINERACT_KEYCLOAK_CLIENT_ID: "${{ vars.FINERACT_KEYCLOAK_CLIENT_ID }}"
+          FINERACT_KEYCLOAK_TOKEN_URL: "${{ vars.FINERACT_KEYCLOAK_TOKEN_URL }}"
+          FINERACT_KEYCLOAK_AUTH_SERVER_URL: "${{ vars.FINERACT_KEYCLOAK_AUTH_SERVER_URL }}"
+          FINERACT_KEYCLOAK_API_URL: "${{ vars.FINERACT_KEYCLOAK_API_URL }}"
+          FINERACT_HOST_HOME_URL: "${{ vars.FINERACT_HOST_HOME_URL }}"
+          FINERACT_BASE_URL: "${{ vars.FINERACT_BASE_URL }}"
+          FINERACT_AUTH_URL: "${{ vars.FINERACT_AUTH_URL }}"
+          FINERACT_API_URL: "${{ vars.FINERACT_API_URL }}"
+          MATOMO_SITE_ID: "${{ vars.MATOMO_SITE_ID }}"
+          MATOMO_SITE_URL: "${{ vars.MATOMO_SITE_URL }}"
+          SENTRY_DSN: "${{ secrets.SENTRY_DSN }}"
+
+  QA:
+    runs-on: ubuntu-latest
+    needs: Integration
     if: github.event.ref == 'refs/heads/develop'
-    uses: ./.github/workflows/deploy.yml
-    with:
-      environment: "QA"
-    secrets:
-      k8s_url: ${{ secrets.K8S_QA_URL }}
-      k8s_secret: ${{ secrets.K8S_QA_DEFAULT }}
-      DEPLOYMENT_ACR_PULL_PASSWORD: ${{ secrets.ACR_PULL_PASSWORD }}
-      DEPLOYMENT_SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
-
-  UAT-k8s:
+    environment:
+      name: QA
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
+
+      - name: Setup Helm
+        uses: one-acre-fund/oaf-actions/helm_setup@1.0.0
+        with:
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+          RUN_ID: "${{ github.run_id }}"
+          CI_REPOSITORY: "${{ github.repository }}"
+          K8S_URL: "${{ secrets.K8S_QA_URL }}"
+          K8S_SECRET: "${{ secrets.K8S_QA_DEFAULT }}"
+
+      - name: Deploy using Helm
+        uses: "./.github/actions/helm_fineract_frontend"
+        with:
+          NAMESPACE: "${{ vars.NAMESPACE }}"
+          ACR_REGISTRY: "${{ vars.ACR_REGISTRY }}"
+          ACR_PULL_PASSWORD: "${{ secrets.ACR_PULL_PASSWORD }}"
+          ACR_PULL_USERNAME: "${{ vars.ACR_PULL_USERNAME }}"
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          REPLICAS: "${{ vars.REPLICAS }}"
+          RELEASE_NAME: "${{ vars.RELEASE_NAME }}"
+          FINERACT_PROXY_URL: "${{ vars.FINERACT_PROXY_URL }}"
+          FINERACT_PROXY_HTTPS_PORT: "${{ vars.FINERACT_PROXY_HTTPS_PORT }}"
+          FINERACT_PROXY_HTTP_PORT: "${{ vars.FINERACT_PROXY_HTTP_PORT }}"
+          FINERACT_KEYCLOAK_REALM: "${{ vars.FINERACT_KEYCLOAK_REALM }}"
+          FINERACT_KEYCLOAK_CLIENT_ID: "${{ vars.FINERACT_KEYCLOAK_CLIENT_ID }}"
+          FINERACT_KEYCLOAK_TOKEN_URL: "${{ vars.FINERACT_KEYCLOAK_TOKEN_URL }}"
+          FINERACT_KEYCLOAK_AUTH_SERVER_URL: "${{ vars.FINERACT_KEYCLOAK_AUTH_SERVER_URL }}"
+          FINERACT_KEYCLOAK_API_URL: "${{ vars.FINERACT_KEYCLOAK_API_URL }}"
+          FINERACT_HOST_HOME_URL: "${{ vars.FINERACT_HOST_HOME_URL }}"
+          FINERACT_BASE_URL: "${{ vars.FINERACT_BASE_URL }}"
+          FINERACT_AUTH_URL: "${{ vars.FINERACT_AUTH_URL }}"
+          FINERACT_API_URL: "${{ vars.FINERACT_API_URL }}"
+          MATOMO_SITE_ID: "${{ vars.MATOMO_SITE_ID }}"
+          MATOMO_SITE_URL: "${{ vars.MATOMO_SITE_URL }}"
+          SENTRY_DSN: "${{ secrets.SENTRY_DSN }}"
+
+  UAT:
path: .github/workflows/build.yml
user: login: github-advanced-security[bot]
body: ## Workflow does not contain permissions

Actions Job or Workflow does not set permissions

[Show more details](https://github.com/one-acre-fund/fineract-frontend-v2/security/code-scanning/23)
created_at: 2025-04-23T13:15:30Z
author_association: NONE
diff_hunk: @@ -13,160 +13,313 @@
       - master
       - main
       - develop
-      - 'release/*'
+      - release/*
 
 env:
   SHOULD_PUBLISH: ${{ github.ref  == 'refs/heads/master' ||  github.ref == 'refs/heads/develop' || startsWith(github.ref , 'refs/heads/release') }}
   IS_RELEASE: ${{ github.ref  == 'refs/heads/master' }}
   ARTIFACT_NAME: fineract-frontend-v2
 
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
 jobs:
-  # This workflow contains a single job called "build"
-  build:
-    # The type of runner that the job will run on
-    name: Build and Deploy
+  Build:
+    name: Build
     runs-on: ubuntu-latest
-
-    # Steps represent a sequence of tasks that will be executed as part of the job
     steps:
-      - name: Checkout Repository
-        uses: actions/checkout@v4
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
         with:
           fetch-depth: 0
           fetch-tags: true
           show-progress: false
 
-      - name: Setup Node.js to use
-        uses: actions/setup-node@v4
+      - name: Setup Node.js
+        uses: actions/setup-node@v4.2.0
         with:
           node-version: 18
+
       - name: Angular CLI install
         run: npm install -g --silent @angular/cli@13.3.10
 
       - name: Set image tag & other env variables
+        id: set-env
         run: |
           VERSION_TAG=$(sed 's/.*"version": "\(.*\)".*/\1/;t;d' ./package.json)
           echo "VERSION_TAG=$VERSION_TAG"
~
~          echo "Is Release=$IS_RELEASE"
~
~          if [ $IS_RELEASE == 'true' ]; then
~            echo "This is a release"
~            IMAGE_TAGS=$VERSION_TAG
~          else
~            echo "This is a normal build"
~            IMAGE_TAGS="${VERSION_TAG}.$(date '+%Y.%m.%d').${{ github.run_number }}"
           fi
           echo "Tags: $IMAGE_TAGS"
 
-          echo "VERSION_TAG=$VERSION_TAG" >> $GITHUB_ENV
-          echo "IMAGE_TAGS=$IMAGE_TAGS" >> $GITHUB_ENV
+          echo "VERSION_TAG=$VERSION_TAG" >> $GITHUB_OUTPUT
+          echo "IMAGE_TAGS=$IMAGE_TAGS" >> $GITHUB_OUTPUT
 
       - name: Install Node Packages
         run: npm install
 
-      - name: Docker build
-        uses: docker/build-push-action@v5.1.0
-        with:
-          push: false
-          tags: oaftech.azurecr.io/oneacrefund/fineract-frontend-v2:${{ env.IMAGE_TAGS }}
-          context: ${{ github.workspace }}
-
       - name: Login to Azure registry
-        uses: docker/login-action@v3.0.0
+        uses: docker/login-action@v3.3.0
         if: ${{ env.SHOULD_PUBLISH == 'true'}}
         with:
-          registry: oaftech.azurecr.io
+          registry: ${{ vars.ACR_REGISTRY }}
           username: ${{ vars.ACR_PULL_USERNAME }}
           password: ${{ secrets.ACR_PULL_PASSWORD }}
 
-      - name: Push an image to container registry
-        if: ${{ env.SHOULD_PUBLISH == 'true'}}
-        run: docker push oaftech.azurecr.io/oneacrefund/fineract-frontend-v2:${{ env.IMAGE_TAGS }}
+      - name: Docker Build & Push
+        uses: docker/Build-push-action@v6.13.0
+        with:
+          push: ${{ env.SHOULD_PUBLISH == 'true'}}
+          tags: ${{ vars.ACR_REGISTRY }}/oneacrefund/fineract-frontend-v2:${{ steps.set-env.outputs.IMAGE_TAGS }}
+          context: ${{ github.workspace }}
 
       - name: Use latest image tag
-        run: yq -i '.image.tag = "${{ env.IMAGE_TAGS }}"' ${{ github.workspace }}/deployment/values.yaml
+        run: yq -i '.image.tag = "${{ steps.set-env.outputs.IMAGE_TAGS }}"' ${{ github.workspace }}/deployment/values.yaml
 
       - name: Publish configuration package
-        uses: actions/upload-artifact@v4.3.1
+        uses: actions/upload-artifact@v4.6.0
         if: ${{ env.SHOULD_PUBLISH == 'true'}}
         with:
-          name: fineract-frontend-v2
+          name: ${{ env.ARTIFACT_NAME }}
           path: ${{ github.workspace }}/deployment
-  sonarcloud:
-    name: Sonarcloud analyze
+
+  QualityCheck:
+    name: Quality Check
     runs-on: ubuntu-latest
-    environment: dev
     steps:
-      - name: Checkout Repository
-        uses: actions/checkout@v4
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
         with:
           fetch-depth: 0
           fetch-tags: true
           show-progress: false
-      - uses: actions/setup-node@v4
+
+      - name: Setup Node.js
+        uses: actions/setup-node@v4.2.0
         with:
-          fetch-depth: 0
-      - name: Install dependencies
+          node-version: 18
+
+      - name: Install Dependencies
         run: npm install
+
       - name: Run Lint and Unit Tests
         continue-on-error: true
         run: npm run test:ci
-      - name: Test and coverage
+
+      - name: Test Coverage
         continue-on-error: true
         run: npm run test:cov
+
       - name: SonarCloud Scan
-        uses: SonarSource/sonarcloud-github-action@master
+        uses: SonarSource/sonarqube-scan-action@v5.0.0
         env:
-          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
           SONAR_TOKEN: "${{ secrets.SONAR_TOKEN }}"
 
-  ## Deploy to the various clusters
-  Integration-k8s:
+  Integration:
     if: github.event.ref == 'refs/heads/develop'
-    needs: [build, sonarcloud]
-    uses: ./.github/workflows/deploy.yml
-    with:
-      environment: "Integration"
-    secrets:
-      k8s_url: ${{ secrets.K8S_TEST_URL }}
-      k8s_secret: ${{ secrets.K8S_TEST_DEFAULT }}
-      DEPLOYMENT_ACR_PULL_PASSWORD: ${{ secrets.ACR_PULL_PASSWORD }}
-      DEPLOYMENT_SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
-
-  QA-k8s:
-    needs: Integration-k8s
+    runs-on: ubuntu-latest
+    needs: [Build, QualityCheck]
+    environment:
+      name: Integration
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
+
+      - name: Setup Helm
+        uses: one-acre-fund/oaf-actions/helm_setup@1.0.0
+        with:
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+          RUN_ID: "${{ github.run_id }}"
+          CI_REPOSITORY: "${{ github.repository }}"
+          K8S_URL: "${{ secrets.K8S_TEST_URL }}"
+          K8S_SECRET: "${{ secrets.K8S_TEST_DEFAULT }}"
+
+      - name: Deploy using Helm
+        uses: "./.github/actions/helm_fineract_frontend"
+        with:
+          NAMESPACE: "${{ vars.NAMESPACE }}"
+          ACR_REGISTRY: "${{ vars.ACR_REGISTRY }}"
+          ACR_PULL_PASSWORD: "${{ secrets.ACR_PULL_PASSWORD }}"
+          ACR_PULL_USERNAME: "${{ vars.ACR_PULL_USERNAME }}"
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          REPLICAS: "${{ vars.REPLICAS }}"
+          RELEASE_NAME: "${{ vars.RELEASE_NAME }}"
+          FINERACT_PROXY_URL: "${{ vars.FINERACT_PROXY_URL }}"
+          FINERACT_PROXY_HTTPS_PORT: "${{ vars.FINERACT_PROXY_HTTPS_PORT }}"
+          FINERACT_PROXY_HTTP_PORT: "${{ vars.FINERACT_PROXY_HTTP_PORT }}"
+          FINERACT_KEYCLOAK_REALM: "${{ vars.FINERACT_KEYCLOAK_REALM }}"
+          FINERACT_KEYCLOAK_CLIENT_ID: "${{ vars.FINERACT_KEYCLOAK_CLIENT_ID }}"
+          FINERACT_KEYCLOAK_TOKEN_URL: "${{ vars.FINERACT_KEYCLOAK_TOKEN_URL }}"
+          FINERACT_KEYCLOAK_AUTH_SERVER_URL: "${{ vars.FINERACT_KEYCLOAK_AUTH_SERVER_URL }}"
+          FINERACT_KEYCLOAK_API_URL: "${{ vars.FINERACT_KEYCLOAK_API_URL }}"
+          FINERACT_HOST_HOME_URL: "${{ vars.FINERACT_HOST_HOME_URL }}"
+          FINERACT_BASE_URL: "${{ vars.FINERACT_BASE_URL }}"
+          FINERACT_AUTH_URL: "${{ vars.FINERACT_AUTH_URL }}"
+          FINERACT_API_URL: "${{ vars.FINERACT_API_URL }}"
+          MATOMO_SITE_ID: "${{ vars.MATOMO_SITE_ID }}"
+          MATOMO_SITE_URL: "${{ vars.MATOMO_SITE_URL }}"
+          SENTRY_DSN: "${{ secrets.SENTRY_DSN }}"
+
+  QA:
+    runs-on: ubuntu-latest
+    needs: Integration
     if: github.event.ref == 'refs/heads/develop'
-    uses: ./.github/workflows/deploy.yml
-    with:
-      environment: "QA"
-    secrets:
-      k8s_url: ${{ secrets.K8S_QA_URL }}
-      k8s_secret: ${{ secrets.K8S_QA_DEFAULT }}
-      DEPLOYMENT_ACR_PULL_PASSWORD: ${{ secrets.ACR_PULL_PASSWORD }}
-      DEPLOYMENT_SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
-
-  UAT-k8s:
+    environment:
+      name: QA
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
+
+      - name: Setup Helm
+        uses: one-acre-fund/oaf-actions/helm_setup@1.0.0
+        with:
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+          RUN_ID: "${{ github.run_id }}"
+          CI_REPOSITORY: "${{ github.repository }}"
+          K8S_URL: "${{ secrets.K8S_QA_URL }}"
+          K8S_SECRET: "${{ secrets.K8S_QA_DEFAULT }}"
+
+      - name: Deploy using Helm
+        uses: "./.github/actions/helm_fineract_frontend"
+        with:
+          NAMESPACE: "${{ vars.NAMESPACE }}"
+          ACR_REGISTRY: "${{ vars.ACR_REGISTRY }}"
+          ACR_PULL_PASSWORD: "${{ secrets.ACR_PULL_PASSWORD }}"
+          ACR_PULL_USERNAME: "${{ vars.ACR_PULL_USERNAME }}"
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          REPLICAS: "${{ vars.REPLICAS }}"
+          RELEASE_NAME: "${{ vars.RELEASE_NAME }}"
+          FINERACT_PROXY_URL: "${{ vars.FINERACT_PROXY_URL }}"
+          FINERACT_PROXY_HTTPS_PORT: "${{ vars.FINERACT_PROXY_HTTPS_PORT }}"
+          FINERACT_PROXY_HTTP_PORT: "${{ vars.FINERACT_PROXY_HTTP_PORT }}"
+          FINERACT_KEYCLOAK_REALM: "${{ vars.FINERACT_KEYCLOAK_REALM }}"
+          FINERACT_KEYCLOAK_CLIENT_ID: "${{ vars.FINERACT_KEYCLOAK_CLIENT_ID }}"
+          FINERACT_KEYCLOAK_TOKEN_URL: "${{ vars.FINERACT_KEYCLOAK_TOKEN_URL }}"
+          FINERACT_KEYCLOAK_AUTH_SERVER_URL: "${{ vars.FINERACT_KEYCLOAK_AUTH_SERVER_URL }}"
+          FINERACT_KEYCLOAK_API_URL: "${{ vars.FINERACT_KEYCLOAK_API_URL }}"
+          FINERACT_HOST_HOME_URL: "${{ vars.FINERACT_HOST_HOME_URL }}"
+          FINERACT_BASE_URL: "${{ vars.FINERACT_BASE_URL }}"
+          FINERACT_AUTH_URL: "${{ vars.FINERACT_AUTH_URL }}"
+          FINERACT_API_URL: "${{ vars.FINERACT_API_URL }}"
+          MATOMO_SITE_ID: "${{ vars.MATOMO_SITE_ID }}"
+          MATOMO_SITE_URL: "${{ vars.MATOMO_SITE_URL }}"
+          SENTRY_DSN: "${{ secrets.SENTRY_DSN }}"
+
+  UAT:
+    runs-on: ubuntu-latest
     if: github.event.ref == 'refs/heads/main' || contains(github.event.ref, 'refs/heads/hotfix/') || contains(github.event.ref, 'refs/heads/release/')
-    needs: [build, sonarcloud]
-    uses: ./.github/workflows/deploy.yml
-    with:
-      environment: "UAT"
-    secrets:
-      k8s_url: ${{ secrets.K8S_UAT_URL }}
-      k8s_secret: ${{ secrets.K8S_UAT_DEFAULT }}
-      DEPLOYMENT_ACR_PULL_PASSWORD: ${{ secrets.ACR_PULL_PASSWORD }}
-      DEPLOYMENT_SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
-
-  Prod-k8s:
-    needs: UAT-k8s
+    needs: [Build, QualityCheck]
+    environment:
+      name: UAT
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
+
+      - name: Setup Helm
+        uses: one-acre-fund/oaf-actions/helm_setup@1.0.0
+        with:
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+          RUN_ID: "${{ github.run_id }}"
+          CI_REPOSITORY: "${{ github.repository }}"
+          K8S_URL: "${{ secrets.K8S_UAT_URL }}"
+          K8S_SECRET: "${{ secrets.K8S_UAT_DEFAULT }}"
+
+      - name: Deploy using Helm
+        uses: "./.github/actions/helm_fineract_frontend"
+        with:
+          NAMESPACE: "${{ vars.NAMESPACE }}"
+          ACR_REGISTRY: "${{ vars.ACR_REGISTRY }}"
+          ACR_PULL_PASSWORD: "${{ secrets.ACR_PULL_PASSWORD }}"
+          ACR_PULL_USERNAME: "${{ vars.ACR_PULL_USERNAME }}"
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          REPLICAS: "${{ vars.REPLICAS }}"
+          RELEASE_NAME: "${{ vars.RELEASE_NAME }}"
+          FINERACT_PROXY_URL: "${{ vars.FINERACT_PROXY_URL }}"
+          FINERACT_PROXY_HTTPS_PORT: "${{ vars.FINERACT_PROXY_HTTPS_PORT }}"
+          FINERACT_PROXY_HTTP_PORT: "${{ vars.FINERACT_PROXY_HTTP_PORT }}"
+          FINERACT_KEYCLOAK_REALM: "${{ vars.FINERACT_KEYCLOAK_REALM }}"
+          FINERACT_KEYCLOAK_CLIENT_ID: "${{ vars.FINERACT_KEYCLOAK_CLIENT_ID }}"
+          FINERACT_KEYCLOAK_TOKEN_URL: "${{ vars.FINERACT_KEYCLOAK_TOKEN_URL }}"
+          FINERACT_KEYCLOAK_AUTH_SERVER_URL: "${{ vars.FINERACT_KEYCLOAK_AUTH_SERVER_URL }}"
+          FINERACT_KEYCLOAK_API_URL: "${{ vars.FINERACT_KEYCLOAK_API_URL }}"
+          FINERACT_HOST_HOME_URL: "${{ vars.FINERACT_HOST_HOME_URL }}"
+          FINERACT_BASE_URL: "${{ vars.FINERACT_BASE_URL }}"
+          FINERACT_AUTH_URL: "${{ vars.FINERACT_AUTH_URL }}"
+          FINERACT_API_URL: "${{ vars.FINERACT_API_URL }}"
+          MATOMO_SITE_ID: "${{ vars.MATOMO_SITE_ID }}"
+          MATOMO_SITE_URL: "${{ vars.MATOMO_SITE_URL }}"
+          SENTRY_DSN: "${{ secrets.SENTRY_DSN }}"
+
+  Production:
path: .github/workflows/build.yml
user: login: github-advanced-security[bot]
body: ## Workflow does not contain permissions

Actions Job or Workflow does not set permissions

[Show more details](https://github.com/one-acre-fund/fineract-frontend-v2/security/code-scanning/24)
created_at: 2025-04-23T13:15:30Z
author_association: NONE
diff_hunk: @@ -13,160 +13,313 @@
       - master
       - main
       - develop
-      - 'release/*'
+      - release/*
 
 env:
   SHOULD_PUBLISH: ${{ github.ref  == 'refs/heads/master' ||  github.ref == 'refs/heads/develop' || startsWith(github.ref , 'refs/heads/release') }}
   IS_RELEASE: ${{ github.ref  == 'refs/heads/master' }}
   ARTIFACT_NAME: fineract-frontend-v2
 
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
 jobs:
-  # This workflow contains a single job called "build"
-  build:
-    # The type of runner that the job will run on
-    name: Build and Deploy
+  Build:
+    name: Build
     runs-on: ubuntu-latest
-
-    # Steps represent a sequence of tasks that will be executed as part of the job
     steps:
-      - name: Checkout Repository
-        uses: actions/checkout@v4
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
         with:
           fetch-depth: 0
           fetch-tags: true
           show-progress: false
 
-      - name: Setup Node.js to use
-        uses: actions/setup-node@v4
+      - name: Setup Node.js
+        uses: actions/setup-node@v4.2.0
         with:
           node-version: 18
+
       - name: Angular CLI install
         run: npm install -g --silent @angular/cli@13.3.10
 
       - name: Set image tag & other env variables
+        id: set-env
         run: |
           VERSION_TAG=$(sed 's/.*"version": "\(.*\)".*/\1/;t;d' ./package.json)
           echo "VERSION_TAG=$VERSION_TAG"
~
~          echo "Is Release=$IS_RELEASE"
~
~          if [ $IS_RELEASE == 'true' ]; then
~            echo "This is a release"
~            IMAGE_TAGS=$VERSION_TAG
~          else
~            echo "This is a normal build"
~            IMAGE_TAGS="${VERSION_TAG}.$(date '+%Y.%m.%d').${{ github.run_number }}"
           fi
           echo "Tags: $IMAGE_TAGS"
 
-          echo "VERSION_TAG=$VERSION_TAG" >> $GITHUB_ENV
-          echo "IMAGE_TAGS=$IMAGE_TAGS" >> $GITHUB_ENV
+          echo "VERSION_TAG=$VERSION_TAG" >> $GITHUB_OUTPUT
+          echo "IMAGE_TAGS=$IMAGE_TAGS" >> $GITHUB_OUTPUT
 
       - name: Install Node Packages
         run: npm install
 
-      - name: Docker build
-        uses: docker/build-push-action@v5.1.0
-        with:
-          push: false
-          tags: oaftech.azurecr.io/oneacrefund/fineract-frontend-v2:${{ env.IMAGE_TAGS }}
-          context: ${{ github.workspace }}
-
       - name: Login to Azure registry
-        uses: docker/login-action@v3.0.0
+        uses: docker/login-action@v3.3.0
         if: ${{ env.SHOULD_PUBLISH == 'true'}}
         with:
-          registry: oaftech.azurecr.io
+          registry: ${{ vars.ACR_REGISTRY }}
           username: ${{ vars.ACR_PULL_USERNAME }}
           password: ${{ secrets.ACR_PULL_PASSWORD }}
 
-      - name: Push an image to container registry
-        if: ${{ env.SHOULD_PUBLISH == 'true'}}
-        run: docker push oaftech.azurecr.io/oneacrefund/fineract-frontend-v2:${{ env.IMAGE_TAGS }}
+      - name: Docker Build & Push
+        uses: docker/Build-push-action@v6.13.0
+        with:
+          push: ${{ env.SHOULD_PUBLISH == 'true'}}
+          tags: ${{ vars.ACR_REGISTRY }}/oneacrefund/fineract-frontend-v2:${{ steps.set-env.outputs.IMAGE_TAGS }}
+          context: ${{ github.workspace }}
 
       - name: Use latest image tag
-        run: yq -i '.image.tag = "${{ env.IMAGE_TAGS }}"' ${{ github.workspace }}/deployment/values.yaml
+        run: yq -i '.image.tag = "${{ steps.set-env.outputs.IMAGE_TAGS }}"' ${{ github.workspace }}/deployment/values.yaml
 
       - name: Publish configuration package
-        uses: actions/upload-artifact@v4.3.1
+        uses: actions/upload-artifact@v4.6.0
         if: ${{ env.SHOULD_PUBLISH == 'true'}}
         with:
-          name: fineract-frontend-v2
+          name: ${{ env.ARTIFACT_NAME }}
           path: ${{ github.workspace }}/deployment
-  sonarcloud:
-    name: Sonarcloud analyze
+
+  QualityCheck:
+    name: Quality Check
     runs-on: ubuntu-latest
-    environment: dev
     steps:
-      - name: Checkout Repository
-        uses: actions/checkout@v4
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
         with:
           fetch-depth: 0
           fetch-tags: true
           show-progress: false
-      - uses: actions/setup-node@v4
+
+      - name: Setup Node.js
+        uses: actions/setup-node@v4.2.0
         with:
-          fetch-depth: 0
-      - name: Install dependencies
+          node-version: 18
+
+      - name: Install Dependencies
         run: npm install
+
       - name: Run Lint and Unit Tests
         continue-on-error: true
         run: npm run test:ci
-      - name: Test and coverage
+
+      - name: Test Coverage
         continue-on-error: true
         run: npm run test:cov
+
       - name: SonarCloud Scan
-        uses: SonarSource/sonarcloud-github-action@master
+        uses: SonarSource/sonarqube-scan-action@v5.0.0
         env:
-          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
           SONAR_TOKEN: "${{ secrets.SONAR_TOKEN }}"
 
-  ## Deploy to the various clusters
-  Integration-k8s:
+  Integration:
     if: github.event.ref == 'refs/heads/develop'
-    needs: [build, sonarcloud]
-    uses: ./.github/workflows/deploy.yml
-    with:
-      environment: "Integration"
-    secrets:
-      k8s_url: ${{ secrets.K8S_TEST_URL }}
-      k8s_secret: ${{ secrets.K8S_TEST_DEFAULT }}
-      DEPLOYMENT_ACR_PULL_PASSWORD: ${{ secrets.ACR_PULL_PASSWORD }}
-      DEPLOYMENT_SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
-
-  QA-k8s:
-    needs: Integration-k8s
+    runs-on: ubuntu-latest
+    needs: [Build, QualityCheck]
+    environment:
+      name: Integration
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
+
+      - name: Setup Helm
+        uses: one-acre-fund/oaf-actions/helm_setup@1.0.0
+        with:
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+          RUN_ID: "${{ github.run_id }}"
+          CI_REPOSITORY: "${{ github.repository }}"
+          K8S_URL: "${{ secrets.K8S_TEST_URL }}"
+          K8S_SECRET: "${{ secrets.K8S_TEST_DEFAULT }}"
+
+      - name: Deploy using Helm
+        uses: "./.github/actions/helm_fineract_frontend"
+        with:
+          NAMESPACE: "${{ vars.NAMESPACE }}"
+          ACR_REGISTRY: "${{ vars.ACR_REGISTRY }}"
+          ACR_PULL_PASSWORD: "${{ secrets.ACR_PULL_PASSWORD }}"
+          ACR_PULL_USERNAME: "${{ vars.ACR_PULL_USERNAME }}"
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          REPLICAS: "${{ vars.REPLICAS }}"
+          RELEASE_NAME: "${{ vars.RELEASE_NAME }}"
+          FINERACT_PROXY_URL: "${{ vars.FINERACT_PROXY_URL }}"
+          FINERACT_PROXY_HTTPS_PORT: "${{ vars.FINERACT_PROXY_HTTPS_PORT }}"
+          FINERACT_PROXY_HTTP_PORT: "${{ vars.FINERACT_PROXY_HTTP_PORT }}"
+          FINERACT_KEYCLOAK_REALM: "${{ vars.FINERACT_KEYCLOAK_REALM }}"
+          FINERACT_KEYCLOAK_CLIENT_ID: "${{ vars.FINERACT_KEYCLOAK_CLIENT_ID }}"
+          FINERACT_KEYCLOAK_TOKEN_URL: "${{ vars.FINERACT_KEYCLOAK_TOKEN_URL }}"
+          FINERACT_KEYCLOAK_AUTH_SERVER_URL: "${{ vars.FINERACT_KEYCLOAK_AUTH_SERVER_URL }}"
+          FINERACT_KEYCLOAK_API_URL: "${{ vars.FINERACT_KEYCLOAK_API_URL }}"
+          FINERACT_HOST_HOME_URL: "${{ vars.FINERACT_HOST_HOME_URL }}"
+          FINERACT_BASE_URL: "${{ vars.FINERACT_BASE_URL }}"
+          FINERACT_AUTH_URL: "${{ vars.FINERACT_AUTH_URL }}"
+          FINERACT_API_URL: "${{ vars.FINERACT_API_URL }}"
+          MATOMO_SITE_ID: "${{ vars.MATOMO_SITE_ID }}"
+          MATOMO_SITE_URL: "${{ vars.MATOMO_SITE_URL }}"
+          SENTRY_DSN: "${{ secrets.SENTRY_DSN }}"
+
+  QA:
+    runs-on: ubuntu-latest
+    needs: Integration
     if: github.event.ref == 'refs/heads/develop'
-    uses: ./.github/workflows/deploy.yml
-    with:
-      environment: "QA"
-    secrets:
-      k8s_url: ${{ secrets.K8S_QA_URL }}
-      k8s_secret: ${{ secrets.K8S_QA_DEFAULT }}
-      DEPLOYMENT_ACR_PULL_PASSWORD: ${{ secrets.ACR_PULL_PASSWORD }}
-      DEPLOYMENT_SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
-
-  UAT-k8s:
+    environment:
+      name: QA
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
+
+      - name: Setup Helm
+        uses: one-acre-fund/oaf-actions/helm_setup@1.0.0
+        with:
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+          RUN_ID: "${{ github.run_id }}"
+          CI_REPOSITORY: "${{ github.repository }}"
+          K8S_URL: "${{ secrets.K8S_QA_URL }}"
+          K8S_SECRET: "${{ secrets.K8S_QA_DEFAULT }}"
+
+      - name: Deploy using Helm
+        uses: "./.github/actions/helm_fineract_frontend"
+        with:
+          NAMESPACE: "${{ vars.NAMESPACE }}"
+          ACR_REGISTRY: "${{ vars.ACR_REGISTRY }}"
+          ACR_PULL_PASSWORD: "${{ secrets.ACR_PULL_PASSWORD }}"
+          ACR_PULL_USERNAME: "${{ vars.ACR_PULL_USERNAME }}"
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          REPLICAS: "${{ vars.REPLICAS }}"
+          RELEASE_NAME: "${{ vars.RELEASE_NAME }}"
+          FINERACT_PROXY_URL: "${{ vars.FINERACT_PROXY_URL }}"
+          FINERACT_PROXY_HTTPS_PORT: "${{ vars.FINERACT_PROXY_HTTPS_PORT }}"
+          FINERACT_PROXY_HTTP_PORT: "${{ vars.FINERACT_PROXY_HTTP_PORT }}"
+          FINERACT_KEYCLOAK_REALM: "${{ vars.FINERACT_KEYCLOAK_REALM }}"
+          FINERACT_KEYCLOAK_CLIENT_ID: "${{ vars.FINERACT_KEYCLOAK_CLIENT_ID }}"
+          FINERACT_KEYCLOAK_TOKEN_URL: "${{ vars.FINERACT_KEYCLOAK_TOKEN_URL }}"
+          FINERACT_KEYCLOAK_AUTH_SERVER_URL: "${{ vars.FINERACT_KEYCLOAK_AUTH_SERVER_URL }}"
+          FINERACT_KEYCLOAK_API_URL: "${{ vars.FINERACT_KEYCLOAK_API_URL }}"
+          FINERACT_HOST_HOME_URL: "${{ vars.FINERACT_HOST_HOME_URL }}"
+          FINERACT_BASE_URL: "${{ vars.FINERACT_BASE_URL }}"
+          FINERACT_AUTH_URL: "${{ vars.FINERACT_AUTH_URL }}"
+          FINERACT_API_URL: "${{ vars.FINERACT_API_URL }}"
+          MATOMO_SITE_ID: "${{ vars.MATOMO_SITE_ID }}"
+          MATOMO_SITE_URL: "${{ vars.MATOMO_SITE_URL }}"
+          SENTRY_DSN: "${{ secrets.SENTRY_DSN }}"
+
+  UAT:
+    runs-on: ubuntu-latest
     if: github.event.ref == 'refs/heads/main' || contains(github.event.ref, 'refs/heads/hotfix/') || contains(github.event.ref, 'refs/heads/release/')
-    needs: [build, sonarcloud]
-    uses: ./.github/workflows/deploy.yml
-    with:
-      environment: "UAT"
-    secrets:
-      k8s_url: ${{ secrets.K8S_UAT_URL }}
-      k8s_secret: ${{ secrets.K8S_UAT_DEFAULT }}
-      DEPLOYMENT_ACR_PULL_PASSWORD: ${{ secrets.ACR_PULL_PASSWORD }}
-      DEPLOYMENT_SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
-
-  Prod-k8s:
-    needs: UAT-k8s
+    needs: [Build, QualityCheck]
+    environment:
+      name: UAT
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
+
+      - name: Setup Helm
+        uses: one-acre-fund/oaf-actions/helm_setup@1.0.0
+        with:
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+          RUN_ID: "${{ github.run_id }}"
+          CI_REPOSITORY: "${{ github.repository }}"
+          K8S_URL: "${{ secrets.K8S_UAT_URL }}"
+          K8S_SECRET: "${{ secrets.K8S_UAT_DEFAULT }}"
+
+      - name: Deploy using Helm
+        uses: "./.github/actions/helm_fineract_frontend"
+        with:
+          NAMESPACE: "${{ vars.NAMESPACE }}"
+          ACR_REGISTRY: "${{ vars.ACR_REGISTRY }}"
+          ACR_PULL_PASSWORD: "${{ secrets.ACR_PULL_PASSWORD }}"
+          ACR_PULL_USERNAME: "${{ vars.ACR_PULL_USERNAME }}"
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          REPLICAS: "${{ vars.REPLICAS }}"
+          RELEASE_NAME: "${{ vars.RELEASE_NAME }}"
+          FINERACT_PROXY_URL: "${{ vars.FINERACT_PROXY_URL }}"
+          FINERACT_PROXY_HTTPS_PORT: "${{ vars.FINERACT_PROXY_HTTPS_PORT }}"
+          FINERACT_PROXY_HTTP_PORT: "${{ vars.FINERACT_PROXY_HTTP_PORT }}"
+          FINERACT_KEYCLOAK_REALM: "${{ vars.FINERACT_KEYCLOAK_REALM }}"
+          FINERACT_KEYCLOAK_CLIENT_ID: "${{ vars.FINERACT_KEYCLOAK_CLIENT_ID }}"
+          FINERACT_KEYCLOAK_TOKEN_URL: "${{ vars.FINERACT_KEYCLOAK_TOKEN_URL }}"
+          FINERACT_KEYCLOAK_AUTH_SERVER_URL: "${{ vars.FINERACT_KEYCLOAK_AUTH_SERVER_URL }}"
+          FINERACT_KEYCLOAK_API_URL: "${{ vars.FINERACT_KEYCLOAK_API_URL }}"
+          FINERACT_HOST_HOME_URL: "${{ vars.FINERACT_HOST_HOME_URL }}"
+          FINERACT_BASE_URL: "${{ vars.FINERACT_BASE_URL }}"
+          FINERACT_AUTH_URL: "${{ vars.FINERACT_AUTH_URL }}"
+          FINERACT_API_URL: "${{ vars.FINERACT_API_URL }}"
+          MATOMO_SITE_ID: "${{ vars.MATOMO_SITE_ID }}"
+          MATOMO_SITE_URL: "${{ vars.MATOMO_SITE_URL }}"
+          SENTRY_DSN: "${{ secrets.SENTRY_DSN }}"
+
+  Production:
+    runs-on: ubuntu-latest
+    needs: UAT
     if: github.event.ref == 'refs/heads/main' || contains(github.event.ref, 'refs/heads/hotfix/') || contains(github.event.ref, 'refs/heads/release/')
-    uses: ./.github/workflows/deploy.yml
-    with:
-      environment: "Production"
-    secrets:
-      k8s_url: ${{ secrets.K8S_PROD_URL }}
-      k8s_secret: ${{ secrets.K8S_PROD_DEFAULT }}
-      DEPLOYMENT_ACR_PULL_PASSWORD: ${{ secrets.ACR_PULL_PASSWORD }}
-      DEPLOYMENT_SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
+    environment:
+      name: Production
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4.2.2
+
+      - name: Setup Helm
+        uses: one-acre-fund/oaf-actions/helm_setup@1.0.0
+        with:
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+          RUN_ID: "${{ github.run_id }}"
+          CI_REPOSITORY: "${{ github.repository }}"
+          K8S_URL: "${{ secrets.K8S_PROD_URL }}"
+          K8S_SECRET: "${{ secrets.K8S_PROD_DEFAULT }}"
+
+      - name: Start Maintenance Window
+        id: start_maintenance
+        uses: one-acre-fund/uptime-kuma-create-maintenance@1.0.0
+        with:
+          UPTIME_USERNAME: ${{ secrets.UPTIME_USERNAME }}
+          UPTIME_PASSWORD: ${{ secrets.UPTIME_PASSWORD }}
+          UPTIME_API_URL: ${{ vars.UPTIME_API_URL }}
+          MAINTENANCE_TITLE: "Service Deployment"
+          MONITOR_ID: ${{ vars.MONITOR_ID }}
+          MONITOR_NAME: ${{ vars.MONITOR_NAME }}
+
+      - name: Deploy using Helm
+        uses: "./.github/actions/helm_fineract_frontend"
+        with:
+          NAMESPACE: "${{ vars.NAMESPACE }}"
+          ACR_REGISTRY: "${{ vars.ACR_REGISTRY }}"
+          ACR_PULL_PASSWORD: "${{ secrets.ACR_PULL_PASSWORD }}"
+          ACR_PULL_USERNAME: "${{ vars.ACR_PULL_USERNAME }}"
+          ARTIFACT_NAME: "${{ env.ARTIFACT_NAME }}"
+          REPLICAS: "${{ vars.REPLICAS }}"
+          RELEASE_NAME: "${{ vars.RELEASE_NAME }}"
+          FINERACT_PROXY_URL: "${{ vars.FINERACT_PROXY_URL }}"
+          FINERACT_PROXY_HTTPS_PORT: "${{ vars.FINERACT_PROXY_HTTPS_PORT }}"
+          FINERACT_PROXY_HTTP_PORT: "${{ vars.FINERACT_PROXY_HTTP_PORT }}"
+          FINERACT_KEYCLOAK_REALM: "${{ vars.FINERACT_KEYCLOAK_REALM }}"
+          FINERACT_KEYCLOAK_CLIENT_ID: "${{ vars.FINERACT_KEYCLOAK_CLIENT_ID }}"
+          FINERACT_KEYCLOAK_TOKEN_URL: "${{ vars.FINERACT_KEYCLOAK_TOKEN_URL }}"
+          FINERACT_KEYCLOAK_AUTH_SERVER_URL: "${{ vars.FINERACT_KEYCLOAK_AUTH_SERVER_URL }}"
+          FINERACT_KEYCLOAK_API_URL: "${{ vars.FINERACT_KEYCLOAK_API_URL }}"
+          FINERACT_HOST_HOME_URL: "${{ vars.FINERACT_HOST_HOME_URL }}"
+          FINERACT_BASE_URL: "${{ vars.FINERACT_BASE_URL }}"
+          FINERACT_AUTH_URL: "${{ vars.FINERACT_AUTH_URL }}"
+          FINERACT_API_URL: "${{ vars.FINERACT_API_URL }}"
+          MATOMO_SITE_ID: "${{ vars.MATOMO_SITE_ID }}"
+          MATOMO_SITE_URL: "${{ vars.MATOMO_SITE_URL }}"
+          SENTRY_DSN: "${{ secrets.SENTRY_DSN }}"
+
+      - name: Delete Maintenance Window
+        if: always()
+        uses: one-acre-fund/uptime-kuma-delete-maintenance@1.0.0
+        with:
+          UPTIME_USERNAME: ${{ secrets.UPTIME_USERNAME }}
+          UPTIME_PASSWORD: ${{ secrets.UPTIME_PASSWORD }}
+          UPTIME_API_URL: ${{ vars.UPTIME_API_URL }}
+          MAINTENANCE_ID: ${{ steps.start_maintenance.outputs.maintenance_id }}
path: .github/workflows/build.yml
user: login: github-advanced-security[bot]
body: ## Workflow does not contain permissions

Actions Job or Workflow does not set permissions

[Show more details](https://github.com/one-acre-fund/fineract-frontend-v2/security/code-scanning/25)
created_at: 2025-04-23T13:15:30Z
author_association: NONE

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-04-23T13:15:31Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- This is an auto-generated comment: skip review by coderabbit.ai -->

> [!IMPORTANT]
> ## Review skipped
> 
> Auto reviews are disabled on base/target branches other than the default branch.
> 
> <details>
> <summary>🗂️ Base branches to auto review (2)</summary>
> 
> * main
> * develop
> 
> </details>
> 
> Please check the settings in the CodeRabbit UI or the `.coderabbit.yaml` file in this repository. To trigger a single review, invoke the `@coderabbitai review` command.
> 
> You can disable this status message by setting the `reviews.review_status` to `false` in the CodeRabbit configuration file.

<!-- end of auto-generated comment: skip review by coderabbit.ai -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=one-acre-fund/fineract-frontend-v2&utm_content=240):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-04-23T13:17:01Z
body: ## [🦙 MegaLinter](https://megalinter.io/8.4.2) status: ✅ [SUCCESS](https://github.com/one-acre-fund/fineract-frontend-v2/actions/runs/14619112373)

| Descriptor  |                                   Linter                                    |Files|Fixed|Errors|Elapsed time|
|-------------|-----------------------------------------------------------------------------|----:|----:|-----:|------------|
|✅ DOCKERFILE|[hadolint](https://megalinter.io/8.4.2/descriptors/dockerfile_hadolint)      |    1|     |     0|0.08s       |
|✅ HTML      |[htmlhint](https://megalinter.io/8.4.2/descriptors/html_htmlhint)            |    1|     |     0|0.2s        |
|✅ MARKDOWN  |[markdownlint](https://megalinter.io/8.4.2/descriptors/markdown_markdownlint)|    1|    0|     0|0.55s       |
|✅ YAML      |[yamllint](https://megalinter.io/8.4.2/descriptors/yaml_yamllint)            |    6|     |     0|0.46s       |

See detailed report in [MegaLinter reports](https://github.com/one-acre-fund/fineract-frontend-v2/actions/runs/14619112373)
_Set `VALIDATE_ALL_CODEBASE: true` in mega-linter.yml to validate all sources, not only the diff_

[![MegaLinter is graciously provided by OX Security](https://raw.githubusercontent.com/oxsecurity/megalinter/main/docs/assets/images/ox-banner.png)](https://www.ox.security/?ref=megalinter)

<!-- megalinter: github-comment-reporter workflow='MegaLinter' jobid='MegaLinter' -->

author_association: NONE
user: login: sonarqubecloud[bot]
created_at: 2025-04-23T13:23:56Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=one-acre-fund_fineract-frontend-v2&pullRequest=240) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=one-acre-fund_fineract-frontend-v2&pullRequest=240&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=one-acre-fund_fineract-frontend-v2&pullRequest=240&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=one-acre-fund_fineract-frontend-v2&pullRequest=240&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=one-acre-fund_fineract-frontend-v2&pullRequest=240&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [50.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=one-acre-fund_fineract-frontend-v2&pullRequest=240&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=one-acre-fund_fineract-frontend-v2&pullRequest=240)


author_association: NONE