You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by al...@apache.org on 2022/05/04 13:12:01 UTC

[fineract] branch develop updated: FINERACT-1470: Fineract release plugin

This is an automated email from the ASF dual-hosted git repository.

aleks pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git


The following commit(s) were added to refs/heads/develop by this push:
     new 40eb547a5 FINERACT-1470: Fineract release plugin
40eb547a5 is described below

commit 40eb547a5c2c5232d7243ccdd7eed4ee7b9ebc12
Author: Aleks <al...@apache.org>
AuthorDate: Mon Jan 17 12:11:56 2022 +0100

    FINERACT-1470: Fineract release plugin
---
 .github/workflows/build-docker-postgresql.yml      |   1 +
 .github/workflows/build-docker.yml                 |   1 +
 .github/workflows/build-postgresql.yml             |   1 +
 .github/workflows/build.yml                        |   1 +
 .github/workflows/sonarqube.yml                    |   1 +
 .gitignore                                         |   5 +-
 README.md                                          |  53 --
 build.gradle                                       | 167 +-----
 buildSrc/build.gradle                              |  51 ++
 .../groovy/org.apache.fineract.dependencies.gradle | 183 +++++++
 .../main/groovy/org.apache.fineract.release.gradle | 263 ++++++++++
 .../apache/fineract/gradle/FineractPlugin.groovy   | 581 +++++++++++++++++++++
 .../fineract/gradle/FineractPluginExtension.groovy | 164 ++++++
 .../gradle/service/ConfluenceService.groovy        | 209 ++++++++
 .../fineract/gradle/service/EmailService.groovy    |  87 +++
 .../fineract/gradle/service/GitService.groovy      | 136 +++++
 .../fineract/gradle/service/GpgService.groovy      | 148 ++++++
 .../fineract/gradle/service/JiraService.groovy     | 324 ++++++++++++
 .../gradle/service/SubversionService.groovy        |  74 +++
 .../fineract/gradle/service/TemplateService.groovy |  84 +++
 .../org.apache.fineract.gradle.properties          |  20 +
 .../src/main/resources/confluence/release.html.ftl |  34 ++
 .../email/release.step01.headsup.message.ftl       |  39 ++
 .../email/release.step01.headsup.subject.ftl       |  21 +
 .../email/release.step03.branch.message.ftl        |  35 ++
 .../email/release.step03.branch.subject.ftl        |  21 +
 .../email/release.step10.vote.message.ftl          |  43 ++
 .../email/release.step10.vote.subject.ftl          |  21 +
 .../email/release.step11.vote.message.ftl          |  89 ++++
 .../email/release.step11.vote.subject.ftl          |  21 +
 .../email/release.step15.announce.message.ftl      |  43 ++
 .../email/release.step15.announce.subject.ftl      |  21 +
 .../resources/git/release.step05.tag.message.ftl   |  21 +
 .../src/main/resources/instructions/step13.txt.ftl |  38 ++
 .../src/main/resources/instructions/step14.txt.ftl |  28 +
 .../src/main/resources/instructions/step2.txt.ftl  |  39 ++
 .../src/main/resources/instructions/step4.txt.ftl  |  29 +
 .../src/main/resources/instructions/step9.txt.ftl  |  38 ++
 .../src/main/resources/jira/changelog.adoc.ftl     |  33 ++
 buildSrc/src/main/resources/jira/changelog.txt.ftl |  26 +
 .../src/main/resources/vote/result.template.json   |  22 +
 fineract-client/build.gradle                       |  23 +-
 fineract-doc/.asciidoctorconfig                    |   9 +-
 fineract-doc/build.gradle                          |  33 +-
 fineract-doc/src/docs/en/appendix.adoc             |   1 -
 fineract-doc/src/docs/en/architecture.adoc         | 272 ----------
 .../src/docs/en/chapters/appendix/index.adoc       |   5 +
 .../appendix/properties-authentication.adoc        |  22 +
 .../en/chapters/appendix/properties-cache.adoc     |  16 +
 .../en/chapters/appendix/properties-database.adoc  |  51 ++
 .../docs/en/chapters/appendix/properties-pool.adoc | 116 ++++
 .../docs/en/chapters/appendix/properties-ssl.adoc  |  36 ++
 .../en/chapters/appendix/properties-tomcat.adoc    |  42 ++
 .../src/docs/en/chapters/appendix/properties.adoc  |  16 +
 .../src/docs/en/chapters/appendix/software.adoc    |   4 +
 .../src/docs/en/chapters/architecture/design.adoc  |  42 ++
 .../docs/en/chapters/architecture/functional.adoc  |  41 ++
 .../src/docs/en/chapters/architecture/history.adoc |  18 +
 .../src/docs/en/chapters/architecture/index.adoc   |  25 +
 .../en/{ => chapters/architecture}/modules.adoc    |  26 +-
 .../docs/en/chapters/architecture/persistence.adoc |  64 +++
 .../docs/en/chapters/architecture/principles.adoc  |  63 +++
 .../docs/en/chapters/architecture/resources.adoc   |   5 +
 .../src/docs/en/chapters/architecture/system.adoc  |  18 +
 .../docs/en/chapters/architecture/technology.adoc  |  14 +
 .../en/{ => chapters/architecture}/validation.adoc |  14 +-
 .../src/docs/en/chapters/deployment/apache.adoc    |   5 +
 .../src/docs/en/chapters/deployment/appserver.adoc |  25 +
 .../src/docs/en/chapters/deployment/aws.adoc       |   3 +
 .../src/docs/en/chapters/deployment/google.adoc    |   5 +
 .../deployment/https.adoc}                         |  29 +-
 .../src/docs/en/chapters/deployment/index.adoc     |  17 +
 .../docs/en/chapters/deployment/kubernetes.adoc    |   3 +
 .../src/docs/en/chapters/deployment/local.adoc     |   3 +
 .../src/docs/en/chapters/deployment/plugins.adoc   |  18 +
 .../en/chapters/development/docker-compose.adoc    |   3 +
 .../en/chapters/development/docker-podman.adoc     |   3 +
 .../en/chapters/development/docker-rancher.adoc    |   3 +
 .../src/docs/en/chapters/development/docker.adoc   |   9 +
 .../en/chapters/development/git-configuration.adoc |   9 +
 .../src/docs/en/chapters/development/git-fork.adoc |  17 +
 .../src/docs/en/chapters/development/git.adoc      |   3 +
 .../src/docs/en/chapters/development/gpg.adoc      |   7 +
 .../src/docs/en/chapters/development/gradle.adoc   |   3 +
 .../docs/en/chapters/development/ide-eclipse.adoc  |   3 +
 .../docs/en/chapters/development/ide-intellij.adoc |   3 +
 .../docs/en/chapters/development/ide-vscode.adoc   |   3 +
 .../src/docs/en/chapters/development/ide.adoc      |   9 +
 .../src/docs/en/chapters/development/index.adoc    |  17 +
 .../en/chapters/development/kubernetes-helm.adoc   |   3 +
 .../en/chapters/development/kubernetes-k3d.adoc    |   3 +
 .../chapters/development/kubernetes-microk8s.adoc  |   3 +
 .../chapters/development/kubernetes-minikube.adoc  |   3 +
 .../docs/en/chapters/development/kubernetes.adoc   |  11 +
 .../docs/en/chapters/development/tools-brew.adoc   |   9 +
 .../docs/en/chapters/development/tools-sdkman.adoc |  10 +
 .../src/docs/en/chapters/development/tools.adoc    |   7 +
 .../src/docs/en/chapters/documentation/antora.adoc |   5 +
 .../documentation/asciidoc-cheatsheet.adoc         |   3 +
 .../chapters/documentation/asciidoc-tutorial.adoc  |   5 +
 .../docs/en/chapters/documentation/asciidoc.adoc   |   9 +
 .../en/chapters/documentation/editor-eclipse.adoc  |   9 +
 .../en/chapters/documentation/editor-intellij.adoc |   9 +
 .../en/chapters/documentation/editor-vscode.adoc   |   9 +
 .../src/docs/en/chapters/documentation/editor.adoc |   9 +
 .../src/docs/en/chapters/documentation/index.adoc  |  16 +
 .../src/docs/en/chapters/documentation/layout.adoc |  19 +
 .../documentation/plantuml-cheatsheet.adoc         |   3 +
 .../chapters/documentation/plantuml-tutorial.adoc  |   3 +
 .../docs/en/chapters/documentation/plantuml.adoc   |   9 +
 .../en/chapters/release/configuration-email.adoc   |  28 +
 .../en/chapters/release/configuration-gpg.adoc     | 225 ++++++++
 .../en/chapters/release/configuration-gradle.adoc  |  38 ++
 .../en/chapters/release/configuration-secrets.adoc |  37 ++
 .../docs/en/chapters/release/configuration.adoc    |  20 +
 .../src/docs/en/chapters/release/index.adoc        |  13 +
 .../docs/en/chapters/release/process-step01.adoc   |  26 +
 .../docs/en/chapters/release/process-step02.adoc   |  34 ++
 .../docs/en/chapters/release/process-step03.adoc   |  56 ++
 .../docs/en/chapters/release/process-step04.adoc   |  15 +
 .../docs/en/chapters/release/process-step05.adoc   |  24 +
 .../docs/en/chapters/release/process-step06.adoc   |  39 ++
 .../docs/en/chapters/release/process-step07.adoc   |  23 +
 .../docs/en/chapters/release/process-step08.adoc   |  34 ++
 .../docs/en/chapters/release/process-step09.adoc   |  26 +
 .../docs/en/chapters/release/process-step10.adoc   |  20 +
 .../docs/en/chapters/release/process-step11.adoc   |  20 +
 .../docs/en/chapters/release/process-step12.adoc   |  24 +
 .../docs/en/chapters/release/process-step13.adoc   |  29 +
 .../docs/en/chapters/release/process-step14.adoc   |  18 +
 .../docs/en/chapters/release/process-step15.adoc   |  20 +
 .../src/docs/en/chapters/release/process.adoc      |  47 ++
 .../src/docs/en/{ => chapters/sdk}/api.adoc        |   2 +-
 .../src/docs/en/{ => chapters/sdk}/client.adoc     |   8 +-
 fineract-doc/src/docs/en/chapters/sdk/index.adoc   |   7 +
 .../src/docs/en/chapters/security/index.adoc       |   5 +
 .../src/docs/en/{ => chapters/security}/oauth.adoc |  10 +-
 .../en/chapters/testing/cucumber-cheatsheet.adoc   |   3 +
 .../en/chapters/testing/cucumber-introduction.adoc |   3 +
 .../en/chapters/testing/cucumber-tutorial.adoc     |   3 +
 .../src/docs/en/chapters/testing/cucumber.adoc     |   9 +
 .../src/docs/en/chapters/testing/index.adoc        |   9 +
 .../src/docs/en/chapters/testing/integration.adoc  |   3 +
 .../src/docs/en/chapters/testing/unit.adoc         |   3 +
 fineract-doc/src/docs/en/colophon.adoc             |   1 +
 fineract-doc/src/docs/en/config.adoc               |   7 +-
 .../docs/en/diagrams/architecture-overview.puml    |   3 +
 .../src/docs/en/diagrams/release-process.puml      |  24 +
 .../src/docs/en/diagrams/release-schedule.puml     |  13 +
 fineract-doc/src/docs/en/faq.adoc                  |   4 +
 fineract-doc/src/docs/en/glossary.adoc             |   3 +
 fineract-doc/src/docs/en/index.adoc                |  35 +-
 fineract-doc/src/docs/en/indices.adoc              |   6 +-
 fineract-doc/src/docs/en/introduction.adoc         |  10 +-
 fineract-doc/src/docs/en/license.adoc              |   2 +-
 fineract-doc/src/docs/en/preface.adoc              |   2 +-
 fineract-doc/src/docs/en/testing.adoc              |   5 -
 fineract-provider/build.gradle                     |   4 +-
 fineract-provider/dependencies.gradle              |   4 +-
 fineract-war/build.gradle                          |  39 +-
 160 files changed, 4954 insertions(+), 638 deletions(-)

diff --git a/.github/workflows/build-docker-postgresql.yml b/.github/workflows/build-docker-postgresql.yml
index 22fb7c1e0..544c21b8a 100644
--- a/.github/workflows/build-docker-postgresql.yml
+++ b/.github/workflows/build-docker-postgresql.yml
@@ -16,6 +16,7 @@ jobs:
         with:
           java-version: '17'
           distribution: 'zulu'
+          cache: gradle
       - name: Build the image
         run: ./gradlew :fineract-provider:clean :fineract-provider:jibDockerBuild -x test
       - name: Start the stack
diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml
index 90c1d3441..143fd4c50 100644
--- a/.github/workflows/build-docker.yml
+++ b/.github/workflows/build-docker.yml
@@ -16,6 +16,7 @@ jobs:
         with:
           java-version: '17'
           distribution: 'zulu'
+          cache: gradle
       - name: Build the image
         run: ./gradlew :fineract-provider:clean :fineract-provider:jibDockerBuild -x test
       - name: Start the stack
diff --git a/.github/workflows/build-postgresql.yml b/.github/workflows/build-postgresql.yml
index 47f575d32..862451e64 100644
--- a/.github/workflows/build-postgresql.yml
+++ b/.github/workflows/build-postgresql.yml
@@ -45,6 +45,7 @@ jobs:
         with:
           java-version: '17'
           distribution: 'zulu'
+          cache: gradle
       - name: Validate Gradle wrapper
         uses: gradle/wrapper-validation-action@859c33240bd026ce8d5f711f5adcc65c2f8eafc1
       - name: Verify PostgreSQL connection
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d4c057bac..b40cb8f63 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -44,6 +44,7 @@ jobs:
         with:
           java-version: '17'
           distribution: 'zulu'
+          cache: gradle
       - name: Validate Gradle wrapper
         uses: gradle/wrapper-validation-action@859c33240bd026ce8d5f711f5adcc65c2f8eafc1
       - name: Verify MariaDB connection
diff --git a/.github/workflows/sonarqube.yml b/.github/workflows/sonarqube.yml
index e47d371d8..ff151adfb 100644
--- a/.github/workflows/sonarqube.yml
+++ b/.github/workflows/sonarqube.yml
@@ -34,6 +34,7 @@ jobs:
         with:
           java-version: '17'
           distribution: 'zulu'
+          cache: gradle
       - name: Validate Gradle wrapper
         uses: gradle/wrapper-validation-action@859c33240bd026ce8d5f711f5adcc65c2f8eafc1
       - name: Sonarqube
diff --git a/.gitignore b/.gitignore
index d69540d04..991d4b73a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,4 +21,7 @@ bin/
 fineract-provider/out/
 fineract-provider/config/swagger/config.json
 fineract-provider/config/swagger/fineract-input.yaml
