diff --git a/.github/workflows/build-core.yml b/.github/workflows/build-core.yml new file mode 100644 index 00000000000..1a5f435742e --- /dev/null +++ b/.github/workflows/build-core.yml @@ -0,0 +1,91 @@ +name: Fineract Build Core + +on: + workflow_call: + +permissions: + contents: read + +jobs: + build-core: + runs-on: ubuntu-24.04 + timeout-minutes: 60 + + env: + TZ: Asia/Kolkata + DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} + + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Set up JDK 21 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + java-version: '21' + distribution: 'zulu' + + - name: Cache Gradle dependencies + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + + - name: Setup Gradle and Validate Wrapper + uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + with: + validate-wrappers: true + + - name: Build Avro Java SDK + run: ./gradlew --no-daemon :fineract-avro-schemas:buildJavaSdk -x test -x cucumber -x doc -x javadoc -x javadocJar -x checkstyleMain -x checkstyleTest -x checkstyleJmh -x spotbugsMain -x spotbugsTest -x spotlessCheck -x spotlessApply -x rat + + - name: Compile Fineract Provider + run: ./gradlew --no-daemon :fineract-provider:compileJava -x test -x cucumber -x doc -x buildJavaSdk -x javadoc -x javadocJar -x checkstyleMain -x checkstyleTest -x checkstyleJmh -x spotbugsMain -x spotbugsTest -x spotlessCheck -x spotlessApply -x rat + + - name: Generate Fineract Git Properties + run: ./gradlew --no-daemon :fineract-provider:generateGitProperties -x javadoc -x javadocJar -x checkstyleMain -x checkstyleTest -x checkstyleJmh -x spotbugsMain -x spotbugsTest -x spotlessCheck -x spotlessApply -x rat + + - name: Verify generated git.properties + run: test -f fineract-provider/build/resources/main/git.properties + + - name: Build Fineract Client Java SDK + run: ./gradlew --no-daemon :fineract-client:buildJavaSdk -x test -x cucumber -x doc -x javadoc -x javadocJar -x checkstyleMain -x checkstyleTest -x checkstyleJmh -x spotbugsMain -x spotbugsTest -x spotlessCheck -x spotlessApply -x rat + + - name: Build Fineract Client Feign Java SDK + run: ./gradlew --no-daemon :fineract-client-feign:buildJavaSdk -x test -x cucumber -x doc -x javadoc -x javadocJar -x checkstyleMain -x checkstyleTest -x checkstyleJmh -x spotbugsMain -x spotbugsTest -x spotlessCheck -x spotlessApply -x rat + + - name: Build Fineract + run: ./gradlew --no-daemon build -x test -x cucumber -x doc -x javadoc -x javadocJar -x checkstyleMain -x checkstyleTest -x checkstyleJmh -x spotbugsMain -x spotbugsTest -x spotlessCheck -x spotlessApply -x rat + + - name: Pack workspace + run: | + tar --exclude='./fineract-workspace.tar' -cf fineract-workspace.tar . + + - name: Upload workspace + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: fineract-workspace-${{ github.run_id }} + path: fineract-workspace.tar + retention-days: 1 + + - name: Archive test results + if: always() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: test-results-build-core + path: '**/build/reports/' + if-no-files-found: ignore + retention-days: 5 + + - name: Archive server logs + if: always() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: server-logs-build-core + path: '**/build/cargo/' + retention-days: 5 diff --git a/.github/workflows/build-cucumber.yml b/.github/workflows/build-cucumber.yml index ddb3224fc66..9dc221ef5c5 100644 --- a/.github/workflows/build-cucumber.yml +++ b/.github/workflows/build-cucumber.yml @@ -1,114 +1,57 @@ -name: Fineract Build & Cucumber tests (without E2E tests) +name: Fineract Cucumber tests (without E2E tests) -on: [push, pull_request] +on: + workflow_call: permissions: contents: read jobs: - verify: + cucumber: runs-on: ubuntu-24.04 timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - task: build-core - job_type: main - - task: cucumber - job_type: main - - task: build-progressive-loan - job_type: progressive-loan - env: TZ: Asia/Kolkata DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} steps: - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 - fetch-tags: true - - name: Set up JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: java-version: '21' distribution: 'zulu' - - name: Cache Gradle dependencies - uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 + - name: Download workspace + uses: actions/download-artifact@v5 with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + name: fineract-workspace-${{ github.run_id }} + path: . + + - name: Extract workspace + run: tar -xf fineract-workspace.tar - name: Setup Gradle and Validate Wrapper uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 with: validate-wrappers: true - - name: Run Gradle Task - if: matrix.job_type == 'main' - run: | - set -e # Fail the script if any command fails - - case "${{ matrix.task }}" in - build-core) - ./gradlew --no-daemon build -x test -x cucumber -x doc - ;; - cucumber) - ./gradlew --no-daemon cucumber -x :fineract-e2e-tests-runner:cucumber -x checkstyleJmh -x checkstyleMain -x checkstyleTest -x spotlessCheck -x spotlessApply -x spotbugsMain -x spotbugsTest -x javadoc -x javadocJar -x modernizer - ;; - esac - - - name: Build and Test Progressive Loan - if: matrix.job_type == 'progressive-loan' - run: | - # Build the JAR - ./gradlew --no-daemon --console=plain :fineract-progressive-loan-embeddable-schedule-generator:shadowJar - - # Store the JAR filename in an environment variable - EMBEDDABLE_JAR_FILE=$(ls fineract-progressive-loan-embeddable-schedule-generator/build/libs/*-all.jar | head -n 1) - echo "EMBEDDABLE_JAR_FILE=$EMBEDDABLE_JAR_FILE" >> $GITHUB_ENV - echo "JAR file: $EMBEDDABLE_JAR_FILE" - - # Run unit tests - ./gradlew --no-daemon --console=plain :fineract-progressive-loan-embeddable-schedule-generator:test - - # Build and run sample application - mkdir -p sample-app - javac -cp "$EMBEDDABLE_JAR_FILE" -d sample-app fineract-progressive-loan-embeddable-schedule-generator/misc/Main.java - java -cp "$EMBEDDABLE_JAR_FILE:sample-app" Main - java -cp "$EMBEDDABLE_JAR_FILE:sample-app" Main 25 + - name: Run Cucumber + run: ./gradlew --no-daemon cucumber -x :fineract-e2e-tests-runner:cucumber -x checkstyleJmh -x checkstyleMain -x checkstyleTest -x spotlessCheck -x spotlessApply -x spotbugsMain -x spotbugsTest -x javadoc -x javadocJar -x modernizer -x buildJavaSdk - name: Archive test results if: always() uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: - name: test-results-${{ matrix.task }} - path: | - **/build/reports/ - **/fineract-progressive-loan-embeddable-schedule-generator/build/reports/ + name: test-results-cucumber + path: '**/build/reports/' if-no-files-found: ignore retention-days: 5 - - name: Archive Progressive Loan JAR - if: matrix.job_type == 'progressive-loan' && always() - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 - with: - name: progressive-loan-jar - path: ${{ env.EMBEDDABLE_JAR_FILE }} - retention-days: 5 - if-no-files-found: ignore - - name: Archive server logs if: always() uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: - name: server-logs-${{ matrix.task }} + name: server-logs-cucumber path: '**/build/cargo/' retention-days: 5 diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml index 18a6d6b6656..1e208328754 100644 --- a/.github/workflows/build-docker.yml +++ b/.github/workflows/build-docker.yml @@ -1,6 +1,7 @@ name: Fineract Docker Builds -on: [push, pull_request] +on: + workflow_call: permissions: contents: read @@ -26,21 +27,32 @@ jobs: IMAGE_NAME: fineract steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 - - name: Set up JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: java-version: '21' distribution: 'zulu' + - name: Download workspace + uses: actions/download-artifact@v5 + with: + name: fineract-workspace-${{ github.run_id }} + path: . + + - name: Extract workspace + run: tar -xf fineract-workspace.tar + - name: Setup Gradle uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 - name: Build the image - run: ./gradlew --no-daemon --console=plain :fineract-provider:jibDockerBuild -Djib.to.image=$IMAGE_NAME -x test -x cucumber + run: ./gradlew --no-daemon --console=plain :fineract-provider:jibDockerBuild -Djib.to.image=$IMAGE_NAME -x test -x cucumber -x buildJavaSdk + + - name: Verify git.properties in image + run: | + docker create --name fineract-inspect $IMAGE_NAME + docker export fineract-inspect | tar -tf - | grep 'git.properties' + docker rm fineract-inspect - name: Start the ${{ matrix.db_type }} stack run: docker compose -f ${{ matrix.compose_file }} up -d @@ -52,4 +64,7 @@ jobs: run: curl -f -k --retry 60 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/health - name: Check info Manager - run: (( $(curl -f -k --retry 5 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/info | wc --chars) > 100 )) + run: | + curl -f -k --retry 5 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/info -o actuator-info.json + cat actuator-info.json + jq -e '.git | type == "object"' actuator-info.json diff --git a/.github/workflows/build-documentation.yml b/.github/workflows/build-documentation.yml index 10af8cb47c0..84c24bd224c 100644 --- a/.github/workflows/build-documentation.yml +++ b/.github/workflows/build-documentation.yml @@ -1,5 +1,6 @@ name: Fineract Documentation build -on: [push, pull_request] +on: + workflow_call: permissions: contents: read jobs: @@ -9,15 +10,18 @@ jobs: env: DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} steps: - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 - name: Set up JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: java-version: '21' distribution: 'zulu' + - name: Download workspace + uses: actions/download-artifact@v5 + with: + name: fineract-workspace-${{ github.run_id }} + path: . + - name: Extract workspace + run: tar -xf fineract-workspace.tar - name: Setup Gradle uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 @@ -32,4 +36,4 @@ jobs: sudo apt-get update sudo apt-get install ghostscript graphviz -y - name: Documentation build - run: ./gradlew --no-daemon --console=plain doc + run: ./gradlew --no-daemon --console=plain doc -x buildJavaSdk diff --git a/.github/workflows/build-e2e-tests.yml b/.github/workflows/build-e2e-tests.yml index 4eece516891..94c9cf4d86c 100644 --- a/.github/workflows/build-e2e-tests.yml +++ b/.github/workflows/build-e2e-tests.yml @@ -1,6 +1,7 @@ name: Fineract E2E Tests -on: [push, pull_request] +on: + workflow_call: permissions: contents: read @@ -32,17 +33,21 @@ jobs: ACTIVEMQ_TOPIC_NAME: events steps: - - name: Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 - - name: Set up JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: java-version: '21' distribution: 'zulu' + - name: Download workspace + uses: actions/download-artifact@v5 + with: + name: fineract-workspace-${{ github.run_id }} + path: . + + - name: Extract workspace + run: tar -xf fineract-workspace.tar + - name: Setup Gradle uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 @@ -57,7 +62,7 @@ jobs: cat feature_shard_${{ matrix.shard_index }}.txt - name: Build the image - run: ./gradlew --no-daemon --console=plain :fineract-provider:jibDockerBuild -Djib.to.image=$IMAGE_NAME -x test -x cucumber + run: ./gradlew --no-daemon --console=plain :fineract-provider:jibDockerBuild -Djib.to.image=$IMAGE_NAME -x test -x cucumber -x buildJavaSdk - name: Start the Fineract stack run: docker compose -f docker-compose-postgresql-test-activemq.yml up -d @@ -116,7 +121,11 @@ jobs: :fineract-e2e-tests-runner:cucumber \ -Pcucumber.features="$feature_file" \ -Dallure.results.directory="allure-results-shard-${{ matrix.shard_index }}/$safe_name" \ - allureReport; then + allureReport \ + -x buildJavaSdk \ + -x :fineract-client:buildJavaSdk \ + -x :fineract-client-feign:buildJavaSdk \ + -x :fineract-avro-schemas:buildJavaSdk; then echo "::error::Test failed for $feature_file" FAILED=1 diff --git a/.github/workflows/build-mariadb.yml b/.github/workflows/build-mariadb.yml index 2dce16dba90..66237757c2e 100644 --- a/.github/workflows/build-mariadb.yml +++ b/.github/workflows/build-mariadb.yml @@ -1,6 +1,7 @@ name: Fineract Cargo & Unit- & Integration tests - MariaDB -on: [push, pull_request] +on: + workflow_call: permissions: contents: read @@ -43,25 +44,20 @@ jobs: FINERACT_REPORT_EXPORT_S3_BUCKET_NAME: fineract-reports steps: - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 - fetch-tags: true - - name: Set up JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: java-version: '21' distribution: 'zulu' - - name: Cache Gradle dependencies - uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 + - name: Download workspace + uses: actions/download-artifact@v5 with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + name: fineract-workspace-${{ github.run_id }} + path: . + + - name: Extract workspace + run: tar -xf fineract-workspace.tar - name: Setup Gradle and Validate Wrapper uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 @@ -81,8 +77,8 @@ jobs: - name: Initialise databases run: | - ./gradlew --no-daemon -q createDB -PdbName=fineract_tenants - ./gradlew --no-daemon -q createDB -PdbName=fineract_default + ./gradlew --no-daemon -q createDB -PdbName=fineract_tenants -x buildJavaSdk + ./gradlew --no-daemon -q createDB -PdbName=fineract_default -x buildJavaSdk - name: Start LocalStack run: | @@ -123,7 +119,7 @@ jobs: test_args=$(for class in ${module_tests[$module]}; do echo --tests "$class"; done | xargs) # Run test task for this module - if ! ./gradlew "$module:test" $test_args -x checkstyleJmh -x checkstyleMain -x checkstyleTest -x spotlessCheck -x spotlessApply -x spotbugsMain -x spotbugsTest -x javadoc -x javadocJar -x modernizer; then + if ! ./gradlew --no-daemon "$module:test" $test_args -x checkstyleJmh -x checkstyleMain -x checkstyleTest -x spotlessCheck -x spotlessApply -x spotbugsMain -x spotbugsTest -x javadoc -x javadocJar -x modernizer -x buildJavaSdk ; then echo "::error::Tests failed in module $module" FAILED=1 fi diff --git a/.github/workflows/build-mysql.yml b/.github/workflows/build-mysql.yml index 89798cf8a67..1d8f874f4bd 100644 --- a/.github/workflows/build-mysql.yml +++ b/.github/workflows/build-mysql.yml @@ -1,6 +1,7 @@ name: Fineract Cargo & Unit- & Integration tests - MySQL -on: [push, pull_request] +on: + workflow_call: permissions: contents: read @@ -43,25 +44,20 @@ jobs: FINERACT_REPORT_EXPORT_S3_BUCKET_NAME: fineract-reports steps: - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 - fetch-tags: true - - name: Set up JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: java-version: '21' distribution: 'zulu' - - name: Cache Gradle dependencies - uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 + - name: Download workspace + uses: actions/download-artifact@v5 with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + name: fineract-workspace-${{ github.run_id }} + path: . + + - name: Extract workspace + run: tar -xf fineract-workspace.tar - name: Setup Gradle and Validate Wrapper uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 @@ -76,8 +72,8 @@ jobs: - name: Initialise databases run: | - ./gradlew --no-daemon -q createMySQLDB -PdbName=fineract_tenants - ./gradlew --no-daemon -q createMySQLDB -PdbName=fineract_default + ./gradlew --no-daemon -q createMySQLDB -PdbName=fineract_tenants -x buildJavaSdk + ./gradlew --no-daemon -q createMySQLDB -PdbName=fineract_default -x buildJavaSdk - name: Start LocalStack run: | @@ -118,7 +114,7 @@ jobs: test_args=$(for class in ${module_tests[$module]}; do echo --tests "$class"; done | xargs) # Run test task for this module - if ! ./gradlew "$module:test" $test_args -PdbType=mysql -x checkstyleJmh -x checkstyleMain -x checkstyleTest -x spotlessCheck -x spotlessApply -x spotbugsMain -x spotbugsTest -x javadoc -x javadocJar -x modernizer; then + if ! ./gradlew --no-daemon "$module:test" $test_args -PdbType=mysql -x checkstyleJmh -x checkstyleMain -x checkstyleTest -x spotlessCheck -x spotlessApply -x spotbugsMain -x spotbugsTest -x javadoc -x javadocJar -x modernizer -x buildJavaSdk ; then echo "::error::Tests failed in module $module" FAILED=1 fi diff --git a/.github/workflows/build-postgresql.yml b/.github/workflows/build-postgresql.yml index a16a579a1ca..2a6e222039b 100644 --- a/.github/workflows/build-postgresql.yml +++ b/.github/workflows/build-postgresql.yml @@ -1,6 +1,7 @@ name: Fineract Cargo & Unit- & Integration tests - PostgreSQL -on: [push, pull_request] +on: + workflow_call: permissions: contents: read @@ -44,25 +45,20 @@ jobs: FINERACT_REPORT_EXPORT_S3_BUCKET_NAME: fineract-reports steps: - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 - fetch-tags: true - - name: Set up JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: java-version: '21' distribution: 'zulu' - - name: Cache Gradle dependencies - uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 + - name: Download workspace + uses: actions/download-artifact@v5 with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + name: fineract-workspace-${{ github.run_id }} + path: . + + - name: Extract workspace + run: tar -xf fineract-workspace.tar - name: Setup Gradle and Validate Wrapper uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 @@ -77,8 +73,8 @@ jobs: - name: Initialise databases run: | - ./gradlew --no-daemon -q createPGDB -PdbName=fineract_tenants - ./gradlew --no-daemon -q createPGDB -PdbName=fineract_default + ./gradlew --no-daemon -q createPGDB -PdbName=fineract_tenants -x buildJavaSdk + ./gradlew --no-daemon -q createPGDB -PdbName=fineract_default -x buildJavaSdk - name: Start LocalStack run: | @@ -119,7 +115,7 @@ jobs: test_args=$(for class in ${module_tests[$module]}; do echo --tests "$class"; done | xargs) # Run test task for this module - if ! ./gradlew "$module:test" $test_args -PdbType=postgresql -x checkstyleJmh -x checkstyleMain -x checkstyleTest -x spotlessCheck -x spotlessApply -x spotbugsMain -x spotbugsTest -x javadoc -x javadocJar -x modernizer; then + if ! ./gradlew --no-daemon "$module:test" $test_args -PdbType=postgresql -x checkstyleJmh -x checkstyleMain -x checkstyleTest -x spotlessCheck -x spotlessApply -x spotbugsMain -x spotbugsTest -x javadoc -x javadocJar -x modernizer -x buildJavaSdk ; then echo "::error::Tests failed in module $module" FAILED=1 fi diff --git a/.github/workflows/build-progressive-loan.yml b/.github/workflows/build-progressive-loan.yml new file mode 100644 index 00000000000..b9addbdaa3c --- /dev/null +++ b/.github/workflows/build-progressive-loan.yml @@ -0,0 +1,84 @@ +name: Fineract Progressive Loan build + +on: + workflow_call: + +permissions: + contents: read + +jobs: + build-progressive-loan: + runs-on: ubuntu-24.04 + timeout-minutes: 60 + + env: + TZ: Asia/Kolkata + DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} + + steps: + - name: Set up JDK 21 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + java-version: '21' + distribution: 'zulu' + + - name: Download workspace + uses: actions/download-artifact@v5 + with: + name: fineract-workspace-${{ github.run_id }} + path: . + + - name: Extract workspace + run: tar -xf fineract-workspace.tar + + - name: Setup Gradle and Validate Wrapper + uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + with: + validate-wrappers: true + + - name: Build and Test Progressive Loan + run: | + # Build the JAR + ./gradlew --no-daemon --console=plain :fineract-progressive-loan-embeddable-schedule-generator:shadowJar -x buildJavaSdk + + # Store the JAR filename in an environment variable + EMBEDDABLE_JAR_FILE=$(ls fineract-progressive-loan-embeddable-schedule-generator/build/libs/*-all.jar | head -n 1) + echo "EMBEDDABLE_JAR_FILE=$EMBEDDABLE_JAR_FILE" >> $GITHUB_ENV + echo "JAR file: $EMBEDDABLE_JAR_FILE" + + # Run unit tests + ./gradlew --no-daemon --console=plain :fineract-progressive-loan-embeddable-schedule-generator:test -x buildJavaSdk + + # Build and run sample application + mkdir -p sample-app + javac -cp "$EMBEDDABLE_JAR_FILE" -d sample-app fineract-progressive-loan-embeddable-schedule-generator/misc/Main.java + java -cp "$EMBEDDABLE_JAR_FILE:sample-app" Main + java -cp "$EMBEDDABLE_JAR_FILE:sample-app" Main 25 + + - name: Archive test results + if: always() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: test-results-build-progressive-loan + path: | + **/build/reports/ + **/fineract-progressive-loan-embeddable-schedule-generator/build/reports/ + if-no-files-found: ignore + retention-days: 5 + + - name: Archive Progressive Loan JAR + if: always() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: progressive-loan-jar + path: ${{ env.EMBEDDABLE_JAR_FILE }} + retention-days: 5 + if-no-files-found: ignore + + - name: Archive server logs + if: always() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: server-logs-build-progressive-loan + path: '**/build/cargo/' + retention-days: 5 diff --git a/.github/workflows/build-quality-checks.yml b/.github/workflows/build-quality-checks.yml new file mode 100644 index 00000000000..56778b274af --- /dev/null +++ b/.github/workflows/build-quality-checks.yml @@ -0,0 +1,204 @@ +name: Fineract Quality Checks + +on: + workflow_call: + +permissions: + contents: read + +jobs: + javadoc: + runs-on: ubuntu-24.04 + timeout-minutes: 30 + + env: + TZ: Asia/Kolkata + DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} + + steps: + - name: Set up JDK 21 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + java-version: '21' + distribution: 'zulu' + + - name: Download workspace + uses: actions/download-artifact@v5 + with: + name: fineract-workspace-${{ github.run_id }} + path: . + + - name: Extract workspace + run: tar -xf fineract-workspace.tar + + - name: Setup Gradle and Validate Wrapper + uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + with: + validate-wrappers: true + + - name: Generate Javadocs + run: ./gradlew --no-daemon javadoc -x test -x cucumber -x doc -x buildJavaSdk + + - name: Archive Javadoc reports + if: always() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: javadoc-reports-quality-checks + path: '**/build/docs/javadoc/' + if-no-files-found: ignore + retention-days: 5 + + checkstyle: + runs-on: ubuntu-24.04 + timeout-minutes: 30 + + env: + TZ: Asia/Kolkata + DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} + + steps: + - name: Set up JDK 21 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + java-version: '21' + distribution: 'zulu' + + - name: Download workspace + uses: actions/download-artifact@v5 + with: + name: fineract-workspace-${{ github.run_id }} + path: . + + - name: Extract workspace + run: tar -xf fineract-workspace.tar + + - name: Setup Gradle and Validate Wrapper + uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + with: + validate-wrappers: true + + - name: Run Checkstyle + run: ./gradlew --no-daemon checkstyleMain checkstyleTest checkstyleJmh -x test -x cucumber -x doc -x javadoc -x javadocJar -x buildJavaSdk + + - name: Archive Checkstyle reports + if: always() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: checkstyle-reports-quality-checks + path: '**/build/reports/checkstyle/' + if-no-files-found: ignore + retention-days: 5 + + rat: + runs-on: ubuntu-24.04 + timeout-minutes: 30 + + env: + TZ: Asia/Kolkata + DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} + + steps: + - name: Set up JDK 21 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + java-version: '21' + distribution: 'zulu' + + - name: Download workspace + uses: actions/download-artifact@v5 + with: + name: fineract-workspace-${{ github.run_id }} + path: . + + - name: Extract workspace + run: tar -xf fineract-workspace.tar + + - name: Setup Gradle and Validate Wrapper + uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + with: + validate-wrappers: true + + - name: Run RAT + run: ./gradlew --no-daemon rat -x test -x cucumber -x doc -x javadoc -x javadocJar -x buildJavaSdk + + - name: Archive RAT reports + if: always() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: rat-reports-quality-checks + path: '**/build/reports/rat/' + if-no-files-found: ignore + retention-days: 5 + + spotbugs: + runs-on: ubuntu-24.04 + timeout-minutes: 30 + + env: + TZ: Asia/Kolkata + DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} + + steps: + - name: Set up JDK 21 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + java-version: '21' + distribution: 'zulu' + + - name: Download workspace + uses: actions/download-artifact@v5 + with: + name: fineract-workspace-${{ github.run_id }} + path: . + + - name: Extract workspace + run: tar -xf fineract-workspace.tar + + - name: Setup Gradle and Validate Wrapper + uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + with: + validate-wrappers: true + + - name: Run SpotBugs + run: ./gradlew --no-daemon spotbugsMain spotbugsTest -x test -x cucumber -x doc -x javadoc -x javadocJar -x buildJavaSdk + + - name: Archive SpotBugs reports + if: always() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + with: + name: spotbugs-reports-quality-checks + path: '**/build/reports/spotbugs/' + if-no-files-found: ignore + retention-days: 5 + + spotless: + runs-on: ubuntu-24.04 + timeout-minutes: 30 + + env: + TZ: Asia/Kolkata + DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} + + steps: + - name: Set up JDK 21 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + java-version: '21' + distribution: 'zulu' + + - name: Download workspace + uses: actions/download-artifact@v5 + with: + name: fineract-workspace-${{ github.run_id }} + path: . + + - name: Extract workspace + run: tar -xf fineract-workspace.tar + + - name: Setup Gradle and Validate Wrapper + uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 + with: + validate-wrappers: true + + - name: Run Spotless + run: ./gradlew --no-daemon spotlessCheck -x test -x cucumber -x doc -x javadoc -x javadocJar -x buildJavaSdk diff --git a/.github/workflows/full-build-ci.yml b/.github/workflows/full-build-ci.yml new file mode 100644 index 00000000000..bb2defc0d77 --- /dev/null +++ b/.github/workflows/full-build-ci.yml @@ -0,0 +1,92 @@ +name: Fineract CI + +on: [push, pull_request] + +permissions: + contents: read + pull-requests: write + +jobs: + build-core: + uses: ./.github/workflows/build-core.yml + secrets: inherit + + build-embeddable-progressive-loan-jar: + needs: build-core + uses: ./.github/workflows/build-progressive-loan.yml + secrets: inherit + + build-docker-image: + needs: build-core + uses: ./.github/workflows/build-docker.yml + secrets: inherit + + build-documentation: + needs: build-core + uses: ./.github/workflows/build-documentation.yml + secrets: inherit + + run-quality-checks: + needs: build-core + uses: ./.github/workflows/build-quality-checks.yml + secrets: inherit + + run-cucumber-tests: + needs: build-core + uses: ./.github/workflows/build-cucumber.yml + secrets: inherit + + run-integrations-tests-on-postgresql: + needs: build-core + uses: ./.github/workflows/build-postgresql.yml + secrets: inherit + + run-integrations-tests-on-mysql: + needs: build-core + uses: ./.github/workflows/build-mysql.yml + secrets: inherit + + run-integrations-tests-on-mariadb: + needs: build-core + uses: ./.github/workflows/build-mariadb.yml + secrets: inherit + + run-e2e-tests: + needs: build-core + uses: ./.github/workflows/build-e2e-tests.yml + secrets: inherit + + run-liquibase-only-on-postgresql: + needs: build-core + uses: ./.github/workflows/liquibase-only-postgresql.yml + secrets: inherit + + run-messaging-smoke-tests: + needs: build-core + uses: ./.github/workflows/smoke-messaging.yml + secrets: inherit + + run-api-backward-compatibility: + needs: build-core + uses: ./.github/workflows/verify-api-backward-compatibility.yml + secrets: inherit + + run-liquibase-backward-compatibility: + needs: build-core + uses: ./.github/workflows/verify-liquibase-backward-compatibility.yml + secrets: inherit + + run-sonarqube: + needs: build-core + uses: ./.github/workflows/sonarqube.yml + secrets: inherit + + run-integration-tests-sequentially-on-postgresql: + needs: build-core + uses: ./.github/workflows/run-integration-test-sequentially-postgresql.yml + secrets: inherit + + publish-dockerhub: + needs: build-core + uses: ./.github/workflows/publish-dockerhub.yml + secrets: inherit diff --git a/.github/workflows/liquibase-only-postgresql.yml b/.github/workflows/liquibase-only-postgresql.yml index 0461677702b..cd5d1b47609 100644 --- a/.github/workflows/liquibase-only-postgresql.yml +++ b/.github/workflows/liquibase-only-postgresql.yml @@ -1,6 +1,7 @@ name: Fineract Liquibase Only mode - PostgreSQL -on: [push, pull_request] +on: + workflow_call: permissions: contents: read @@ -25,25 +26,20 @@ jobs: DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} steps: - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 - fetch-tags: true - - name: Set up JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: java-version: '21' distribution: 'zulu' - - name: Cache Gradle dependencies - uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 + - name: Download workspace + uses: actions/download-artifact@v5 with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + name: fineract-workspace-${{ github.run_id }} + path: . + + - name: Extract workspace + run: tar -xf fineract-workspace.tar - name: Setup Gradle and Validate Wrapper uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 @@ -58,8 +54,8 @@ jobs: - name: Initialise databases run: | - ./gradlew --no-daemon -q createPGDB -PdbName=fineract_tenants - ./gradlew --no-daemon -q createPGDB -PdbName=fineract_default + ./gradlew --no-daemon -q createPGDB -PdbName=fineract_tenants -x buildJavaSdk + ./gradlew --no-daemon -q createPGDB -PdbName=fineract_default -x buildJavaSdk - name: Run Fineract in Liquibase only mode env: @@ -78,4 +74,4 @@ jobs: FINERACT_HIKARI_USERNAME: "root" SPRING_PROFILES_ACTIVE: "liquibase-only" run: - ./gradlew fineract-provider:bootRun + ./gradlew --no-daemon fineract-provider:bootRun -x buildJavaSdk diff --git a/.github/workflows/mifos-fineract-client-publish.yml b/.github/workflows/mifos-fineract-client-publish.yml index 9b980ee4ff9..4f27e8a1ed5 100644 --- a/.github/workflows/mifos-fineract-client-publish.yml +++ b/.github/workflows/mifos-fineract-client-publish.yml @@ -33,4 +33,4 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 - name: Build the image - run: ./gradlew publish -Pfineract.config.username=$ARTIFACTORY_USERNAME -Pfineract.config.password=$ARTIFACTORY_PASSWORD -Pfineract.release.version=${BUILD_NUMBER} + run: ./gradlew --no-daemon publish -Pfineract.config.username=$ARTIFACTORY_USERNAME -Pfineract.config.password=$ARTIFACTORY_PASSWORD -Pfineract.release.version=${BUILD_NUMBER} -x buildJavaSdk diff --git a/.github/workflows/publish-dockerhub.yml b/.github/workflows/publish-dockerhub.yml index e38c399bc68..e610bdcb1ee 100644 --- a/.github/workflows/publish-dockerhub.yml +++ b/.github/workflows/publish-dockerhub.yml @@ -1,30 +1,31 @@ name: Fineract Publish to DockerHub on: - push: - branches: - - develop - tags: - - 1.* + workflow_call: permissions: contents: read jobs: build: + if: ${{ github.event_name == 'push' && (github.ref_name == 'develop' || startsWith(github.ref_name, '1.')) }} runs-on: ubuntu-24.04 timeout-minutes: 60 env: DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} steps: - - name: Checkout Source Code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 - - name: Set up JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: java-version: '21' distribution: 'zulu' + - name: Download workspace + uses: actions/download-artifact@v5 + with: + name: fineract-workspace-${{ github.run_id }} + path: . + + - name: Extract workspace + run: tar -xf fineract-workspace.tar + - name: Setup Gradle uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 @@ -37,10 +38,16 @@ jobs: - name: Build the Apache Fineract image run: | TAGS=${{ github.ref_name }} - if [ "${{ github.ref_name }}" == "develop" ]; then + if [ "$TAGS" == "develop" ]; then TAGS="$TAGS,${{ steps.git_hashes.outputs.short_hash }},${{ steps.git_hashes.outputs.long_hash }}" + else + TAGS=$(git tag --points-at HEAD | grep -E '^1\.' | head -n 1 || true) + if [ -z "$TAGS" ]; then + echo "Skipping DockerHub publish because this run is not for develop or a 1.* tag." + exit 0 + fi fi - ./gradlew --no-daemon --console=plain :fineract-provider:jib -x test -x cucumber \ + ./gradlew --no-daemon --console=plain :fineract-provider:jib -x test -x cucumber -x buildJavaSdk \ -Djib.to.auth.username=${{secrets.DOCKERHUB_USER}} \ -Djib.to.auth.password=${{secrets.DOCKERHUB_TOKEN}} \ -Djib.from.platforms=linux/amd64,linux/arm64 \ diff --git a/.github/workflows/run-integration-test-sequentially-postgresql.yml b/.github/workflows/run-integration-test-sequentially-postgresql.yml index 32ead6b9254..0b601254456 100644 --- a/.github/workflows/run-integration-test-sequentially-postgresql.yml +++ b/.github/workflows/run-integration-test-sequentially-postgresql.yml @@ -1,14 +1,12 @@ name: Fineract Cargo & Unit- & Integration tests - Sequential Execution - PostgreSQL on: - workflow_dispatch: - push: - branches: - - develop + workflow_call: permissions: contents: read jobs: build: + if: ${{ github.event_name == 'push' && github.ref_name == 'develop' }} runs-on: ubuntu-24.04 timeout-minutes: 180 @@ -32,17 +30,18 @@ jobs: TZ: Asia/Kolkata DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} steps: - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 - fetch-tags: true - - name: Set up JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: java-version: '21' distribution: 'zulu' + - name: Download workspace + uses: actions/download-artifact@v5 + with: + name: fineract-workspace-${{ github.run_id }} + path: . + - name: Extract workspace + run: tar -xf fineract-workspace.tar - name: Setup Gradle and Validate Wrapper uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 with: @@ -54,8 +53,8 @@ jobs: done - name: Initialise databases run: | - ./gradlew --no-daemon -q createPGDB -PdbName=fineract_tenants - ./gradlew --no-daemon -q createPGDB -PdbName=fineract_default + ./gradlew --no-daemon -q createPGDB -PdbName=fineract_tenants -x buildJavaSdk + ./gradlew --no-daemon -q createPGDB -PdbName=fineract_default -x buildJavaSdk - name: Start LocalStack env: @@ -77,11 +76,10 @@ jobs: FINERACT_REPORT_EXPORT_S3_ENABLED: true FINERACT_REPORT_EXPORT_S3_BUCKET_NAME: fineract-reports run: | - ./gradlew --no-daemon --console=plain build -x cucumber -x test -x doc - ./gradlew --no-daemon --console=plain cucumber -x :fineract-e2e-tests-runner:cucumber - ./gradlew --no-daemon --console=plain test -x :twofactor-tests:test -x :oauth2-test:test -x :fineract-e2e-tests-runner:test -PdbType=postgresql - ./gradlew --no-daemon --console=plain :twofactor-tests:test -PdbType=postgresql - ./gradlew --no-daemon --console=plain :oauth2-tests:test -PdbType=postgresql + ./gradlew --no-daemon --console=plain cucumber -x :fineract-e2e-tests-runner:cucumber -x buildJavaSdk + ./gradlew --no-daemon --console=plain test -x :twofactor-tests:test -x :oauth2-test:test -x :fineract-e2e-tests-runner:test -PdbType=postgresql -x buildJavaSdk + ./gradlew --no-daemon --console=plain :twofactor-tests:test -PdbType=postgresql -x buildJavaSdk + ./gradlew --no-daemon --console=plain :oauth2-tests:test -PdbType=postgresql -x buildJavaSdk - name: Archive test results if: always() uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 diff --git a/.github/workflows/smoke-messaging.yml b/.github/workflows/smoke-messaging.yml index c74daad6c20..14c9b7f25f0 100644 --- a/.github/workflows/smoke-messaging.yml +++ b/.github/workflows/smoke-messaging.yml @@ -1,6 +1,7 @@ name: Fineract Messaging Smoke Tests -on: [push, pull_request] +on: + workflow_call: permissions: contents: read @@ -24,21 +25,32 @@ jobs: IMAGE_NAME: fineract steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 - - name: Set up JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: java-version: '21' distribution: 'zulu' + - name: Download workspace + uses: actions/download-artifact@v5 + with: + name: fineract-workspace-${{ github.run_id }} + path: . + + - name: Extract workspace + run: tar -xf fineract-workspace.tar + - name: Setup Gradle uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 - name: Build the image - run: ./gradlew --no-daemon --console=plain :fineract-provider:jibDockerBuild -Djib.to.image=$IMAGE_NAME -x test -x cucumber + run: ./gradlew --no-daemon --console=plain :fineract-provider:jibDockerBuild -Djib.to.image=$IMAGE_NAME -x test -x cucumber -x buildJavaSdk + + - name: Verify git.properties in image + run: | + docker create --name fineract-inspect $IMAGE_NAME + docker export fineract-inspect | tar -tf - | grep 'git.properties' + docker rm fineract-inspect - name: Start the ${{ matrix.messaging }} Stack run: docker compose -f ${{ matrix.compose_file }} up --scale fineract-worker=1 -d @@ -53,10 +65,16 @@ jobs: run: curl -f -k --retry 60 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8444/fineract-provider/actuator/health - name: Check info Manager - run: (( $(curl -f -k --retry 5 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/info | wc --chars) > 100 )) + run: | + curl -f -k --retry 5 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8443/fineract-provider/actuator/info -o actuator-info-manager.json + cat actuator-info-manager.json + jq -e '.git | type == "object"' actuator-info-manager.json - name: Check info Worker1 - run: (( $(curl -f -k --retry 5 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8444/fineract-provider/actuator/info | wc --chars) > 100 )) + run: | + curl -f -k --retry 5 --retry-all-errors --connect-timeout 30 --retry-delay 30 https://localhost:8444/fineract-provider/actuator/info -o actuator-info-worker1.json + cat actuator-info-worker1.json + jq -e '.git | type == "object"' actuator-info-worker1.json - name: Run Smoke Test with Remote COB - run: ./gradlew --no-daemon --console=plain :integration-tests:cleanTest :integration-tests:test --tests "org.apache.fineract.integrationtests.investor.externalassetowner.InitiateExternalAssetOwnerTransferTest.saleActiveLoanToExternalAssetOwnerAndBuybackADayLater" -PcargoDisabled + run: ./gradlew --no-daemon --console=plain :integration-tests:cleanTest :integration-tests:test --tests "org.apache.fineract.integrationtests.investor.externalassetowner.InitiateExternalAssetOwnerTransferTest.saleActiveLoanToExternalAssetOwnerAndBuybackADayLater" -PcargoDisabled -x buildJavaSdk diff --git a/.github/workflows/sonarqube.yml b/.github/workflows/sonarqube.yml index c48ee8e94d5..c42e6e173d9 100644 --- a/.github/workflows/sonarqube.yml +++ b/.github/workflows/sonarqube.yml @@ -1,12 +1,11 @@ name: Fineract Sonarqube on: - push: - branches: - - develop + workflow_call: permissions: contents: read jobs: build: + if: ${{ github.event_name == 'push' && github.ref_name == 'develop' }} runs-on: ubuntu-24.04 timeout-minutes: 60 env: @@ -19,20 +18,21 @@ jobs: DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_ACCESS_KEY }} JAVA_BINARIES: . steps: - - name: Checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 - name: Set up JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: java-version: '21' distribution: 'zulu' + - name: Download workspace + uses: actions/download-artifact@v5 + with: + name: fineract-workspace-${{ github.run_id }} + path: . + - name: Extract workspace + run: tar -xf fineract-workspace.tar - name: Setup Gradle and Validate Wrapper uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 with: validate-wrappers: true - - name: Build - run: ./gradlew --no-daemon --console=plain :fineract-provider:build -x test -x cucumber - name: Sonar - run: ./gradlew --no-daemon --console=plain -Dsonar.verbose=true -Dsonar.token=$SONAR_TOKEN -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.organization=$SONAR_ORGANIZATION -Dsonar.projectKey=$SONAR_PROJECT_KEY -Dsonar.java.binaries=$JAVA_BINARIES --info --stacktrace sonar + run: ./gradlew --no-daemon --console=plain -Dsonar.verbose=true -Dsonar.token=$SONAR_TOKEN -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.organization=$SONAR_ORGANIZATION -Dsonar.projectKey=$SONAR_PROJECT_KEY -Dsonar.java.binaries=$JAVA_BINARIES --info --stacktrace sonar -x buildJavaSdk diff --git a/.github/workflows/verify-api-backward-compatibility.yml b/.github/workflows/verify-api-backward-compatibility.yml index 66026da22a6..03c1cb47677 100644 --- a/.github/workflows/verify-api-backward-compatibility.yml +++ b/.github/workflows/verify-api-backward-compatibility.yml @@ -1,6 +1,7 @@ name: Verify API Backward Compatibility -on: [pull_request] +on: + workflow_call: permissions: contents: read @@ -8,6 +9,7 @@ permissions: jobs: api-compatibility-check: + if: ${{ github.event_name == 'pull_request' }} runs-on: ubuntu-24.04 timeout-minutes: 30 @@ -23,24 +25,16 @@ jobs: fetch-depth: 0 path: baseline - - name: Checkout PR branch - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - repository: ${{ github.event.pull_request.head.repo.full_name }} - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 - path: current - - name: Compute merge-base commit id: merge-base run: | cd baseline - # For fork PRs, fetch PR head from the local current/ checkout - git fetch "${GITHUB_WORKSPACE}/current" HEAD --no-tags 2>/dev/null || true - MERGE_BASE=$(git merge-base ${{ github.event.pull_request.base.ref }} ${{ github.event.pull_request.head.sha }}) + git fetch "https://github.com/${{ github.event.pull_request.head.repo.full_name }}.git" \ + "${{ github.event.pull_request.head.ref }}:refs/remotes/pr-head" --no-tags + MERGE_BASE=$(git merge-base "origin/${{ github.event.pull_request.base.ref }}" "refs/remotes/pr-head") echo "Merge-base commit: ${MERGE_BASE}" echo "sha=${MERGE_BASE}" >> "$GITHUB_OUTPUT" - BASE_HEAD=$(git rev-parse ${{ github.event.pull_request.base.ref }}) + BASE_HEAD=$(git rev-parse "origin/${{ github.event.pull_request.base.ref }}") if [ "${MERGE_BASE}" != "${BASE_HEAD}" ]; then echo "::notice::PR is not rebased on latest ${{ github.event.pull_request.base.ref }}. Using merge-base ${MERGE_BASE} as baseline (branch HEAD: ${BASE_HEAD})." fi @@ -55,14 +49,19 @@ jobs: distribution: 'zulu' java-version: '21' + - name: Download workspace + uses: actions/download-artifact@v5 + with: + name: fineract-workspace-${{ github.run_id }} + path: . + + - name: Extract workspace + run: tar -xf fineract-workspace.tar + - name: Generate baseline spec working-directory: baseline run: ./gradlew :fineract-provider:resolve --no-daemon - - name: Generate PR spec - working-directory: current - run: ./gradlew :fineract-provider:resolve --no-daemon - - name: Sanitize specs run: | python3 -c " @@ -86,25 +85,28 @@ jobs: print(f'{path}: fixed {fixed} entries') sanitize('${GITHUB_WORKSPACE}/baseline/fineract-provider/build/resources/main/static/fineract.json') - sanitize('${GITHUB_WORKSPACE}/current/fineract-provider/build/resources/main/static/fineract.json') + sanitize('${GITHUB_WORKSPACE}/fineract-provider/build/resources/main/static/fineract.json') " - name: Check breaking changes id: breaking-check continue-on-error: true - working-directory: current run: | set -o pipefail - ./gradlew :fineract-provider:checkBreakingChanges \ + ./gradlew --no-daemon :fineract-provider:checkBreakingChanges \ -PapiBaseline="${GITHUB_WORKSPACE}/baseline/fineract-provider/build/resources/main/static/fineract.json" \ - -PapiNew="${GITHUB_WORKSPACE}/current/fineract-provider/build/resources/main/static/fineract.json" \ - --no-daemon + -PapiNew="${GITHUB_WORKSPACE}/fineract-provider/build/resources/main/static/fineract.json" \ + --no-daemon \ + -x buildJavaSdk \ + -x :fineract-client:buildJavaSdk \ + -x :fineract-client-feign:buildJavaSdk \ + -x :fineract-avro-schemas:buildJavaSdk - name: Build report if: steps.breaking-check.outcome == 'failure' id: report run: | - REPORT_DIR="current/fineract-provider/build/swagger-brake" + REPORT_DIR="fineract-provider/build/swagger-brake" python3 -c " import json, glob, os @@ -234,7 +236,7 @@ jobs: uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: api-compatibility-report - path: current/fineract-provider/build/swagger-brake/ + path: fineract-provider/build/swagger-brake/ retention-days: 30 - name: Fail if breaking changes detected diff --git a/.github/workflows/verify-liquibase-backward-compatibility.yml b/.github/workflows/verify-liquibase-backward-compatibility.yml index 744bf27e074..d945253229b 100644 --- a/.github/workflows/verify-liquibase-backward-compatibility.yml +++ b/.github/workflows/verify-liquibase-backward-compatibility.yml @@ -1,12 +1,14 @@ name: Verify Liquibase Backward Compatibility -on: [pull_request] +on: + workflow_call: permissions: contents: read jobs: liquibase-backward-compatibility-check: + if: ${{ github.event_name == 'pull_request' }} runs-on: ubuntu-24.04 timeout-minutes: 30 @@ -39,19 +41,21 @@ jobs: fetch-depth: 0 path: baseline - - name: Checkout PR merge commit - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - ref: ${{ github.sha }} - fetch-depth: 0 - path: current - - name: Set up JDK 21 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 with: distribution: 'zulu' java-version: '21' + - name: Download workspace + uses: actions/download-artifact@v5 + with: + name: fineract-workspace-${{ github.run_id }} + path: . + + - name: Extract workspace + run: tar -xf fineract-workspace.tar + - name: Wait for PostgreSQL run: | until pg_isready -h localhost -U $DB_USER; do @@ -72,19 +76,19 @@ jobs: echo "${{ github.event.pull_request.base.sha }}" echo "PR head SHA:" echo "${{ github.event.pull_request.head.sha }}" - echo "GitHub merge SHA:" - echo "${{ github.sha }}" + echo "GitHub PR merge ref:" + echo "refs/pull/${{ github.event.pull_request.number }}/merge" echo "Baseline revision:" git -C baseline rev-parse HEAD git -C baseline log -1 --oneline echo "Merged PR revision:" - git -C current rev-parse HEAD - git -C current log -1 --oneline + git rev-parse HEAD + git log -1 --oneline - name: Start backend on base commit working-directory: baseline run: | - ./gradlew :fineract-provider:devRun --args="\ + ./gradlew --no-daemon :fineract-provider:devRun --args="\ --spring.datasource.hikari.driverClassName=org.postgresql.Driver \ --spring.datasource.hikari.jdbcUrl=jdbc:postgresql://localhost:5432/fineract_tenants \ --spring.datasource.hikari.username=root \ @@ -132,9 +136,8 @@ jobs: sleep 10 - name: Start backend on merged PR commit - working-directory: current run: | - ./gradlew :fineract-provider:devRun --args="\ + ./gradlew --no-daemon :fineract-provider:devRun --args="\ --spring.datasource.hikari.driverClassName=org.postgresql.Driver \ --spring.datasource.hikari.jdbcUrl=jdbc:postgresql://localhost:5432/fineract_tenants \ --spring.datasource.hikari.username=root \ @@ -176,7 +179,6 @@ jobs: - name: Stop PR backend if: always() - working-directory: current run: | kill $(cat backend.pid) sleep 10 diff --git a/build.gradle b/build.gradle index 08bc0c24bf4..6d153b01345 100644 --- a/build.gradle +++ b/build.gradle @@ -558,6 +558,14 @@ configure(project.fineractJavaProjects) { checkstyle 'com.github.sevntu-checkstyle:sevntu-checks:1.44.1' } + tasks.withType(org.gradle.api.plugins.quality.Checkstyle).configureEach { + exclude("**/*.avsc") + + if (project.path.startsWith(':custom:acme:')) { + enabled = false + } + } + // Configuration for JaCoCo code coverage task // https://www.eclemma.org/jacoco/ jacoco { @@ -759,6 +767,11 @@ configure(project.fineractJavaProjects) { } } } + tasks.withType(com.github.spotbugs.snom.SpotBugsTask).configureEach { + if (project.path.startsWith(':custom:acme:')) { + enabled = false + } + } // Configuration for https://github.com/andygoossens/gradle-modernizer-plugin modernizer { @@ -934,7 +947,3 @@ tasks.register('printSourceSetInformation') { } } } - -tasks.withType(Checkstyle).configureEach { - exclude("**/*.avsc") -} diff --git a/fineract-client-feign/build.gradle b/fineract-client-feign/build.gradle index c158b75aa68..26021aaed8d 100644 --- a/fineract-client-feign/build.gradle +++ b/fineract-client-feign/build.gradle @@ -92,20 +92,23 @@ task cleanupGeneratedJavaFiles() { def tempDir = file("$buildDir/generated/temp-java") def targetDir = file("$buildDir/generated/java") - inputs.dir(tempDir) + inputs.dir(tempDir).optional() outputs.dir(targetDir) + onlyIf { tempDir.exists() } doLast { - copy { - from tempDir - into targetDir - filter { line -> - line - .replaceAll(", \\)", ")") - .replaceAll(", , @HeaderMap", ", @HeaderMap") - .replaceAll("\\(, ", "(") + if (tempDir.exists()) { + copy { + from tempDir + into targetDir + filter { line -> + line + .replaceAll(", \\)", ")") + .replaceAll(", , @HeaderMap", ", @HeaderMap") + .replaceAll("\\(, ", "(") + } + duplicatesStrategy = DuplicatesStrategy.EXCLUDE } - duplicatesStrategy = DuplicatesStrategy.EXCLUDE } } dependsOn("buildJavaSdk") diff --git a/fineract-client/build.gradle b/fineract-client/build.gradle index 4acfe358a29..24025ae321d 100644 --- a/fineract-client/build.gradle +++ b/fineract-client/build.gradle @@ -49,6 +49,14 @@ idea { } } +spotbugsMain { + enabled = false +} + +spotbugsTest { + enabled = false +} + task buildJavaSdk(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask) { generatorName = 'java' verbose = false @@ -150,31 +158,38 @@ task cleanupGeneratedJavaFiles() { def tempDir = file("$buildDir/generated/temp-java") def targetDir = file("$buildDir/generated/java") - inputs.dir(tempDir) + inputs.dir(tempDir).optional() outputs.dir(targetDir) + onlyIf { tempDir.exists() } //TODO: remove harcoded, autogenerated Oltu's OAuthOkHttpClient.java from the generated files doFirst { - delete fileTree(tempDir) { - include "src/main/java/org/apache/fineract/client/auth/OAuthOkHttpClient.java" + if (tempDir.exists()) { + delete fileTree(tempDir) { + include "src/main/java/org/apache/fineract/client/auth/OAuthOkHttpClient.java" + } } - delete fileTree(targetDir) { - include "src/main/java/org/apache/fineract/client/auth/OAuthOkHttpClient.java" + if (targetDir.exists()) { + delete fileTree(targetDir) { + include "src/main/java/org/apache/fineract/client/auth/OAuthOkHttpClient.java" + } } } doLast { - copy { - from tempDir - into targetDir - filter { line -> - line - .replaceAll("import org\\.joda\\.time\\.\\*;", "") - .replaceAll(", \\)", ")") - .replaceAll(", , @HeaderMap", ", @HeaderMap") - .replaceAll("\\(, ", "(") + if (tempDir.exists()) { + copy { + from tempDir + into targetDir + filter { line -> + line + .replaceAll("import org\\.joda\\.time\\.\\*;", "") + .replaceAll(", \\)", ")") + .replaceAll(", , @HeaderMap", ", @HeaderMap") + .replaceAll("\\(, ", "(") + } + // Also set duplicates strategy for the copy task + duplicatesStrategy = DuplicatesStrategy.EXCLUDE } - // Also set duplicates strategy for the copy task - duplicatesStrategy = DuplicatesStrategy.EXCLUDE } } dependsOn("buildJavaSdk") diff --git a/fineract-provider/build.gradle b/fineract-provider/build.gradle index 576b921210b..4307e747b80 100644 --- a/fineract-provider/build.gradle +++ b/fineract-provider/build.gradle @@ -340,20 +340,19 @@ cucumber { ] } -tasks.jib.dependsOn(bootJar, resolve) -tasks.jibDockerBuild.dependsOn(bootJar, resolve) +tasks.jib.dependsOn(bootJar, resolve, generateGitProperties) +tasks.jibDockerBuild.dependsOn(bootJar, resolve, generateGitProperties) // Configuration for git properties gradle plugin // https://github.com/n0mer/gradle-git-properties gitProperties { - gitPropertiesResourceDir = file("$buildDir/classes/java/main") + gitPropertiesResourceDir = file("$buildDir/resources/main") dateFormat = "yyyy-MM-dd'T'HH:mmZ" dateFormatTimeZone = "GMT" failOnNoGitDirectory = false } -// make sure the generateGitProperties task always executes (even when git.properties is not changed) -generateGitProperties.outputs.upToDateWhen { false } +processResources.dependsOn generateGitProperties // NOTE: Gradle suggested these dependencies jar.dependsOn resolve diff --git a/gradle.properties b/gradle.properties index 92840b1c2bd..70829cbd9bb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,13 +16,13 @@ # specific language governing permissions and limitations # under the License. # -org.gradle.jvmargs=-Xmx12g --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.management/javax.management=ALL-UNNAMED --add-opens=java.naming/javax.naming=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=null +org.gradle.jvmargs=-Xmx8g --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.management/javax.management=ALL-UNNAMED --add-opens=java.naming/javax.naming=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=null buildType=BUILD org.gradle.caching=true org.gradle.parallel=true # Keep worker concurrency below CPU count to avoid heap spikes from parallel project tasks # and forked Java compilation running alongside Avro code generation. -org.gradle.workers.max=4 +#org.gradle.workers.max=4 org.gradle.daemon.idletimeout=10800000 # Temporarily disabled until we fix configuration cache compatibility #org.gradle.configuration-cache=true