diff --git a/.github/workflows/bi-connectors.yml b/.github/workflows/bi-connectors.yml
index 7e339967b0..bb0f9dd809 100644
--- a/.github/workflows/bi-connectors.yml
+++ b/.github/workflows/bi-connectors.yml
@@ -42,13 +42,13 @@ jobs:
       working-directory: bi-connectors/PowerBIConnector
     - name: Upload Tableau JDBC connector
       if: steps.pack-tableau-jdbc.outcome == 'success'
-      uses: actions/upload-artifact@v2
+      uses: actions/upload-artifact@v4
       with:
         name: TableauConnectors
         path: bi-connectors/TableauConnector/opensearch_sql_jdbc/opensearch_sql_jdbc.taco
     - name: Upload Power BI ODBC connectors
       if: steps.pack-powerbi-odbc-os-proj.outcome == 'success' || (steps.prep-powerbi-odbc-amz-os-svc.outcome == 'success' && steps.pack-powerbi-odbc-amz-os-svc.outcome == 'success')
-      uses: actions/upload-artifact@v2
+      uses: actions/upload-artifact@v4
       with:
         name: PBIConnectors
         path: 'bi-connectors/PowerBIConnector/*.mez'
diff --git a/.github/workflows/sql-cli-test-and-build-workflow.yml b/.github/workflows/sql-cli-test-and-build-workflow.yml
index 3de1ff3aa5..a52d130486 100644
--- a/.github/workflows/sql-cli-test-and-build-workflow.yml
+++ b/.github/workflows/sql-cli-test-and-build-workflow.yml
@@ -57,7 +57,7 @@ jobs:
           cp -r ./dist/*.tar.gz ./dist/*.whl opensearchsql-builds/
 
       - name: Upload Artifact
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v4
         with:
           name: opensearchsql
           path: sql-cli/opensearchsql-builds
diff --git a/.github/workflows/sql-jdbc-test-and-build-workflow.yml b/.github/workflows/sql-jdbc-test-and-build-workflow.yml
index f32cfd9511..2e5320c8a1 100644
--- a/.github/workflows/sql-jdbc-test-and-build-workflow.yml
+++ b/.github/workflows/sql-jdbc-test-and-build-workflow.yml
@@ -27,7 +27,7 @@ jobs:
         cp ./build/libs/*.jar sql-jdbc-builds
 
     - name: Upload Artifacts
-      uses: actions/upload-artifact@v1
+      uses: actions/upload-artifact@v4
       with:
         name: sql-jdbc
         path: sql-jdbc/sql-jdbc-builds
diff --git a/.github/workflows/sql-odbc-main.yml b/.github/workflows/sql-odbc-main.yml
index 0a22780aa9..264d59bfd3 100644
--- a/.github/workflows/sql-odbc-main.yml
+++ b/.github/workflows/sql-odbc-main.yml
@@ -23,7 +23,7 @@ jobs:
         sh run_cppcheck.sh
     - name: upload-cppcheck-results
       if: failure()
-      uses: actions/upload-artifact@v1
+      uses: actions/upload-artifact@v4
       with:
         name: cppcheck-results
         path: sql-odbc/cppcheck-results.log
@@ -61,19 +61,19 @@ jobs:
     #    cp ./bin64/*.log test-output
     - name: upload-build
       if: success()
-      uses: actions/upload-artifact@v1
+      uses: actions/upload-artifact@v4
       with:
         name: mac64-build
         path: sql-odbc/build-output
     - name: upload-installer
       if: success()
-      uses: actions/upload-artifact@v1
+      uses: actions/upload-artifact@v4
       with:
         name: mac64-installer
         path: sql-odbc/installer
     #- name: upload-test-results
-    #  if: success()
-    #  uses: actions/upload-artifact@v1
+    #  if: always()
+    #  uses: actions/upload-artifact@v4
     #  with:
     #    name: mac-test-results
     #    path: test-output
@@ -106,19 +106,19 @@ jobs:
         .\scripts\prepare_ci_output.ps1 $Env:ODBC_BIN_PATH $Env:ODBC_LIB_PATH $Env:ODBC_BUILD_PATH
     - name: upload-build
       if: always()
-      uses: actions/upload-artifact@v1
+      uses: actions/upload-artifact@v4
       with:
         name: windows32-build
         path: sql-odbc/ci-output/build
     - name: upload-installer
       if: always()
-      uses: actions/upload-artifact@v1
+      uses: actions/upload-artifact@v4
       with:
         name: windows32-installer
         path: sql-odbc/ci-output/installer
     #- name: upload-test-results
     #  if: always()
-    #  uses: actions/upload-artifact@v1
+    #  uses: actions/upload-artifact@v4
     #  with:
     #    name: windows-test-results
     #    path: $CI_OUTPUT_PATH/test
@@ -151,19 +151,19 @@ jobs:
         .\scripts\prepare_ci_output.ps1 $Env:ODBC_BIN_PATH $Env:ODBC_LIB_PATH $Env:ODBC_BUILD_PATH
     - name: upload-build
       if: always()
-      uses: actions/upload-artifact@v1
+      uses: actions/upload-artifact@v4
       with:
         name: windows64-build
         path: sql-odbc/ci-output/build
     - name: upload-installer
       if: always()
-      uses: actions/upload-artifact@v1
+      uses: actions/upload-artifact@v4
       with:
         name: windows64-installer
         path: sql-odbc/ci-output/installer
     #- name: upload-test-results
     #  if: always()
-    #  uses: actions/upload-artifact@v1
+    #  uses: actions/upload-artifact@v4
     #  with:
     #    name: windows-test-results
     #    path: sql-odbc/ci-output/test-output
diff --git a/.github/workflows/sql-test-and-build-workflow.yml b/.github/workflows/sql-test-and-build-workflow.yml
index 2db8063f96..d669264b22 100644
--- a/.github/workflows/sql-test-and-build-workflow.yml
+++ b/.github/workflows/sql-test-and-build-workflow.yml
@@ -42,7 +42,7 @@ jobs:
         token: ${{ secrets.CODECOV_TOKEN }}
 
     - name: Upload Artifacts
-      uses: actions/upload-artifact@v1
+      uses: actions/upload-artifact@v4
       with:
         name: opensearch-sql
         path: opensearch-sql-builds
diff --git a/.github/workflows/sql-test-workflow.yml b/.github/workflows/sql-test-workflow.yml
new file mode 100644
index 0000000000..c0899d3419
--- /dev/null
+++ b/.github/workflows/sql-test-workflow.yml
@@ -0,0 +1,95 @@
+name: SQL Plugin Tests
+
+on:
+  workflow_dispatch:
+    inputs:
+      name:
+        required: false
+        type: string
+
+run-name:
+  ${{ inputs.name == '' && format('{0} @ {1}', github.ref_name, github.sha) || inputs.name }}
+
+jobs:
+  build:
+    strategy:
+      matrix:
+        java:
+          - 11
+          - 17
+    runs-on: ubuntu-latest
+
+    steps:
+    - uses: actions/checkout@v3
+
+    - name: Set up JDK ${{ matrix.java }}
+      uses: actions/setup-java@v3
+      with:
+        distribution: 'temurin'
+        java-version: ${{ matrix.java }}
+
+    - name: Run tests
+      id: tests
+      run: |
+        # checkstyle
+        ./gradlew :opensearch:checkstyleMain              || echo "* Checkstyle failed for opensearch/src" > report.log
+        ./gradlew :opensearch:checkstyleTest              || echo "* Checkstyle failed for opensearch/test" >> report.log
+        ./gradlew :sql:checkstyleMain                     || echo "* Checkstyle failed for sql/src" >> report.log
+        ./gradlew :sql:checkstyleTest                     || echo "* Checkstyle failed for sql/test" >> report.log
+        ./gradlew :ppl:checkstyleMain                     || echo "* Checkstyle failed for ppl/src" >> report.log
+        ./gradlew :ppl:checkstyleTest                     || echo "* Checkstyle failed for ppl/test" >> report.log
+        ./gradlew :core:checkstyleMain                    || echo "* Checkstyle failed for core/src" >> report.log
+        ./gradlew :core:checkstyleTest                    || echo "* Checkstyle failed for core/test" >> report.log
+        ./gradlew :common:checkstyleMain                  || echo "* Checkstyle failed for common/src" >> report.log
+        ./gradlew :common:checkstyleTest                  || echo "* Checkstyle failed for common/test" >> report.log
+        ./gradlew :legacy:checkstyleMain                  || echo "* Checkstyle failed for legacy/src" >> report.log
+        ./gradlew :legacy:checkstyleTest                  || echo "* Checkstyle failed for legacy/test" >> report.log
+        ./gradlew :protocol:checkstyleMain                || echo "* Checkstyle failed for protocol/src" >> report.log
+        ./gradlew :protocol:checkstyleTest                || echo "* Checkstyle failed for protocol/test" >> report.log
+        ./gradlew :opensearch-sql-plugin:checkstyleMain   || echo "* Checkstyle failed for plugin/src" >> report.log
+        ./gradlew :opensearch-sql-plugin:checkstyleTest   || echo "* Checkstyle failed for plugin/test" >> report.log
+        # Add checkstyle for `integ-test` when fixed
+        # Unit tests
+        ./gradlew :opensearch:test                        || echo "* Unit tests failed for opensearch" >> report.log
+        ./gradlew :ppl:test                               || echo "* Unit tests failed for sql" >> report.log
+        ./gradlew :sql:test                               || echo "* Unit tests failed for ppl" >> report.log
+        ./gradlew :core:test                              || echo "* Unit tests failed for core" >> report.log
+        ./gradlew :protocol:test                          || echo "* Unit tests failed for protocol" >> report.log
+        ./gradlew :opensearch-sql-plugin:test             || echo "* Unit tests failed for plugin" >> report.log
+        ./gradlew :legacy:test                            || echo "* Unit tests failed for legacy" >> report.log
+        # jacoco
+        ./gradlew :opensearch:jacocoTestCoverageVerification             || echo "* Jacoco failed for opensearch" >> report.log
+        ./gradlew :ppl:jacocoTestCoverageVerification                    || echo "* Jacoco failed for sql" >> report.log
+        ./gradlew :sql:jacocoTestCoverageVerification                    || echo "* Jacoco failed for ppl" >> report.log
+        ./gradlew :core:jacocoTestCoverageVerification                   || echo "* Jacoco failed for core" >> report.log
+        ./gradlew :protocol:jacocoTestCoverageVerification               || echo "* Jacoco failed for protocol" >> report.log
+        ./gradlew :opensearch-sql-plugin:jacocoTestCoverageVerification  || echo "* Jacoco failed for plugin" >> report.log
+        # Misc tests
+        ./gradlew :integ-test:integTest                   || echo "* Integration test failed" >> report.log
+        ./gradlew :doctest:doctest                        || echo "* Doctest failed" >> report.log
+        ./scripts/bwctest.sh                              || echo "* Backward compatibility test failed" >> report.log
+
+    - name: Verify test results
+      run: |
+        if [[ -e report.log ]]
+        then
+          echo "## FAILED TESTS :facepalm::warning::bangbang:" >> $GITHUB_STEP_SUMMARY
+          cat report.log >> $GITHUB_STEP_SUMMARY
+          exit 1
+        fi
+
+    - name: Upload test reports
+      if: always()
+      uses: actions/upload-artifact@v4
+      with:
+        name: test-reports
+        path: |
+          sql/build/reports/**
+          ppl/build/reports/**
+          core/build/reports/**
+          common/build/reports/**
+          opensearch/build/reports/**
+          integ-test/build/reports/**
+          protocol/build/reports/**
+          legacy/build/reports/**
+          plugin/build/reports/**
diff --git a/build.gradle b/build.gradle
index d3e1a51f06..77a5fbb063 100644
--- a/build.gradle
+++ b/build.gradle
@@ -6,7 +6,8 @@
 
 buildscript {
     ext {
-        opensearch_version = System.getProperty("opensearch.version", "1.3.3-SNAPSHOT")
+        opensearch_version = System.getProperty("opensearch.version", "1.3.4-SNAPSHOT")
+        spring_version = "5.3.39"
     }
 
     repositories {
diff --git a/core/build.gradle b/core/build.gradle
index 17bb1e1a71..5ced00381a 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -40,8 +40,8 @@ repositories {
 
 dependencies {
     compile group: 'com.google.guava', name: 'guava', version: '31.0.1-jre'
-    compile group: 'org.springframework', name: 'spring-context', version: '5.2.20.RELEASE'
-    compile group: 'org.springframework', name: 'spring-beans', version: '5.2.20.RELEASE'
+    compile group: 'org.springframework', name: 'spring-context', version: "${spring_version}"
+    compile group: 'org.springframework', name: 'spring-beans', version: "${spring_version}"
     compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.10'
     compile group: 'com.facebook.presto', name: 'presto-matching', version: '0.240'
     compile group: 'org.apache.commons', name: 'commons-math3', version: '3.6.1'
@@ -49,7 +49,7 @@ dependencies {
 
     testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
     testCompile group: 'org.hamcrest', name: 'hamcrest-library', version: '2.1'
-    testCompile group: 'org.springframework', name: 'spring-test', version: '5.2.20.RELEASE'
+    testCompile group: 'org.springframework', name: 'spring-test', version: "${spring_version}"
     testCompile group: 'org.mockito', name: 'mockito-core', version: '3.3.3'
     testCompile group: 'org.mockito', name: 'mockito-junit-jupiter', version: '3.3.3'
 }
diff --git a/plugin/build.gradle b/plugin/build.gradle
index 3ed4407ebe..e220ad4831 100644
--- a/plugin/build.gradle
+++ b/plugin/build.gradle
@@ -65,7 +65,7 @@ configurations.all {
 }
 
 dependencies {
-    compile group: 'org.springframework', name: 'spring-beans', version: '5.2.20.RELEASE'
+    compile group: 'org.springframework', name: 'spring-beans', version: "${spring_version}"
     compile project(":ppl")
     compile project(':legacy')
     compile project(':opensearch')
diff --git a/ppl/build.gradle b/ppl/build.gradle
index 4b0d361555..8b96d302d8 100644
--- a/ppl/build.gradle
+++ b/ppl/build.gradle
@@ -48,8 +48,8 @@ dependencies {
     compile group: 'com.google.guava', name: 'guava', version: '31.0.1-jre'
     compile group: 'org.opensearch', name: 'opensearch-x-content', version: "${opensearch_version}"
     compile group: 'org.json', name: 'json', version: '20180813'
-    compile group: 'org.springframework', name: 'spring-context', version: '5.2.20.RELEASE'
-    compile group: 'org.springframework', name: 'spring-beans', version: '5.2.20.RELEASE'
+    compile group: 'org.springframework', name: 'spring-context', version: "${spring_version}"
+    compile group: 'org.springframework', name: 'spring-beans', version: "${spring_version}"
     compile group: 'org.apache.logging.log4j', name: 'log4j-core', version:'2.17.1'
     compile project(':common')
     compile project(':core')
diff --git a/sql/build.gradle b/sql/build.gradle
index e49810fb5f..8572be7f3f 100644
--- a/sql/build.gradle
+++ b/sql/build.gradle
@@ -47,8 +47,8 @@ dependencies {
     compile "org.antlr:antlr4-runtime:4.7.1"
     implementation group: 'com.google.guava', name: 'guava', version: '31.0.1-jre'
     compile group: 'org.json', name: 'json', version:'20180813'
-    compile group: 'org.springframework', name: 'spring-context', version: '5.2.20.RELEASE'
-    compile group: 'org.springframework', name: 'spring-beans', version: '5.2.20.RELEASE'
+    compile group: 'org.springframework', name: 'spring-context', version: "${spring_version}"
+    compile group: 'org.springframework', name: 'spring-beans', version: "${spring_version}"
     compile project(':common')
     compile project(':core')
     compile project(':protocol')