-licenses
\ No newline at end of file
+licenses
+**/.asciidoctor/images/*
+**/.asciidoctor/diagram/*
+**/images/diag-*.svg
\ No newline at end of file
diff --git a/README.md b/README.md
index 1c50f6c73..ddfd35c2b 100644
--- a/README.md
+++ b/README.md
@@ -457,59 +457,6 @@ Upgrades sometimes require package name changes.  Changed code should ideally ha
 Our `ClasspathHellDuplicatesCheckRuleTest` detects classes that appear in more than 1 JAR.  If a version bump in [`build.gradle`](https://github.com/search?q=repo%3Aapache%2Ffineract+filename%3Abuild.gradle&type=Code&ref=advsearch&l=&l=) causes changes in transitives dependencies, then you may have to add related `exclude` to our [`dependencies.gradle`](https://github.com/apache/fineract/search?q=dependencies.gradle).  Running `./gradlew dependencies` helps to understand what is required.
 
 
-Releasing
----------
-
-[How to Release Apache Fineract](https://cwiki.apache.org/confluence/x/DRwIB) documents the process how we make the source code that is available here in this Git repository into a binary release tar.gz available on http://fineract.apache.org.
-
-Before you use Gradle to create a release you need to make sure that you provide the proper GPG parameters. You have to options:
-
-1. Provide the parameters via ~/.gradle/gradle.properties in your home folder:
-```
-signing.gnupg.keyName=7890ABCD
-signing.gnupg.passphrase=secret
-```
-
-IMPORTANT: Do not set your GPG secrets in one of the project gradle.properties and double check that you are not accidentally committing them to Git.
-
-The release command would look then look like this:
-```
-./gradlew -Pfineract.release clean build
-```
-
-2. Another way to provide these parameters are via project parameters on the command line. A release command would then look like this:
-```
-./gradlew -Pfineract.release -Psigning.gnupg.keyName=7890ABCD -Psigning.gnupg.passphrase=secret clean build
-```
-
-NOTE: Let's assume your GPG key ID would be "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCD" then you have to use the last 8 characters (i. e. "7890ABCD") for the signing plugin property "signing.gnupg.keyName".
-
-Above tasks will create the following files in folder build/distributions:
-
-- binary distribution file: apache-fineract-1.6.0-binary.tar.gz
-- ASCII armored signature for binary distribution: apache-fineract-1.6.0-binary.tar.gz.asc
-- SHA512 checksum for binary distribution: apache-fineract-1.6.0-binary.tar.gz.sha512
-- source distribution file: apache-fineract-1.6.0-src.tar.gz
-- ASCII armored signature for source distribution: apache-fineract-1.6.0-src.tar.gz.asc
-- SHA512 checksum for source distribution: apache-fineract-1.6.0-src.tar.gz.sha512
-
-The signatures are automatically verified by the build script. It will throw an exception if the verification fails.
-
-Additionally, you can verify the validity of the release distribution files e. g. with:
-```
-gpg --verify build/distributions/apache-fineract-1.6.0-binary.tar.gz.asc
-```
-
-The output should look somewhat like this:
-```
-gpg: assuming signed data in 'build/distributions/apache-fineract-1.6.0-binary.tgz'
-gpg: Signature made Mi 26 Aug 2020 17:17:45 CEST
-gpg:                using RSA key ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCD
-gpg: Good signature from "Aleksandar Vidakovic (Apache Fineract Release Manager) <al...@apache.org>" [ultimate]
-```
-
-NOTE: All commands shown above are assuming that the current working directory is the project root folder.
-
 More Information
 ============
 More details of the project can be found at <https://cwiki.apache.org/confluence/display/FINERACT>.
diff --git a/build.gradle b/build.gradle
index 8d3ea4758..c874d2482 100644
--- a/build.gradle
+++ b/build.gradle
@@ -56,10 +56,9 @@ buildscript {
 }
 
 plugins {
-    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
     id "org.barfuin.gradle.taskinfo" version "1.4.0"
     id 'com.adarshr.test-logger' version '3.2.0'
-    id 'com.diffplug.spotless' version '6.5.0' apply false
+    id 'com.diffplug.spotless' version '6.5.1' apply false
     id 'org.nosphere.apache.rat' version '0.7.1' apply false
     id 'com.github.hierynomus.license' version '0.16.1' apply false
     id 'com.github.jk1.dependency-license-report' version '2.1' apply false
@@ -68,7 +67,7 @@ plugins {
     id 'org.springframework.boot' version '2.6.7' apply false
     id 'net.ltgt.errorprone' version '2.0.2' apply false
     id 'io.swagger.core.v3.swagger-gradle-plugin' version '2.2.0' apply false
-    id 'com.gorylenko.gradle-git-properties' version '2.4.0' apply false
+    id 'com.gorylenko.gradle-git-properties' version '2.4.1' apply false
     id 'org.asciidoctor.jvm.convert' version '3.3.2' apply false
     id 'org.asciidoctor.jvm.pdf' version '3.3.2' apply false
     id 'org.asciidoctor.jvm.epub' version '3.3.2' apply false
@@ -83,6 +82,8 @@ plugins {
     id 'se.thinkcode.cucumber-runner' version '0.0.10' apply false
 }
 
+apply from: "${rootDir}/buildSrc/src/main/groovy/org.apache.fineract.release.gradle"
+
 description = '''\
 Run as:
 gradle clean bootRun'''
@@ -91,6 +92,8 @@ ext['groovy.version'] = '3.0.10'
 ext['swaggerFile'] = "$rootDir/fineract-provider/build/classes/java/main/static/fineract.yaml".toString()
 
 allprojects  {
+    apply from: "${rootDir}/buildSrc/src/main/groovy/org.apache.fineract.dependencies.gradle"
+
     group = 'org.apache.fineract'
 
     jgitver {
@@ -103,7 +106,6 @@ allprojects  {
         mavenCentral()
     }
 
-    apply plugin: 'io.spring.dependency-management'
     apply plugin: 'com.adarshr.test-logger'
     apply plugin: 'com.diffplug.spotless'
     apply plugin: 'com.github.hierynomus.license'
@@ -111,158 +113,6 @@ allprojects  {
     apply plugin: 'project-report'
     apply plugin: 'com.github.jk1.dependency-license-report'
 
-    // Configuration for the dependency management plugin
-    // https://github.com/spring-gradle-plugins/dependency-management-plugin
-    dependencyManagement {
-        imports {
-            mavenBom 'org.springframework:spring-framework-bom:5.3.19'
-            mavenBom 'org.springframework.boot:spring-boot-dependencies:2.6.7'
-            mavenBom 'org.jetbrains.kotlin:kotlin-bom:1.6.21'
-            mavenBom 'org.junit:junit-bom:5.8.2'
-            mavenBom 'com.fasterxml.jackson:jackson-bom:2.13.2.1'
-            mavenBom 'io.cucumber:cucumber-bom:7.3.2'
-            mavenBom 'io.netty:netty-bom:4.1.76.Final'
-            mavenBom 'org.mockito:mockito-bom:4.5.1'
-            mavenBom 'io.github.swagger2markup:swagger2markup-bom:1.3.4'
-        }
-
-        dependencies {
-            // We use fixed versions, instead of inheriting them from the Spring BOM, to be able to be on more recent ones.
-            // We do not use :+ to get the latest available version available on Maven Central, as that could suddenly break things.
-            // We use the Renovate Bot to automatically propose Pull Requests (PRs) when upgrades for all of these versions are available.
-
-            dependency 'org.slf4j:slf4j-api:1.7.36'
-            dependency 'org.slf4j:slf4j-simple:1.7.36'
-            dependency 'org.slf4j:jcl-over-slf4j:1.7.36'
-            dependency 'org.slf4j:jul-to-slf4j:1.7.36'
-            dependency 'org.slf4j:log4j-over-slf4j:1.7.36'
-            dependency 'ch.qos.logback:logback-core:1.2.11'
-            dependency 'ch.qos.logback:logback-classic:1.2.11'
-
-            dependency 'org.eclipse.persistence:org.eclipse.persistence.jpa:2.7.10'
-            dependency 'com.google.guava:guava:31.1-jre'
-            dependency 'com.google.code.gson:gson:2.9.0'
-            dependency 'com.google.truth:truth:1.1.3'
-            dependency 'com.google.truth.extensions:truth-java8-extension:1.1.3'
-            dependency 'com.google.googlejavaformat:google-java-format:1.15.0'
-            dependency ('org.apache.commons:commons-email:1.5') {
-                exclude 'com.sun.mail:javax.mail'
-                exclude 'javax.activation:activation'
-            }
-            dependency 'commons-io:commons-io:2.11.0'
-            dependency 'com.github.librepdf:openpdf:1.3.27'
-            dependency ('org.mnode.ical4j:ical4j:3.2.2') {
-                exclude 'com.sun.mail:javax.mail'
-            }
-            dependency 'org.quartz-scheduler:quartz:2.3.2'
-            dependency 'com.amazonaws:aws-java-sdk-s3:1.12.205'
-            dependency 'org.ehcache:ehcache:3.10.0'
-            dependency 'com.github.spullara.mustache.java:compiler:0.9.10'
-            dependency 'com.jayway.jsonpath:json-path:2.7.0'
-            dependency 'org.apache.tika:tika-core:2.3.0'
-            dependency 'org.apache.httpcomponents:httpclient:4.5.13'
-            dependency 'jakarta.management.j2ee:jakarta.management.j2ee-api:1.1.4'
-            dependency 'jakarta.jms:jakarta.jms-api:2.0.3'
-            dependency 'org.glassfish.jaxb:jaxb-runtime:2.3.6' // Swagger needs exactly this version
-            dependency 'org.apache.bval:org.apache.bval.bundle:2.0.5'
-            dependency 'joda-time:joda-time:2.10.14'
-
-            dependency 'io.github.classgraph:classgraph:4.8.146'
-            dependency 'org.awaitility:awaitility:4.2.0'
-            dependency 'com.github.spotbugs:spotbugs-annotations:4.6.0'
-            dependency 'javax.cache:cache-api:1.1.1'
-            dependency 'org.mock-server:mockserver-junit-jupiter:5.13.2'
-            dependency 'org.webjars:webjars-locator-core:0.50'
-            dependency 'com.icegreen:greenmail-junit5:1.6.8'
-            dependency 'com.intuit.karate:karate-junit5:1.2.0.RC6'
-
-            // fineract client dependencies
-            dependency "com.squareup.retrofit2:retrofit:$retrofitVersion"
-            dependency "com.squareup.retrofit2:retrofit-mock:$retrofitVersion"
-            dependency "com.squareup.retrofit2:adapter-java8:$retrofitVersion"
-            dependency "com.squareup.retrofit2:adapter-rxjava2:$retrofitVersion"
-            dependency "com.squareup.retrofit2:adapter-rxjava3:$retrofitVersion"
-            dependency "com.squareup.retrofit2:adapter-guava:$retrofitVersion"
-            dependency "com.squareup.retrofit2:converter-wire:$retrofitVersion"
-            dependency "com.squareup.retrofit2:converter-jackson:$retrofitVersion"
-            dependency "com.squareup.retrofit2:converter-simplexml:$retrofitVersion"
-            dependency "com.squareup.retrofit2:converter-jaxb:$retrofitVersion"
-            dependency "com.squareup.retrofit2:converter-java8:$retrofitVersion"
-            dependency "com.squareup.retrofit2:converter-scalars:$retrofitVersion"
-            dependency "com.squareup.retrofit2:converter-gson:$retrofitVersion"
-            dependency "com.squareup.retrofit2:converter-protobuf:$retrofitVersion"
-            dependency "org.apache.oltu.oauth2:org.apache.oltu.oauth2.common:$oltuVersion"
-            dependency "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:$oltuVersion"
-            dependency "org.apache.oltu.oauth2:org.apache.oltu.oauth2.httpclient4:$oltuVersion"
-            dependency "com.squareup.okhttp3:okhttp:$okhttpVersion"
-            dependency "com.squareup.okhttp3:okcurl:$okhttpVersion"
-            dependency "com.squareup.okhttp3:logging-interceptor:$okhttpVersion"
-            dependency "com.squareup.okhttp3:okhttp-apache:$okhttpVersion"
-            dependency "com.squareup.okhttp3:okhttp-android-support:$okhttpVersion"
-            dependency "com.squareup.okhttp3:okhttp-urlconnection:$okhttpVersion"
-            dependency "com.squareup.okhttp3:okhttp-sse:$okhttpVersion"
-            dependency "io.gsonfire:gson-fire:1.8.5"
-            dependency "com.google.code.findbugs:jsr305:3.0.2"
-            dependency "commons-codec:commons-codec:1.15"
-            dependency "org.bouncycastle:bcpkix-jdk15to18:1.70"
-            dependency "org.bouncycastle:bcprov-jdk15to18:1.70"
-            dependency "org.projectlombok:lombok:1.18.24"
-
-            dependency 'org.springdoc:springdoc-openapi-ui:1.6.8'
-            dependency 'org.springdoc:springdoc-openapi-webmvc-core:1.6.8'
-            dependency 'org.springdoc:springdoc-openapi-common:1.6.8'
-            dependency 'org.springdoc:springdoc-openapi-security:1.6.8'
-            dependency 'org.springdoc:springdoc-openapi-javadoc:1.6.8'
-
-            dependency ('org.apache.activemq:activemq-broker:5.17.0') {
-                exclude 'javax.annotation:javax.annotation-api'
-            }
-
-            dependency 'io.swagger:swagger-annotations:1.6.6'
-            dependency 'io.swagger.core.v3:swagger-annotations:2.2.0'
-            dependency ('io.swagger.core.v3:swagger-jaxrs2:2.2.0') {
-                exclude 'jakarta.activation:jakarta.activation-api'
-            }
-            dependency ('io.swagger.core.v3:swagger-core:2.2.0') {
-                exclude 'jakarta.activation:jakarta.activation-api'
-            }
-
-            dependency "jakarta.annotation:jakarta.annotation-api:1.3.5"
-            dependency 'jakarta.activation:jakarta.activation-api:1.2.2'
-            dependency ('com.sun.mail:jakarta.mail:1.6.7') {
-                exclude 'com.sun.activation:jakarta.activation'
-            }
-            dependency ('jakarta.xml.bind:jakarta.xml.bind-api:2.3.3') {
-                exclude 'jakarta.activation:jakarta.activation-api'
-            }
-
-            dependency ('org.liquibase:liquibase-core:4.9.1') {
-                exclude 'javax.xml.bind:jaxb-api'
-            }
-
-            dependency ('org.dom4j:dom4j:2.1.3') {
-                exclude 'relaxngDatatype:relaxngDatatype' // already in com.sun.xml.bind:jaxb-osgi:2.3.0.1
-                // FINERACT-940 && FINERACT-966 https://github.com/spotbugs/spotbugs/issues/1128
-                exclude 'xpp3:xpp3'
-                exclude 'pull-parser:pull-parser'
-            }
-
-            dependency 'org.owasp.esapi:esapi:2.3.0.0'
-
-            dependencySet(group: 'org.apache.poi', version: '5.2.2') {
-                entry 'poi'
-                entry 'poi-ooxml'
-                entry 'poi-ooxml-schemas'
-            }
-
-            dependencySet(group: 'io.rest-assured', version: '4.5.1') {
-                entry 'rest-assured'
-                entry 'json-path'
-                entry 'xml-path'
-            }
-        }
-    }
-
     // Configuration for the sonarqube plugin is now in GitHub Actions
 
     // Configuration for the spotless plugin
@@ -415,6 +265,7 @@ configure(project.fineractJavaProjects) {
     apply plugin: 'com.github.andygoossens.modernizer'
     apply plugin: 'se.thinkcode.cucumber-runner'
 
+
     /* define the valid syntax level for source files */
     sourceCompatibility = JavaVersion.VERSION_17
     /* define binary compatibility version */
@@ -528,8 +379,8 @@ configure(project.fineractJavaProjects) {
     // Configuration for the Checkstyle plugin
     // https://docs.gradle.org/current/userguide/checkstyle_plugin.html
     dependencies {
-        checkstyle 'com.puppycrawl.tools:checkstyle:10.1'
-        checkstyle 'com.github.sevntu-checkstyle:sevntu-checks:1.41.0'
+        checkstyle 'com.puppycrawl.tools:checkstyle:10.2'
+        checkstyle 'com.github.sevntu-checkstyle:sevntu-checks:1.42.0'
     }
 
     // Configuration for JaCoCo code coverage task
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
new file mode 100644
index 000000000..3d3b868d3
--- /dev/null
+++ b/buildSrc/build.gradle
@@ -0,0 +1,51 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+plugins {
+    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
+    id 'groovy'
+    id 'java-gradle-plugin'
+    id 'groovy-gradle-plugin'
+}
+
+apply from: "${projectDir}/src/main/groovy/org.apache.fineract.dependencies.gradle"
+
+description = 'Fineract Gradle Plugin'
+
+repositories {
+    gradlePluginPortal()
+    mavenCentral()
+}
+
+dependencies {
+    implementation 'com.sun.mail:jakarta.mail'
+    implementation 'org.freemarker:freemarker'
+    implementation 'org.tmatesoft.svnkit:svnkit'
+    implementation 'org.bouncycastle:bcprov-jdk15on'
+    implementation 'org.bouncycastle:bcpg-jdk15on'
+    implementation 'org.eclipse.jgit:org.eclipse.jgit'
+    implementation 'org.eclipse.jgit:org.eclipse.jgit.ssh.apache'
+    implementation 'com.vdurmont:semver4j'
+    implementation 'org.beryx:text-io'
+    implementation 'commons-io:commons-io'
+    implementation 'com.squareup.okhttp3:okhttp'
+    implementation 'com.squareup.okhttp3:logging-interceptor'
+    implementation 'com.squareup.retrofit2:retrofit'
+    implementation 'com.squareup.retrofit2:converter-jackson'
+    implementation 'com.fasterxml.jackson.core:jackson-databind'
+}
diff --git a/buildSrc/src/main/groovy/org.apache.fineract.dependencies.gradle b/buildSrc/src/main/groovy/org.apache.fineract.dependencies.gradle
new file mode 100644
index 000000000..09aaefbf1
--- /dev/null
+++ b/buildSrc/src/main/groovy/org.apache.fineract.dependencies.gradle
@@ -0,0 +1,183 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+apply plugin: 'io.spring.dependency-management'
+
+// Configuration for the dependency management plugin
+// https://github.com/spring-gradle-plugins/dependency-management-plugin
+dependencyManagement {
+    imports {
+        mavenBom 'org.springframework:spring-framework-bom:5.3.19'
+        mavenBom 'org.springframework.boot:spring-boot-dependencies:2.6.7'
+        mavenBom 'org.jetbrains.kotlin:kotlin-bom:1.6.21'
+        mavenBom 'org.junit:junit-bom:5.8.2'
+        mavenBom 'com.fasterxml.jackson:jackson-bom:2.13.2.1'
+        mavenBom 'io.cucumber:cucumber-bom:7.3.3'
+        mavenBom 'io.netty:netty-bom:4.1.76.Final'
+        mavenBom 'org.mockito:mockito-bom:4.5.1'
+        mavenBom 'io.github.swagger2markup:swagger2markup-bom:1.3.4'
+    }
+
+    dependencies {
+        // We use fixed versions, instead of inheriting them from the Spring BOM, to be able to be on more recent ones.
+        // We do not use :+ to get the latest available version available on Maven Central, as that could suddenly break things.
+        // We use the Renovate Bot to automatically propose Pull Requests (PRs) when upgrades for all of these versions are available.
+
+        dependency 'org.slf4j:slf4j-api:1.7.36'
+        dependency 'org.slf4j:slf4j-simple:1.7.36'
+        dependency 'org.slf4j:jcl-over-slf4j:1.7.36'
+        dependency 'org.slf4j:jul-to-slf4j:1.7.36'
+        dependency 'org.slf4j:log4j-over-slf4j:1.7.36'
+        dependency 'ch.qos.logback:logback-core:1.2.11'
+        dependency 'ch.qos.logback:logback-classic:1.2.11'
+
+        dependency 'org.eclipse.persistence:org.eclipse.persistence.jpa:2.7.10'
+        dependency 'com.google.guava:guava:31.1-jre'
+        dependency 'com.google.code.gson:gson:2.9.0'
+        dependency 'com.google.truth:truth:1.1.3'
+        dependency 'com.google.truth.extensions:truth-java8-extension:1.1.3'
+        dependency 'com.google.googlejavaformat:google-java-format:1.15.0'
+        dependency ('org.apache.commons:commons-email:1.5') {
+            exclude 'com.sun.mail:javax.mail'
+            exclude 'javax.activation:activation'
+        }
+        dependency 'commons-io:commons-io:2.11.0'
+        dependency 'com.github.librepdf:openpdf:1.3.27'
+        dependency ('org.mnode.ical4j:ical4j:3.2.2') {
+            exclude 'com.sun.mail:javax.mail'
+        }
+        dependency 'org.quartz-scheduler:quartz:2.3.2'
+        dependency 'com.amazonaws:aws-java-sdk-s3:1.12.210'
+        dependency 'org.ehcache:ehcache:3.10.0'
+        dependency 'com.github.spullara.mustache.java:compiler:0.9.10'
+        dependency 'com.jayway.jsonpath:json-path:2.7.0'
+        dependency 'org.apache.tika:tika-core:2.3.0'
+        dependency 'org.apache.httpcomponents:httpclient:4.5.13'
+        dependency 'jakarta.management.j2ee:jakarta.management.j2ee-api:1.1.4'
+        dependency 'jakarta.jms:jakarta.jms-api:2.0.3'
+        dependency 'org.glassfish.jaxb:jaxb-runtime:2.3.6' // Swagger needs exactly this version
+        dependency 'org.apache.bval:org.apache.bval.bundle:2.0.5'
+        dependency 'joda-time:joda-time:2.10.14'
+
+        dependency 'io.github.classgraph:classgraph:4.8.146'
+        dependency 'org.awaitility:awaitility:4.2.0'
+        dependency 'com.github.spotbugs:spotbugs-annotations:4.6.0'
+        dependency 'javax.cache:cache-api:1.1.1'
+        dependency 'org.mock-server:mockserver-junit-jupiter:5.13.2'
+        dependency 'org.webjars:webjars-locator-core:0.50'
+        dependency 'com.icegreen:greenmail-junit5:1.6.8'
+        dependency 'com.intuit.karate:karate-junit5:1.2.0.RC6'
+
+        // fineract client dependencies
+        dependency "com.squareup.retrofit2:retrofit:2.9.0"
+        dependency "com.squareup.retrofit2:retrofit-mock:2.9.0"
+        dependency "com.squareup.retrofit2:adapter-java8:2.9.0"
+        dependency "com.squareup.retrofit2:adapter-rxjava2:2.9.0"
+        dependency "com.squareup.retrofit2:adapter-rxjava3:2.9.0"
+        dependency "com.squareup.retrofit2:adapter-guava:2.9.0"
+        dependency "com.squareup.retrofit2:converter-wire:2.9.0"
+        dependency "com.squareup.retrofit2:converter-jackson:2.9.0"
+        dependency "com.squareup.retrofit2:converter-simplexml:2.9.0"
+        dependency "com.squareup.retrofit2:converter-jaxb:2.9.0"
+        dependency "com.squareup.retrofit2:converter-java8:2.9.0"
+        dependency "com.squareup.retrofit2:converter-scalars:2.9.0"
+        dependency "com.squareup.retrofit2:converter-gson:2.9.0"
+        dependency "com.squareup.retrofit2:converter-protobuf:2.9.0"
+        dependency "org.apache.oltu.oauth2:org.apache.oltu.oauth2.common:1.0.1"
+        dependency "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:1.0.1"
+        dependency "org.apache.oltu.oauth2:org.apache.oltu.oauth2.httpclient4:1.0.1"
+        dependency "com.squareup.okhttp3:okhttp:4.9.3"
+        dependency "com.squareup.okhttp3:okcurl:4.9.3"
+        dependency "com.squareup.okhttp3:logging-interceptor:4.9.3"
+        dependency "com.squareup.okhttp3:okhttp-apache:4.9.3"
+        dependency "com.squareup.okhttp3:okhttp-android-support:4.9.3"
+        dependency "com.squareup.okhttp3:okhttp-urlconnection:4.9.3"
+        dependency "com.squareup.okhttp3:okhttp-sse:4.9.3"
+        dependency "io.gsonfire:gson-fire:1.8.5"
+        dependency "com.google.code.findbugs:jsr305:3.0.2"
+        dependency "commons-codec:commons-codec:1.15"
+        dependency "org.projectlombok:lombok:1.18.24"
+
+        dependency 'org.bouncycastle:bcpkix-jdk15to18:1.70'
+        dependency 'org.bouncycastle:bcprov-jdk15to18:1.70'
+        dependency 'org.bouncycastle:bcprov-jdk15on:1.70'
+        dependency 'org.bouncycastle:bcpg-jdk15on:1.70'
+
+        dependency 'org.eclipse.jgit:org.eclipse.jgit:6.1.0.202203080745-r'
+        dependency 'org.eclipse.jgit:org.eclipse.jgit.ssh.apache:6.1.0.202203080745-r'
+
+        dependency 'org.tmatesoft.svnkit:svnkit:1.10.5'
+        dependency 'com.vdurmont:semver4j:3.1.0'
+        dependency 'org.beryx:text-io:3.4.1'
+
+        dependency 'org.springdoc:springdoc-openapi-ui:1.6.8'
+        dependency 'org.springdoc:springdoc-openapi-webmvc-core:1.6.8'
+        dependency 'org.springdoc:springdoc-openapi-common:1.6.8'
+        dependency 'org.springdoc:springdoc-openapi-security:1.6.8'
+        dependency 'org.springdoc:springdoc-openapi-javadoc:1.6.8'
+
+        dependency 'com.google.cloud.sql:mysql-socket-factory-connector-j-8:1.5.0'
+
+        dependency ('org.apache.activemq:activemq-broker:5.17.1') {
+            exclude 'javax.annotation:javax.annotation-api'
+        }
+
+        dependency 'io.swagger:swagger-annotations:1.6.6'
+        dependency 'io.swagger.core.v3:swagger-annotations:2.2.0'
+        dependency ('io.swagger.core.v3:swagger-jaxrs2:2.2.0') {
+            exclude 'jakarta.activation:jakarta.activation-api'
+        }
+        dependency ('io.swagger.core.v3:swagger-core:2.2.0') {
+            exclude 'jakarta.activation:jakarta.activation-api'
+        }
+
+        dependency "jakarta.annotation:jakarta.annotation-api:1.3.5"
+        dependency 'jakarta.activation:jakarta.activation-api:1.2.2'
+        dependency ('com.sun.mail:jakarta.mail:1.6.7') {
+            exclude 'com.sun.activation:jakarta.activation'
+        }
+        dependency ('jakarta.xml.bind:jakarta.xml.bind-api:2.3.3') {
+            exclude 'jakarta.activation:jakarta.activation-api'
+        }
+
+        dependency ('org.liquibase:liquibase-core:4.9.1') {
+            exclude 'javax.xml.bind:jaxb-api'
+        }
+
+        dependency ('org.dom4j:dom4j:2.1.3') {
+            exclude 'relaxngDatatype:relaxngDatatype' // already in com.sun.xml.bind:jaxb-osgi:2.3.0.1
+            // FINERACT-940 && FINERACT-966 https://github.com/spotbugs/spotbugs/issues/1128
+            exclude 'xpp3:xpp3'
+            exclude 'pull-parser:pull-parser'
+        }
+
+        dependency 'org.owasp.esapi:esapi:2.4.0.0'
+
+        dependencySet(group: 'org.apache.poi', version: '5.2.2') {
+            entry 'poi'
+            entry 'poi-ooxml'
+            entry 'poi-ooxml-schemas'
+        }
+
+        dependencySet(group: 'io.rest-assured', version: '4.5.1') {
+            entry 'rest-assured'
+            entry 'json-path'
+            entry 'xml-path'
+        }
+    }
+}
diff --git a/buildSrc/src/main/groovy/org.apache.fineract.release.gradle b/buildSrc/src/main/groovy/org.apache.fineract.release.gradle
new file mode 100644
index 000000000..50bd11a9d
--- /dev/null
+++ b/buildSrc/src/main/groovy/org.apache.fineract.release.gradle
@@ -0,0 +1,263 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+apply plugin: 'org.apache.fineract.gradle'
+apply from: "${rootDir}/buildSrc/src/main/groovy/org.apache.fineract.dependencies.gradle"
+
+fineract {
+    config {
+        username = "${findProperty('fineract.config.username')}"
+        password = "${findProperty('fineract.config.password')}"
+
+        doc {
+            url = 'git@github.com:apache/fineract-site.git'
+            directory = "${System.getProperty("java.io.tmpdir")}/fineract-site"
+            branch = "asf-site"
+        }
+        git {
+            dir = "${projectDir.absolutePath}/.git"
+            sections = [
+                [
+                    section: "user",
+                    name: "name",
+                    value: "${findProperty('fineract.config.name')}",
+                ],
+                [
+                    section: "user",
+                    name: "email",
+                    value: "${findProperty('fineract.config.email')}",
+                ],
+                [
+                    section: "user",
+                    name: "signingkey",
+                    value: "${findProperty('fineract.config.gnupg.keyName')}",
+                ],
+                [
+                    section: "commit",
+                    name: "gpgsign",
+                    value: "true",
+                ],
+            ]
+        }
+        template {
+            templateDir = "${projectDir}/buildSrc/src/main/resources"
+        }
+        gpg {
+            keyName = "${findProperty('fineract.config.gnupg.keyName')}"
+            publicKeyring = "${findProperty('fineract.config.gnupg.publicKeyring')}"
+            secretKeyring = "${findProperty('fineract.config.gnupg.secretKeyring')}"
+            password = "${findProperty('fineract.config.gnupg.password')}"
+        }
+        smtp {
+            host = 'smtp.gmail.com'
+            username = "${findProperty('fineract.config.smtp.username')}"
+            password = "${findProperty('fineract.config.smtp.password')}"
+            tls = true
+            ssl = true
+        }
+        subversion {
+            username = "${findProperty('fineract.config.username')}"
+            password = "${findProperty('fineract.config.password')}"
+            revision = 'HEAD'
+        }
+        jira {
+            url = 'https://issues.apache.org/jira/rest/api/2/'
+            username = "${findProperty('fineract.config.username')}"
+            password = "${findProperty('fineract.config.password')}"
+        }
+        confluence {
+            url = 'https://cwiki.apache.org/confluence/rest/api/'
+            username = "${findProperty('fineract.config.username')}"
+            password = "${findProperty('fineract.config.password')}"
+        }
+    }
+
+    steps = [
+        test: [
+            order: 0,
+            description: 'Test',
+            email: [
+                from: "${findProperty('fineract.config.email')}",
+                to: "${findProperty('fineract.config.email')}",
+                mime: 'text/plain',
+                subject: "[FINERACT] [TEST] πŸ“£ 🏁 πŸ—³οΈ πŸš€ πŸ“ˆ πŸ”€ 🌠 Propose new release ${version}",
+                messageTemplate: [
+                    templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step01.headsup.message.ftl"
+                ]
+            ],
+            subversion: [
+                url: 'https://dist.apache.org/repos/dist/dev/fineract',
+                directory: "${System.getProperty("java.io.tmpdir")}"
+            ],
+            jira: [
+                query: "project in (\'FINERACT\') and fixVersion = ${findProperty('fineract.release.version')} and status in (CLOSED, RESOLVED)"
+            ],
+            template: [
+                templateFile: "${projectDir}/buildSrc/src/main/resources/jira/changelog.txt.ftl"
+            ],
+            gpg: [
+                file: "${projectDir}/buildSrc/build/libs/buildSrc.jar"
+            ]
+        ],
+        step1: [
+            order: 1,
+            description: 'Send heads-up email to dev mailing list',
+            email: [
+                from: "${findProperty('fineract.config.email')}",
+                name: "${findProperty('fineract.config.name')}",
+                to: "${findProperty('fineract.config.email')}",
+                // to: 'dev@fineract.apache.org',
+                mime: 'text/plain',
+                subjectTemplate: [
+                    templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step01.headsup.subject.ftl"
+                ],
+                messageTemplate: [
+                    templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step01.headsup.message.ftl"
+                ]
+            ]
+        ],
+        step2: [
+            order: 2,
+            description: 'Clean up JIRA',
+        ],
+        step3: [
+            order: 3,
+            description: 'Create a release branch',
+            email: [
+                from: "${findProperty('fineract.config.email')}",
+                name: "${findProperty('fineract.config.name')}",
+                to: "${findProperty('fineract.config.email')}",
+                // to: 'dev@fineract.apache.org',
+                mime: 'text/plain',
+                subjectTemplate: [
+                    templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step03.branch.subject.ftl"
+                ],
+                messageTemplate: [
+                    templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step03.branch.message.ftl"
+                ]
+            ]
+        ],
+        step4: [
+            order: 4,
+            description: 'Freeze JIRA version',
+        ],
+        step5: [
+            order: 5,
+            description: 'Create release tag',
+            git: [
+                messageTemplate: [
+                    templateFile: "${projectDir}/buildSrc/src/main/resources/git/release.step05.tag.message.ftl"
+                ]
+            ]
+        ],
+        step6: [
+            order: 6,
+            description: 'Create a distribution',
+        ],
+        step7: [
+            order: 7,
+            description: 'Sign the distribution artifacts',
+            gpg: [
+                file: "${rootDir}/fineract-war/build/distributions/apache-fineract-binary-${project.version}.tar.gz"
+            ]
+        ],
+        step8: [
+            order: 8,
+            description: 'Upload distribution artifacts to staging environment',
+            subversion: [
+                url: 'https://dist.apache.org/repos/dist/dev/fineract',
+                directory: "${System.getProperty("java.io.tmpdir")}/fineract-dist-dev"
+            ],
+        ],
+        step9: [
+            order: 9,
+            description: 'Verify distribution in staging environment',
+        ],
+        step10: [
+            order: 10,
+            description: 'Start voting on the dev mailing list',
+            email: [
+                from: "${findProperty('fineract.config.email')}",
+                name: "${findProperty('fineract.config.name')}",
+                to: "${findProperty('fineract.config.email')}",
+                // to: 'dev@fineract.apache.org',
+                mime: 'text/plain',
+                subjectTemplate: [
+                    templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step10.vote.subject.ftl"
+                ],
+                messageTemplate: [
+                    templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step10.vote.message.ftl"
+                ]
+            ]
+        ],
+        step11: [
+            order: 11,
+            description: 'Conclude the vote and announce results',
+            email: [
+                from: "${findProperty('fineract.config.email')}",
+                name: "${findProperty('fineract.config.name')}",
+                to: "${findProperty('fineract.config.email')}",
+                // to: 'dev@fineract.apache.org',
+                mime: 'text/plain',
+                subjectTemplate: [
+                    templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step11.vote.subject.ftl"
+                ],
+                messageTemplate: [
+                    templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step11.vote.message.ftl"
+                ]
+            ]
+        ],
+        step12: [
+            order: 12,
+            description: 'Upload distribution artifacts to release environment',
+            subversion: [
+                url: 'https://dist.apache.org/repos/dist/release/fineract',
+                directory: "${System.getProperty("java.io.tmpdir")}/fineract-dist-release"
+            ],
+        ],
+        step13: [
+            order: 13,
+            description: 'Close release branch and merge to \'develop\'',
+        ],
+        step14: [
+            order: 14,
+            description: 'Update website (not yet automated)',
+        ],
+        step15: [
+            order: 15,
+            description: 'Send email to announcement mailing list',
+            jira: [
+                projectId: "12319420",
+                query: "project in (\'FINERACT\') and fixVersion = ${findProperty('fineract.release.version')} and status in (CLOSED, RESOLVED, WONTFIX)"
+            ],
+            email: [
+                from: "${findProperty('fineract.config.email')}",
+                name: "${findProperty('fineract.config.name')}",
+                to: "${findProperty('fineract.config.email')}",
+                // to: 'dev@fineract.apache.org',
+                mime: 'text/plain',
+                subjectTemplate: [
+                    templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step15.announce.subject.ftl"
+                ],
+                messageTemplate: [
+                    templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step15.announce.message.ftl"
+                ]
+            ]
+        ]
+    ]
+}
diff --git a/buildSrc/src/main/groovy/org/apache/fineract/gradle/FineractPlugin.groovy b/buildSrc/src/main/groovy/org/apache/fineract/gradle/FineractPlugin.groovy
new file mode 100644
index 000000000..fb308c7a2
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/fineract/gradle/FineractPlugin.groovy
@@ -0,0 +1,581 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.gradle
+
+import groovy.json.JsonSlurper
+import org.apache.commons.io.FileUtils
+import org.apache.commons.io.filefilter.NotFileFilter
+import org.apache.commons.io.filefilter.PrefixFileFilter
+import org.apache.fineract.gradle.service.*
+import org.beryx.textio.TextIO
+import org.beryx.textio.TextIoFactory
+import org.beryx.textio.TextTerminal
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+
+class FineractPlugin implements Plugin<Project> {
+    private static final Logger log = LoggerFactory.getLogger(FineractPlugin.class)
+
+    private JiraService jiraService
+    private ConfluenceService confluenceService
+    private SubversionService subversionService
+    private EmailService emailService
+    private GpgService gpgService
+    private TemplateService templateService
+    private GitService gitService
+    private Map<String, ?> context;
+
+    static {
+        System.setProperty("org.beryx.textio.TextTerminal", "org.beryx.textio.system.SystemTextTerminal")
+    }
+
+    void apply(Project project) {
+        def extension = project.extensions.create("fineract", FineractPluginExtension, project)
+
+        project.fineract.extensions.create("config", FineractPluginExtension.FineractPluginConfig)
+        project.fineract.config.extensions.create("doc", FineractPluginExtension.FineractPluginConfigDoc)
+        project.fineract.config.extensions.create("template", FineractPluginExtension.FineractPluginConfigTemplate)
+        project.fineract.config.extensions.create("smtp", FineractPluginExtension.FineractPluginConfigSmtp)
+        project.fineract.config.extensions.create("subversion", FineractPluginExtension.FineractPluginConfigSubversion)
+        project.fineract.config.extensions.create("jira", FineractPluginExtension.FineractPluginConfigJira)
+        project.fineract.config.extensions.create("confluence", FineractPluginExtension.FineractPluginConfigConfluence)
+        project.fineract.config.extensions.create("gpg", FineractPluginExtension.FineractPluginConfigGpg)
+        project.fineract.config.extensions.create("git", FineractPluginExtension.FineractPluginConfigGit)
+
+        project.afterEvaluate {
+            this.templateService = new TemplateService(extension.config.template)
+            this.jiraService = new JiraService(extension.config.jira)
+            this.confluenceService = new ConfluenceService(extension.config.confluence)
+            this.subversionService = new SubversionService(extension.config.subversion)
+            this.emailService = new EmailService(extension.config.smtp)
+            this.gpgService = new GpgService(extension.config.gpg)
+            this.gitService = new GitService(extension.config.git, extension.config.gpg)
+            this.context = context(project)
+        }
+
+        project.tasks.register("fineractDocPublish") {
+            dependsOn(":fineract-doc:doc")
+
+            doLast {
+                log.warn("Fineract Publish Doc...")
+
+                def url = extension.config.doc.url?:"git@github.com:apache/fineract-site.git";
+                def branch = extension.config.doc.branch?:"asf-site"
+                def directory = extension.config.doc.directory?:System.getProperty("java.io.tmpdir")+"/fineract-site"
+
+                def d = new File(directory)
+
+                if(d.exists()) {
+                    gitService.pull(directory)
+                } else {
+                    gitService.clone(url, branch, directory)
+
+                    gitService.config(directory, extension.config.git.sections)
+                }
+
+                def source = new File("fineract-doc/build/docs/html/en");
+                def target = new File(directory + "/docs/current")
+
+                if(!target.name) {
+                    target.mkdirs()
+                }
+
+                FileUtils.copyDirectory(source, target, new NotFileFilter(new PrefixFileFilter(".asciidoctor")), true)
+
+                gitService.commit(directory)
+            }
+        }
+
+        project.tasks.register("fineractReleaseTest") {
+            doFirst {
+                // emojis:
+                // https://gist.github.com/parmentf/035de27d6ed1dce0b36a
+                // https://emojipedia.org/
+                // https://unicode.org/emoji/charts/full-emoji-list.html
+
+                FineractPluginExtension.FineractPluginStep step = step(extension, "test")
+
+                // TODO:
+                // - jira:
+                //   - move tickets to new version
+
+                // jira query
+                FineractPluginExtension.FineractPluginJiraParams result = jiraService.search(step.jira)
+                log.warn(">>>>>>>>>>>>>>>> ISSUE: ${result.result[0]?.id} - ${result.result[0]?.key} - ${result.result[0]?.fields?['summary']} - ${result.result[0]?.fields?['fixVersions']}")
+
+                /*
+
+                // confluence create
+                def content = new ConfluenceService.ConfluenceContent(title: "1.7.0 - Apache Fineract",
+                        space: new ConfluenceService.ConfluenceSpace(key: "FINERACT"),
+                        ancestors: [new ConfluenceService.ConfluenceParent(id: "75974324")],
+                        body: new ConfluenceService.ConfluenceBody(storage: new ConfluenceService.ConfluenceStorage(value: "<h1>Release Artifacts</h1>")))
+                confluenceService.createContent(content)
+
+                // confluence get
+                ConfluenceService.ConfluenceContent content = confluenceService.getContent("211881930")
+                log.warn(">>>>>>>>>>>>>>>>>>>>> CONFLUENCE: ${content.id} - ${content.title} - ${content.body?.storage?.value}")
+
+                // confluence update
+                content.body?.storage?.value = "<h1>Release Artifacts</h1><p><ac:structured-macro ac:macro-id=\"ac1cb3cb-84d4-45aa-820b-05cc42d39dd9\" ac:name=\"jira\" ac:schema-version=\"1\"><ac:parameter ac:name=\"server\">ASF JIRA</ac:parameter><ac:parameter ac:name=\"columnIds\">issuekey,summary,issuetype,created,updated,duedate,assignee,reporter,customfield_12311032,customfield_12311037,customfield_12311022,customfield_12311027,priority,status,resolution</ac:parameter><ac:parameter  [...]
+                content.space = new ConfluenceService.ConfluenceSpace(key: "FINERACT")
+                content.status = null
+                content.version = new ConfluenceService.ConfluenceVersion(number: 3)
+
+                // confluence update
+                content = confluenceService.updateContent(content.id, content)
+                log.warn(">>>>>>>>>>>>>>>>>>>>> CONFLUENCE: ${content.id} - ${content.title} - ${content.body?.storage?.value}")
+
+                // confluence delete
+                ConfluenceService.ConfluenceResponse response = confluenceService.deleteContent("211881930")
+                log.warn(">>>>>>>>>>>>>>>>>>>>> CONFLUENCE: ${response?.statusCode} - ${response?.message}")
+
+                // jira versions
+                def versions = jiraService.getProjectVersions("12319420")
+                versions.findAll {
+                    log.warn(">>>> VERSION: ${it.id} - ${it.name} - ${it.description}")
+                }
+
+                def version = jiraService.getVersion("12351431")
+                log.warn(">>>> !!! VERSION: ${version.id} - ${version.name} - ${version.description} - ${version.archived}")
+
+                version.archived = !version.archived
+
+                jiraService.updateVersion(version)
+                version = jiraService.getVersion("12351431")
+                log.warn(">>>> === VERSION: ${version.id} - ${version.name} - ${version.description} - ${version.archived}")
+
+                // jira projects
+                def projects = jiraService.getProjects()
+
+                projects.findAll {
+                    log.warn(">>>>>>>>>>>> PROJECT: ${it.id} - ${it.key} - ${it.name}")
+                }
+
+                // jira info
+                Map<String, Object> info = jiraService.serverInfo()
+                log.warn(">>>>>>>>>>>>>>>> INFO: ${info}")
+
+                // jira query
+                FineractPluginExtension.FineractPluginJiraParams result = jiraService.search(step.jira)
+                log.warn(">>>>>>>>>>>>>>>> INFO: ${result.result.size()}")
+
+                // format with template
+                def tmp = templateService.render(step.template, [issues: result.result])
+
+                log.warn(tmp.output)
+                */
+            }
+        }
+
+        // TODO: step for creating release Jira ticket missing!
+
+        // step 1
+        project.tasks.register("fineractReleaseStep1") {
+            doFirst {
+                FineractPluginExtension.FineractPluginStep step = step(extension, "step1")
+
+                String version = project.properties?['fineract.release.version']
+                String issue = project.properties?['fineract.release.issue']
+                String date = project.properties?['fineract.release.date']
+
+                if(!version || !issue || !date) {
+                    TextIO textIO = TextIoFactory.getTextIO()
+
+                    if(!version) {
+                        version = textIO.newStringInputReader()
+                                .withPattern("\\d+.\\d+.\\d+")
+                                .read("Release Version");
+                    }
+                    if(!issue) {
+                        issue = textIO.newStringInputReader()
+                                .withMaxLength(4)
+                                .withPattern("\\d+")
+                                .read("Jira Issue");
+                    }
+                    if(!date) {
+                        date = textIO.newStringInputReader()
+                                .withMaxLength(10)
+                                .withPattern("\\d\\d\\d\\d-\\d\\d-\\d\\d")
+                                .read("Date");
+                    }
+
+                    TextTerminal terminal = textIO.getTextTerminal()
+                    terminal.printf("\nResult: %s - FINERACT-%s - %s", version, issue, date)
+                }
+
+                // TODO: input validation, see FINERACT-1610
+
+                this.context?.project?['fineract.release.version'] = version
+                this.context?.project?['fineract.release.issue'] = issue
+                this.context?.project?['fineract.release.date'] = date
+
+                if(step.email) {
+                    emailService.send( processEmailParams(step.email, this.context) )
+                }
+            }
+        }
+
+        // step 2
+        project.tasks.register("fineractReleaseStep2") {
+            doFirst {
+                FineractPluginExtension.FineractPluginStep step = step(extension, "step2")
+
+                // TODO: implement this, see FINERACT-1611
+
+                printInstructions(project, "step2")
+            }
+        }
+
+        // step 3
+        project.tasks.register("fineractReleaseStep3") {
+            doFirst {
+                FineractPluginExtension.FineractPluginStep step = step(extension, "step3")
+
+                String version = project.properties?['fineract.release.version']
+                String date = project.properties?['fineract.release.date']
+
+                if(!version || !date) {
+                    TextIO textIO = TextIoFactory.getTextIO()
+
+                    if(!version) {
+                        version = textIO.newStringInputReader()
+                                .withPattern("\\d+.\\d+.\\d+")
+                                .read("Release Version");
+                    }
+                    if(!date) {
+                        date = textIO.newStringInputReader()
+                                .withMaxLength(10)
+                                .withPattern("\\d\\d\\d\\d-\\d\\d-\\d\\d")
+                                .read("Date");
+                    }
+
+                    TextTerminal terminal = textIO.getTextTerminal()
+                    terminal.printf("\nResult: %s - %s", version, date)
+                }
+
+                // TODO: input validation, see FINERACT-1610
+
+                // TODO: create release branch, see FINERACT-1611
+
+                this.context?.project?['fineract.release.version'] = version
+                this.context?.project?['fineract.release.date'] = date
+
+                if(step.email) {
+                    emailService.send( processEmailParams(step.email, this.context) )
+                }
+            }
+        }
+
+        // step 4
+        project.tasks.register("fineractReleaseStep4") {
+            doFirst {
+                FineractPluginExtension.FineractPluginStep step = step(extension, "step4")
+                // TODO: implement this, see FINERACT-1611
+
+                printInstructions(project, "step4")
+            }
+        }
+
+        // step 5
+        project.tasks.register("fineractReleaseStep5") {
+            doFirst {
+                FineractPluginExtension.FineractPluginStep step = step(extension, "step5")
+
+                String version = project.properties?['fineract.release.version']
+
+                if(!version) {
+                    TextIO textIO = TextIoFactory.getTextIO()
+
+                    if (!version) {
+                        version = textIO.newStringInputReader()
+                                .withPattern("\\d+.\\d+.\\d+")
+                                .read("Release Version");
+                    }
+                }
+
+                this.context?.project?['fineract.release.version'] = version
+
+                def params = processGitParams(step.git, this.context)
+
+                params.tag = params.tag?:version
+
+                gitService.createTag(params.tag, params.message)
+            }
+        }
+
+        // step 6
+        project.tasks.register("fineractReleaseStep6") {
+            dependsOn(":fineract-war:binaryDistTar")
+        }
+
+        // step 7
+        project.tasks.register("fineractReleaseStep7") {
+            doFirst {
+                FineractPluginExtension.FineractPluginStep step = step(extension, "step7")
+
+                gpgService.sign(step.gpg)
+
+                def md5 = gpgService.md5(step.gpg)
+                def md5File = new File("${step.gpg.file}.md5")
+                md5File.write md5
+
+                def sha512 = gpgService.sha512(step.gpg)
+                def sha512File = new File("${step.gpg.file}.sha512")
+                sha512File.write sha512
+            }
+        }
+
+        // step 8
+        project.tasks.register("fineractReleaseStep8") {
+            doFirst {
+                FineractPluginExtension.FineractPluginStep step = step(extension, "step8")
+
+                String version = project.properties?['fineract.release.version']
+
+                if(!version) {
+                    TextIO textIO = TextIoFactory.getTextIO()
+
+                    version = textIO.newStringInputReader()
+                            .withPattern("\\d+.\\d+.\\d+")
+                            .read("Release Version");
+                }
+
+                // TODO: input validation, see FINERACT-1610
+
+                subversionService.checkout(step.subversion)
+
+                def directory = step.subversion.directory?:System.getProperty("java.io.tmpdir") + "/fineract-dist-dev"
+
+                def source = new File("fineract-war/build/distributions")
+                def target = new File("${directory}/${version}")
+
+                FileUtils.copyDirectory(source, target, true)
+
+                subversionService.commit(step.subversion)
+            }
+        }
+
+        // step 9
+        project.tasks.register("fineractReleaseStep9") {
+            doFirst {
+                FineractPluginExtension.FineractPluginStep step = step(extension, "step9")
+                // TODO: implement this, see FINERACT-1611
+
+                printInstructions(project, "step9")
+            }
+        }
+
+        // step 10
+        project.tasks.register("fineractReleaseStep10") {
+            doFirst {
+                FineractPluginExtension.FineractPluginStep step = step(extension, "step10")
+
+                String version = project.properties?['fineract.release.version']
+
+                if(!version) {
+                    TextIO textIO = TextIoFactory.getTextIO();
+
+                    version = textIO.newStringInputReader()
+                            .withPattern("\\d+.\\d+.\\d+")
+                            .read("Release Version");
+                }
+
+                // TODO: input validation, see FINERACT-1610
+
+                this.context?.project?['fineract.release.version'] = version
+
+                if(step.email) {
+                    emailService.send( processEmailParams(step.email, this.context) )
+                }
+            }
+        }
+
+        // step 11
+        project.tasks.register("fineractReleaseStep11") {
+            doFirst {
+                FineractPluginExtension.FineractPluginStep step = step(extension, "step11")
+
+                String version = project.properties?['fineract.release.version']
+
+                if(!version) {
+                    TextIO textIO = TextIoFactory.getTextIO()
+
+                    version = textIO.newStringInputReader()
+                            .withPattern("\\d+.\\d+.\\d+")
+                            .read("Release Version");
+                }
+
+                // TODO: input validation, see FINERACT-1610
+
+                this.context?.project?['fineract.release.version'] = version
+
+                def jsonSlurper = new JsonSlurper()
+                def data = jsonSlurper.parse(new File("buildSrc/src/main/resources/vote/result.${version}.json"))
+
+                this.context?.project?['fineract.vote'] = data
+
+                if(step.email) {
+                    emailService.send( processEmailParams(step.email, this.context) )
+                }
+            }
+        }
+
+        // step 12
+        project.tasks.register("fineractReleaseStep12") {
+            doFirst {
+                FineractPluginExtension.FineractPluginStep step = step(extension, "step12")
+
+                String version = project.properties?['fineract.release.version']
+
+                if(!version) {
+                    TextIO textIO = TextIoFactory.getTextIO()
+
+                    version = textIO.newStringInputReader()
+                            .withPattern("\\d+.\\d+.\\d+")
+                            .read("Release Version");
+                }
+
+                // TODO: input validation, see FINERACT-1610
+
+                subversionService.checkout(step.subversion)
+
+                def directory = step.subversion.directory?:System.getProperty("java.io.tmpdir") + "/fineract-dist-release"
+
+                def source = new File("fineract-war/build/distributions")
+                def target = new File("${directory}/${version}")
+
+                FileUtils.copyDirectory(source, target, true)
+
+                subversionService.commit(step.subversion)
+            }
+        }
+
+        // step 13
+        project.tasks.register("fineractReleaseStep13") {
+            doFirst {
+                FineractPluginExtension.FineractPluginStep step = step(extension, "step13")
+                // TODO: implement this, see FINERACT-1611
+
+                printInstructions(project, "step13")
+            }
+        }
+
+        // step 14
+        project.tasks.register("fineractReleaseStep14") {
+            doFirst {
+                FineractPluginExtension.FineractPluginStep step = step(extension, "step14")
+                // TODO: implement this, see FINERACT-1611
+
+                printInstructions(project, "step14")
+            }
+        }
+
+        // step 15
+        project.tasks.register("fineractReleaseStep15") {
+            doFirst {
+                log.warn("Release step 15: send email to announcement mailing list")
+
+                FineractPluginExtension.FineractPluginStep step = step(extension, "step15")
+
+                String version = project.properties?['fineract.release.version']
+
+                if(!version) {
+                    TextIO textIO = TextIoFactory.getTextIO()
+
+                    version = textIO.newStringInputReader()
+                            .withPattern("\\d+.\\d+.\\d+")
+                            .read("Release Version");
+                }
+
+                // TODO: input validation, see FINERACT-1610
+
+                FineractPluginExtension.FineractPluginJiraParams issues = jiraService.search(step.jira)
+
+                def versions = jiraService.getProjectVersions(step.jira.projectId)
+                def filteredVersions = versions.findAll {
+                    log.warn(">>>> VERSION: ${it.id} - ${it.name} - ${it.description}")
+                    it.name == version
+                }
+
+                this.context?.project?['fineract.release.version'] = version
+                this.context?.project?['fineract.release.issues'] = issues.result
+                this.context?.project?['fineract.release.projectId'] = step.jira.projectId
+                this.context?.project?['fineract.release.versionId'] = filteredVersions[0]?.id
+
+                if(step.email) {
+                    emailService.send( processEmailParams(step.email, this.context) )
+                }
+            }
+        }
+    }
+
+    private FineractPluginExtension.FineractPluginStep step(FineractPluginExtension extension, String id) {
+        FineractPluginExtension.FineractPluginStep step = extension.steps[id]
+
+        if(step) {
+            log.warn("Fineract release step ${step.order}: ${step.description}.")
+        } else {
+            throw new RuntimeException("Could not find any parameters for step with ID '${id}'")
+        }
+
+        return step
+    }
+
+    private FineractPluginExtension.FineractPluginEmailParams processEmailParams(FineractPluginExtension.FineractPluginEmailParams params, Object data) {
+        if(params.subjectTemplate) {
+            def result = templateService.render(params.subjectTemplate, data)
+
+            params.subject = result.output
+        }
+        if(params.messageTemplate) {
+            def result = templateService.render(params.messageTemplate, data)
+
+            params.message = result.output
+        }
+
+        return params
+    }
+
+    private FineractPluginExtension.FineractPluginGitParams processGitParams(FineractPluginExtension.FineractPluginGitParams params, Object data) {
+        if(params.messageTemplate) {
+            def result = templateService.render(params.messageTemplate, data)
+
+            params.message = result.output
+        }
+
+        return params
+    }
+
+    private Map<String, ?> context(Project project) {
+        return Map.of("project", project.getProperties().findAll { it.key != "password"})
+    }
+
+    private void printInstructions(Project project, String step) {
+        String version = project.properties?['fineract.release.version']?:"0.0.0"
+
+        this.context?.project?['fineract.release.version'] = version
+
+        FineractPluginExtension.FineractPluginTemplateParams result = templateService.render(new FineractPluginExtension.FineractPluginTemplateParams(templateFile: new File("buildSrc/src/main/resources/instructions/${step}.txt.ftl")), this.context)
+
+        log.warn(result.output)
+    }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/fineract/gradle/FineractPluginExtension.groovy b/buildSrc/src/main/groovy/org/apache/fineract/gradle/FineractPluginExtension.groovy
new file mode 100644
index 000000000..fad37e071
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/fineract/gradle/FineractPluginExtension.groovy
@@ -0,0 +1,164 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.gradle
+
+import org.apache.fineract.gradle.service.JiraService
+import org.gradle.api.Project
+
+class FineractPluginExtension {
+    Project project
+    Map<String, FineractPluginStep> steps = [:]
+
+    FineractPluginExtension(Project project) {
+        this.project = project
+    }
+
+    static class FineractPluginConfig {
+        String username
+        String password
+    }
+
+    static class FineractPluginConfigDoc {
+        String url
+        String directory
+        String branch
+    }
+
+    static class FineractPluginConfigJira {
+        String url
+        String username
+        String password
+        String project
+    }
+
+    static class FineractPluginConfigConfluence {
+        String url
+        String username
+        String password
+        String project
+    }
+
+    static class FineractPluginConfigGpg {
+        String keyName
+        String publicKeyring
+        String secretKeyring
+        String password
+    }
+
+    static class FineractPluginConfigTemplate {
+        String templateDir
+    }
+
+    static class FineractPluginConfigSmtp {
+        String host
+        int port
+        String username
+        String password
+        boolean tls
+        boolean ssl
+    }
+
+    static class FineractPluginConfigGit {
+        String username
+        String password
+        String dir
+        boolean dryRun
+        List<FineractPluginConfigGitSection> sections
+    }
+
+    static class FineractPluginConfigGitSection {
+        String section
+        String subsection
+        String name
+        String value
+    }
+
+    static class FineractPluginConfigSubversion {
+        String username
+        String password
+        String revision
+    }
+
+    static class FineractPluginStep {
+        int order
+        String description
+        FineractPluginEmailParams email
+        FineractPluginJiraParams jira
+        FineractPluginTemplateParams template
+        FineractPluginConfluenceParams confluence
+        FineractPluginGitParams git
+        FineractPluginSubversionParams subversion
+        FineractPluginGpgParams gpg
+    }
+
+    static class FineractPluginEmailParams {
+        String from
+        String name
+        String to
+        String cc
+        String bcc
+        String mime
+        String subject
+        FineractPluginTemplateParams subjectTemplate
+        String message
+        FineractPluginTemplateParams messageTemplate
+    }
+
+    static class FineractPluginJiraParams {
+        String command
+        String projectId
+        String fields = "*all"
+        String query
+        List<JiraService.JiraIssue> result = new ArrayList<>()
+        int pageOffset = 0
+        int pageSize= 50
+        int total = 1000
+        List<String> includes = ["summary", "status", "assignee", "fixVersions"]
+    }
+
+    static class FineractPluginConfluenceParams {
+        String title
+        String content
+        Integer ancestor
+    }
+
+    static class FineractPluginGitParams {
+        String tag
+        String message
+        FineractPluginTemplateParams messageTemplate
+    }
+
+    static class FineractPluginSubversionParams {
+        String url
+        String command
+        String revision = "HEAD"
+        String directory
+    }
+
+    static class FineractPluginTemplateParams {
+        String template
+        String templateFile
+        String output
+        String outputFile
+    }
+
+    static class FineractPluginGpgParams {
+        String file
+    }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/ConfluenceService.groovy b/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/ConfluenceService.groovy
new file mode 100644
index 000000000..9b9514118
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/ConfluenceService.groovy
@@ -0,0 +1,209 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.gradle.service
+
+import com.fasterxml.jackson.databind.DeserializationFeature
+import com.fasterxml.jackson.databind.ObjectMapper
+import okhttp3.ConnectionPool
+import okhttp3.Credentials
+import okhttp3.Interceptor
+import okhttp3.OkHttpClient
+import okhttp3.Response
+import okhttp3.logging.HttpLoggingInterceptor
+import org.apache.fineract.gradle.FineractPluginExtension.FineractPluginConfigConfluence
+import org.jetbrains.annotations.NotNull
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import retrofit2.Call
+import retrofit2.Callback
+import retrofit2.Retrofit
+import retrofit2.converter.jackson.JacksonConverterFactory
+import retrofit2.http.*
+
+import java.util.concurrent.TimeUnit
+
+class ConfluenceService {
+    private static final Logger log = LoggerFactory.getLogger(ConfluenceService.class)
+
+    private ConfluenceApi api
+
+    ConfluenceService(FineractPluginConfigConfluence config) {
+        def credentials = Credentials.basic(config.username, config.password)
+
+        final ConnectionPool connectionPool = new ConnectionPool(5, 60, TimeUnit.SECONDS);
+
+        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(log::debug)
+        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
+
+        OkHttpClient.Builder okClient = new OkHttpClient.Builder()
+                .connectionPool(connectionPool)
+                .addInterceptor(loggingInterceptor)
+                .addInterceptor(new Interceptor() {
+                    @Override
+                    Response intercept(@NotNull Interceptor.Chain chain) throws IOException {
+                        def request = chain.request()
+                        request = request.newBuilder().header("Authorization", credentials).build()
+                        return chain.proceed(request)
+                    }
+                })
+
+        ObjectMapper mapper = new ObjectMapper()
+                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
+
+        Retrofit.Builder builder = new Retrofit.Builder()
+                .baseUrl(config.url)
+                .client(okClient.build())
+                .addConverterFactory(JacksonConverterFactory.create(mapper))
+
+        Retrofit retrofit = builder.build()
+
+        this.api = retrofit.create(ConfluenceApi.class)
+    }
+
+    ConfluenceContent getContent(String id) {
+        this.api.getContentById(id).execute().body()
+    }
+
+    ConfluenceContent createContent(ConfluenceContent content) {
+        this.api.postContent(content).execute().body()
+    }
+
+    ConfluenceContent updateContent(String id, ConfluenceContent content) {
+        this.api.putContent(id, content).execute().body()
+    }
+
+    ConfluenceResponse deleteContent(String id) {
+        this.api.deleteContentById(id).execute().body()
+    }
+
+    static class ConfluenceContent {
+        String id
+        String type
+        String title
+        String status
+        String self
+        List<ConfluenceParent> ancestors
+        ConfluenceSpace space
+        ConfluenceBody body
+        ConfluenceVersion version
+        ConfluenceHistory history
+    }
+
+    static class ConfluenceContentResult {
+        List<ConfluenceContent> results
+        private int start
+        private int limit
+        private int size
+    }
+
+    static class ConfluenceParent {
+        String id
+        String type
+    }
+
+    static class ConfluenceVersion {
+        ConfluenceCreatedBy by
+        Date when
+        String message
+        Integer number
+    }
+
+    static class ConfluenceCreatedBy {
+        String username
+        String displayName
+    }
+
+    static class ConfluenceHistory {
+        boolean latest
+        ConfluenceCreatedBy createdBy
+        ConfluenceVersion nextVersion
+        ConfluenceVersion previousVersion
+        ConfluenceVersion lastUpdated
+    }
+
+    static class ConfluenceSpace {
+        String key
+        String name
+    }
+
+    static class ConfluenceSpaceResult {
+        List<ConfluenceSpace> results
+    }
+
+    static class ConfluenceBody {
+        ConfluenceStorage storage
+    }
+
+    static class ConfluenceStorage {
+        String value
+        String representation
+    }
+
+    static class ConfluenceResponse {
+        int statusCode
+        String message
+        Map<String, ?> data
+    }
+
+    static interface ConfluenceApi {
+        @GET("content")
+        Call<ConfluenceContentResult> getContentResults();
+
+        @GET("content")
+        Call<ConfluenceContentResult> getContentBySpaceKeyAndTitle(final @Query("key") String key, final @Query("title") String title);
+
+        @GET("content/{id}/child/{type}")
+        Call<ConfluenceContentResult> getChildren(final @Path("id") String parentId, final @Path("type") String type, final @QueryMap Map<String, String> params);
+
+
+        @GET("content/{id}?expand=body.storage")
+        Call<ConfluenceContent> getContentById(final @Path("id") String id);
+
+        @POST("contentbody/convert/{to}")
+        Call<ConfluenceStorage> postContentConversion(final @Body ConfluenceStorage storage, final @Path("to") String convertToFormat);
+
+        @POST("content")
+        Call<ConfluenceContent> postContent(final @Body ConfluenceContent content);
+
+        @PUT("content/{id}")
+        Call<ConfluenceContent> putContent(final @Path("id") String id, final @Body ConfluenceContent content);
+
+        @POST("content")
+        void postContentWithCallback(final @Body ConfluenceContent content, final Callback<ConfluenceContent> callback);
+
+        @DELETE("content/{id}")
+        Call<ConfluenceResponse> deleteContentById(final @Path("id") String id);
+
+        @GET("space")
+        Call<ConfluenceSpaceResult> getSpaces();
+
+        @POST("space")
+        Call<ConfluenceSpace> createSpace(final @Body ConfluenceSpace space);
+
+        @POST("space/_private")
+        Call<ConfluenceSpace> createPrivateSpace(final @Body ConfluenceSpace space);
+
+        @GET("space/{spaceKey}/content/page")
+        Call<ConfluenceContentResult> getAllSpaceContent(final @Path("spaceKey") String spaceKey, final @QueryMap Map<String, String> params);
+
+        @GET("space/{spaceKey}/content/{type}")
+        Call<ConfluenceContentResult> getRootContentBySpaceKey(final @Path("spaceKey") String spaceKey, final @Path("type") String contentType);
+    }
+}
+// curl -u aleks:xxx -X POST -H 'Content-Type: application/json' -d '{"type":"page","title":"1.7.0 - Apache Fineract","space":{"key":"FINERACT"},"ancestors":[{"id":75974324}],"body":{"storage":{"value":"<p>This is <br/> a new page</p>","representation": "storage"}}}' https://cwiki.apache.org/confluence/content/ | python -mjson.tool
\ No newline at end of file
diff --git a/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/EmailService.groovy b/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/EmailService.groovy
new file mode 100644
index 000000000..cde26e3ec
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/EmailService.groovy
@@ -0,0 +1,87 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.gradle.service
+
+import org.apache.fineract.gradle.FineractPluginExtension
+import org.apache.fineract.gradle.FineractPluginExtension.FineractPluginEmailParams
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+
+import javax.mail.*
+import javax.mail.internet.InternetAddress
+import javax.mail.internet.MimeMessage
+
+class EmailService {
+    private static final Logger log = LoggerFactory.getLogger(EmailService.class)
+
+    String username
+    String password
+    Properties properties
+
+    EmailService(FineractPluginExtension.FineractPluginConfigSmtp config) {
+        this.username = config.username
+        this.password = config.password
+
+        this.properties = new Properties()
+        this.properties.put("mail.smtp.host", config.host)
+        this.properties.put("mail.smtp.auth", "true")
+        this.properties.put("mail.smtp.starttls.enable", config.tls.toString())
+        if(config.ssl) {
+            this.properties.put("mail.smtp.port", "465")
+            this.properties.put("mail.smtp.socketFactory.port", "465");
+            this.properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
+
+        } else {
+            this.properties.put("mail.smtp.port", "587")
+        }
+    }
+
+    void send(FineractPluginEmailParams params) {
+        log.warn("Sending email: ${params.from} -> ${params.to} - ${params.subject}")
+
+        Session session = Session.getInstance(this.properties, new Authenticator() {
+            @Override
+            protected PasswordAuthentication getPasswordAuthentication() {
+                return new PasswordAuthentication(getUsername(), getPassword())
+            }
+        })
+
+        try {
+
+            Message msg = new MimeMessage(session)
+            msg.setFrom(new InternetAddress(params.from, params.name))
+            msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(params.to))
+            if(params.cc) {
+                msg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(params.cc))
+            }
+            if(params.bcc) {
+                msg.setRecipients(Message.RecipientType.BCC, InternetAddress.parse(params.bcc))
+            }
+            msg.setSubject(params.subject)
+            msg.setText(params.message);
+
+            Transport.send(msg);
+
+            log.info("Done")
+
+        } catch (MessagingException e) {
+            log.error(e.toString(), e)
+        }
+    }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/GitService.groovy b/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/GitService.groovy
new file mode 100644
index 000000000..fc4b43ae1
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/GitService.groovy
@@ -0,0 +1,136 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.gradle.service
+
+import org.apache.fineract.gradle.FineractPluginExtension
+import org.eclipse.jgit.annotations.NonNull
+import org.eclipse.jgit.annotations.Nullable
+import org.eclipse.jgit.api.Git
+import org.eclipse.jgit.api.errors.CanceledException
+import org.eclipse.jgit.lib.CommitBuilder
+import org.eclipse.jgit.lib.GpgSigner
+import org.eclipse.jgit.lib.PersonIdent
+import org.eclipse.jgit.lib.Repository
+import org.eclipse.jgit.lib.StoredConfig
+import org.eclipse.jgit.storage.file.FileRepositoryBuilder
+import org.eclipse.jgit.transport.CredentialsProvider
+import org.eclipse.jgit.transport.RefSpec
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+
+class GitService {
+    private static final Logger log = LoggerFactory.getLogger(GitService.class)
+
+    private Git git
+    private boolean dryRun
+
+    GitService(FineractPluginExtension.FineractPluginConfigGit config, FineractPluginExtension.FineractPluginConfigGpg gpgConfig) {
+        GpgSigner.setDefault(new GpgSigner() {
+            @Override
+            void sign(@NonNull CommitBuilder commit, @Nullable String gpgSigningKey, @NonNull PersonIdent committer, CredentialsProvider credentialsProvider) throws CanceledException {
+                log.warn("------------------------ KEY: ${gpgSigningKey} IDENT: ${committer}")
+            }
+
+            @Override
+            boolean canLocateSigningKey(@Nullable String gpgSigningKey, @NonNull PersonIdent committer, CredentialsProvider credentialsProvider) throws CanceledException {
+                log.warn("------------------------ KEY: ${gpgSigningKey} IDENT: ${committer}")
+                return false
+            }
+        });
+
+        Repository repository = new FileRepositoryBuilder()
+                .readEnvironment()
+                .setGitDir(new File(config.dir))
+                .findGitDir()
+                .build();
+
+        this.git = new Git(repository)
+        this.dryRun = config.dryRun
+    }
+
+    void clone(String url, String branch, String directory) {
+        def ref = "refs/heads/" + branch
+
+        Git.cloneRepository()
+                .setURI(url)
+                .setDirectory(new File(directory))
+                .setBranchesToClone(Arrays.asList(ref))
+                .setBranch(ref)
+                .call();
+    }
+
+    void pull(String directory) {
+        Git git = Git.open(new File(directory));
+
+        git.pull().call()
+    }
+
+    void commit(String directory) {
+        Git git = Git.open(new File(directory));
+
+        def status = git.status().call()
+
+        if(!status.isClean()) {
+            git.add().addFilepattern(".").call()
+
+            git.commit().setSign(true).setMessage("chore: Publish current docs").call()
+        }
+
+        def result = git.push().call()
+    }
+
+    void config(String directory, List<FineractPluginExtension.FineractPluginConfigGitSection> sections) {
+        Git git = Git.open(new File(directory));
+
+        StoredConfig gitConfig = git.getRepository().getConfig();
+
+        sections.forEach(section -> {
+            gitConfig.setString(section.section, section.subsection, section.name, section.value);
+        })
+        // gitConfig.setString("branch", "master", "merge", "refs/heads/master");
+        gitConfig.save();
+    }
+
+    void createTag(String name, String message) {
+        def ref = git.tag()
+                .setName(name)
+                .setMessage(message)
+                .setAnnotated(true)
+                .setForceUpdate(true)
+                .call()
+
+        try {
+            git.push().setPushTags().setForce(true).setDryRun(dryRun).call()
+
+            log.warn("Tag created: ${name} (${ref.name})")
+        } catch(Exception e) {
+            log.error(e.toString(), e)
+        }
+    }
+
+    // TODO: explicitly provide the directory
+    void removeTag(String name) {
+        git.tagDelete().setTags(name).call()
+
+        RefSpec refSpec = new RefSpec(":refs/tags/${name}");
+        git.push().setRefSpecs(refSpec).setRemote("origin").call()
+
+        log.warn("Tag deleted: ${name}")
+    }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/GpgService.groovy b/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/GpgService.groovy
new file mode 100644
index 000000000..7e8c6470f
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/GpgService.groovy
@@ -0,0 +1,148 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.gradle.service
+
+import org.apache.fineract.gradle.FineractPluginExtension
+import org.apache.fineract.gradle.FineractPluginExtension.FineractPluginConfigGpg
+import org.bouncycastle.bcpg.ArmoredOutputStream
+import org.bouncycastle.bcpg.BCPGOutputStream
+import org.bouncycastle.gpg.keybox.BlobType
+import org.bouncycastle.gpg.keybox.PublicKeyRingBlob
+import org.bouncycastle.gpg.keybox.bc.BcKeyBox
+import org.bouncycastle.jce.provider.BouncyCastleProvider
+import org.bouncycastle.openpgp.*
+import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator
+import org.bouncycastle.openpgp.operator.bc.BcPGPContentSignerBuilder
+import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+
+import java.security.GeneralSecurityException
+import java.security.MessageDigest
+import java.security.Security
+
+class GpgService {
+    private static final Logger log = LoggerFactory.getLogger(GpgService.class)
+
+    private PGPPrivateKey privateKey;
+    private PGPPublicKey publicKey;
+
+    static {
+        Security.addProvider(new BouncyCastleProvider());
+    }
+
+    GpgService(FineractPluginConfigGpg config) {
+        // TODO: provide implementation for *.gpg key rings
+        def keyBox = config.publicKeyring.endsWith(".kbx") ? new BcKeyBox(new FileInputStream(config.publicKeyring)) : null
+
+        if(keyBox) {
+            for(def keyBlob : keyBox.getKeyBlobs()) {
+                switch (keyBlob.type) {
+                    case BlobType.X509_BLOB:
+                        break
+                    case BlobType.OPEN_PGP_BLOB:
+                        def publicKeyRing = (keyBlob as PublicKeyRingBlob).getPGPPublicKeyRing();
+                        def iterator = publicKeyRing.getPublicKeys();
+
+                        while (publicKey == null && iterator.hasNext()) {
+                            def k = iterator.next();
+
+                            if (k.isEncryptionKey()) {
+                                def keyName = Long.toHexString(k.keyID).toUpperCase()
+
+                                if(config.keyName.substring(config.keyName.length()-keyName.length()) == keyName) {
+                                    publicKey = k;
+                                    log.warn("Found: ${publicKey.getUserIDs().next()}")
+                                    break
+                                } else {
+                                    log.warn("Key mismatch: ${config.keyName} <-> ${keyName}")
+                                }
+                            }
+                        }
+                        break
+                }
+            }
+
+            PGPSecretKeyRingCollection secretRingCollection = new PGPSecretKeyRingCollection(new FileInputStream(config.secretKeyring), new BcKeyFingerprintCalculator())
+
+            def secretKey = secretRingCollection.getSecretKey(publicKey.keyID)
+
+            if(secretKey!=null) {
+                this.privateKey = secretKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(BouncyCastleProvider.PROVIDER_NAME).build(config.password.toCharArray()))
+            }
+        } else {
+            log.warn("Could not open the public key ring.")
+        }
+    }
+
+    void sign(FineractPluginExtension.FineractPluginGpgParams params) {
+        InputStream is = new FileInputStream(params.file)
+
+        BCPGOutputStream os = new BCPGOutputStream(new ArmoredOutputStream(new FileOutputStream(params.file + ".asc")))
+        sign(is).encode(os)
+        os.close();
+    }
+
+    PGPSignature sign(InputStream is) throws IOException, PGPException, GeneralSecurityException {
+
+        PGPSignatureGenerator generator = new PGPSignatureGenerator(new BcPGPContentSignerBuilder(publicKey.getAlgorithm(), PGPUtil.SHA1));
+        generator.init(PGPSignature.BINARY_DOCUMENT, privateKey);
+
+        byte[] buf = new byte[4096];
+        int len;
+
+        while ((len = is.read(buf)) >= 0) {
+            generator.update(buf, 0, len);
+        }
+
+        return generator.generate();
+    }
+
+
+    String md5(FineractPluginExtension.FineractPluginGpgParams params) {
+        return calc(new FileInputStream(params.file), MessageDigest.getInstance("MD5", BouncyCastleProvider.PROVIDER_NAME))
+    }
+
+    String sha512(FineractPluginExtension.FineractPluginGpgParams params) {
+        return calc(new FileInputStream(params.file), MessageDigest.getInstance("SHA-512", BouncyCastleProvider.PROVIDER_NAME))
+    }
+
+    private static String calc(InputStream is, MessageDigest digest) {
+        String output
+        int read
+        byte[] buffer = new byte[8192]
+
+        try {
+            while ((read = is.read(buffer)) > 0) {
+                digest.update(buffer, 0, read)
+            }
+            byte[] hash = digest.digest()
+            BigInteger bigInt = new BigInteger(1, hash)
+            output = bigInt.toString(16)
+            while ( output.length() < 32 ) {
+                output = "0"+output
+            }
+        } catch (Exception e) {
+            log.error(e.toString(), e)
+            return null
+        }
+
+        return output
+    }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/JiraService.groovy b/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/JiraService.groovy
new file mode 100644
index 000000000..b6ff34cf0
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/JiraService.groovy
@@ -0,0 +1,324 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.gradle.service
+
+import com.fasterxml.jackson.databind.DeserializationFeature
+import com.fasterxml.jackson.databind.ObjectMapper
+import okhttp3.*
+import okhttp3.logging.HttpLoggingInterceptor
+import org.apache.fineract.gradle.FineractPluginExtension
+import org.jetbrains.annotations.NotNull
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import retrofit2.Call
+import retrofit2.Retrofit
+import retrofit2.converter.jackson.JacksonConverterFactory
+import retrofit2.http.*
+
+import java.util.concurrent.TimeUnit
+
+class JiraService {
+    private static final Logger log = LoggerFactory.getLogger(JiraService.class)
+
+    private JiraApi api
+
+    JiraService(FineractPluginExtension.FineractPluginConfigJira config) {
+        def credentials = Credentials.basic(config.username, config.password)
+
+        final ConnectionPool connectionPool = new ConnectionPool(5, 60, TimeUnit.SECONDS);
+
+        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(log::debug)
+        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
+
+        OkHttpClient.Builder okClient = new OkHttpClient.Builder()
+            .connectionPool(connectionPool)
+            .addInterceptor(loggingInterceptor)
+            .addInterceptor(new Interceptor() {
+                @Override
+                Response intercept(@NotNull Interceptor.Chain chain) throws IOException {
+                    def request = chain.request()
+                    request = request.newBuilder().header("Authorization", credentials).build()
+                    return chain.proceed(request)
+                }
+            })
+
+        ObjectMapper mapper = new ObjectMapper()
+                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
+
+        Retrofit.Builder builder = new Retrofit.Builder()
+                .baseUrl(config.url)
+                .client(okClient.build())
+                .addConverterFactory(JacksonConverterFactory.create(mapper))
+
+        Retrofit retrofit = builder.build()
+
+        this.api = retrofit.create(JiraApi.class)
+    }
+
+    Map<String, Object> serverInfo() {
+        return this.api.serverInfo.execute().body()
+    }
+
+    FineractPluginExtension.FineractPluginJiraParams search(FineractPluginExtension.FineractPluginJiraParams params) {
+        def query = [:]
+
+        query['jql'] = params.query
+        query['startAt'] = params.pageOffset?:0
+        query['maxResults'] = params.pageSize?:50
+        // query['expand'] = [
+        //     "names",
+        //     "schema",
+        //     "operations"
+        // ]
+        // query['fields'] = params.fields?:"*all"
+        query['fields'] = params.includes?:[
+            "summary",
+            "status",
+            "assignee",
+            "fixVersions"
+        ]
+
+        // params.total = params.total?:1000
+        params.total = 1000
+
+        def result = this.api.searchIssues(query).execute().body()
+
+        params.result.addAll(result?.issues as List)
+
+        if(result?.issues.size()>=params.pageSize && params.result.size() < params.total) {
+            params.pageOffset += params.pageSize
+            search(params);
+        }
+
+        return params
+    }
+
+    List getProjects() {
+        return this.api.getProjects()?.execute()?.body()
+    }
+
+    List getProjectVersions(String projectId) {
+        return this.api.getProjectVersions(projectId)?.execute()?.body()
+    }
+
+    JiraVersion getVersion(String id) {
+        return this.api.getVersion(id)?.execute()?.body()
+    }
+
+    void updateVersion(JiraVersion version) {
+        this.api.updateVersion(version.id, version).execute()
+    }
+
+    static class JiraVersion {
+        String self
+        String id
+        String description
+        String name
+        boolean archived
+        boolean released
+        String releaseDate
+        String userReleaseDate
+        String project
+        Integer projectId
+    }
+
+    static class JiraSearchResult {
+        String expand
+        Integer startAt
+        Integer maxResults
+        Integer total
+        List<JiraIssue> issues
+        List<String> warningMessages
+        Map<String, Object> names
+        Map<String, Object> schema
+    }
+
+    static class JiraIssue {
+        String expand
+        String self
+        String id
+        String key
+        Map<String, Object> renderedFields
+        Map<String, Object> properties
+        Map<String, Object> names
+        Map<String, Object> schema
+        Map<String, Object> fields
+    }
+
+    static class JiraIssueUpdateRequest {
+        Map<String, Map<String, Object>> historyMetadata
+        Map<String, List<Map<String, Object>>> update
+        Map<String, Object> fields
+        Map<String, List<Map<String, Object>>> properties
+    }
+
+    static interface JiraApi {
+        // Server Info
+        @GET("serverInfo")
+        Call<Map<String, Object>> getServerInfo()
+
+        // Components
+        @GET("component/{id}")
+        Call<Object> getComponent(@Path("id") String id)
+
+        @POST("component")
+        Call<Object> createComponent(@Body Object component)
+
+        @PUT("component/{id}")
+        Call<Void> updateComponent(@Path("id") String id, @Body Object component)
+
+        @GET("component/{id}/relatedIssueCounts")
+        Call<Object> getComponentIssueCount(@Path("id") String id)
+
+        // Issue
+        @GET("issue/{issueIdOrKey}")
+        Call<Object> getIssue(@Path("issueIdOrKey") String issueIdOrKey)
+
+        @POST("issue")
+        Call<Object> createIssue(@Body Object issue)
+
+        @PUT("issue/{issueIdOrKey}")
+        Call<Object> updateIssue(@Path("issueIdOrKey") String issueIdOrKey, @Body Object issue, @QueryMap Map<String, String> queryMap)
+
+        @POST("issue/bulk")
+        Call<Object> createIssues(@Body Object issues)
+
+        @PUT("issue/{issueIdOrKey}/assignee")
+        Call<Void> assignIssue(@Path("issueIdOrKey") String issueIdOrKey, @Body Object user)
+
+        @GET("issue/{issueIdOrKey}/comment")
+        Call<Object> getComments(@Path("issueIdOrKey") String issueIdOrKey)
+
+        @POST("issue/{issueIdOrKey}/comment")
+        Call<Object> addComment(@Path("issueIdOrKey") String issueIdOrKey, @Body Object comment)
+
+        @PUT("issue/{issueIdOrKey}/comment/{id}")
+        Call<Object> updateComment(@Path("issueIdOrKey") String issueIdOrKey, @Path("id") String id, @Body Object comment)
+
+        @GET("issue/{issueIdOrKey}/comment/{id}")
+        Call<Object> getComment(@Path("issueIdOrKey") String issueIdOrKey, @Path("id") String id)
+
+        @POST("issue/{issueIdOrKey}/notify")
+        Call<Void> notifyIssue(@Path("issueIdOrKey") String issueIdOrKey, @Body Object notify)
+
+        @GET("issue/{issueIdOrKey}/transitions?expand=transitions.fields")
+        Call<Object> getTransitions(@Path("issueIdOrKey") String issueIdOrKey)
+
+        @POST("issue/{issueIdOrKey}/transitions")
+        Call<Void> transitionIssue(@Path("issueIdOrKey") String issueIdOrKey, @Body Object issue)
+
+        @GET("issue/{issueIdOrKey}/watchers")
+        Call<Object> getIssueWatches(@Path("issueIdOrKey") String issueIdOrKey)
+
+        @POST("issue/{issueIdOrKey}/watchers")
+        Call<Void> addIssueWatcher(@Path("issueIdOrKey") String issueIdOrKey, @Body String user)
+
+        // Remote Issue Links
+        @GET("issue/{issueIdOrKey}/remotelink")
+        Call<Object> getIssueRemoteLinks(@Path("issueIdOrKey") String issueIdOrKey, @Query("globalId") String globalId)
+
+        @GET("issue/{issueIdOrKey}/remotelink/{linkId}")
+        Call<Object> getIssueRemoteLink(@Path("issueIdOrKey") String issueIdOrKey, @Path("linkId") String linkId)
+
+        @POST("issue/{issueIdOrKey}/remotelink")
+        Call<Object> createIssueRemoteLink(@Path("issueIdOrKey") String issueIdOrKey, @Body Object issueLink)
+
+        @POST("issue/{issueIdOrKey}/remotelink/{linkId}")
+        Call<Object> updateIssueRemoteLink(@Path("issueIdOrKey") String issueIdOrKey, @Path("linkId") String linkId, @Body Object issueLink)
+
+        @DELETE("issue/{issueIdOrKey}/remotelink")
+        Call<Object> deleteIssueRemoteLinks(@Path("issueIdOrKey") String issueIdOrKey, @Query("globalId") String globalId)
+
+        @DELETE("issue/{issueIdOrKey}/remotelink/{linkId}")
+        Call<Object> deleteIssueRemoteLink(@Path("issueIdOrKey") String issueIdOrKey, @Path("linkId") String linkId)
+
+        // Issue Links
+        @POST("issueLink")
+        Call<Void> createIssueLink(@Body Object issueLink)
+
+        @GET("issueLink/{linkId}")
+        Call<Object> getIssueLink(@Path("linkId") String linkId)
+
+        @DELETE("issueLink/{linkId}")
+        Call<Object> deleteIssueLink(@Path("linkId") String linkId)
+
+        // Issue Link Types
+        @GET("issueLinkType")
+        Call<Object> getIssueLinkTypes()
+
+        // Project
+        @GET("project?expand=lead,description")
+        Call<List> getProjects()
+
+        @GET("project/{projectIdOrKey}")
+        Call<Object> getProject(@Path("projectIdOrKey") String projectId)
+
+        @GET("project/{projectIdOrKey}/statuses")
+        Call<Object> getProjectStatuses(@Path("projectIdOrKey") String projectId)
+
+        @GET("project/{projectIdOrKey}/components")
+        Call<Object> getProjectComponents(@Path("projectIdOrKey") String projectId)
+
+        @GET("project/{projectIdOrKey}/versions")
+        Call<List<JiraVersion>> getProjectVersions(@Path("projectIdOrKey") String projectId)
+
+        // Search
+        @POST("search")
+        Call<JiraSearchResult> searchIssues(@Body Map<String, Object> search)
+
+        // Version
+        @POST("version")
+        Call<JiraVersion> createVersion(@Body JiraVersion version)
+
+        @GET("version/{id}")
+        Call<JiraVersion> getVersion(@Path("id") String id)
+
+        @PUT("version/{id}")
+        Call<Void> updateVersion(@Path("id") String id, @Body JiraVersion version)
+
+        // Fields
+        @GET("field")
+        Call<Object> getFields()
+
+        @POST("field")
+        Call<Object> createField(@Body Object field)
+
+        // Users
+        @GET("user/search")
+        Call<Object> userSearch(@Query("username") String userName, @Query("startAt") int startAt, @Query("maxResults") int maxResults)
+
+        @GET("user/assignable/search")
+        Call<Object> assignableUserSearch(@Query("username") String userName, @Query("project") String project, @Query("issueKey") String issueKey, @Query("startAt") int startAt, @Query("maxResults") int maxResults)
+
+        @Multipart
+        @retrofit2.http.Headers("X-Atlassian-Token: no-check")
+        @POST("issue/{issueIdOrKey}/attachments")
+        Call<Object> uploadAttachment(@Path("issueIdOrKey") String issueIdOrKey, @Part MultipartBody.Part file)
+
+        @GET("attachment/{attachmentId}")
+        Call<Object> getAttachment(@Path("attachmentId") String attachmentId)
+
+        @DELETE("attachment/{attachmentId}")
+        Call<Object> deleteAttachment(@Path("attachmentId") String attachmentId)
+
+        @Streaming
+        @GET
+        Call<ResponseBody> downloadFileWithDynamicUrl(@Url String fileUrl)
+    }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/SubversionService.groovy b/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/SubversionService.groovy
new file mode 100644
index 000000000..bb771a45f
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/SubversionService.groovy
@@ -0,0 +1,74 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.gradle.service
+
+import org.apache.fineract.gradle.FineractPluginExtension
+import org.gradle.api.GradleException
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import org.tmatesoft.svn.core.SVNCancelException
+import org.tmatesoft.svn.core.SVNDepth
+import org.tmatesoft.svn.core.SVNException
+import org.tmatesoft.svn.core.SVNURL
+import org.tmatesoft.svn.core.wc.*
+
+class SubversionService {
+    private static final Logger log = LoggerFactory.getLogger(SubversionService.class)
+
+    private SVNUpdateClient client;
+    private String revision;
+
+    SubversionService(FineractPluginExtension.FineractPluginConfigSubversion config) {
+        ISVNOptions options = SVNWCUtil.createDefaultOptions(true)
+        SVNClientManager clientManager = SVNClientManager.newInstance(options, SVNWCUtil.createDefaultAuthenticationManager(config.username, config.password))
+
+        this.client = clientManager.updateClient;
+        this.client.ignoreExternals = false
+        this.client.eventHandler = new ISVNEventHandler() {
+            @Override
+            void handleEvent(SVNEvent event, double progress) throws SVNException {
+                println ">>> PROGRESS: ${progress>0?:'-'}"
+            }
+
+            @Override
+            void checkCancelled() throws SVNCancelException {
+
+            }
+        }
+
+        this.revision = config.revision
+    }
+
+    void checkout(FineractPluginExtension.FineractPluginSubversionParams params) {
+        SVNURL svnUrl = SVNURL.parseURIEncoded(params.url)
+
+        SVNRevision svnRevision = this.revision == null ? SVNRevision.HEAD : SVNRevision.parse(this.revision)
+
+        if (svnRevision == SVNRevision.UNDEFINED) {
+            throw new GradleException("Invalid SVN revision: " + this.revision)
+        }
+
+        this.client.doCheckout(svnUrl, new File(params.directory), SVNRevision.HEAD, svnRevision, SVNDepth.INFINITY, false)
+    }
+
+    void commit(FineractPluginExtension.FineractPluginSubversionParams params) {
+        // TODO: implement this
+        SVNURL svnUrl = SVNURL.parseURIEncoded(params.url)
+    }
+}
diff --git a/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/TemplateService.groovy b/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/TemplateService.groovy
new file mode 100644
index 000000000..356c9bb05
--- /dev/null
+++ b/buildSrc/src/main/groovy/org/apache/fineract/gradle/service/TemplateService.groovy
@@ -0,0 +1,84 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.gradle.service
+
+import freemarker.core.Environment
+import freemarker.template.Configuration
+import freemarker.template.Template
+import freemarker.template.TemplateException
+import freemarker.template.TemplateExceptionHandler
+import org.apache.fineract.gradle.FineractPluginExtension
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+
+class TemplateService {
+    private static final Logger log = LoggerFactory.getLogger(TemplateService.class)
+
+    private Configuration config
+
+    TemplateService(FineractPluginExtension.FineractPluginConfigTemplate config) {
+        def dir = new File(config.templateDir);
+
+        this.config = new Configuration(Configuration.VERSION_2_3_31);
+        this.config.setDirectoryForTemplateLoading(dir)
+        this.config.setDefaultEncoding("UTF-8");
+        this.config.setLogTemplateExceptions(false);
+        this.config.setWrapUncheckedExceptions(true);
+        this.config.setFallbackOnNullLoopVariable(false);
+        this.config.setTemplateExceptionHandler(new TemplateExceptionHandler() {
+            @Override
+            void handleTemplateException(TemplateException te, Environment env, Writer out) throws TemplateException {
+                if (!env.isInAttemptBlock()) {
+                    PrintWriter pw = (out instanceof PrintWriter) ? (PrintWriter) out : new PrintWriter(out);
+                    pw.print("FreeMarker template error\n");
+                    te.printStackTrace(pw, false, true, false);
+                    pw.flush();  // To commit the HTTP response
+                }
+            }}
+        )
+    }
+
+    FineractPluginExtension.FineractPluginTemplateParams render(FineractPluginExtension.FineractPluginTemplateParams params, Object data) {
+        Template template = null;
+
+        if(params.templateFile) {
+            template = new Template("template", new FileReader(new File(params.templateFile)), this.config)
+        }
+        if(params.template) {
+            template = new Template("template", new StringReader(params.template), this.config)
+        }
+
+        if(template) {
+            if(params.outputFile) {
+                def output = new File(params.outputFile)
+                output.createNewFile()
+
+                template.process(data, new FileWriter(output, false))
+            } else {
+                def output = new StringWriter()
+
+                template.process(data, output)
+
+                params.output = output.toString()
+            }
+        }
+
+        return params
+    }
+}
diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/org.apache.fineract.gradle.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/org.apache.fineract.gradle.properties
new file mode 100644
index 000000000..acbd85578
--- /dev/null
+++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/org.apache.fineract.gradle.properties
@@ -0,0 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+implementation-class=org.apache.fineract.gradle.FineractPlugin
diff --git a/buildSrc/src/main/resources/confluence/release.html.ftl b/buildSrc/src/main/resources/confluence/release.html.ftl
new file mode 100644
index 000000000..831d57533
--- /dev/null
+++ b/buildSrc/src/main/resources/confluence/release.html.ftl
@@ -0,0 +1,34 @@
+<#--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<h1>Release Artifacts</h1>
+<p>
+  <ac:structured-macro ac:macro-id="ac1cb3cb-84d4-45aa-820b-05cc42d39dd9" ac:name="jira" ac:schema-version="1">
+    <ac:parameter ac:name="server">ASF JIRA</ac:parameter>
+    <ac:parameter ac:name="columnIds">issuekey,summary,issuetype,created,updated,duedate,assignee,reporter,customfield_12311032,customfield_12311037,customfield_12311022,customfield_12311027,priority,status,resolution</ac:parameter>
+    <ac:parameter ac:name="columns">key,summary,type,created,updated,due,assignee,reporter,Priority,Priority,Priority,Priority,priority,status,resolution</ac:parameter>
+    <ac:parameter ac:name="maximumIssues">50</ac:parameter>
+    <ac:parameter ac:name="jqlQuery">project = FINERACT AND fixVersion = ${project['fineract.release.version']} AND status not in (Open) </ac:parameter>
+    <ac:parameter ac:name="serverId">5aa69414-a9e9-3523-82ec-879b028fb15b</ac:parameter>
+  </ac:structured-macro>
+</p>
+<p>
+  <br/>
+</p>
diff --git a/buildSrc/src/main/resources/email/release.step01.headsup.message.ftl b/buildSrc/src/main/resources/email/release.step01.headsup.message.ftl
new file mode 100644
index 000000000..4c10f083a
--- /dev/null
+++ b/buildSrc/src/main/resources/email/release.step01.headsup.message.ftl
@@ -0,0 +1,39 @@
+<#--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+Hello everyone,
+
+... based on our "How to Release Apache Fineract" process documented at https://cwiki.apache.org/confluence/x/DRwIB:
+
+I will create a ${project['fineract.release.version']} branch off develop in our git repository at https://github.com/apache/fineract on ${project['fineract.release.date']}.
+
+The release tracking umbrella issue for tracking all activity in JIRA is FINERACT-${project['fineract.release.issue']!'0000'} (https://issues.apache.org/jira/browse/FINERACT-${project['fineract.release.issue']!'0000'}) for this Fineract ${project['fineract.release.version']}.
+
+If you have any work in progress that you would like to see included in this release, please add "blocking" links to the release JIRA issue.
+
+I am the release manager for this release.
+
+Cheers,
+
+${project['fineract.config.name']}
+
+
+
+πŸŽ‰ Powered by Fineract Release Plugin 🎊
\ No newline at end of file
diff --git a/buildSrc/src/main/resources/email/release.step01.headsup.subject.ftl b/buildSrc/src/main/resources/email/release.step01.headsup.subject.ftl
new file mode 100644
index 000000000..3a1e4751f
--- /dev/null
+++ b/buildSrc/src/main/resources/email/release.step01.headsup.subject.ftl
@@ -0,0 +1,21 @@
+<#--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+[FINERACT] [PROPOSAL] πŸ“¦ New release ${project['fineract.release.version']}
\ No newline at end of file
diff --git a/buildSrc/src/main/resources/email/release.step03.branch.message.ftl b/buildSrc/src/main/resources/email/release.step03.branch.message.ftl
new file mode 100644
index 000000000..0c5665e82
--- /dev/null
+++ b/buildSrc/src/main/resources/email/release.step03.branch.message.ftl
@@ -0,0 +1,35 @@
+<#--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+Hello everyone,
+
+... as previously announced, I've just created the release branch for our upcoming ${project['fineract.release.version']} release.
+
+You can continue working and merging PRs to the develop branch for future releases, as always.
+
+The DRAFT release notes are on https://cwiki.apache.org/confluence/display/FINERACT/${project['fineract.release.version']}+-+Apache+Fineract.  Does anyone see anything missing?
+
+Does anyone have any last minutes changes they would like to see cherry-picked to branch ${project['fineract.release.version']}, or are we good go and actually cut the release based on this branch as it is?
+
+I'll initiate the final stage of actually creating the release on ${project['fineract.release.date']} if nobody objects.
+
+Cheers,
+
+${project['fineract.config.name']}
diff --git a/buildSrc/src/main/resources/email/release.step03.branch.subject.ftl b/buildSrc/src/main/resources/email/release.step03.branch.subject.ftl
new file mode 100644
index 000000000..0a7f333dc
--- /dev/null
+++ b/buildSrc/src/main/resources/email/release.step03.branch.subject.ftl
@@ -0,0 +1,21 @@
+<#--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+[FINERACT] [ANNOUNCE] πŸ”€ ${project['fineract.release.version']} release branch
\ No newline at end of file
diff --git a/buildSrc/src/main/resources/email/release.step10.vote.message.ftl b/buildSrc/src/main/resources/email/release.step10.vote.message.ftl
new file mode 100644
index 000000000..6e6d6dd11
--- /dev/null
+++ b/buildSrc/src/main/resources/email/release.step10.vote.message.ftl
@@ -0,0 +1,43 @@
+<#--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+Hello everyone,
+
+... we have created Apache Fineract ${project['fineract.release.version']} release, with the artifacts below up for a vote.
+
+It fixes the following issues: https://cwiki.apache.org/confluence/display/FINERACT/${project['fineract.release.version']}+-+Apache+Fineract
+
+Source & Binary files : https://dist.apache.org/repos/dist/dev/fineract/${project['fineract.release.version']}/
+
+Tag to be voted on (rc#): https://gitbox.apache.org/repos/asf?p=fineract.git;a=commit;h=refs/heads/${project['fineract.release.version']}
+
+Fineract's KEYS containing the PGP key we used to sign the release: https://dist.apache.org/repos/dist/dev/fineract/KEYS
+
+Note that this release contains source and binary artifacts.
+
+This vote will be open for 72 hours:
+
+[ ] +1 approve
+[ ] +0 no opinion
+[ ] -1 disapprove (and reason why)
+
+Cheers,
+
+${project['fineract.config.name']}
diff --git a/buildSrc/src/main/resources/email/release.step10.vote.subject.ftl b/buildSrc/src/main/resources/email/release.step10.vote.subject.ftl
new file mode 100644
index 000000000..adb471fe4
--- /dev/null
+++ b/buildSrc/src/main/resources/email/release.step10.vote.subject.ftl
@@ -0,0 +1,21 @@
+<#--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+[FINERACT] [VOTE] πŸ—³οΈ ${project['fineract.release.version']} for release
\ No newline at end of file
diff --git a/buildSrc/src/main/resources/email/release.step11.vote.message.ftl b/buildSrc/src/main/resources/email/release.step11.vote.message.ftl
new file mode 100644
index 000000000..232dd67f0
--- /dev/null
+++ b/buildSrc/src/main/resources/email/release.step11.vote.message.ftl
@@ -0,0 +1,89 @@
+<#--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+<#if (project['fineract.vote'].approve.binding?size + project['fineract.vote'].approve.nonBinding?size > project['fineract.vote'].disapprove.binding?size + project['fineract.vote'].disapprove.nonBinding?size)>
+Voting is now closed and has passed with the following tally,
+
+Binding +1s: ${project['fineract.vote'].approve.binding?size}
+Non binding +1s: ${project['fineract.vote'].approve.nonBinding?size}
+<#else>
+Voting is now closed and has not passed with the following tally,
+
+Binding +1s: ${project['fineract.vote'].approve.binding?size}
+Non binding +1s: ${project['fineract.vote'].approve.nonBinding?size}
+
+Binding -1s: ${project['fineract.vote'].disapprove.binding?size}
+Non binding -1s: ${project['fineract.vote'].disapprove.nonBinding?size}
+</#if>
+
+Here are the detailed results:
+
+<#list project['fineract.vote'].approve.binding>
+Binding +1s:
+    <#items as item>
+- ${item.name} (${item.email})
+    </#items>
+</#list>
+
+
+<#list project['fineract.vote'].approve.nonBinding>
+Non binding +1s:
+    <#items as item>
+- ${item.name} (${item.email})
+    </#items>
+</#list>
+
+
+<#list project['fineract.vote'].disapprove.binding>
+Binding -1s:
+    <#items as item>
+- ${item.name} (${item.email})
+    </#items>
+</#list>
+
+<#list project['fineract.vote'].disapprove.nonBinding>
+Non binding -1s:
+    <#items as item>
+- ${item.name} (${item.email})
+    </#items>
+</#list>
+
+
+<#list project['fineract.vote'].noOpinion.binding>
+Binding +0s:
+    <#items as item>
+- ${item.name} (${item.email})
+    </#items>
+</#list>
+
+<#list project['fineract.vote'].noOpinion.nonBinding>
+Non binding +0s:
+    <#items as item>
+- ${item.name} (${item.email})
+    </#items>
+</#list>
+
+<#if (project['fineract.vote'].approve.binding?size + project['fineract.vote'].approve.nonBinding?size > project['fineract.vote'].disapprove.binding?size + project['fineract.vote'].disapprove.nonBinding?size)>
+Thanks to everyone who voted! I'll now continue with the rest of the release process.
+<#else>
+Thanks to everyone who voted! Looks like we have to repeat the vote.
+</#if>
+
+${project['fineract.config.name']}
diff --git a/buildSrc/src/main/resources/email/release.step11.vote.subject.ftl b/buildSrc/src/main/resources/email/release.step11.vote.subject.ftl
new file mode 100644
index 000000000..9dfa8ec5a
--- /dev/null
+++ b/buildSrc/src/main/resources/email/release.step11.vote.subject.ftl
@@ -0,0 +1,21 @@
+<#--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+[FINERACT] [VOTE] [RESULT] 🧾️ ${project['fineract.release.version']} for release
\ No newline at end of file
diff --git a/buildSrc/src/main/resources/email/release.step15.announce.message.ftl b/buildSrc/src/main/resources/email/release.step15.announce.message.ftl
new file mode 100644
index 000000000..f6d4bfb0f
--- /dev/null
+++ b/buildSrc/src/main/resources/email/release.step15.announce.message.ftl
@@ -0,0 +1,43 @@
+<#--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+The Apache Fineract project is pleased to announce
+the release of Apache Fineract ${project['fineract.release.version']}.
+The release is available for download from
+https://fineract.apache.org/#downloads
+
+Fineract provides a reliable, robust, and affordable solution for entrepreneurs,
+financial institutions, and service providers to offer financial services to the
+world’s 2 billion underbanked and unbanked. Fineract is aimed at innovative mobile
+and cloud-based solutions, and enables digital transaction accounts for all.
+
+This release addressed ${project['fineract.release.issues']?size} issues.
+
+Readme: https://github.com/apache/fineract/blob/${project['fineract.release.version']}/README.md
+
+Release page: https://cwiki.apache.org/confluence/display/FINERACT/${project['fineract.release.version']}+-+Apache+Fineract
+
+List of fixed issues:
+https://issues.apache.org/jira/secure/ReleaseNote.jspa?version=${project['fineract.release.versionId']}&styleName=Html&projectId=${project['fineract.release.projectId']}
+
+For more information on Apache Fineract please visit
+project home page: https://fineract.apache.org
+
+The Apache Fineract Team
\ No newline at end of file
diff --git a/buildSrc/src/main/resources/email/release.step15.announce.subject.ftl b/buildSrc/src/main/resources/email/release.step15.announce.subject.ftl
new file mode 100644
index 000000000..2701e86ba
--- /dev/null
+++ b/buildSrc/src/main/resources/email/release.step15.announce.subject.ftl
@@ -0,0 +1,21 @@
+<#--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+[ANNOUNCE] Apache Fineract ${project['fineract.release.version']} Release
\ No newline at end of file
diff --git a/buildSrc/src/main/resources/git/release.step05.tag.message.ftl b/buildSrc/src/main/resources/git/release.step05.tag.message.ftl
new file mode 100644
index 000000000..645090334
--- /dev/null
+++ b/buildSrc/src/main/resources/git/release.step05.tag.message.ftl
@@ -0,0 +1,21 @@
+<#--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+Fineract ${project['fineract.release.version']} release
\ No newline at end of file
diff --git a/buildSrc/src/main/resources/instructions/step13.txt.ftl b/buildSrc/src/main/resources/instructions/step13.txt.ftl
new file mode 100644
index 000000000..64f6ff9bc
--- /dev/null
+++ b/buildSrc/src/main/resources/instructions/step13.txt.ftl
@@ -0,0 +1,38 @@
+<#--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+
+[INSTRUCTIONS:START]
+
+As discussed in https://issues.apache.org/jira/browse/FINERACT-1154, now that everything is final, please do the following to remove the release branch (and just keep the tag),
+and make sure that everything on the release tag is merged to develop and that e.g. git describe works:
+
+>> git checkout develop
+>> git branch -D ${project['fineract.release.version']}
+>> git push origin :${project['fineract.release.version']}
+>> git checkout develop
+>> git checkout -b merge-${project['fineract.release.version']}
+>> git merge -s recursive -Xignore-all-space ${project['fineract.release.version']}
+>> git commit
+>> git push <USER>
+>> hub pull-request
+
+[INSTRUCTIONS:END]
diff --git a/buildSrc/src/main/resources/instructions/step14.txt.ftl b/buildSrc/src/main/resources/instructions/step14.txt.ftl
new file mode 100644
index 000000000..e7e28dd38
--- /dev/null
+++ b/buildSrc/src/main/resources/instructions/step14.txt.ftl
@@ -0,0 +1,28 @@
+<#--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+
+[INSTRUCTIONS:START]
+
+Finally update the https://fineract.apache.org website with the latest release details.
+The website's HTML source code is available at https://github.com/apache/fineract-site.
+
+[INSTRUCTIONS:END]
diff --git a/buildSrc/src/main/resources/instructions/step2.txt.ftl b/buildSrc/src/main/resources/instructions/step2.txt.ftl
new file mode 100644
index 000000000..d75f07618
--- /dev/null
+++ b/buildSrc/src/main/resources/instructions/step2.txt.ftl
@@ -0,0 +1,39 @@
+<#--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+
+[INSTRUCTIONS:START]
+
+Before a release is done, make sure that any issues that are fixed have their fix version setup correctly.
+
+"project = FINERACT and resolution = fixed and fixVersion is empty"
+
+Move all unresolved JIRA issues which have this release as Fix Version to the next release
+
+"project = FINERACT and fixVersion = ${project['fineract.release.version']} and status not in ( Resolved, Done, Accepted, Closed )"
+
+You can also run the following query to make sure that the issues fixed for the to-be-released version look accurate:
+
+"project = FINERACT and fixVersion = ${project['fineract.release.version']}"
+
+Finally, check out the output of the JIRA release note tool to see which tickets are included in the release, in order to do a sanity check.
+
+[INSTRUCTIONS:END]
diff --git a/buildSrc/src/main/resources/instructions/step4.txt.ftl b/buildSrc/src/main/resources/instructions/step4.txt.ftl
new file mode 100644
index 000000000..fd0b8b498
--- /dev/null
+++ b/buildSrc/src/main/resources/instructions/step4.txt.ftl
@@ -0,0 +1,29 @@
+<#--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+
+[INSTRUCTIONS:START]
+
+You first need to close the release in JIRA so that the about to be released version cannot be used as "fixVersion" for new bugs anymore.
+Go to JIRA "Administer project" page and follow "Versions" in left menu. Table with list of all releases should appear, click on additional menu on the right of your release and choose "Release" option.
+Submit release date and you're done.
+
+[INSTRUCTIONS:END]
diff --git a/buildSrc/src/main/resources/instructions/step9.txt.ftl b/buildSrc/src/main/resources/instructions/step9.txt.ftl
new file mode 100644
index 000000000..3b243749b
--- /dev/null
+++ b/buildSrc/src/main/resources/instructions/step9.txt.ftl
@@ -0,0 +1,38 @@
+<#--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+
+[INSTRUCTIONS:START]
+
+Following are the typical things we need to verify before voting on a release candidate. And the release manager should verify them too before calling out a vote.
+
+Make sure release artifacts are hosted at https://dist.apache.org/repos/dist/dev/fineract
+
+* Release candidates should be in format apache-fineract-${project['fineract.release.version']}-binary.tar.gz
+* Verify signatures and hashes. You may have to import the public key of the release manager to verify the signatures. (`gpg --recv-key <key id>`)
+* Git tag matches the released bits (diff -rf)
+* Can compile successfully from source
+* Verify DISCLAIMER, NOTICE and LICENSE (year etc)
+* All files have correct headers (Rat check should be clean - gradlew rat)
+* No jar files in the source artifacts
+* Integration tests should work
+
+[INSTRUCTIONS:END]
diff --git a/buildSrc/src/main/resources/jira/changelog.adoc.ftl b/buildSrc/src/main/resources/jira/changelog.adoc.ftl
new file mode 100644
index 000000000..d6efbd695
--- /dev/null
+++ b/buildSrc/src/main/resources/jira/changelog.adoc.ftl
@@ -0,0 +1,33 @@
+<#--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+= Changelog
+
+== Breaking Changes
+
+<#list issues?filter(i -> i.fields.labels?seq_contains("BreakingChange")) as issue>
+* [[${issue.key}]]${issue.key} - ${issue.fields.summary}
+</#list>
+
+== Issues
+
+<#list issues as issue>
+* [[${issue.key}]]${issue.key} - ${issue.fields.summary}
+</#list>
\ No newline at end of file
diff --git a/buildSrc/src/main/resources/jira/changelog.txt.ftl b/buildSrc/src/main/resources/jira/changelog.txt.ftl
new file mode 100644
index 000000000..3007d4880
--- /dev/null
+++ b/buildSrc/src/main/resources/jira/changelog.txt.ftl
@@ -0,0 +1,26 @@
+<#--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+Changelog
+=========
+
+<#list issues as issue>
+* ${issue.key} - ${issue.fields.summary}
+</#list>
\ No newline at end of file
diff --git a/buildSrc/src/main/resources/vote/result.template.json b/buildSrc/src/main/resources/vote/result.template.json
new file mode 100644
index 000000000..1be0e627a
--- /dev/null
+++ b/buildSrc/src/main/resources/vote/result.template.json
@@ -0,0 +1,22 @@
+{
+  "approve": {
+    "binding": [
+      {
+        "name": "Some Body",
+        "email": "bob@apache.org"
+      }
+    ]
+  },
+  "disapprove": {
+    "binding": [
+    ],
+    "nonBinding": [
+    ]
+  },
+  "noOpinion": {
+    "binding": [
+    ],
+    "nonBinding": [
+    ]
+  }
+}
diff --git a/fineract-client/build.gradle b/fineract-client/build.gradle
index d07c01f02..01d994cc6 100644
--- a/fineract-client/build.gradle
+++ b/fineract-client/build.gradle
@@ -87,12 +87,27 @@ task buildTypescriptAngularSdk(type: org.openapitools.generator.gradle.plugin.ta
     ]
 }
 
-licenseFormatMain.dependsOn buildJavaSdk
-licenseFormatMain.dependsOn buildTypescriptAngularSdk
-compileJava.dependsOn licenseFormatMain
+task buildAsciidoc(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask){
+    generatorName = 'asciidoc'
+    verbose = false
+    validateSpec = false
+    skipValidateSpec = true
+    inputSpec = "file:///$swaggerFile"
+    outputDir = "$buildDir/generated/asciidoc".toString()
+    apiPackage = 'org.apache.fineract.client.services'
+    invokerPackage = 'org.apache.fineract.client'
+    modelPackage = 'org.apache.fineract.client.models'
+    dependsOn = [
+        ':fineract-provider:resolve'
+    ]
+}
 
 // TODO: @vidakovic we could provide even more client libs in different languages (Go, Ruby, Swift etc.)
-compileJava.dependsOn buildJavaSdk, buildTypescriptAngularSdk, spotlessMiscApply
+licenseMain.dependsOn(buildJavaSdk, licenseFormatMain, spotlessMiscApply)
+licenseMain.dependsOn(buildTypescriptAngularSdk, licenseFormatMain, spotlessMiscApply)
+licenseMain.dependsOn(buildAsciidoc, licenseFormatMain, spotlessMiscApply)
+
+compileJava.dependsOn(licenseFormatMain, spotlessMiscApply)
 
 java {
     // keep this at Java 8, not 17; see https://issues.apache.org/jira/browse/FINERACT-1214
diff --git a/fineract-doc/.asciidoctorconfig b/fineract-doc/.asciidoctorconfig
index 5b1ed1d8f..26a82e248 100644
--- a/fineract-doc/.asciidoctorconfig
+++ b/fineract-doc/.asciidoctorconfig
@@ -1,5 +1,8 @@
 :years: 2015-2022
-:revnumber: 1.0.0
+:revnumber: 1.7.0
 :draft: true
-:rootdir: ../../../..
-:generated: ../../../build/generated/asciidoc
\ No newline at end of file
+:rootdir: {asciidoctorconfigdir}/..
+:generated: {asciidoctorconfigdir}/build/generated/asciidoc
+:diagramsdir: {asciidoctorconfigdir}/src/docs/en/diagrams
+:imagesdir: {asciidoctorconfigdir}/src/docs/en/images
+:icons: font
diff --git a/fineract-doc/build.gradle b/fineract-doc/build.gradle
index a426e3c2d..8d5d6219a 100644
--- a/fineract-doc/build.gradle
+++ b/fineract-doc/build.gradle
@@ -26,14 +26,14 @@ asciidoctorj {
     version = '2.5.3'
 
     attributes = [
-        version: "$project.version",
+        version: "${project.version}",
         generated: "${buildDir}/generated/asciidoc",
-        imagesdir: 'images',
-        diagrams: 'diagrams',
+        imagesdir: "${projectDir}/src/docs/en/images",
+        diagramsdir: "${projectDir}/src/docs/en/diagrams",
         years: '2015-2022',
-        revnumber: "$project.version".toString(),
-        rootdir: "$rootDir".toString(),
-        baseurl: 'fineract.apache.org'
+        revnumber: "${project.version}".toString(),
+        rootdir: "${rootDir}".toString(),
+        baseurl: 'fineract.apache.org',
     ]
 
     modules {
@@ -56,6 +56,8 @@ asciidoctor {
         include('index.adoc')
     }
     outputDir 'build/docs/html'
+
+    dependsOn ':fineract-client:buildAsciidoc'
 }
 
 // asciidoctorEpub {
@@ -68,6 +70,8 @@ asciidoctor {
 //     }
 //     outputDir 'build/docs/epub'
 //     ebookFormats 'epub3'
+//
+//     dependsOn ':fineract-client:buildAsciidoc'
 // }
 
 asciidoctorPdf {
@@ -88,21 +92,26 @@ asciidoctorPdf {
     //     }
     // }
     // fontsDir "$projectDir/src/resources/fonts"
+    dependsOn ':fineract-client:buildAsciidoc'
 }
 
 task doc(type: Zip) {
     dependsOn asciidoctor, asciidoctorPdf
 
-    into("$project.name-$project.version") {
+    into("fineract-${project.version}/html") {
         from("$buildDir/docs/html") {
             include "**/*"
+            exclude "**/.asciidoctor"
         }
     }
-    from ("$buildDir/docs/pdf") {
-        include "index.pdf"
-        rename {
-            "$project.name-$project.version\\.pdf"
+    into("fineract-${project.version}/pdf") {
+        from("$buildDir/docs/pdf") {
+            include "**/index.pdf"
+            exclude "**/.asciidoctor"
+            rename {
+                "fineract-${project.version}.pdf"
+            }
         }
     }
-    archiveName "$project.name-$project.version\\.zip"
+    archiveName "${project.name}-${project.version}.zip"
 }
diff --git a/fineract-doc/src/docs/en/appendix.adoc b/fineract-doc/src/docs/en/appendix.adoc
deleted file mode 100644
index d2dbbad95..000000000
--- a/fineract-doc/src/docs/en/appendix.adoc
+++ /dev/null
@@ -1 +0,0 @@
-[appendix]
diff --git a/fineract-doc/src/docs/en/architecture.adoc b/fineract-doc/src/docs/en/architecture.adoc
deleted file mode 100644
index 3fc1afad7..000000000
--- a/fineract-doc/src/docs/en/architecture.adoc
+++ /dev/null
@@ -1,272 +0,0 @@
-== Fineract Platform Software Architecture Document
-
-=== Summary
-
-This document captures the major architectural decisions in platform. The purpose of the document is to provide a guide to the overall structure of the platform; where it fits in the overall context of an MIS solution and its internals so that contributors can more effectively understand how changes that they are considering can be made, and the consequences of those changes.
-
-The target audience for this report is both system integrators (who will use the document to gain an understanding of the structure of the platform and its design rationale) and platform contributors who will use the document to reason about future changes and who will update the document as the system evolves.
-
-=== Introduction
-
-==== The Idea
-
-Fineract was an idea born out of a wish to create and deploy technology that allows the microfinance industry to scale. The goal is to:
-
-- Produce a gold standard management information system suitable for microfinance operations
-- Acts as the basis of a platform for microfinance
-- Open source, owned and driven by member organisations in the community
-- Enabling potential for eco-system of providers located near to MFIs
-
-==== History
-
-- 2006: Project intiated by Grameen Foundation
-- Late 2011: Grameen Foundation handed over full responsibility to open source community.
-- 2012: Mifos X platform started. Previous members of project come together under the name of Community for Open Source Microfinance (COSM / OpenMF)
-- 2013: COSM / OpenMF officially rebranded to Mifos Initiative and receive US 501c3 status.
-- 2016: Fineract 1.x began incubation at Apache
-
-==== Project Related
-
-- Project url is https://github.com/apache/fineract
-- Issue tracker is https://issues.apache.org/jira/projects/FINERACT/summary
-- Download from http://fineract.apache.org/
-
-=== System Overview
-
-.Platform System Overview
-image::platform-systemview.png[]
-
-Financial institutions deliver their services to customers through a variety of means today.
-
-- Customers can call direct into branches (teller model)
-- Customers can organise into groups (or centers) and agree to meetup at a location and time with FI staff (traditional microfinance).
-- An FI might have a public facing information portal that customers can use for variety of reasons including account management (online banking).
-- An FI might be integrated into a ATM/POS/Card services network that the customer can use.
-- An FI might be integrated with a mobile money operator and support mobile money services for customer (present/future microfinance).
-- An FI might use third party agents to sell on products/services from other banks/FIs.
-
-As illustrated in the above diagram, the various stakeholders leverage business apps to perform specific customer or FI related actions. The functionality contained in these business apps can be bundled up and packaged in any way. In the diagram, several of the apps may be combined into one app or any one of the blocks representing an app could be further broken up as needed.
-
-The platform is the core engine of the MIS. It hides alot of the complexity that exists in the business and technical domains needed for an MIS in FIs behind a relatively simple API. It is this API that frees up app developers to innovate and produce apps that can be as general or as bespoke as FIs need them to be.
-
-=== Functional Overview
-
-As ALL capabilities of the platform are exposed through an API, The API docs are the best place to view a detailed breakdown of what the platform does. See online API Documentation.
-
-.Platform Functional Overview
-image::platform-categories.png[]
-
-At a higher level though we see the capabilities fall into the following categories:
-
-* Infrastructure
-** Codes
-** Extensible Data Tables
-** Reporting
-
-* User Administration
-** Users
-** Roles
-** Permissions
-
-* Organisation Modelling
-** Offices
-** Staff
-** Currency
-
-* Product Configuration
-** Charges
-** Loan Products
-** Deposit Products
-
-* Client Data
-** Know Your Client (KYC)
-
-* Portfolio Management
-** Loan Accounts
-** Deposit Accounts
-** Client/Groups
-
-* GL Account Management
-** Chart of Accounts
-** General Ledger
-
-=== Technology
-
-* Java: http://www.oracle.com/technetwork/java/javase/downloads/index.html
-* JAX-RS using Jersey 
-* JSON using Google GSON
-* Spring I/O Platform: http://spring.io/platform
-** Spring Framework
-** Spring Boot
-** Spring Security
-** Spring Data (JPA) backed by EclipseLink
-* MySQL: http://www.oracle.com/us/products/mysql/overview/index.html
-* PostgreSQL
-
-=== Principles
-
-==== RESTful API
-
-The platform exposes all its functionality via a *practically-RESTful API*, that communicates using JSON.
-
-We use the term *practically-RESTful* in order to make it clear we are not trying to be fully REST compliant but still maintain important RESTful attributes like:
-
-* Stateless: platform maintains no conversational or session-based state. The result of this is ability to scale horizontally with ease.
-* Resource-oriented: API is focussed around set of resources using HTTP vocabulary and conventions e.g GET, PUT, POST, DELETE, HTTP status codes. This results in a simple and consistent API for clients.
-
-See online API Documentation for more detail.
-
-==== Multi-tenanted
-
-The Fineract platform has been developed with support for multi-tenancy at the core of its design. This means that it is just as easy to use the platform for Software-as-a-Service (SaaS) type offerings as it is for local installations.
-
-The platform uses an approach that isolates an FIs data per database/schema (See Separate Databases and Shared Database, Separate Schemas).
-
-==== Extensible
-
-Whilst each tenant will have a set of core tables, the platform tables can be extended in different ways for each tenant through the use of Data tables functionality.
-
-==== Command Query Seperation
-
-We seperate *commands* (that change data) from *queries* (that read data).
-
-Why? There are numerous reasons for choosing this approach which at present is not an attempt at full blown CQRS. The main advantages at present are:
-
-* State changing commands are persisted providing an audit of all state changes.
-* Used to support a general approach to *maker-checker*.
-* State changing commands use the Object-Oriented paradign (and hence ORM) whilst querys can stay in the data paradigm.
-
-==== Maker-Checker
-
-Also known as *four-eyes principal*. Enables apps to support a maker-checker style workflow process. Commands that pass validation will be persisted. Maker-checker can be enabled/disabled at fine-grained level for any state changing API.
-Fine grained access control
-
-A fine grained permission is associated with each API. Administrators have fine grained control over what roles or users have access to.
-
-=== Code Packaging
-
-The intention is for platform code to be packaged in a vertical slice way (as opposed to layers).
-Source code starts from https://github.com/apache/fineract/tree/develop/fineract-provider/src/main/java/org/apache/fineract
-
-* accounting
-* useradministration
-* infrastructure
-* portfolio
-** charge
-** client
-** fund
-** loanaccount
-* accounting
-
-Within each vertical slice is some common packaging structure:
-
-* api - XXXApiResource.java - REST api implementation files
-* handler - XXXCommandHandler.java - specific handlers invoked
-* service - contains read + write services for functional area
-* domain - OO concepts for the functional area
-* data - Data concepts for the area
-* serialization - ability to convert from/to API JSON for functional area
-
-=== Design Overview
-
-NOTE: The implementation of the platform code to process commands through handlers whilst supporting maker-checker and authorisation checks is a little bit convoluted at present and is an area pin-pointed for clean up to make it easier to on board new platform developers. In the mean time below content is used to explain its workings at present.
-
-.CQRS
-image::command-query.png[]
-
-Taking into account example shown above for the *users* resource.
-
-* Query: GET /users
-* HTTPS API: retrieveAll method on *org.apache.fineract.useradministration.api.UsersApiResource* invoked
-* UsersApiResource.retrieveAll: Check user has permission to access this resources data.
-* UsersApiResource.retrieveAll: Use 'read service' to fetch all users data ('read services' execute simple SQL queries against Database using JDBC)
-* UsersApiResource.retrieveAll: Data returned to coverted into JSON response
-* Command: POST /users (Note: data passed in request body)
-* HTTPS API: create method on org.apache.fineract.useradministration.api.UsersApiResource invoked
-
-.UsersApiResource.create
-[source,java]
-----
-include::{rootdir}/fineract-provider/src/main/java/org/apache/fineract/useradministration/api/UsersApiResource.java[lines=168..188]
-----
-
-.Create a CommandWrapper object that represents this create user command and JSON request body. Pass off responsiblity for processing to PortfolioCommandSourceWritePlatformService.logCommandSource
-[source,java]
-----
-include::{rootdir}/fineract-provider/src/main/java/org/apache/fineract/commands/service/PortfolioCommandSourceWritePlatformServiceImpl.java[lines=69..129]
-----
-
-.Check user has permission for this action. if ok, a) parse the json request body, b) create a JsonCommand object to wrap the command details, c) use CommandProcessingService to handle command
-[source,java]
-----
-include::{rootdir}/fineract-provider/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java[lines=84..150]
-----
-
-NOTE: if a RollbackTransactionAsCommandIsNotApprovedByCheckerException occurs at this point. The original transaction will of been aborted and we only log an entry for the command in the audit table setting its status as 'Pending'.
-
-* Check that if maker-checker configuration enabled for this action. If yes and this is not a 'checker' approving the command - rollback at the end. We rollback at the end in order to test if the command will pass 'domain validation' which requires commit to database for full check.
-* findCommandHandler - Find the correct Hanlder to process this command.
-* Process command using handler (In transactional scope).
-* CommandSource object created/updated with all details for logging to 'm_portfolio_command_source' table.
-* In update scenario, we check to see if there where really any changes/updates. If so only JSON for changes is stored in audit log.
-
-=== Database support
-
-Fineract supports multiple databases:
-
-* MySQL compatible databases (e.g. MariaDB)
-* PostgreSQL
-
-The platform differentiates between these database types in certain cases when there's a need to use some database specific tooling. To do so, the platform examines the JDBC driver used for running the platform and tries to determine which database is being used.
-
-The currently supported JDBC driver and corresponding mappings can be found below.
-
-[cols="1,1"]
-|===
-|*JDBC driver class name*
-|*Resolved database type*
-
-|`org.mariadb.jdbc.Driver`
-|MySQL
-
-|`com.mysql.jdbc.Driver`
-|MySQL
-
-|`org.postgresql.Driver`
-|PostgreSQL
-
-|===
-
-The actual code can be found in the `DatabaseTypeResolver` class.
-
-=== Data-access layer
-
-The data-access layer of Fineract is implemented by using JPA (Java Persistence API) with the EclipseLink provider.
-Despite the fact that JPA is used quite extensively in the system, there are cases where the performance is a key element for an operation therefore you can easily find native SQLs as well.
-
-The data-access layer of Fineract is compatible with different databases. Since a lot of the native queries are using specific database functions, a wrapper class - `DatabaseSpecificSQLGenerator` -  has been introduced to handle these database specifics. Whenever there's a need to rely on new database level functions, make sure to extend this class and implement the specific functions provided by the database.
-
-Fineract has been developed for 10+ years by the community and unfortunately there are places where entity relationships are configured with `EAGER` fetching strategy. This must not confuse anybody. The long-term goal is to use the `LAZY` fetching strategy for every single relationship. If you're about to introduce a new one, make sure to use `LAZY` as a fetching strategy, otherwise your PR will be rejected.
-
-=== Database schema migration
-
-As for every system, the database structure will and need to evolve over time. Fineract is no different. Originally for Fineract, Flyway was used until Fineract 1.6.x.
-
-After 1.6.x, PostgreSQL support was added to the platform hence there was a need to make the data-access layer and the schema migration as database independent as possible. Becuase of that, from Fineract 1.7.0, Flyway is not used anymore but Liquibase is.
-
-Some of the changesets in the Liquibase changelogs have database specifics into it but they only run for the relevant databases. This is controller by Liquibase contexts.
-
-The currently available Liquibase contexts are:
-
-* `mysql` - only set when the database is a MySQL compatible database (e.g. MariaDB)
-* `postgresql` - only set when the database is a PostgreSQL database
-* configured Spring active profiles
-* `tenant_store_db` - only set when the database migration runs the Tenant Store upgrade
-* `tenant_db` - only set when the database migration runs the Tenant upgrade
-* `initial_switch` - this is a technical context and should *NOT* be used
-
-The switch from Flyway (1.6.x) to Liquibase (1.7.x) was planned to be as smooth as possible so there's no need for manual work hence the behavior is described as following:
-
-* If the database is empty, Liquibase will create the database schema from scratch
-* If the database contains the latest Fineract 1.6.x database structure which was previously migrated with Flyway. Liquibase will seamlessly upgrade it to the latest version. Note: the Flyway related 2 database tables are left as they are and are not deleted.
-* If the database contains an earlier version of the database structure than Fineract 1.6.x. Liquibase will *NOT* do anything and *will fail the application during startup*. The proper approach in this case is to first upgrade your application version to the latest Fineract 1.6.x so that the latest Flyway changes are executed and then upgrade to the newer Fineract version where Liquibase will seamlessly take over the database upgrades.
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/chapters/appendix/index.adoc b/fineract-doc/src/docs/en/chapters/appendix/index.adoc
new file mode 100644
index 000000000..5075ee98a
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/appendix/index.adoc
@@ -0,0 +1,5 @@
+// NOTE: no section title needed here!
+
+include::properties.adoc[leveloffset=+1]
+
+include::software.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/chapters/appendix/properties-authentication.adoc b/fineract-doc/src/docs/en/chapters/appendix/properties-authentication.adoc
new file mode 100644
index 000000000..0f3987b57
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/appendix/properties-authentication.adoc
@@ -0,0 +1,22 @@
+= Authentication Properties
+
+.Authentication Properties
+|===
+|Name |Env Variable |Default Value |Description
+
+|fineract.security.basicauth.enabled
+|FINERACT_SECURITY_BASICAUTH_ENABLED
+|true
+|TBD
+
+|fineract.security.oauth.enabled
+|FINERACT_SECURITY_OAUTH_ENABLED
+|false
+|TBD
+
+|fineract.security.2fa.enabled
+|FINERACT_SECURITY_2FA_ENABLED
+|false
+|TBD
+|===
+
diff --git a/fineract-doc/src/docs/en/chapters/appendix/properties-cache.adoc b/fineract-doc/src/docs/en/chapters/appendix/properties-cache.adoc
new file mode 100644
index 000000000..e1f31396e
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/appendix/properties-cache.adoc
@@ -0,0 +1,16 @@
+= Cache Properties
+
+.Cache Properties
+|===
+|Name |Env Variable |Default Value |Description
+
+|Column 1, row 1
+|Column 2, row 1
+|Column 3, row 1
+|TBD
+
+|Column 1, row 2
+|Column 2, row 2
+|Column 3, row 2
+|TBD
+|===
diff --git a/fineract-doc/src/docs/en/chapters/appendix/properties-database.adoc b/fineract-doc/src/docs/en/chapters/appendix/properties-database.adoc
new file mode 100644
index 000000000..cb3ce2bc6
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/appendix/properties-database.adoc
@@ -0,0 +1,51 @@
+= Tenant Database Properties
+
+.Tenant Database Properties
+|===
+|Name |Env Variable |Default Value |Description
+
+|fineract.tenant.host
+|FINERACT_DEFAULT_TENANTDB_HOSTNAME
+|localhost
+|TBD
+
+|fineract.tenant.port
+|FINERACT_DEFAULT_TENANTDB_PORT
+|3306
+|TBD
+
+|fineract.tenant.username
+|FINERACT_DEFAULT_TENANTDB_UID
+|root
+|TBD
+
+|fineract.tenant.password
+|FINERACT_DEFAULT_TENANTDB_PWD
+|mysql
+|TBD
+
+|fineract.tenant.parameters
+|FINERACT_DEFAULT_TENANTDB_CONN_PARAMS
+|
+|TBD
+
+|fineract.tenant.timezone
+|FINERACT_DEFAULT_TENANTDB_TIMEZONE
+|Asia/Kolkata
+|TBD
+
+|fineract.tenant.identifier
+|FINERACT_DEFAULT_TENANTDB_IDENTIFIER
+|default
+|TBD
+
+|fineract.tenant.name
+|FINERACT_DEFAULT_TENANTDB_NAME
+|fineract_default
+|TBD
+
+|fineract.tenant.description
+|FINERACT_DEFAULT_TENANTDB_DESCRIPTION
+|Default Demo Tenant
+|TBD
+|===
diff --git a/fineract-doc/src/docs/en/chapters/appendix/properties-pool.adoc b/fineract-doc/src/docs/en/chapters/appendix/properties-pool.adoc
new file mode 100644
index 000000000..04ec342a3
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/appendix/properties-pool.adoc
@@ -0,0 +1,116 @@
+= Hikari Connection Pool Properties
+
+.Hikari Connection Pool Properties
+|===
+|Name |Env Variable |Default Value |Description
+
+|spring.datasource.hikari.driverClassName
+|FINERACT_HIKARI_DRIVER_SOURCE_CLASS_NAME
+|org.mariadb.jdbc.Driver
+|TBD
+
+|spring.datasource.hikari.jdbcUrl
+|FINERACT_HIKARI_JDBC_URL
+|jdbc:mariadb://localhost:3306/fineract_tenants
+|TBD
+
+|spring.datasource.hikari.username
+|FINERACT_HIKARI_USERNAME
+|root
+|TBD
+
+|spring.datasource.hikari.password
+|FINERACT_HIKARI_PASSWORD
+|mysql
+|TBD
+
+|spring.datasource.hikari.minimumIdle
+|FINERACT_HIKARI_MINIMUM_IDLE
+|3
+|TBD
+
+|spring.datasource.hikari.maximumPoolSize
+|FINERACT_HIKARI_MAXIMUM_POOL_SIZE
+|10
+|TBD
+
+|spring.datasource.hikari.idleTimeout
+|FINERACT_HIKARI_IDLE_TIMEOUT
+|60000
+|TBD
+
+|spring.datasource.hikari.connectionTimeout
+|FINERACT_HIKARI_CONNECTION_TIMEOUT
+|20000
+|TBD
+
+|spring.datasource.hikari.connectionTestquery
+|FINERACT_HIKARI_TEST_QUERY
+|SELECT 1
+|TBD
+
+|spring.datasource.hikari.autoCommit
+|FINERACT_HIKARI_AUTO_COMMIT
+|true
+|TBD
+
+|spring.datasource.hikari.dataSourceProperties['cachePrepStmts']
+|FINERACT_HIKARI_DS_PROPERTIES_CACHE_PREP_STMTS
+|true
+|TBD
+
+|spring.datasource.hikari.dataSourceProperties['prepStmtCacheSize']
+|FINERACT_HIKARI_DS_PROPERTIES_PREP_STMT_CACHE_SIZE
+|250
+|TBD
+
+|spring.datasource.hikari.dataSourceProperties['prepStmtCacheSqlLimit']
+|FINERACT_HIKARI_DS_PROPERTIES_PREP_STMT_CACHE_SQL_LIMIT
+|2048
+|TBD
+
+|spring.datasource.hikari.dataSourceProperties['useServerPrepStmts']
+|FINERACT_HIKARI_DS_PROPERTIES_USE_SERVER_PREP_STMTS
+|true
+|TBD
+
+|spring.datasource.hikari.dataSourceProperties['useLocalSessionState']
+|FINERACT_HIKARI_DS_PROPERTIES_USE_LOCAL_SESSION_STATE
+|true
+|TBD
+
+|spring.datasource.hikari.dataSourceProperties['rewriteBatchedStatements']
+|FINERACT_HIKARI_DS_PROPERTIES_REWRITE_BATCHED_STATEMENTS
+|true
+|TBD
+
+|spring.datasource.hikari.dataSourceProperties['cacheResultSetMetadata']
+|FINERACT_HIKARI_DS_PROPERTIES_CACHE_RESULT_SET_METADATA
+|true
+|TBD
+
+|spring.datasource.hikari.dataSourceProperties['cacheServerConfiguration']
+|FINERACT_HIKARI_DS_PROPERTIES_CACHE_SERVER_CONFIGURATION
+|true
+|TBD
+
+|spring.datasource.hikari.dataSourceProperties['elideSetAutoCommits']
+|FINERACT_HIKARI_DS_PROPERTIES_ELIDE_SET_AUTO_COMMITS
+|true
+|TBD
+
+|spring.datasource.hikari.dataSourceProperties['maintainTimeStats']
+|FINERACT_HIKARI_DS_PROPERTIES_MAINTAIN_TIME_STATS
+|false
+|TBD
+
+|spring.datasource.hikari.dataSourceProperties['logSlowQueries']
+|FINERACT_HIKARI_DS_PROPERTIES_LOG_SLOW_QUERIES
+|true
+|TBD
+
+|spring.datasource.hikari.dataSourceProperties['dumpQueriesOnException']
+|FINERACT_HIKARI_DS_PROPERTIES_DUMP_QUERIES_IN_EXCEPTION
+|true
+|TBD
+|===
diff --git a/fineract-doc/src/docs/en/chapters/appendix/properties-ssl.adoc b/fineract-doc/src/docs/en/chapters/appendix/properties-ssl.adoc
new file mode 100644
index 000000000..c5c102ef0
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/appendix/properties-ssl.adoc
@@ -0,0 +1,36 @@
+= SSL Properties
+
+.SSL Properties
+|===
+|Name |Env Variable |Default Value |Description
+
+|server.ssl.enabled
+|FINERACT_SERVER_SSL_ENABLED
+|true
+|TBD
+
+|server.ssl.protocol
+|FINERACT_SERVER_SSL_PROTOCOL
+|TLS
+|TBD
+
+|server.ssl.ciphers
+|FINERACT_SERVER_SSL_CIPHERS
+|TLS_RSA_WITH_AES_128_CBC_SHA256
+|TBD
+
+|server.ssl.enabled-protocols
+|FINERACT_SERVER_SSL_PROTOCOLS
+|TLSv1.2
+|TBD
+
+|server.ssl.key-store
+|FINERACT_SERVER_SSL_KEY_STORE
+|classpath:keystore.jks
+|TBD
+
+|server.ssl.key-store-password
+|FINERACT_SERVER_SSL_KEY_STORE_PASSWORD
+|openmf
+|TBD
+|===
diff --git a/fineract-doc/src/docs/en/chapters/appendix/properties-tomcat.adoc b/fineract-doc/src/docs/en/chapters/appendix/properties-tomcat.adoc
new file mode 100644
index 000000000..6804e24f3
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/appendix/properties-tomcat.adoc
@@ -0,0 +1,42 @@
+= Tomcat Properties
+
+.Tomcat Properties
+|===
+|Name |Env Variable |Default Value |Description
+
+|server.tomcat.accept-count
+|FINERACT_SERVER_TOMCAT_ACCEPT_COUNT
+|100
+|TBD
+
+|server.tomcat.accesslog.enabled
+|FINERACT_SERVER_TOMCAT_ACCESSLOG_ENABLED
+|false
+|TBD
+
+|server.tomcat.max-connections
+|FINERACT_SERVER_TOMCAT_MAX_CONNECTIONS
+|8192
+|TBD
+
+|server.tomcat.max-http-form-post-size
+|FINERACT_SERVER_TOMCAT_MAX_HTTP_FORM_POST_SIZE
+|2MB
+|TBD
+
+|server.tomcat.max-keep-alive-requests
+|FINERACT_SERVER_TOMCAT_MAX_KEEP_ALIVE_REQUESTS
+|100
+|TBD
+
+|server.tomcat.threads.max
+|FINERACT_SERVER_TOMCAT_THREADS_MAX
+|200
+|TBD
+
+|server.tomcat.threads.min-spare
+|FINERACT_SERVER_TOMCAT_THREADS_MIN_SPARE
+|10
+|TBD
+|===
+
diff --git a/fineract-doc/src/docs/en/chapters/appendix/properties.adoc b/fineract-doc/src/docs/en/chapters/appendix/properties.adoc
new file mode 100644
index 000000000..928de87cb
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/appendix/properties.adoc
@@ -0,0 +1,16 @@
+[appendix]
+= Fineract Application Properties
+
+TBD
+
+include::properties-database.adoc[leveloffset=+1]
+
+include::properties-pool.adoc[leveloffset=+1]
+
+include::properties-ssl.adoc[leveloffset=+1]
+
+include::properties-authentication.adoc[leveloffset=+1]
+
+include::properties-tomcat.adoc[leveloffset=+1]
+
+// include::properties-cache.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/chapters/appendix/software.adoc b/fineract-doc/src/docs/en/chapters/appendix/software.adoc
new file mode 100644
index 000000000..1e4d8f702
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/appendix/software.adoc
@@ -0,0 +1,4 @@
+[appendix]
+= Third Party Software
+
+TBD
diff --git a/fineract-doc/src/docs/en/chapters/architecture/design.adoc b/fineract-doc/src/docs/en/chapters/architecture/design.adoc
new file mode 100644
index 000000000..ce68dc22c
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/architecture/design.adoc
@@ -0,0 +1,42 @@
+= Design Overview
+
+NOTE: The implementation of the platform code to process commands through handlers whilst supporting maker-checker and authorisation checks is a little bit convoluted at present and is an area pin-pointed for clean up to make it easier to on board new platform developers. In the mean time below content is used to explain its workings at present.
+
+.CQRS
+image::{imagesdir}/command-query.png[]
+
+Taking into account example shown above for the *users* resource.
+
+* Query: GET /users
+* HTTPS API: retrieveAll method on *org.apache.fineract.useradministration.api.UsersApiResource* invoked
+* UsersApiResource.retrieveAll: Check user has permission to access this resources data.
+* UsersApiResource.retrieveAll: Use 'read service' to fetch all users data ('read services' execute simple SQL queries against Database using JDBC)
+* UsersApiResource.retrieveAll: Data returned to coverted into JSON response
+* Command: POST /users (Note: data passed in request body)
+* HTTPS API: create method on org.apache.fineract.useradministration.api.UsersApiResource invoked
+
+.UsersApiResource.create
+[source,java]
+----
+include::{rootdir}/fineract-provider/src/main/java/org/apache/fineract/useradministration/api/UsersApiResource.java[lines=168..188]
+----
+
+.Create a CommandWrapper object that represents this create user command and JSON request body. Pass off responsiblity for processing to PortfolioCommandSourceWritePlatformService.logCommandSource
+[source,java]
+----
+include::{rootdir}/fineract-provider/src/main/java/org/apache/fineract/commands/service/PortfolioCommandSourceWritePlatformServiceImpl.java[lines=69..129]
+----
+
+.Check user has permission for this action. if ok, a) parse the json request body, b) create a JsonCommand object to wrap the command details, c) use CommandProcessingService to handle command
+[source,java]
+----
+include::{rootdir}/fineract-provider/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java[lines=84..150]
+----
+
+NOTE: if a RollbackTransactionAsCommandIsNotApprovedByCheckerException occurs at this point. The original transaction will of been aborted and we only log an entry for the command in the audit table setting its status as 'Pending'.
+
+* Check that if maker-checker configuration enabled for this action. If yes and this is not a 'checker' approving the command - rollback at the end. We rollback at the end in order to test if the command will pass 'domain validation' which requires commit to database for full check.
+* findCommandHandler - Find the correct Hanlder to process this command.
+* Process command using handler (In transactional scope).
+* CommandSource object created/updated with all details for logging to 'm_portfolio_command_source' table.
+* In update scenario, we check to see if there where really any changes/updates. If so only JSON for changes is stored in audit log.
diff --git a/fineract-doc/src/docs/en/chapters/architecture/functional.adoc b/fineract-doc/src/docs/en/chapters/architecture/functional.adoc
new file mode 100644
index 000000000..b99440524
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/architecture/functional.adoc
@@ -0,0 +1,41 @@
+= Functional Overview
+
+As ALL capabilities of the platform are exposed through an API, The API docs are the best place to view a detailed breakdown of what the platform does. See online API Documentation.
+
+.Platform Functional Overview
+image::{imagesdir}/platform-categories.png[]
+
+At a higher level though we see the capabilities fall into the following categories:
+
+* Infrastructure
+** Codes
+** Extensible Data Tables
+** Reporting
+
+* User Administration
+** Users
+** Roles
+** Permissions
+
+* Organisation Modelling
+** Offices
+** Staff
+** Currency
+
+* Product Configuration
+** Charges
+** Loan Products
+** Deposit Products
+
+* Client Data
+** Know Your Client (KYC)
+
+* Portfolio Management
+** Loan Accounts
+** Deposit Accounts
+** Client/Groups
+
+* GL Account Management
+** Chart of Accounts
+** General Ledger
+
diff --git a/fineract-doc/src/docs/en/chapters/architecture/history.adoc b/fineract-doc/src/docs/en/chapters/architecture/history.adoc
new file mode 100644
index 000000000..a1b922164
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/architecture/history.adoc
@@ -0,0 +1,18 @@
+= History
+
+== The Idea
+
+Fineract was an idea born out of a wish to create and deploy technology that allows the microfinance industry to scale. The goal is to:
+
+* Produce a gold standard management information system suitable for microfinance operations
+* Acts as the basis of a platform for microfinance
+* Open source, owned and driven by member organisations in the community
+* Enabling potential for eco-system of providers located near to MFIs
+
+== Timeline
+
+* 2006: Project intiated by Grameen Foundation
+* Late 2011: Grameen Foundation handed over full responsibility to open source community.
+* 2012: Mifos X platform started. Previous members of project come together under the name of Community for Open Source Microfinance (COSM / OpenMF)
+* 2013: COSM / OpenMF officially rebranded to Mifos Initiative and receive US 501c3 status.
+* 2016: Fineract 1.x began incubation at Apache
diff --git a/fineract-doc/src/docs/en/chapters/architecture/index.adoc b/fineract-doc/src/docs/en/chapters/architecture/index.adoc
new file mode 100644
index 000000000..4a847478d
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/architecture/index.adoc
@@ -0,0 +1,25 @@
+= Architecture
+
+This document captures the major architectural decisions in platform. The purpose of the document is to provide a guide to the overall structure of the platform; where it fits in the overall context of an MIS solution and its internals so that contributors can more effectively understand how changes that they are considering can be made, and the consequences of those changes.
+
+The target audience for this report is both system integrators (who will use the document to gain an understanding of the structure of the platform and its design rationale) and platform contributors who will use the document to reason about future changes and who will update the document as the system evolves.
+
+include::history.adoc[leveloffset=+1]
+
+include::resources.adoc[leveloffset=+1]
+
+include::system.adoc[leveloffset=+1]
+
+include::functional.adoc[leveloffset=+1]
+
+include::principles.adoc[leveloffset=+1]
+
+include::design.adoc[leveloffset=+1]
+
+include::persistence.adoc[leveloffset=+1]
+
+include::validation.adoc[leveloffset=+1]
+
+include::technology.adoc[leveloffset=+1]
+
+include::modules.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/modules.adoc b/fineract-doc/src/docs/en/chapters/architecture/modules.adoc
similarity index 95%
rename from fineract-doc/src/docs/en/modules.adoc
rename to fineract-doc/src/docs/en/chapters/architecture/modules.adoc
index f96fc7d8d..d6fba1c28 100644
--- a/fineract-doc/src/docs/en/modules.adoc
+++ b/fineract-doc/src/docs/en/chapters/architecture/modules.adoc
@@ -1,8 +1,8 @@
-== Modules
+= Modules
 
 Currently modules are a proof of concept feature in Fineract.
 
-=== How to create a Fineract module
+== How to create a Fineract module
 
 NOTE: At the moment the only module we have that follows these stricter guidelines is the example module we describe in detail in the next section. In the future we will try to split up Fineract's monolithic code base and move features (like loan product, accounts etc.) to separate modules as described here. Before that happens we need to do some code cleanups first.
 
@@ -17,7 +17,7 @@ The final folder and file structure should look somewhat like this:
 +
 [plantuml, format=svg]
 ----
-include::diagrams/modules-folder-structure.puml[]
+include::{diagramsdir}/modules-folder-structure.puml[]
 ----
 
 1. Make sure that your new modules are present in settings.gradle:
@@ -38,7 +38,7 @@ include ':fineract-doc'
 ----
 <.> The `settings.gradle` file should contain something like this (and following).
 
-=== How to replace an existing Fineract service
+== How to replace an existing Fineract service
 
 Creating customizations for Fineract services is easy. The method described here will work both with our future module guidelines (aka "clean room" modules) and with the intermediary solution we will put in place to avoid major refactorings.
 
@@ -61,7 +61,7 @@ The final folder and file structure should look somewhat like this:
 +
 [plantuml, format=svg]
 ----
-include::diagrams/custom-folder-structure.puml[]
+include::{diagramsdir}/custom-folder-structure.puml[]
 ----
 +
 Please make sure that your `service` module's build.gradle file has a unique group:
@@ -107,9 +107,9 @@ dependencies {
 
 IMPORTANT: Do not include your custom module in `fineract-provider`'s dependency.gradle file. This creates a circular dependency and will fail your build. Instead you have to add your JAR file e. g. to the Docker image (in Fineract's libs folder; similar like we do it with Pentaho reporting). This setup will give you the best developer experience for now with proper source references until we have separate JAR files ready on Maven Central. In the next section we describe the "clean room" [...]
 
-=== Example
+== Example
 
-==== Dummy Module Structure
+=== Dummy Module Structure
 
 We've created a demonstration how modules are supposed to be used. A module has usually at least two sub-modules:
 
@@ -179,7 +179,7 @@ dependencies {
 Hello: DEFAULT DUMMY!
 ----
 
-==== Replace the default implementation of DummyService
+=== Replace the default implementation of DummyService
 
 This is why we created module `foo` in folder `module/foo`. There's only only one sub-module that contains an implementation of `DummyService` that will replace the default implementation:
 
@@ -207,7 +207,7 @@ dependencies {
 Hello: Foo!
 ----
 
-==== Testing
+=== Testing
 
 There's a simple unit test in `fineract-provider` that demonstrates both scenarios (without any override of the default implementation and with an overriding alternative implementation)
 
@@ -237,14 +237,14 @@ The important part in the `foo` configuration is this line:
 include::{rootdir}/fineract-provider/src/test/java/org/apache/fineract/module/example/TestFooConfiguration.java[lines=26..26]
 ----
 
-==== Deployment
+=== Deployment
 
 Modules (better: the JAR files) only need to be dropped in Fineract's `libs` folder. Dynamic loading of external JARs is provided since Fineract version 1.5.0.
 
-==== How can I start replacing services now
+=== How can I start replacing services now
 
-As said the "clean room" modules will take a while to arrive. In the meanwhile we'll prepare the existing monolithic code base for pluggability. As a proof of concept the services `org.apache.fineract.portfolio.note.service.NoteReadPlatformService` and `org.apache.fineract.portfolio.note.service.NoteWritePlatformService` can be replaced/overriden by custom implementations. We'll add more shortly and will list them here.
+As said the "clean room" modules will take a while to arrive. In the meanwhile we'll prepare the existing monolithic code base for pluggability. As a proof of concept the services `org.apache.fineract.portfolio.note.service.NoteReadPlatformService` and `org.apache.fineract.portfolio.note.service.NoteWritePlatformService` can be replaced/overriden by custom implementations. We'll add more shortly and will list them here. Reach out on the mailing list if you need a specific service to be r [...]
 
-==== Outlook
+=== Outlook
 
 If this proof of concept is accepted we could refactor Fineract's services one by one and rearrange them in the proposed module structure. As discussed at ApacheCon 2021 there will be most likely some work to do to properly extract those modules (loan product, client, savings account etc.) from the monolithic code base. The main challenge are cross-dependencies between the _modules_, but there are major benefits if we split up the code like this. One - as demonstrated - is the replacemen [...]
diff --git a/fineract-doc/src/docs/en/chapters/architecture/persistence.adoc b/fineract-doc/src/docs/en/chapters/architecture/persistence.adoc
new file mode 100644
index 000000000..3e3c03f07
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/architecture/persistence.adoc
@@ -0,0 +1,64 @@
+= Persistence
+
+TBD
+
+== Database support
+
+Fineract supports multiple databases:
+
+* MySQL compatible databases (e.g. MariaDB)
+* PostgreSQL
+
+The platform differentiates between these database types in certain cases when there's a need to use some database specific tooling. To do so, the platform examines the JDBC driver used for running the platform and tries to determine which database is being used.
+
+The currently supported JDBC driver and corresponding mappings can be found below.
+
+[cols="1,1"]
+|===
+|*JDBC driver class name*
+|*Resolved database type*
+
+|`org.mariadb.jdbc.Driver`
+|MySQL
+
+|`com.mysql.jdbc.Driver`
+|MySQL
+
+|`org.postgresql.Driver`
+|PostgreSQL
+
+|===
+
+The actual code can be found in the `DatabaseTypeResolver` class.
+
+== Data-access layer
+
+The data-access layer of Fineract is implemented by using JPA (Java Persistence API) with the EclipseLink provider.
+Despite the fact that JPA is used quite extensively in the system, there are cases where the performance is a key element for an operation therefore you can easily find native SQLs as well.
+
+The data-access layer of Fineract is compatible with different databases. Since a lot of the native queries are using specific database functions, a wrapper class - `DatabaseSpecificSQLGenerator` -  has been introduced to handle these database specifics. Whenever there's a need to rely on new database level functions, make sure to extend this class and implement the specific functions provided by the database.
+
+Fineract has been developed for 10+ years by the community and unfortunately there are places where entity relationships are configured with `EAGER` fetching strategy. This must not confuse anybody. The long-term goal is to use the `LAZY` fetching strategy for every single relationship. If you're about to introduce a new one, make sure to use `LAZY` as a fetching strategy, otherwise your PR will be rejected.
+
+== Database schema migration
+
+As for every system, the database structure will and need to evolve over time. Fineract is no different. Originally for Fineract, Flyway was used until Fineract 1.6.x.
+
+After 1.6.x, PostgreSQL support was added to the platform hence there was a need to make the data-access layer and the schema migration as database independent as possible. Becuase of that, from Fineract 1.7.0, Flyway is not used anymore but Liquibase is.
+
+Some of the changesets in the Liquibase changelogs have database specifics into it but they only run for the relevant databases. This is controller by Liquibase contexts.
+
+The currently available Liquibase contexts are:
+
+* `mysql` - only set when the database is a MySQL compatible database (e.g. MariaDB)
+* `postgresql` - only set when the database is a PostgreSQL database
+* configured Spring active profiles
+* `tenant_store_db` - only set when the database migration runs the Tenant Store upgrade
+* `tenant_db` - only set when the database migration runs the Tenant upgrade
+* `initial_switch` - this is a technical context and should *NOT* be used
+
+The switch from Flyway (1.6.x) to Liquibase (1.7.x) was planned to be as smooth as possible so there's no need for manual work hence the behavior is described as following:
+
+* If the database is empty, Liquibase will create the database schema from scratch
+* If the database contains the latest Fineract 1.6.x database structure which was previously migrated with Flyway. Liquibase will seamlessly upgrade it to the latest version. Note: the Flyway related 2 database tables are left as they are and are not deleted.
+* If the database contains an earlier version of the database structure than Fineract 1.6.x. Liquibase will *NOT* do anything and *will fail the application during startup*. The proper approach in this case is to first upgrade your application version to the latest Fineract 1.6.x so that the latest Flyway changes are executed and then upgrade to the newer Fineract version where Liquibase will seamlessly take over the database upgrades.
diff --git a/fineract-doc/src/docs/en/chapters/architecture/principles.adoc b/fineract-doc/src/docs/en/chapters/architecture/principles.adoc
new file mode 100644
index 000000000..f1eecf12e
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/architecture/principles.adoc
@@ -0,0 +1,63 @@
+= Principles
+
+== RESTful API
+
+The platform exposes all its functionality via a *practically-RESTful API*, that communicates using JSON.
+
+We use the term *practically-RESTful* in order to make it clear we are not trying to be fully REST compliant but still maintain important RESTful attributes like:
+
+* Stateless: platform maintains no conversational or session-based state. The result of this is ability to scale horizontally with ease.
+* Resource-oriented: API is focussed around set of resources using HTTP vocabulary and conventions e.g GET, PUT, POST, DELETE, HTTP status codes. This results in a simple and consistent API for clients.
+
+See online API Documentation for more detail.
+
+== Multi-tenanted
+
+The Fineract platform has been developed with support for multi-tenancy at the core of its design. This means that it is just as easy to use the platform for Software-as-a-Service (SaaS) type offerings as it is for local installations.
+
+The platform uses an approach that isolates an FIs data per database/schema (See Separate Databases and Shared Database, Separate Schemas).
+
+== Extensible
+
+Whilst each tenant will have a set of core tables, the platform tables can be extended in different ways for each tenant through the use of Data tables functionality.
+
+== Command Query Seperation
+
+We seperate *commands* (that change data) from *queries* (that read data).
+
+Why? There are numerous reasons for choosing this approach which at present is not an attempt at full blown CQRS. The main advantages at present are:
+
+* State changing commands are persisted providing an audit of all state changes.
+* Used to support a general approach to *maker-checker*.
+* State changing commands use the Object-Oriented paradign (and hence ORM) whilst querys can stay in the data paradigm.
+
+== Maker-Checker
+
+Also known as *four-eyes principal*. Enables apps to support a maker-checker style workflow process. Commands that pass validation will be persisted. Maker-checker can be enabled/disabled at fine-grained level for any state changing API.
+Fine grained access control
+
+A fine grained permission is associated with each API. Administrators have fine grained control over what roles or users have access to.
+
+== Package Structure
+
+The intention is for platform code to be packaged in a vertical slice way (as opposed to layers).
+Source code starts from https://github.com/apache/fineract/tree/develop/fineract-provider/src/main/java/org/apache/fineract
+
+* accounting
+* useradministration
+* infrastructure
+* portfolio
+** charge
+** client
+** fund
+** loanaccount
+* accounting
+
+Within each vertical slice is some common packaging structure:
+
+* api - XXXApiResource.java - REST api implementation files
+* handler - XXXCommandHandler.java - specific handlers invoked
+* service - contains read + write services for functional area
+* domain - OO concepts for the functional area
+* data - Data concepts for the area
+* serialization - ability to convert from/to API JSON for functional area
diff --git a/fineract-doc/src/docs/en/chapters/architecture/resources.adoc b/fineract-doc/src/docs/en/chapters/architecture/resources.adoc
new file mode 100644
index 000000000..ca32eccd0
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/architecture/resources.adoc
@@ -0,0 +1,5 @@
+= Resources
+
+* Project URL is https://github.com/apache/fineract
+* Issue tracker is https://issues.apache.org/jira/projects/FINERACT/summary
+* Download from http://fineract.apache.org/
diff --git a/fineract-doc/src/docs/en/chapters/architecture/system.adoc b/fineract-doc/src/docs/en/chapters/architecture/system.adoc
new file mode 100644
index 000000000..b34f0e650
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/architecture/system.adoc
@@ -0,0 +1,18 @@
+= System Overview
+
+.Platform System Overview
+image::{imagesdir}/platform-systemview.png[]
+
+Financial institutions deliver their services to customers through a variety of means today.
+
+* Customers can call direct into branches (teller model)
+* Customers can organise into groups (or centers) and agree to meetup at a location and time with FI staff (traditional microfinance).
+* An FI might have a public facing information portal that customers can use for variety of reasons including account management (online banking).
+* An FI might be integrated into a ATM/POS/Card services network that the customer can use.
+* An FI might be integrated with a mobile money operator and support mobile money services for customer (present/future microfinance).
+* An FI might use third party agents to sell on products/services from other banks/FIs.
+
+As illustrated in the above diagram, the various stakeholders leverage business apps to perform specific customer or FI related actions. The functionality contained in these business apps can be bundled up and packaged in any way. In the diagram, several of the apps may be combined into one app or any one of the blocks representing an app could be further broken up as needed.
+
+The platform is the core engine of the MIS. It hides alot of the complexity that exists in the business and technical domains needed for an MIS in FIs behind a relatively simple API. It is this API that frees up app developers to innovate and produce apps that can be as general or as bespoke as FIs need them to be.
+
diff --git a/fineract-doc/src/docs/en/chapters/architecture/technology.adoc b/fineract-doc/src/docs/en/chapters/architecture/technology.adoc
new file mode 100644
index 000000000..f34e80391
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/architecture/technology.adoc
@@ -0,0 +1,14 @@
+= Technology
+
+* Java: http://www.oracle.com/technetwork/java/javase/downloads/index.html
+* JAX-RS using Jersey
+* JSON using Google GSON
+* Spring I/O Platform: http://spring.io/platform
+** Spring Framework
+** Spring Boot
+** Spring Security
+** Spring Data (JPA) backed by EclipseLink
+* MySQL: http://www.oracle.com/us/products/mysql/overview/index.html
+* PostgreSQL
+
+TBD
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/validation.adoc b/fineract-doc/src/docs/en/chapters/architecture/validation.adoc
similarity index 52%
rename from fineract-doc/src/docs/en/validation.adoc
rename to fineract-doc/src/docs/en/chapters/architecture/validation.adoc
index 907b62793..e20eca46c 100644
--- a/fineract-doc/src/docs/en/validation.adoc
+++ b/fineract-doc/src/docs/en/chapters/architecture/validation.adoc
@@ -1,8 +1,8 @@
-== Validation
+= Validation
 
-=== Programmatic
+== Programmatic
 
-Use the [DataValidatorBuilder](https://github.com/apache/fineract/search?q=%22class+DataValidatorBuilder%22), e.g. like so:
+Use the https://github.com/apache/fineract/search?q=%22class+DataValidatorBuilder%22[DataValidatorBuilder], e.g. like so:
 
 [source,java]
 ----
@@ -12,8 +12,7 @@ new DataValidatorBuilder().resource("fileUpload")
     .throwValidationErrors();
 ----
 
-Such code is often encapsulated in [`*Validator`](https://github.com/apache/fineract/search?q=Validator)
-classes (if more than a few lines, and/or reused from several places; avoid copy/paste), like so:
+Such code is often encapsulated in https://github.com/apache/fineract/search?q=Validator[`*Validator`] classes (if more than a few lines, and/or reused from several places; avoid copy/paste), like so:
 
 [source,java]
 ----
@@ -28,7 +27,6 @@ public class YourThingValidator {
 ----
 
 
-=== Declarative
+== Declarative
 
-[FINERACT-1229](https://issues.apache.org/jira/browse/FINERACT-1229) is an open issue about adopting
-Bean Validation for _declarative_ instead of _programmatic_ (as above) validation.  Contributions welcome!
+[FINERACT-1229](https://issues.apache.org/jira/browse/FINERACT-1229) is an open issue about adopting Bean Validation for _declarative_ instead of _programmatic_ (as above) validation.  Contributions welcome!
diff --git a/fineract-doc/src/docs/en/chapters/deployment/apache.adoc b/fineract-doc/src/docs/en/chapters/deployment/apache.adoc
new file mode 100644
index 000000000..a557fa3d6
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/deployment/apache.adoc
@@ -0,0 +1,5 @@
+= Apache Software Foundation Infrastructure
+
+We can order a server from Apache's infrastructure team and deploy a demo instance...
+
+TBD
diff --git a/fineract-doc/src/docs/en/chapters/deployment/appserver.adoc b/fineract-doc/src/docs/en/chapters/deployment/appserver.adoc
new file mode 100644
index 000000000..8a210960e
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/deployment/appserver.adoc
@@ -0,0 +1,25 @@
+= Application Server
+
+== Tomcat
+
+TBD
+
+== Undertow
+
+TBD
+
+== Jetty
+
+TBD
+
+== JBoss
+
+TBD
+
+== Weblogic
+
+TBD
+
+== Payara
+
+TBD
diff --git a/fineract-doc/src/docs/en/chapters/deployment/aws.adoc b/fineract-doc/src/docs/en/chapters/deployment/aws.adoc
new file mode 100644
index 000000000..9341b86bf
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/deployment/aws.adoc
@@ -0,0 +1,3 @@
+= AWS
+
+TBD
diff --git a/fineract-doc/src/docs/en/chapters/deployment/google.adoc b/fineract-doc/src/docs/en/chapters/deployment/google.adoc
new file mode 100644
index 000000000..0c5a11de1
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/deployment/google.adoc
@@ -0,0 +1,5 @@
+= Google Cloud
+
+The https://www.fineract.dev demo server runs on Google Cloud.
+
+https://docs.google.com/presentation/d/1-VP4bNkc5kZ3B0yme_vYLiY1qpswnfz8ainnX5fp3l8/[The Running Fineract.dev, SRE style presentation] given at _ApacheCon 2020_ has some related background.
diff --git a/fineract-doc/src/docs/en/deployment.adoc b/fineract-doc/src/docs/en/chapters/deployment/https.adoc
similarity index 55%
rename from fineract-doc/src/docs/en/deployment.adoc
rename to fineract-doc/src/docs/en/chapters/deployment/https.adoc
index b3f29a62d..de06f1228 100644
--- a/fineract-doc/src/docs/en/deployment.adoc
+++ b/fineract-doc/src/docs/en/chapters/deployment/https.adoc
@@ -1,24 +1,4 @@
-== Deployment
-
-=== Plugins
-
-Apache Fineract is extensible through plugin JARs (https://issues.apache.org/jira/browse/FINERACT-1177[FINERACT-1177]; based on 
-https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-executable-jar-format.html[Spring Boot's support]). To launch Fineract with plugin JARs in `libs/*.jar`, use:
-
-----
-java -Dloader.path=libs/ -jar fineract-provider.jar
-----
-
-The Fineract "Docker" container image's `ENTRYPOINT` uses this, see our `Dockerfile`. You could therefore build your customized Fineract distribution container image with your own `Dockerfile` using e.g. `FROM apache/fineract:latest` and then drop some plugin JARs into `/app/libs/`.
-
-The WAR distribution does not directly support such plugins, but one could "explode" the WAR and drop JARs into `WEB-INF/lib`; if you know what you are doing, and feel nostalgic of the 1990s still using WARs, instead of the recommended modern Spring Boot distribution.
-
-Here is a list of known 3rd-party plugin projects which can be dropped into `libs/`:
-
-* https://github.com/vorburger/fineract-pentaho
-
-
-=== HTTPS
+= HTTPS
 
 Because Apache Fineract deals with customer sensitive personally identifiable information (PII), it very strongly encourages all developers, implementors and end-users to always only use HTTPS. This is why it does not run on HTTP even for local development and enforces use of HTTPS.
 
@@ -31,10 +11,3 @@ Such products, when correctly configured, add the conventional `X-Forwarded-For`
 Alternatively, you could replace the built-in default SSL certificate with one you obtained from a Certificate Authority.  We currently do not document how to do this, because we do not recommend this approach, as its cumbersome to configure and support and less secure than a managed auto rotating solution.
 
 The Fineract API client supports an insecure mode (`FineractClient.Builder#insecure()`), and API users such as mobile apps may expose Settings to let end-users accept the self signed certificate. This should always be used for testing only, never in production.
-
-
-=== Google Cloud
-
-The https://www.fineract.dev demo server runs on Google Cloud.
-
-https://docs.google.com/presentation/d/1-VP4bNkc5kZ3B0yme_vYLiY1qpswnfz8ainnX5fp3l8/[The Running Fineract.dev, SRE style presentation] given at _ApacheCon 2020_ has some related background.
diff --git a/fineract-doc/src/docs/en/chapters/deployment/index.adoc b/fineract-doc/src/docs/en/chapters/deployment/index.adoc
new file mode 100644
index 000000000..c622891ad
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/deployment/index.adoc
@@ -0,0 +1,17 @@
+= Deployment
+
+include::plugins.adoc[leveloffset=+1]
+
+include::https.adoc[leveloffset=+1]
+
+include::local.adoc[leveloffset=+1]
+
+include::appserver.adoc[leveloffset=+1]
+
+include::kubernetes.adoc[leveloffset=+1]
+
+include::aws.adoc[leveloffset=+1]
+
+include::google.adoc[leveloffset=+1]
+
+include::apache.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/chapters/deployment/kubernetes.adoc b/fineract-doc/src/docs/en/chapters/deployment/kubernetes.adoc
new file mode 100644
index 000000000..d69ba2f74
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/deployment/kubernetes.adoc
@@ -0,0 +1,3 @@
+= Kubernetes
+
+TBD
diff --git a/fineract-doc/src/docs/en/chapters/deployment/local.adoc b/fineract-doc/src/docs/en/chapters/deployment/local.adoc
new file mode 100644
index 000000000..c79cfee79
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/deployment/local.adoc
@@ -0,0 +1,3 @@
+= Docker Compose
+
+TBD
diff --git a/fineract-doc/src/docs/en/chapters/deployment/plugins.adoc b/fineract-doc/src/docs/en/chapters/deployment/plugins.adoc
new file mode 100644
index 000000000..ddbe59ca7
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/deployment/plugins.adoc
@@ -0,0 +1,18 @@
+= Plugins
+
+Apache Fineract is extensible through plugin JARs (https://issues.apache.org/jira/browse/FINERACT-1177[FINERACT-1177]; based on
+https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-executable-jar-format.html[Spring Boot's support]). To launch Fineract with plugin JARs in `libs/*.jar`, use:
+
+----
+java -Dloader.path=libs/ -jar fineract-provider.jar
+----
+
+The Fineract "Docker" container image's `ENTRYPOINT` uses this, see our `Dockerfile`. You could therefore build your customized Fineract distribution container image with your own `Dockerfile` using e.g. `FROM apache/fineract:latest` and then drop some plugin JARs into `/app/libs/`.
+
+The WAR distribution does not directly support such plugins, but one could "explode" the WAR and drop JARs into `WEB-INF/lib`; if you know what you are doing, and feel nostalgic of the 1990s still using WARs, instead of the recommended modern Spring Boot distribution.
+
+Here is a list of known 3rd-party plugin projects which can be dropped into `libs/`:
+
+* https://github.com/vorburger/fineract-pentaho
+
+NOTE: The reporting module became our first module experiment out of necessity. We are currently developing a strategy to split up even more internals of Fineract into proper modules. Those that have an incompatible license will be hosted in a separate Git repository (probably on Github under the Mifos organisation). We'll send out an announcement as soon as we have more to say on this topic.
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/chapters/development/docker-compose.adoc b/fineract-doc/src/docs/en/chapters/development/docker-compose.adoc
new file mode 100644
index 000000000..f63a4af63
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/docker-compose.adoc
@@ -0,0 +1,3 @@
+= Docker Compose
+
+TBD
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/chapters/development/docker-podman.adoc b/fineract-doc/src/docs/en/chapters/development/docker-podman.adoc
new file mode 100644
index 000000000..5c4caf320
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/docker-podman.adoc
@@ -0,0 +1,3 @@
+= Podman
+
+TBD
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/chapters/development/docker-rancher.adoc b/fineract-doc/src/docs/en/chapters/development/docker-rancher.adoc
new file mode 100644
index 000000000..8343ac963
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/docker-rancher.adoc
@@ -0,0 +1,3 @@
+= Rancher Docker Desktop
+
+TBD
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/chapters/development/docker.adoc b/fineract-doc/src/docs/en/chapters/development/docker.adoc
new file mode 100644
index 000000000..3b35b7b0e
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/docker.adoc
@@ -0,0 +1,9 @@
+= Docker
+
+TBD
+
+include::docker-compose.adoc[leveloffset=+1]
+
+include::docker-podman.adoc[leveloffset=+1]
+
+include::docker-rancher.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/chapters/development/git-configuration.adoc b/fineract-doc/src/docs/en/chapters/development/git-configuration.adoc
new file mode 100644
index 000000000..faca7f275
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/git-configuration.adoc
@@ -0,0 +1,9 @@
+= Configuration
+
+Configure your personal details properly:
+
+* email
+* name
+* GPG key
+
+TBD
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/chapters/development/git-fork.adoc b/fineract-doc/src/docs/en/chapters/development/git-fork.adoc
new file mode 100644
index 000000000..c3023bd37
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/git-fork.adoc
@@ -0,0 +1,17 @@
+= Fork
+
+Make sure to disable Github Actions in your forked repository. See: https://github.com/vidakovic/fineract/settings/actions
+
+TBD
+
+== Upstream Configuration
+
+TBD
+
+== Syncing Upstream
+
+TBD
+
+== Pull Requests
+
+TBD
diff --git a/fineract-doc/src/docs/en/chapters/development/git.adoc b/fineract-doc/src/docs/en/chapters/development/git.adoc
new file mode 100644
index 000000000..1b7a1feef
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/git.adoc
@@ -0,0 +1,3 @@
+= Git
+
+TBD
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/chapters/development/gpg.adoc b/fineract-doc/src/docs/en/chapters/development/gpg.adoc
new file mode 100644
index 000000000..8c7e4edea
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/gpg.adoc
@@ -0,0 +1,7 @@
+= GPG
+
+TBD
+
+== Committers
+
+Please make sure to provide your GPG fingerprint in your Apache committer profile at https://id.apache.org.
diff --git a/fineract-doc/src/docs/en/chapters/development/gradle.adoc b/fineract-doc/src/docs/en/chapters/development/gradle.adoc
new file mode 100644
index 000000000..2d4321536
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/gradle.adoc
@@ -0,0 +1,3 @@
+= Gradle
+
+TBD
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/chapters/development/ide-eclipse.adoc b/fineract-doc/src/docs/en/chapters/development/ide-eclipse.adoc
new file mode 100644
index 000000000..2b1bf170c
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/ide-eclipse.adoc
@@ -0,0 +1,3 @@
+= Eclipse
+
+TBD
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/chapters/development/ide-intellij.adoc b/fineract-doc/src/docs/en/chapters/development/ide-intellij.adoc
new file mode 100644
index 000000000..372b0d414
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/ide-intellij.adoc
@@ -0,0 +1,3 @@
+= IntelliJ
+
+TBD
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/chapters/development/ide-vscode.adoc b/fineract-doc/src/docs/en/chapters/development/ide-vscode.adoc
new file mode 100644
index 000000000..66565bd1f
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/ide-vscode.adoc
@@ -0,0 +1,3 @@
+= VSCode
+
+TBD
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/chapters/development/ide.adoc b/fineract-doc/src/docs/en/chapters/development/ide.adoc
new file mode 100644
index 000000000..82596272b
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/ide.adoc
@@ -0,0 +1,9 @@
+= IDE
+
+TBD
+
+include::ide-intellij.adoc[leveloffset=+1]
+
+include::ide-eclipse.adoc[leveloffset=+1]
+
+include::ide-vscode.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/chapters/development/index.adoc b/fineract-doc/src/docs/en/chapters/development/index.adoc
new file mode 100644
index 000000000..51d0adbbf
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/index.adoc
@@ -0,0 +1,17 @@
+= Fineract Development Environment
+
+TBD
+
+include::git.adoc[leveloffset=+1]
+
+include::gpg.adoc[leveloffset=+1]
+
+include::docker.adoc[leveloffset=+1]
+
+include::gradle.adoc[leveloffset=+1]
+
+include::ide.adoc[leveloffset=+1]
+
+include::kubernetes.adoc[leveloffset=+1]
+
+include::tools.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/chapters/development/kubernetes-helm.adoc b/fineract-doc/src/docs/en/chapters/development/kubernetes-helm.adoc
new file mode 100644
index 000000000..2f7964bf7
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/kubernetes-helm.adoc
@@ -0,0 +1,3 @@
+= Helm Charts
+
+TBD
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/chapters/development/kubernetes-k3d.adoc b/fineract-doc/src/docs/en/chapters/development/kubernetes-k3d.adoc
new file mode 100644
index 000000000..2b8b9d857
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/kubernetes-k3d.adoc
@@ -0,0 +1,3 @@
+= K3d
+
+TBD
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/chapters/development/kubernetes-microk8s.adoc b/fineract-doc/src/docs/en/chapters/development/kubernetes-microk8s.adoc
new file mode 100644
index 000000000..0fd270ee3
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/kubernetes-microk8s.adoc
@@ -0,0 +1,3 @@
+= Microk8s
+
+TBD
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/chapters/development/kubernetes-minikube.adoc b/fineract-doc/src/docs/en/chapters/development/kubernetes-minikube.adoc
new file mode 100644
index 000000000..ff43c7f62
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/kubernetes-minikube.adoc
@@ -0,0 +1,3 @@
+= Minikube
+
+TBD
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/chapters/development/kubernetes.adoc b/fineract-doc/src/docs/en/chapters/development/kubernetes.adoc
new file mode 100644
index 000000000..526a10eae
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/kubernetes.adoc
@@ -0,0 +1,11 @@
+= Kubernetes
+
+TBD
+
+include::kubernetes-minikube.adoc[leveloffset=+1]
+
+include::kubernetes-microk8s.adoc[leveloffset=+1]
+
+include::kubernetes-k3d.adoc[leveloffset=+1]
+
+include::kubernetes-helm.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/chapters/development/tools-brew.adoc b/fineract-doc/src/docs/en/chapters/development/tools-brew.adoc
new file mode 100644
index 000000000..e78ffa249
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/tools-brew.adoc
@@ -0,0 +1,9 @@
+= Brew
+
+== MacOS
+
+TBD
+
+== Linux
+
+TBD
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/chapters/development/tools-sdkman.adoc b/fineract-doc/src/docs/en/chapters/development/tools-sdkman.adoc
new file mode 100644
index 000000000..d34d1a8a5
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/tools-sdkman.adoc
@@ -0,0 +1,10 @@
+= SDKMAN
+
+We recommend using SKDMAN to manage the following developer tools:
+
+- JDK
+- Spring Boot CLI
+- Gradle (if you need a global installation)
+- AsciidoctorJ
+
+TBD
diff --git a/fineract-doc/src/docs/en/chapters/development/tools.adoc b/fineract-doc/src/docs/en/chapters/development/tools.adoc
new file mode 100644
index 000000000..caae8711a
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/development/tools.adoc
@@ -0,0 +1,7 @@
+= Tools
+
+TBD
+
+include::tools-sdkman.adoc[leveloffset=+1]
+
+include::tools-brew.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/chapters/documentation/antora.adoc b/fineract-doc/src/docs/en/chapters/documentation/antora.adoc
new file mode 100644
index 000000000..91a5773f8
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/documentation/antora.adoc
@@ -0,0 +1,5 @@
+= Antora
+
+See: https://antora.org/
+
+TBD
diff --git a/fineract-doc/src/docs/en/chapters/documentation/asciidoc-cheatsheet.adoc b/fineract-doc/src/docs/en/chapters/documentation/asciidoc-cheatsheet.adoc
new file mode 100644
index 000000000..58c70e86e
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/documentation/asciidoc-cheatsheet.adoc
@@ -0,0 +1,3 @@
+= Cheatsheet
+
+TBD
diff --git a/fineract-doc/src/docs/en/chapters/documentation/asciidoc-tutorial.adoc b/fineract-doc/src/docs/en/chapters/documentation/asciidoc-tutorial.adoc
new file mode 100644
index 000000000..3af79bf1c
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/documentation/asciidoc-tutorial.adoc
@@ -0,0 +1,5 @@
+= Tutorial
+
+See: https://www.vogella.com/tutorials/AsciiDoc/article.html
+
+TBD
diff --git a/fineract-doc/src/docs/en/chapters/documentation/asciidoc.adoc b/fineract-doc/src/docs/en/chapters/documentation/asciidoc.adoc
new file mode 100644
index 000000000..2e4f79198
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/documentation/asciidoc.adoc
@@ -0,0 +1,9 @@
+= Asciidoc
+
+See: https://asciidoctor.org/
+
+TBD
+
+include::asciidoc-tutorial.adoc[leveloffset=+1]
+
+include::asciidoc-cheatsheet.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/chapters/documentation/editor-eclipse.adoc b/fineract-doc/src/docs/en/chapters/documentation/editor-eclipse.adoc
new file mode 100644
index 000000000..5ed0d17ed
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/documentation/editor-eclipse.adoc
@@ -0,0 +1,9 @@
+= Eclipse
+
+== Asciidoc
+
+See: https://marketplace.eclipse.org/content/asciidoctor-editor
+
+== PlantUML
+
+See: https://plantuml.com/eclipse
diff --git a/fineract-doc/src/docs/en/chapters/documentation/editor-intellij.adoc b/fineract-doc/src/docs/en/chapters/documentation/editor-intellij.adoc
new file mode 100644
index 000000000..a457c07a9
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/documentation/editor-intellij.adoc
@@ -0,0 +1,9 @@
+= IntelliJ IDEA
+
+== Asciidoc
+
+See: https://plugins.jetbrains.com/plugin/7391-asciidoc
+
+== PlantUML
+
+See: https://plugins.jetbrains.com/plugin/7017-plantuml-integration
diff --git a/fineract-doc/src/docs/en/chapters/documentation/editor-vscode.adoc b/fineract-doc/src/docs/en/chapters/documentation/editor-vscode.adoc
new file mode 100644
index 000000000..06b53fd76
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/documentation/editor-vscode.adoc
@@ -0,0 +1,9 @@
+= VSCode
+
+== Asciidoc
+
+See: https://marketplace.visualstudio.com/items?itemName=asciidoctor.asciidoctor-vscode
+
+== PlantUML
+
+See: https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml
diff --git a/fineract-doc/src/docs/en/chapters/documentation/editor.adoc b/fineract-doc/src/docs/en/chapters/documentation/editor.adoc
new file mode 100644
index 000000000..d2258cd92
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/documentation/editor.adoc
@@ -0,0 +1,9 @@
+= Editor
+
+TBD
+
+include::editor-intellij.adoc[leveloffset=+1]
+
+include::editor-eclipse.adoc[leveloffset=+1]
+
+include::editor-vscode.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/chapters/documentation/index.adoc b/fineract-doc/src/docs/en/chapters/documentation/index.adoc
new file mode 100644
index 000000000..7ac4570c4
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/documentation/index.adoc
@@ -0,0 +1,16 @@
+= Documentation
+
+We try to assemble all Fineract related documentation in this document. We use Asciidoc...
+
+TBD
+
+include::layout.adoc[leveloffset=+1]
+
+include::asciidoc.adoc[leveloffset=+1]
+
+include::plantuml.adoc[leveloffset=+1]
+
+include::editor.adoc[leveloffset=+1]
+
+include::antora.adoc[leveloffset=+1]
+
diff --git a/fineract-doc/src/docs/en/chapters/documentation/layout.adoc b/fineract-doc/src/docs/en/chapters/documentation/layout.adoc
new file mode 100644
index 000000000..66a67da2a
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/documentation/layout.adoc
@@ -0,0 +1,19 @@
+= File and Folder Layout
+
+TBD
+
+== Book
+
+TBD
+
+== Chapter
+
+TBD
+
+== Diagrams
+
+TBD
+
+== Images
+
+TBD
diff --git a/fineract-doc/src/docs/en/chapters/documentation/plantuml-cheatsheet.adoc b/fineract-doc/src/docs/en/chapters/documentation/plantuml-cheatsheet.adoc
new file mode 100644
index 000000000..58c70e86e
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/documentation/plantuml-cheatsheet.adoc
@@ -0,0 +1,3 @@
+= Cheatsheet
+
+TBD
diff --git a/fineract-doc/src/docs/en/chapters/documentation/plantuml-tutorial.adoc b/fineract-doc/src/docs/en/chapters/documentation/plantuml-tutorial.adoc
new file mode 100644
index 000000000..b704924d7
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/documentation/plantuml-tutorial.adoc
@@ -0,0 +1,3 @@
+= Tutorial
+
+TBD
diff --git a/fineract-doc/src/docs/en/chapters/documentation/plantuml.adoc b/fineract-doc/src/docs/en/chapters/documentation/plantuml.adoc
new file mode 100644
index 000000000..10cd7506c
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/documentation/plantuml.adoc
@@ -0,0 +1,9 @@
+= PlantUML
+
+See: https://plantuml.com/
+
+TBD
+
+include::plantuml-tutorial.adoc[leveloffset=+1]
+
+include::plantuml-cheatsheet.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/chapters/release/configuration-email.adoc b/fineract-doc/src/docs/en/chapters/release/configuration-email.adoc
new file mode 100644
index 000000000..e00d3e335
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/configuration-email.adoc
@@ -0,0 +1,28 @@
+= Email
+
+Official communication related to releases needs to be done with an Apache email address. The Apache Foundation doesn't provide any real email inboxes anymore and just relays emails to your configured private account (GMail etc.).
+
+IMPORTANT: At the moment we are supporting only GMail accounts. Please let us know if you have other configuration recipes for other email providers.
+
+== GMail
+
+You can configure your GMail account and add another profile to use the Apache relay server if you need to send official messages. Please follow these instructions:
+
+TBD.
+
+See also: https://gmail.googleblog.com/2009/07/send-mail-from-another-address-without.html[Send mail from another address without "on behalf of"]
+
+To be able to send emails via SMTP with your GMail account you probably need to create an app password. Please follow these instructions:
+
+1. Go to your Google Account.
+1. Select Security.
+1. Under "Signing in to Google," select App Passwords. You may need to sign in. If you don't have this option, it might be because:
+1. 2-Step Verification is not set up for your account.
+1. 2-Step Verification is only set up for security keys.
+1. Your account is through work, school, or other organization.
+1. You turned on Advanced Protection.
+1. At the bottom, choose Select app and choose the app you using and then Select device and choose the device you're using and then Generate.
+1. Follow the instructions to enter the App Password. The App Password is the 16-character code in the yellow bar on your device.
+1. Tap Done.
+
+See also: https://support.google.com/accounts/answer/185833?p=InvalidSecondFactor&visit_id=637856439524128323-869822459&rd=1[Google Support: Sign in with App Passwords] for more details.
diff --git a/fineract-doc/src/docs/en/chapters/release/configuration-gpg.adoc b/fineract-doc/src/docs/en/chapters/release/configuration-gpg.adoc
new file mode 100644
index 000000000..830157bf6
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/configuration-gpg.adoc
@@ -0,0 +1,225 @@
+= GPG
+
+Generate GPG key pairs if you don't already have them and publish them. Please use your Apache email address when creating your GPG keypair. If you already have configured GPG and associated your keypair with a non-Apache email address then please consider creating a separate one just for all things related to Fineract (or Apache in general).
+
+Instructions:
+
+1. Check your GPG version:
++
+.Input GPG version
+[source,bash]
+----
+gpg --version
+----
++
+.Output GPG version
+[source,bash]
+----
+gpg (GnuPG) 2.2.27
+libgcrypt 1.9.4
+Copyright (C) 2021 Free Software Foundation, Inc.
+License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
+
+Home: /home/aleks/.gnupg
+Supported algorithms:
+Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
+Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
+        CAMELLIA128, CAMELLIA192, CAMELLIA256
+Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
+Compression: Uncompressed, ZIP, ZLIB, BZIP2
+
+----
++
+CAUTION: The insecure hash algorithm SHA1 is still supported in version 2.2.27. SHA1 is obsolete and you don't want to use it to generate your signature.
+
+1. Generate your GPG key pair:
++
+.Input generate GPG key pair
+[source,bash]
+----
+gpg --full-gen-key
+----
++
+.Output generate GPG key pair (step 1: key type selection)
+[source,bash]
+----
+gpg (GnuPG) 2.2.27; Copyright (C) 2021 Free Software Foundation, Inc.
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
+
+Please select what kind of key you want:
+   (1) RSA and RSA (default)
+   (2) DSA and Elgamal
+   (3) DSA (sign only)
+   (4) RSA (sign only)
+  (14) Existing key from card
+Your selection?
+----
++
+There are four options. The default is to use RSA to create the key pair. Good enough for us.
++
+.Output generate GPG key pair (step 2: key length selection)
+[source,bash]
+----
+RSA keys may be between 1024 and 4096 bits long.
+What keysize do you want? (2048)
+----
++
+The default key length is 2048 bits. 1024 is obsolete and a longer 4096 RSA key will not provide more security than 2048 RSA key. Use the default.
++
+.Output generate GPG key pair (step 3: validity selection)
+[source,bash]
+----
+Requested keysize is 2048 bits
+Please specify how long the key should be valid.
+ 0 = key does not expire
+ <n> = key expires in n days
+ <n>w = key expires in n weeks
+ <n>m = key expires in n months
+ <n>y = key expires in n years
+Key is valid for? (0)2y
+----
++
+2 years for the validity of your keys should be fine. You can always update the expiration time later on.
++
+.Output generate GPG key pair (step 4: confirmation)
+[source,bash]
+----
+Key expires at Sun 16 Apr 2024 08:10:24 PM UTC
+Is this correct? (y/N)y
+----
++
+Confirm if everything is correct.
++
+.Output generate GPG key pair (step 5: provide user details)
+[source,bash]
+----
+GnuPG needs to construct a user ID to identify your key.
+Real name: Aleksandar Vidakovic
+Email address: aleks@apache.org
+Comment:
+----
++
+Provide your user details for the key. This is important because this information will be included in our key. It's one way of indicating who is owner of this key. The email address is a unique identifier for a person. You can leave Comment blank.
++
+.Output generate GPG key pair (step 6: user ID selection)
+[source,bash]
+----
+You selected this USER-ID:
+"Aleksandar Vidakovic <al...@apache.org>"
+Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
+----
++
+Select `Okay`.
++
+After the selection of your user ID GPG will ask for a passphrase to protect your private key. Maybe time to open your password manager and generate a secure one and save it in your vault. Once you've confirmed your password GPG will start to generate your keys.
++
+CAUTION: Don't lose your private key password. You won't be able to unlock and use your private key without it.
++
+.Output generate GPG key pair (step 7: gpg key pair generation)
+[source,bash]
+----
+We need to generate a lot of random bytes. It is a good idea to perform
+some other action (type on the keyboard, move the mouse, utilize the
+disks) during the prime generation; this gives the random number
+generator a better chance to gain enough entropy.
+----
++
+Generating the GPG keys will take a while.
++
+.Output generate GPG key pair (step 8: gpg key pair finished)
+[source,bash]
+----
+gpg: key 7890ABCD marked as ultimately trusted <1>
+gpg: directory '/home/aleks/.gnupg/openpgp-revocs.d' created
+gpg: revocation certificate stored as '/home/aleks/.gnupg/openpgp-revocs.d/ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCD.rev' <2>
+public and secret key created and signed.
+
+gpg: checking the trustdb
+gpg: marginals needed: 3 completes needed: 1 trust model: PGP
+gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
+gpg: next trustdb check due at 2024-04-16
+pub rsa2048/7890ABCD 2022-04-16 [S] [expires: 2024-04-16] <3>
+Key fingerprint = ABCD EFGH IJKL MNOP QRST UVWX YZ12 3456 7890 ABCD <4>
+uid     [ultimate] Aleksandar Vidakovic <al...@apache.org> <5>
+sub rsa2048/4FGHIJ56 2022-04-16 [] [expires: 2024-04-16]
+----
++
+<1> GPG created a unique identifier in HEX format for your public key. When someone wants to download your public key, they can refer to it either with your email address or this HEX value.
++
+<2> GPG created a revocation certificate and its directory. You should never share your private key. If your private key is compromised, you need to use your revocation certificate to revoke your key.
++
+<3> The public key is 2048 bits using RSA algorithm and shows the expiration date of 16 Apr 2024. The public key ID `7890ABCD` matches the last 8 bits of key fingerprint.
+<4> The key fingerprint (`ABCD EFGH IJKL MNOP QRST UVWX YZ12 3456 7890 ABCD`) is a hash of your public key.
++
+<5> Your name and your email address are shown with information about the subkey.
++
+Now you can find that there are two files created under ~/.gnupg/private-keys-v1.d/ directory. These two files are binary files with .key extension.
+
+1. Export your public key:
++
+[source,bash]
+----
+gpg --armor --export aleks@apache.org > pubkey.asc
+----
+
+1. Export Your Private Key:
++
+[source,bash]
+----
+gpg --export-secret-keys --armor aleks@apache.org > privkey.asc
+----
+
+1. Protect Your Private Key and Revocation Certificate
++
+Your private key should be kept in a safe place, like an encrypted flash drive. Treat it like your house key. Only you can have it and don't lose it. And you must remember your passphrase, otherwise you can't unlock your private key.
++
+You should protect your revocation certificate. Anyone in posession of your revocation certificate, could immediately revoke your public/private key pair and generate fake ones.
+
+IMPORTANT: Please contact a PMC member to add your GPG public key in Fineract's Subversion repository. This is necessary to be able to validate published releases.
+
+1. Upload your GPG key to a keyserver:
++
+[source,bash]
+----
+gpg --send-keys ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCD
+----
++
+Before doing this, make sure that your default keyserver is hkp://keyserver.ubuntu.com/. You can do this by changing the default keyserver in ~/.gnupg/dirmngr.conf:
++
+[source,bash]
+----
+keyserver hkp://keyserver.ubuntu.com/
+----
++
+Alternatively you can provide the keyserver whith the send command:
++
+[source,bash]
+----
+gpg --keyserver 'hkp://keyserver.ubuntu.com:11371' --send-keys ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCD
+----
++
+Another option to publish your key is to submit an armored public key directly at https://keyserver.ubuntu.com/. You can create the necessary data with this command by providing the email address that you used when you created your key pair:
++
+[source,bash]
+----
+gpg --armor --export aleks@apache.org
+----
++
+Output:
++
+[source,bash]
+----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQINBF8iGq0BEADGRqeSsOoNDc1sV3L9sQ34KhmoQrACnMYGztx33TD98aWplul+
+jm8uGtMmBus4DJJJap1bVQ1oMehw2mscmDHpfJjLNZ/q+vUqbExx1/CER7XvLryN
+<--- snip --->
+2nHBuBftxDRpDHQ+O5XYwSDSTDMmthPjx0vJGBH4K1kO8XK99e01A6/oYLV2SMKp
+gXXeWjafxBmHT1cM8hoBZBYzgTu9nK5UnllWunfaHXiCBG4oQQ==
+=85/F
+-----END PGP PUBLIC KEY BLOCK-----
+----
++
diff --git a/fineract-doc/src/docs/en/chapters/release/configuration-gradle.adoc b/fineract-doc/src/docs/en/chapters/release/configuration-gradle.adoc
new file mode 100644
index 000000000..d3df3b5eb
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/configuration-gradle.adoc
@@ -0,0 +1,38 @@
+= Gradle
+
+TBD
+
+== User Properties
+
+There are a couple of properties that contain committer/release manager related secrets. Please add the following properties to your personal global Gradle properties (you will find them at `~/.gradle/gradle.properties` in your home folder).
+
+[source,properties]
+----
+fineract.config.gnupg.keyName=ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCD<1>
+fineract.config.gnupg.password=******
+fineract.config.gnupg.publicKeyring=~/.gnupg/pubring.kbx<2>
+fineract.config.gnupg.secretKeyring=~/.gnupg/secring.gpg
+fineract.config.smtp.username=aleks@gmail.com <3>
+fineract.config.smtp.password=******
+fineract.config.name=Aleksandar Vidakovic
+fineract.config.email=aleks@apache.org
+fineract.config.username=aleks <4>
+fineract.config.password=******
+----
+<1> Make sure you use the full GPG key name (you can list yours via `gpg --list-secret-keys --keyid-format=long`)
+<2> GnuPG has it's own kbx format to store the public key ring. At the moment we are only supporting this format
+<3> Currently we only have instructions for GMail
+<4> Apache committer credentials
+
+CAUTION: **Never** add any personal secrets in the project gradle.properties. Double check that you are not accidentally committing them to Git!
+
+== Release Plugin
+
+Creating Apache Fineract releases was a very manual and tedious procedure before we created the Gradle release plugin. It was easy - even with documentation - to forget a detail. Some ideas are borrowed from the excellent https://jreleaser.org[JReleaser] tool. Unfortunately at the moment we can't use it for the full release process. Being an Apache project we have certain requirements that are not fully covered by https://jreleaser.org[JReleaser].
+
+=== Release Plugin Configuration
+
+[source,groovy]
+----
+include::{rootdir}/buildSrc/src/main/groovy/org.apache.fineract.release.gradle[lines=32..105]
+----
diff --git a/fineract-doc/src/docs/en/chapters/release/configuration-secrets.adoc b/fineract-doc/src/docs/en/chapters/release/configuration-secrets.adoc
new file mode 100644
index 000000000..2272260d1
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/configuration-secrets.adoc
@@ -0,0 +1,37 @@
+= Secrets
+
+TBD
+
+== Infrastructure Team
+
+A couple of secrets for third party services are automatically configured by the infrastructure team at The Apache Foundation for the Fineract Github account. At the moment this includes environment variables for:
+
+* Github token (e. g. to publish Github Pages, use the Github API in Github Actions)
+* Docker Hub token (to publish our Docker images)
+* Sonar Cloud token (for our code quality reports)
+
+See also:
+
+* https://infra.apache.org/github-pages.html
+* https://cwiki.apache.org/confluence/display/INFRA/Github+Actions+to+DockerHub
+* https://github.com/apache/jmeter-site-preview
+* https://github.com/apache/fineract-site
+* https://github.com/apache/systemds-website/blob/main/.asf.yaml
+
+== Lastpass
+
+It seems that Apache has some kind of org account or similar. Popped up a couple of times in the infrastructure documentation.
+
+TBD
+
+== 1Password
+
+Other Fineract development related secrets, e. g. for deployments of demo systems on Google Cloud, AWS etc. are managed in a team account at 1Password. At the moment the following committers are members of the 1Password team account:
+
+* mailto:edcable@apache.org[Ed Cable]
+* mailto:vorburger@apache.org[Michael Vorburger]
+* mailto:ptuomola@apache.org[Petri Tuomola]
+* mailto:arnold@apache.org[Arnold Galovics]
+* mailto:aleks@apache.org[Aleksandar Vidakovic]
+
+NOTE: If you need access or have any questions related to those secrets then please reach out to one of the team members.
diff --git a/fineract-doc/src/docs/en/chapters/release/configuration.adoc b/fineract-doc/src/docs/en/chapters/release/configuration.adoc
new file mode 100644
index 000000000..3b4de6997
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/configuration.adoc
@@ -0,0 +1,20 @@
+= Configuration
+
+Before you can start using the Fineract release plugin to create releases you have to configure and setup a couple of things first.
+
+* All official communication concerning releases happens on the mailto:dev@fineract.apache.org[mailing list]. Every release manager needs to be a member of and engaging on the mailing list for credibility.
+* Make sure you have edit permissions on the https://cwiki.apache.org/confluence/display/FINERACT[Apache Confluence Wiki]
+* You need full permissions on https://issues.apache.org/jira[Apache JIRA] to be able to move issues to the next release
+* Git committer privileges to be allowed to create tags and the release branch
+* Familiarity with building Fineract locally and creating release distributions is required
+* You need to be a member of the PMC to be able to upload release artifacts; this task can be delegated though
+* A general Familiarity with PGP/GPG is recommended (at least to setup your keypairs), but the release plugin does most of the heavy lifting
+* Make sure to read the release plugin documentation for troubleshooting
+
+include::configuration-secrets.adoc[leveloffset=+1]
+
+include::configuration-gpg.adoc[leveloffset=+1]
+
+include::configuration-email.adoc[leveloffset=+1]
+
+include::configuration-gradle.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/chapters/release/index.adoc b/fineract-doc/src/docs/en/chapters/release/index.adoc
new file mode 100644
index 000000000..1c663ab8c
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/index.adoc
@@ -0,0 +1,13 @@
+= Releases
+
+https://cwiki.apache.org/confluence/x/DRwIB[How to Release Apache Fineract] documents the process how we make the source code that is available here in this Git repository into a binary release tar.gz available on http://fineract.apache.org.
+
+.Release Schedule
+[plantuml, format=svg]
+----
+include::{diagramsdir}/release-schedule.puml[]
+----
+
+include::configuration.adoc[leveloffset=+1]
+
+include::process.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/chapters/release/process-step01.adoc b/fineract-doc/src/docs/en/chapters/release/process-step01.adoc
new file mode 100644
index 000000000..364106669
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/process-step01.adoc
@@ -0,0 +1,26 @@
+= Step 1: Heads-Up Email
+
+== Description
+
+The RM should, if one doesn't already exist, first create a new release umbrella issue in JIRA. This issue is dedicated to tracking (a summary of) any discussion related to the planned new release. An example of such an issue is FINERACT-873 - Release Apache Fineract v1.4.0 RESOLVED.
+
+The RM then creates an list of resolved issues & features through an initial check in JIRA for already resolved issues for the release, and then setup a timeline for release branch point. The time for the day the issue list is created to the release branch point must be at least two weeks in order to give the community a chance to prioritize and commit any last minute features and issues they would like to see in the upcoming release.
+
+The RM must then send the pointer to the umbrella issue along with the tentative timeline for branch point to the developer lists. Any work identified as release related that needs to be completed should be added as a sub tasks of the umbrella issue to allow all developers and users to see the overall release progress in one place. The umbrella issue shall also link to any issues still requiring clarification whether or not they will make it into the release.
+
+The RM should then inform users when the git branch is planned to be created, by sending an email based on this template:
+
+[source,text]
+----
+include::{rootdir}/buildSrc/src/main/resources/email/release.step01.headsup.subject.ftl[]
+
+include::{rootdir}/buildSrc/src/main/resources/email/release.step01.headsup.message.ftl[]
+----
+
+== Gradle Task
+
+.Command
+[source,bash,subs="attributes"]
+----
+% ./gradlew fineractReleaseStep1 -Pfineract.release.issue=1234 -Pfineract.release.date="Monday, April 25, 2022" -Pfineract.release.version={revnumber}
+----
diff --git a/fineract-doc/src/docs/en/chapters/release/process-step02.adoc b/fineract-doc/src/docs/en/chapters/release/process-step02.adoc
new file mode 100644
index 000000000..1bbb05fb0
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/process-step02.adoc
@@ -0,0 +1,34 @@
+= Step 2: Clean Up JIRA
+
+== Description
+
+Before a release is done, make sure that any issues that are fixed have their fix version setup correctly.
+
+[source,text]
+----
+project = FINERACT and resolution = fixed and fixVersion is empty
+----
+
+Move all unresolved JIRA issues which have this release as Fix Version to the next release
+[source,text,subs="attributes"]
+----
+project = FINERACT and fixVersion = {revnumber} and status not in ( Resolved, Done, Accepted, Closed )
+----
+
+You can also run the following query to make sure that the issues fixed for the to-be-released version look accurate:
+[source,text,subs="attributes"]
+----
+project = FINERACT and fixVersion = {revnumber}
+----
+
+Finally, check out the output of the JIRA release note tool to see which tickets are included in the release, in order to do a sanity check.
+
+== Gradle Task
+
+.Command
+[source,bash,subs="attributes"]
+----
+% ./gradlew fineractReleaseStep2 -Pfineract.release.version={revnumber}
+----
+
+CAUTION: This task is not yet automated!
diff --git a/fineract-doc/src/docs/en/chapters/release/process-step03.adoc b/fineract-doc/src/docs/en/chapters/release/process-step03.adoc
new file mode 100644
index 000000000..3f142a6bd
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/process-step03.adoc
@@ -0,0 +1,56 @@
+= Step 3: Create Release Branch
+
+== Description
+
+Communicate with the community. You do not need to start a new email thread on the developer mailing list to notify that you are about to branch, just do it ca. 2 weeks after the initial email, or later, based on the discussion on the initial email.
+
+You do not need to ask committers to hold off any commits until you have branched finished, as it's always possible to fast-forward the branch to latest develop, or cherry-pick last minute changes to it. People should be able to continue working on the develop branch on bug fixes and great new features for the next release while the release process for the current release is being worked through.
+
+1. Clone fresh repository copy
++
+[source,bash]
+----
+% git clone git@github.com:apache/fineract.git
+% cd fineract
+----
+
+1. Check that current HEAD points to commit on which you want to base new  release branch. Checkout a particular earlier commit if not.
++
+[source,bash]
+----
+% git log <1>
+----
+<1> Check current branch history. HEAD should point to commit that you want to be base for your release branch
+
+1. Create a new release branch with name "$Version"
++
+[source,bash,subs="attributes"]
+----
+% git checkout -b {revnumber}
+----
+
+1. Push new branch to Apache Fineract repository
++
+[source,bash,subs="attributes"]
+----
+% git push origin {revnumber}
+----
+
+1. Add new release notes in Release Folders. The change list can be swiped from the JIRA release note tool (use the "text" format for the change log). See JIRA Cleanup above to ensure that the release notes generated by this tool are what you are expecting.
+
+1. Send en email announcing the new release branch on the earlier email thread
++
+[source,text]
+----
+include::{rootdir}/buildSrc/src/main/resources/email/release.step03.branch.subject.ftl[]
+
+include::{rootdir}/buildSrc/src/main/resources/email/release.step03.branch.message.ftl[]
+----
+
+== Gradle Task
+
+.Command
+[source,bash,subs="attributes"]
+----
+% ./gradlew fineractReleaseStep3 -Pfineract.release.date="Monday, May 10, 2022" -Pfineract.release.version={revnumber}
+----
diff --git a/fineract-doc/src/docs/en/chapters/release/process-step04.adoc b/fineract-doc/src/docs/en/chapters/release/process-step04.adoc
new file mode 100644
index 000000000..41dc3cf89
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/process-step04.adoc
@@ -0,0 +1,15 @@
+= Step 4: Freeze JIRA
+
+== Description
+
+You first need to close the release in JIRA so that the about to be released version cannot be used as "fixVersion" for new bugs anymore. Go to JIRA "Administer project" page and follow "Versions" in left menu. Table with list of all releases should appear, click on additional menu on the right of your release and choose "Release" option. Submit release date and you're done.
+
+== Gradle Task
+
+.Command
+[source,bash]
+----
+% ./gradlew fineractReleaseStep4
+----
+
+CAUTION: This task is not yet automated!
diff --git a/fineract-doc/src/docs/en/chapters/release/process-step05.adoc b/fineract-doc/src/docs/en/chapters/release/process-step05.adoc
new file mode 100644
index 000000000..bafbae123
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/process-step05.adoc
@@ -0,0 +1,24 @@
+= Step 5: Create Release Tag
+
+== Description
+
+Next, you create a git tag from the HEAD of the release's git branch.
+
+[source,bash,subs="attributes"]
+----
+% git checkout {revnumber}
+% ./gradlew clean integrationTests <1>
+% git tag -a {revnumber} -m "Fineract {revnumber} release"
+% git push origin {revnumber}
+----
+<1> Run additonally manual tests with the community app.
+
+CAUTION: It is important to create so called annotated tags (vs. lightweight) for releases.
+
+== Gradle Task
+
+.Command
+[source,bash,subs="attributes"]
+----
+% ./gradlew fineractReleaseStep5 -Pfineract.release.version={revnumber}
+----
diff --git a/fineract-doc/src/docs/en/chapters/release/process-step06.adoc b/fineract-doc/src/docs/en/chapters/release/process-step06.adoc
new file mode 100644
index 000000000..e9326faa0
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/process-step06.adoc
@@ -0,0 +1,39 @@
+= Step 6: Create Distribution
+
+== Description
+
+Create source and binary artifacts. Make sure to do some sanity checks. The tar and the release branch should match.
+
+[source,bash,subs="attributes"]
+----
+% cd /fineract-release-preparations <1>
+% tar -xvf apache-fineract-{revnumber}-src.tar.gz
+% git clone https://git-wip-us.apache.org/repos/asf/fineract.git
+% cd fineract/
+% git checkout tags/{revnumber}
+% cd ..
+% diff -r fineract apache-fineract-{revnumber}-src
+----
+<1> Do a fresh clone of the tag.
+
+Make sure code compiles and tests pass on the uncompressed source.
+
+[source,bash,subs="attributes"]
+----
+% cd apache-fineract-{revnumber}-src/fineract-provider <1>
+% gradlew clean integrationTest <2>
+% gradlew clean build <3>
+% gradlew rat <4>
+----
+<1> Make sure prerequisites are met before running these commands.
+<2> For running integration tests
+<3> For building deploy able war
+<4> For RAT checks
+
+== Gradle Task
+
+.Command
+[source,bash]
+----
+% ./gradlew fineractReleaseStep6
+----
diff --git a/fineract-doc/src/docs/en/chapters/release/process-step07.adoc b/fineract-doc/src/docs/en/chapters/release/process-step07.adoc
new file mode 100644
index 000000000..169a61cb3
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/process-step07.adoc
@@ -0,0 +1,23 @@
+= Step 7: Sign Distribution
+
+== Description
+
+All release artifacts must be signed. In order to sign a release you will need a PGP key. You should get your key signed by a few other people. You will also need to receive their keys from a public key server.   See the Apache release signing page for more details. Please follow the steps defined in Release Sign.
+
+[source,bash,subs="attributes"]
+----
+% gpg --armor --output apache-fineract-{revnumber}-src.tar.gz.asc --detach-sig apache-fineract-{revnumber}-src.tar.gz
+% gpg --print-md MD5 apache-fineract-{revnumber}-src.tar.gz > apache-fineract-{revnumber}-src.tar.gz.md5
+% gpg --print-md SHA512 apache-fineract-{revnumber}-src.tar.gz > apache-fineract-{revnumber}-src.tar.gz.sha512
+% gpg --armor --output apache-fineract-{revnumber}--binary.tar.gz.asc --detach-sig apache-fineract-{revnumber}-binary.tar.gz
+% gpg --print-md MD5 apache-fineract-{revnumber}-binary.tar.gz > apache-fineract-{revnumber}-binary.tar.gz.md5
+% gpg --print-md SHA512 apache-fineract-{revnumber}-binary.tar.gz > apache-fineract-{revnumber}-binary.tar.gz.sha512
+----
+
+== Gradle Task
+
+.Command
+[source,bash]
+----
+% ./gradlew fineractReleaseStep7
+----
diff --git a/fineract-doc/src/docs/en/chapters/release/process-step08.adoc b/fineract-doc/src/docs/en/chapters/release/process-step08.adoc
new file mode 100644
index 000000000..a954973c2
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/process-step08.adoc
@@ -0,0 +1,34 @@
+= Step 8: Upload Distribution Staging
+
+== Description
+
+Finally create a directory with release name ({revnumber} in this example) in https://dist.apache.org/repos/dist/dev/fineract and add the following files in this new directory:
+
+* apache-fineract-{revnumber}-binary.tar.gz.sha
+* apache-fineract-{revnumber}-binary.tar.gz
+* apache-fineract-{revnumber}-binary.tar.gz.asc
+* apache-fineract-{revnumber}-binary.tar.gz.md5
+* apache-fineract-{revnumber}-src.tar.gz.sha
+* apache-fineract-{revnumber}-src.tar.gz
+* apache-fineract-{revnumber}-src.tar.gz.asc
+* apache-fineract-{revnumber}-src.tar.gz.md5
+
+Upload binary and source archives to ASF's distribution dev (staging) area:
+
+[source,bash,subs="attributes"]
+----
+% svn co https://dist.apache.org/repos/dist/dev/fineract/ fineract-dist-dev
+% mkdir fineract-dist-dev/{revnumber}
+% cp fineract/build/distributions/* fineract-dist-dev/{revnumber}/
+% svn commit
+----
+
+NOTE: You will need your ASF Committer credentials to be able to access the Subversion host https://dist.apache.org via.
+
+== Gradle Task
+
+.Command
+[source,bash,subs="attributes"]
+----
+% ./gradlew fineractReleaseStep8 -Pfineract.release.version={revnumber}
+----
diff --git a/fineract-doc/src/docs/en/chapters/release/process-step09.adoc b/fineract-doc/src/docs/en/chapters/release/process-step09.adoc
new file mode 100644
index 000000000..ecb5feeb5
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/process-step09.adoc
@@ -0,0 +1,26 @@
+= Step 9: Verify Distribution Staging
+
+== Description
+
+Following are the typical things we need to verify before voting on a release candidate. And the release manager should verify them too before calling out a vote.
+
+Make sure release artifacts are hosted at https://dist.apache.org/repos/dist/dev/fineract
+
+* Release candidates should be in format apache-fineract-{revnumber}-binary.tar.gz
+* Verify signatures and hashes. You may have to import the public key of the release manager to verify the signatures. (`gpg --recv-key <key id>`)
+* Git tag matches the released bits (diff -rf)
+* Can compile successfully from source
+* Verify DISCLAIMER, NOTICE and LICENSE (year etc)
+* All files have correct headers (Rat check should be clean - gradlew rat)
+* No jar files in the source artifacts
+* Integration tests should work
+
+== Gradle Task
+
+.Command
+[source,bash,subs="attributes"]
+----
+% ./gradlew fineractReleaseStep9 -Pfineract.release.version={revnumber}
+----
+
+CAUTION: This task is not yet automated!
diff --git a/fineract-doc/src/docs/en/chapters/release/process-step10.adoc b/fineract-doc/src/docs/en/chapters/release/process-step10.adoc
new file mode 100644
index 000000000..d27916112
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/process-step10.adoc
@@ -0,0 +1,20 @@
+= Step 10: Start Vote
+
+== Description
+
+Voting has to be done on dev@fineract.apache.org. You can close the vote after voting period expires (72 hours) and you accumulate sufficient votes (minimum 3 x +1 PMC votes).
+
+[source,text]
+----
+include::{rootdir}/buildSrc/src/main/resources/email/release.step10.vote.subject.ftl[]
+
+include::{rootdir}/buildSrc/src/main/resources/email/release.step10.vote.message.ftl[]
+----
+
+== Gradle Task
+
+.Command
+[source,bash,subs="attributes"]
+----
+% ./gradlew fineractReleaseStep10 -Pfineract.release.version={revnumber}
+----
diff --git a/fineract-doc/src/docs/en/chapters/release/process-step11.adoc b/fineract-doc/src/docs/en/chapters/release/process-step11.adoc
new file mode 100644
index 000000000..e00de88ec
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/process-step11.adoc
@@ -0,0 +1,20 @@
+= Step 11: Finish Vote
+
+== Description
+
+Upon receiving 3 x +1 from the PMC, or after 72 hours (whichever one comes first), reply to the voting thread and add the prefix "[RESULT]" to the subject line with the results, as follows:
+
+[source,text]
+----
+include::{rootdir}/buildSrc/src/main/resources/email/release.step11.vote.subject.ftl[]
+
+include::{rootdir}/buildSrc/src/main/resources/email/release.step11.vote.message.ftl[]
+----
+
+== Gradle Task
+
+.Command
+[source,text,subs="attributes"]
+----
+% ./gradlew fineractReleaseStep11 -Pfineract.release.version={revnumber}
+----
diff --git a/fineract-doc/src/docs/en/chapters/release/process-step12.adoc b/fineract-doc/src/docs/en/chapters/release/process-step12.adoc
new file mode 100644
index 000000000..b93fd7f74
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/process-step12.adoc
@@ -0,0 +1,24 @@
+= Step 12: Upload Distribution Release
+
+== Description
+
+In order to release you have to checkout release repository located on https://dist.apache.org/repos/dist/release/fineract and add release artifacts there.
+
+[source,bash,subs="attributes"]
+----
+% svn co https://dist.apache.org/repos/dist/release/fineract fineract-release
+% mkdir fineract-release/{revnumber}/
+% cp fineract-dist-dev/{revnumber}/* fineract-release/{revnumber}/
+% svn add fineract-release/{revnumber}/
+% svn commit -m "Fineract Release {revnumber}" fineract-release/{revnumber}/
+----
+
+You will now get an automated email from the Apache Reporter Service (no-reply@reporter.apache.org), subject "Please add your release data for 'fineract'" to add the release data (version and date) to the database on https://reporter.apache.org/addrelease.html?fineract (requires PMC membership).
+
+== Gradle Task
+
+.Command
+[source,bash,subs="attributes"]
+----
+% ./gradlew fineractReleaseStep12 -Pfineract.release.version={revnumber}
+----
diff --git a/fineract-doc/src/docs/en/chapters/release/process-step13.adoc b/fineract-doc/src/docs/en/chapters/release/process-step13.adoc
new file mode 100644
index 000000000..49a2725f8
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/process-step13.adoc
@@ -0,0 +1,29 @@
+= Step 13: Close Release Branch
+
+== Description
+
+As discussed in https://issues.apache.org/jira/browse/FINERACT-1154[FINERACT-1154], now that everything is final, please do the following to remove the release branch (and just keep the tag), and make sure that everything on the release tag is merged to develop and that e.g. git describe works:
+
+[source,bash,subs="attributes"]
+----
+% git checkout develop
+% git branch -D {revnumber}
+% git push origin :{revnumber}
+% git checkout develop
+% git checkout -b merge-{revnumber}
+% git merge -s recursive -Xignore-all-space {revnumber}  <1>
+% git commit
+% git push $USER
+% hub pull-request
+----
+<1> Manually resolve merge conflicts, if any
+
+== Gradle Task
+
+.Command
+[source,bash,subs="attributes"]
+----
+% ./gradlew fineractReleaseStep13 -Pfineract.release.version={revnumber}
+----
+
+CAUTION: This task is not yet automated!
diff --git a/fineract-doc/src/docs/en/chapters/release/process-step14.adoc b/fineract-doc/src/docs/en/chapters/release/process-step14.adoc
new file mode 100644
index 000000000..366d20e36
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/process-step14.adoc
@@ -0,0 +1,18 @@
+= Step 14: Update website
+
+== Description
+
+Finally update the https://fineract.apache.org website with the latest release details. The website's HTML source code is available at https://github.com/apache/fineract-site.
+
+CAUTION: This step is not yet updated. We are working on a static site generator setup.
+
+== Gradle Task
+
+.Command
+[source,bash]
+----
+% ./gradlew fineractReleaseStep14 <1>
+----
+<1> Currently doing nothing. Will trigger in the future the static site generator and publish on Github.
+
+CAUTION: This task is not yet automated!
diff --git a/fineract-doc/src/docs/en/chapters/release/process-step15.adoc b/fineract-doc/src/docs/en/chapters/release/process-step15.adoc
new file mode 100644
index 000000000..5e85ee1cd
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/process-step15.adoc
@@ -0,0 +1,20 @@
+= Step 15: Announcement Email
+
+== Description
+
+Send an email to announce@apache.org (sender address must be @apache.org):
+
+[source,text]
+----
+include::{rootdir}/buildSrc/src/main/resources/email/release.step15.announce.subject.ftl[]
+
+include::{rootdir}/buildSrc/src/main/resources/email/release.step15.announce.message.ftl[]
+----
+
+== Gradle Task
+
+.Command
+[source,bash,subs="attributes"]
+----
+% ./gradlew fineractReleaseStep15 -Pfineract.release.version={revnumber}
+----
diff --git a/fineract-doc/src/docs/en/chapters/release/process.adoc b/fineract-doc/src/docs/en/chapters/release/process.adoc
new file mode 100644
index 000000000..6ef1b9f7a
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/release/process.adoc
@@ -0,0 +1,47 @@
+= Release Process
+
+TODO:
+
+* create "Jira anchor ticket" with all issues linked that are going into this release.
+* maintenance: continuously update the "Jira anchor ticket" to make sure we catch all ticket changes
+* maintenance: list tickets that have discrepancies, e. g. tickets still open while associated PR merged, ticket on wrong version (i. e. associated PR already merged before with another release).
+
+TBD
+
+CAUTION: Consider the Gradle plugin commands an experimental feature!
+
+.Release Process Diagram
+[plantuml,format=svg]
+----
+include::{diagramsdir}/release-process.puml[]
+----
+
+include::process-step01.adoc[leveloffset=+1]
+
+include::process-step02.adoc[leveloffset=+1]
+
+include::process-step03.adoc[leveloffset=+1]
+
+include::process-step04.adoc[leveloffset=+1]
+
+include::process-step05.adoc[leveloffset=+1]
+
+include::process-step06.adoc[leveloffset=+1]
+
+include::process-step07.adoc[leveloffset=+1]
+
+include::process-step08.adoc[leveloffset=+1]
+
+include::process-step09.adoc[leveloffset=+1]
+
+include::process-step10.adoc[leveloffset=+1]
+
+include::process-step11.adoc[leveloffset=+1]
+
+include::process-step12.adoc[leveloffset=+1]
+
+include::process-step13.adoc[leveloffset=+1]
+
+include::process-step14.adoc[leveloffset=+1]
+
+include::process-step15.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/api.adoc b/fineract-doc/src/docs/en/chapters/sdk/api.adoc
similarity index 50%
rename from fineract-doc/src/docs/en/api.adoc
rename to fineract-doc/src/docs/en/chapters/sdk/api.adoc
index 538f5342b..7e3fb9b70 100644
--- a/fineract-doc/src/docs/en/api.adoc
+++ b/fineract-doc/src/docs/en/chapters/sdk/api.adoc
@@ -1,4 +1,4 @@
-== Fineract OpenAPI Documentation
+= Fineract OpenAPI Documentation
 
 include::{generated}/overview.adoc[]
 
diff --git a/fineract-doc/src/docs/en/client.adoc b/fineract-doc/src/docs/en/chapters/sdk/client.adoc
similarity index 94%
rename from fineract-doc/src/docs/en/client.adoc
rename to fineract-doc/src/docs/en/chapters/sdk/client.adoc
index 917ca06a7..0a2fb9001 100644
--- a/fineract-doc/src/docs/en/client.adoc
+++ b/fineract-doc/src/docs/en/chapters/sdk/client.adoc
@@ -1,8 +1,8 @@
-== Generate Apache Fineract API Client
+= Generate Apache Fineract API Client
 
 Apache Fineract supports client code generation using https://openapi-generator.tech[OpenAPI Generator]. It uses https://swagger.io/specification/[OpenAPI Specification Version 3.0.3].
 
-=== Fineract SDK Java API Client
+== Fineract SDK Java API Client
 
 The `fineract-client.jar` will eventually be available on Maven Central (watch https://issues.apache.org/jira/browse/FINERACT-1102[FINERACT-1102]). Until it is, you can quite easily build the latest and greatest version locally from source, see below.
 
@@ -16,7 +16,7 @@ import static org.apache.fineract.client.util.Calls.ok;
 include::{rootdir}/fineract-client/src/test/java/org/apache/fineract/client/test/FineractClientDemo.java[tags=documentation]
 ----
 
-=== Generate API Client
+== Generate API Client
 
 The API client is built as part of the standard overall Fineract Gradle build. The client JAR can be found in `fineract-client/build/libs` as `fineract-client.jar`.
 
@@ -26,6 +26,6 @@ If you need to save time to incrementally work on making small changes to Swagge
 ./gradlew -x compileJava -x compileTest -x spotlessJava -x enhance resolve prepareInputYaml :fineract-client:buildJavaSdk
 ----
 
-=== Validate OpenAPI Spec File
+== Validate OpenAPI Spec File
 
 The `resolve` task in https://github.com/apache/fineract/blob/develop/fineract-provider/build.gradle#L80[build.gradle] file will generate the OpenAPI Spec File for the project. To make sure Swagger Codegen generates a correct library, it is important for the OpenAPI Spec file to be valid. Validation is done automatically by the OpenAPI code generator Gradle plugin. If you still have problems during code generation please use https://validator.swagger.io/[Swagger OpenAPI Validator] to val [...]
diff --git a/fineract-doc/src/docs/en/chapters/sdk/index.adoc b/fineract-doc/src/docs/en/chapters/sdk/index.adoc
new file mode 100644
index 000000000..eb8fb0455
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/sdk/index.adoc
@@ -0,0 +1,7 @@
+= Fineract SDKs
+
+TBD
+
+include::client.adoc[leveloffset=+1]
+
+// include::api.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/chapters/security/index.adoc b/fineract-doc/src/docs/en/chapters/security/index.adoc
new file mode 100644
index 000000000..2145ec6d7
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/security/index.adoc
@@ -0,0 +1,5 @@
+= Security
+
+TBD
+
+include::oauth.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/oauth.adoc b/fineract-doc/src/docs/en/chapters/security/oauth.adoc
similarity index 95%
rename from fineract-doc/src/docs/en/oauth.adoc
rename to fineract-doc/src/docs/en/chapters/security/oauth.adoc
index 071c565a4..8f7909d87 100644
--- a/fineract-doc/src/docs/en/oauth.adoc
+++ b/fineract-doc/src/docs/en/chapters/security/oauth.adoc
@@ -1,8 +1,8 @@
-== OAuth
+= OAuth
 
 Fineract has a (basic) OAuth2 support based on Spring Boot Security. Here's how to use it:
 
-=== Build
+== Build
 
 You must re-build the distribution JAR (or WAR) using the special `-Psecurity=oauth` flag:
 
@@ -16,7 +16,7 @@ Previous versions of Fineract included a built-in authorisation server for issui
 
 This instruction describes how to get Fineract OAuth working with a Keycloak (http://keycloak.org) based authentication provider running in a Docker container. The steps required for other OAuth providers will be similar. 
 
-=== Set up Keycloak
+== Set up Keycloak
 
 1. From terminal, run: 'docker run -p 9000:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin quay.io/keycloak/keycloak:15.0.2'
 1. Go to URL 'http://localhost:9000/auth/admin' and login with admin/admin
@@ -38,7 +38,7 @@ Finally we need to change Keycloak configuration so that it uses the username as
 
 You are now ready to test out OAuth:
 
-=== Retrieve an access token from Keycloak
+== Retrieve an access token from Keycloak
 
 ----
 curl --location --request POST \
@@ -53,7 +53,7 @@ curl --location --request POST \
 
 The reply should contain a field 'access_token'. Copy the field's value and use it in the API call below:
 
-=== Invoke APIs and pass `Authorization: bearer ...` header
+== Invoke APIs and pass `Authorization: bearer ...` header
 
 ----
 curl --location --request GET \
diff --git a/fineract-doc/src/docs/en/chapters/testing/cucumber-cheatsheet.adoc b/fineract-doc/src/docs/en/chapters/testing/cucumber-cheatsheet.adoc
new file mode 100644
index 000000000..4a2888a05
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/testing/cucumber-cheatsheet.adoc
@@ -0,0 +1,3 @@
+= Cheatsheet
+
+TBD
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/chapters/testing/cucumber-introduction.adoc b/fineract-doc/src/docs/en/chapters/testing/cucumber-introduction.adoc
new file mode 100644
index 000000000..42839e88a
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/testing/cucumber-introduction.adoc
@@ -0,0 +1,3 @@
+= Introduction
+
+TBD
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/chapters/testing/cucumber-tutorial.adoc b/fineract-doc/src/docs/en/chapters/testing/cucumber-tutorial.adoc
new file mode 100644
index 000000000..912dad8a5
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/testing/cucumber-tutorial.adoc
@@ -0,0 +1,3 @@
+= Tutorial
+
+TBD
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/chapters/testing/cucumber.adoc b/fineract-doc/src/docs/en/chapters/testing/cucumber.adoc
new file mode 100644
index 000000000..81a578358
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/testing/cucumber.adoc
@@ -0,0 +1,9 @@
+= Cucumber
+
+TBD
+
+include::cucumber-introduction.adoc[leveloffset=+1]
+
+include::cucumber-tutorial.adoc[leveloffset=+1]
+
+include::cucumber-cheatsheet.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/chapters/testing/index.adoc b/fineract-doc/src/docs/en/chapters/testing/index.adoc
new file mode 100644
index 000000000..847d24029
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/testing/index.adoc
@@ -0,0 +1,9 @@
+= Testing
+
+TBD
+
+include::cucumber.adoc[leveloffset=+1]
+
+include::unit.adoc[leveloffset=+1]
+
+include::integration.adoc[leveloffset=+1]
diff --git a/fineract-doc/src/docs/en/chapters/testing/integration.adoc b/fineract-doc/src/docs/en/chapters/testing/integration.adoc
new file mode 100644
index 000000000..b802ec0ef
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/testing/integration.adoc
@@ -0,0 +1,3 @@
+= Integration Testing
+
+TBD
diff --git a/fineract-doc/src/docs/en/chapters/testing/unit.adoc b/fineract-doc/src/docs/en/chapters/testing/unit.adoc
new file mode 100644
index 000000000..5729bb82c
--- /dev/null
+++ b/fineract-doc/src/docs/en/chapters/testing/unit.adoc
@@ -0,0 +1,3 @@
+= Unit Testing
+
+TBD
diff --git a/fineract-doc/src/docs/en/colophon.adoc b/fineract-doc/src/docs/en/colophon.adoc
index 8c8032f0d..1454f104c 100644
--- a/fineract-doc/src/docs/en/colophon.adoc
+++ b/fineract-doc/src/docs/en/colophon.adoc
@@ -33,6 +33,7 @@
 | Aleksandar Vidakovic | Initial version | 2020-10-26 | 1.4.0
 | Arnold Galovics | Database architecture section | 2022-03-11 | 1.7.0
 | Aleksandar Vidakovic | Module section | 2022-03-23 | 1.7.0
+| Aleksandar Vidakovic | Release section, file re-organisation | 2022-04-18 | 1.7.0
 |===
 
 toc::[]
diff --git a/fineract-doc/src/docs/en/config.adoc b/fineract-doc/src/docs/en/config.adoc
index 897103e38..f6f597849 100644
--- a/fineract-doc/src/docs/en/config.adoc
+++ b/fineract-doc/src/docs/en/config.adoc
@@ -9,13 +9,12 @@
 :page-layout: base
 :toc-title: Table of Contents
 :toc: macro
+:toclevels: 4
 :icons: font
 :source-highlighter: coderay
 :experimental:
 :source-language: java
-:diagramsdir: diagrams
-:imagesdir: images
-:years: 2017-2022
+:years: 2015-2022
 :lang: en
 :encoding: utf-8
 :linkattrs:
@@ -31,6 +30,8 @@
 // :title-page-background-image: image:{commondir}/images/draft.svg[position=top]
 // endif::[]
 
+ifdef::env-idea[:plantuml-opts: inline]
+
 ifdef::env-vscode[]
 :source-highlighter: highlightjs
 :kroki-fetch-diagram:
diff --git a/fineract-doc/src/docs/en/diagrams/architecture-overview.puml b/fineract-doc/src/docs/en/diagrams/architecture-overview.puml
new file mode 100644
index 000000000..febbbf163
--- /dev/null
+++ b/fineract-doc/src/docs/en/diagrams/architecture-overview.puml
@@ -0,0 +1,3 @@
+@startuml
+Bob -> Alice : Hello
+@enduml
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/diagrams/release-process.puml b/fineract-doc/src/docs/en/diagrams/release-process.puml
new file mode 100644
index 000000000..41195ba56
--- /dev/null
+++ b/fineract-doc/src/docs/en/diagrams/release-process.puml
@@ -0,0 +1,24 @@
+@startuml
+title Fineract Release Process
+
+(*) ---> "Step 0: Select release manager"
+--> "Step 1: Send heads-up email to dev mailing list"
+--> "Step 2: Clean up JIRA"
+--> "Step 3: Create a release branch"
+--> "Step 4: Freeze JIRA version"
+--> "Continue with development on 'develop' branch"
+--> [1-2 weeks] "Step 5: Create release tag"
+--> "Step 6: Create a distribution"
+--> "Step 7: Sign the distribution artifacts"
+--> "Step 8: Upload distribution artifacts to staging environment"
+--> "Step 9: Verify distribution in staging environment"
+--> "Step 10: Start voting on the dev mailing list"
+if "72 hours or 3 yes votes?" then
+  -->[yes] "Step 11: Conclude the vote and announce results"
+endif
+--> "Step 12: Upload distribution artifacts to release environment"
+--> "Step 13: Close release branch and merge to 'develop'"
+--> "Step 14: Update website (not yet automated)"
+--> "Step 15: Send email to announcement mailing list"
+--->(*)
+@enduml
diff --git a/fineract-doc/src/docs/en/diagrams/release-schedule.puml b/fineract-doc/src/docs/en/diagrams/release-schedule.puml
new file mode 100644
index 000000000..32c0c80b2
--- /dev/null
+++ b/fineract-doc/src/docs/en/diagrams/release-schedule.puml
@@ -0,0 +1,13 @@
+@startgantt
+[Heads up email] lasts 1 day
+[Open release branch] lasts 7 day
+[Prepare distribution for staging] lasts 2 days
+[Vote for distribution on staging] lasts 3 days
+[Prepare distribution for release] lasts 2 days
+[Announce release] lasts 2 days
+[Open release branch] starts at [Heads up email]'s end
+[Prepare distribution for staging] starts at [Open release branch]'s end
+[Vote for distribution on staging] starts at [Prepare distribution for staging]'s end
+[Prepare distribution for release] starts at [Vote for distribution on staging]'s end
+[Announce release] starts at [Prepare distribution for release]'s end
+@endgantt
diff --git a/fineract-doc/src/docs/en/faq.adoc b/fineract-doc/src/docs/en/faq.adoc
new file mode 100644
index 000000000..9052177aa
--- /dev/null
+++ b/fineract-doc/src/docs/en/faq.adoc
@@ -0,0 +1,4 @@
+[faq]
+= Frequently Asked Questions
+
+TBD
diff --git a/fineract-doc/src/docs/en/glossary.adoc b/fineract-doc/src/docs/en/glossary.adoc
index eb8fe72e0..675c86822 100644
--- a/fineract-doc/src/docs/en/glossary.adoc
+++ b/fineract-doc/src/docs/en/glossary.adoc
@@ -1 +1,4 @@
 [glossary]
+= Glossary
+
+TBD
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/index.adoc b/fineract-doc/src/docs/en/index.adoc
index 6f32d29be..2b77c7112 100644
--- a/fineract-doc/src/docs/en/index.adoc
+++ b/fineract-doc/src/docs/en/index.adoc
@@ -1,38 +1,39 @@
-:doctitle: Fineract Documentation
+:doctitle: Fineract Platform Documentation
 
 include::config.adoc[]
 
 = Fineract Documentation
 
-include::license.adoc[]
+include::license.adoc[leveloffset=+1]
 
-include::preface.adoc[]
+include::preface.adoc[leveloffset=+1]
 
-include::colophon.adoc[]
+include::colophon.adoc[leveloffset=+1]
 
-include::introduction.adoc[]
+include::introduction.adoc[leveloffset=+1]
 
-include::deployment.adoc[]
+include::chapters/deployment/index.adoc[leveloffset=+1]
 
-include::architecture.adoc[]
+include::chapters/architecture/index.adoc[leveloffset=+1]
 
-include::modules.adoc[]
+include::chapters/development/index.adoc[leveloffset=+1]
 
-include::oauth.adoc[]
+include::chapters/security/index.adoc[leveloffset=+1]
 
-// include::api.adoc[]
+include::{rootdir}/fineract-client/build/generated/asciidoc/index.adoc[leveloffset=+1]
 
-include::client.adoc[]
+include::chapters/sdk/index.adoc[leveloffset=+1]
 
-include::validation.adoc[]
+include::chapters/testing/index.adoc[leveloffset=+1]
 
-include::testing.adoc[]
+include::chapters/documentation/index.adoc[leveloffset=+1]
 
-include::deployment.adoc[]
+include::chapters/release/index.adoc[leveloffset=+1]
 
-include::glossary.adoc[]
+include::faq.adoc[leveloffset=+1]
 
-include::indices.adoc[]
+include::glossary.adoc[leveloffset=+1]
 
-include::appendix.adoc[]
+include::indices.adoc[leveloffset=+1]
 
+include::chapters/appendix/index.adoc[]
diff --git a/fineract-doc/src/docs/en/indices.adoc b/fineract-doc/src/docs/en/indices.adoc
index fac183dab..15e173f62 100644
--- a/fineract-doc/src/docs/en/indices.adoc
+++ b/fineract-doc/src/docs/en/indices.adoc
@@ -1,4 +1,4 @@
-<<<
-
 [index]
-== Index
+= Index
+
+TBD
\ No newline at end of file
diff --git a/fineract-doc/src/docs/en/introduction.adoc b/fineract-doc/src/docs/en/introduction.adoc
index 5d5f6ea81..d2893d926 100644
--- a/fineract-doc/src/docs/en/introduction.adoc
+++ b/fineract-doc/src/docs/en/introduction.adoc
@@ -1,6 +1,6 @@
-== Introduction
+= Introduction
 
-=== Platform for Digital Financial Services
+== Platform for Digital Financial Services
 
 Apache Fineract (\’fΔ«n-,Σ™-,rakt\) is open source software for financial services.
 
@@ -8,7 +8,7 @@ Fineract provides a reliable, robust, and affordable solution for entrepreneurs,
 
 Fineract 1.x is a mature platform with open APIs, while Fineract CN is a cloud native, microservice architecture also supporting open banking APIs.
 
-=== About
+== About
 
 Apache Fineract can be deployed in any environment: cloud or on-premise. It can support front end interfaces on or offline, mobile or PC. It’s extensible enough to support any organizational type or delivery channel, and flexible enough to support any product, service, or lending methodology. For any organization, big or small, it provides the client data management, loan and savings portfolio management, integrated real time accounting, and social and financial reporting needed to bring [...]
 
@@ -18,13 +18,13 @@ Fineract CN operates on the principle that financial services are an innovative
 
 Fineract 1.x began incubation at Apache in December 2015 and is used by an active community of companies who build solutions for both financial inclusion and fintech innovation.
 
-=== Contribute
+== Contribute
 
 The Apache Fineract community welcomes contributors who want to support the Fineract technology. Our community builds everything from this website, to the Fineract code to documentation and best practices information.
 
 We especially welcome additions and corrections to the documentation, wiki, and website to improve the user experience. Bug reports and fixes and additions to the Apache Fineract code are welcome. Helping users learn best practices also earns good karma in our community.
 
-=== Mailing Lists
+== Mailing Lists
 
 Users & Developers
 
diff --git a/fineract-doc/src/docs/en/license.adoc b/fineract-doc/src/docs/en/license.adoc
index 9bd9be395..83f18bb59 100644
--- a/fineract-doc/src/docs/en/license.adoc
+++ b/fineract-doc/src/docs/en/license.adoc
@@ -1,4 +1,4 @@
-== License
+= License
 
 Copyright 2022 Apache Foundation
 
diff --git a/fineract-doc/src/docs/en/preface.adoc b/fineract-doc/src/docs/en/preface.adoc
index 4ccb91079..268dcaf31 100644
--- a/fineract-doc/src/docs/en/preface.adoc
+++ b/fineract-doc/src/docs/en/preface.adoc
@@ -1,5 +1,5 @@
 [preface]
-== Preface
+= Preface
 (C) {years}
 
 :hardbreaks:
diff --git a/fineract-doc/src/docs/en/testing.adoc b/fineract-doc/src/docs/en/testing.adoc
deleted file mode 100644
index 69d991520..000000000
--- a/fineract-doc/src/docs/en/testing.adoc
+++ /dev/null
@@ -1,5 +0,0 @@
-== Testing
-
-=== Cucumber
-
-TBD.
\ No newline at end of file
diff --git a/fineract-provider/build.gradle b/fineract-provider/build.gradle
index eaa7e332f..981c9d64c 100644
--- a/fineract-provider/build.gradle
+++ b/fineract-provider/build.gradle
@@ -231,8 +231,6 @@ bootJar {
     classifier = ''
 }
 
-jar.dependsOn bootJar
-
 jib {
     from {
         image = 'azul/zulu-openjdk-alpine:17'
@@ -241,7 +239,7 @@ jib {
     to {
         image = 'fineract'
         tags = [
-            "${version}",
+            "${project.version}",
             'latest'
         ]
     }
diff --git a/fineract-provider/dependencies.gradle b/fineract-provider/dependencies.gradle
index de3fb667a..d7c7fc6b6 100644
--- a/fineract-provider/dependencies.gradle
+++ b/fineract-provider/dependencies.gradle
@@ -64,7 +64,7 @@ dependencies {
             'com.github.spotbugs:spotbugs-annotations',
             'io.swagger.core.v3:swagger-annotations',
 
-            'com.google.cloud.sql:mysql-socket-factory-connector-j-8:1.5.0',
+            'com.google.cloud.sql:mysql-socket-factory-connector-j-8',
             'com.squareup.retrofit2:converter-gson',
             'com.sun.activation:jakarta.activation',
             'com.sun.mail:jakarta.mail',
@@ -74,7 +74,7 @@ dependencies {
             'org.springdoc:springdoc-openapi-security',
             )
 
-    implementation ('org.apache.commons:commons-email:1.5') {
+    implementation ('org.apache.commons:commons-email') {
         exclude group: 'com.sun.mail', module: 'javax.mail'
         exclude group: 'javax.activation', module: 'activation'
     }
diff --git a/fineract-war/build.gradle b/fineract-war/build.gradle
index 2a1b9d2d4..0e560020d 100644
--- a/fineract-war/build.gradle
+++ b/fineract-war/build.gradle
@@ -20,7 +20,6 @@ description = 'Fineract WAR'
 
 apply plugin: 'war'
 apply plugin: 'distribution'
-apply plugin: 'signing'
 
 war {
     archiveFileName = 'fineract-provider.war'
@@ -82,6 +81,9 @@ distributions {
 
             from "$rootDir/DISCLAIMER"
             from "$rootDir/README.md"
+
+            from "$rootDir/fineract-doc/build/docs/pdf/en/index.pdf"
+            rename ('index.pdf', 'fineract-documentation.pdf')
         }
     }
     src {
@@ -102,38 +104,5 @@ distributions {
 
 tasks.binaryDistZip.enabled false
 tasks.srcDistZip.enabled false
-tasks.binaryDistTar.dependsOn war
+tasks.binaryDistTar.dependsOn = [war, ':fineract-doc:doc']
 // tasks.srcDistTar.dependsOn prepareInputYaml
-
-// create signatures and checksums only if project parameter "fineract.release" is provided on the command line
-if( project.hasProperty("fineract.release") ) {
-    signing {
-        useGpgCmd()
-        sign (binaryDistTar, srcDistTar)
-    }
-    tasks.withType(Tar) { task ->
-        task.doLast {
-            ant.checksum file: task.archivePath, algorithm: 'SHA-512', fileext: '.sha512'
-        }
-    }
-    tasks.withType(Sign) { task ->
-        task.doLast {
-            task.getFilesToSign().each { f ->
-                new ByteArrayOutputStream().withStream { os ->
-                    def result = exec {
-                        workingDir "$buildDir/distributions"
-                        executable 'sh'
-                        args '-c', "gpg --verify ${f}.asc"
-                        standardOutput = os
-                    }
-                    if(result.exitValue==0) {
-                        println '+++ GPG signature correct!'
-                    } else {
-                        println '--- GPG signature incorrect!'
-                        throw new RuntimeException('--- GPG signature incorrect!')
-                    }
-                }
-            }
-        }
-    }
-}