Skip to content

FINERACT-2686: update docs and build for next release#6123

Open
meonkeys wants to merge 9 commits into
apache:developfrom
meonkeys:q-1.15.0-companion
Open

FINERACT-2686: update docs and build for next release#6123
meonkeys wants to merge 9 commits into
apache:developfrom
meonkeys:q-1.15.0-companion

Conversation

@meonkeys

Copy link
Copy Markdown
Contributor

Description

FINERACT-2686

Checklist

Please make sure these boxes are checked before submitting your pull request - thanks!

  • Write the commit message as per our guidelines
  • Acknowledge that we will not review PRs that are not passing the build ("green") - it is your responsibility to get a proposed PR to pass the build, not primarily the project's maintainers.
  • Create/update unit or integration tests for verifying the changes made.
  • Follow our coding conventions.
  • Add required Swagger annotation and update API documentation at fineract-provider/src/main/resources/static/legacy-docs/apiLive.htm with details of any API changes
  • This PR must not be a "code dump". Large changes can be made in a branch, with assistance. Ask for help on the developer mailing list.
  • If merging this PR resolves a JIRA issue, I will mark that issue as resolved and set "Fix Version/s" appropriately.

meonkeys added 9 commits July 10, 2026 10:50
Git checkout is confusing. It does too many things. The relatively new
`git switch` (for switching branches) is clearer. Easier to teach,
learn, and remember. Yes there's some muscle memory to update, that's
OK. And yes the very conservative git-switch(1) and git-restore(1)
manual pages say they are experimental, they are more or less canon by
now.

More on `git checkout` vs. `git switch` and `git restore`:

* https://www.infoq.com/news/2019/08/git-2-23-switch-restore/
* https://stackoverflow.com/questions/57265785/whats-the-difference-between-git-switch-and-git-checkout-branch
This avoids an issue running `./gradlew generateLicenseReport` multiple
times (something I'm having to do while working on the 1.15.0 release).
The issue I was seeing was:

    Error while evaluating property 'classpath' of task ':custom:generateLicenseReport'.
       java.util.ConcurrentModificationException (no error message)

Claude identified the problem and created the patch (model=Sonnet 5,
effort=High). Claude said:

    This is a runaway self-amplifying bug in the dynamic "custom module"
    project-discovery logic, not a transient Gradle glitch.

    The chain of events:

    1. build.gradle:280-282 applies
       com.github.jk1.dependency-license-report to every project
       (allprojects) and sets licenseReport.outputDir =
       "$projectDir/licenses".
    2. settings.gradle:90-99 dynamically walks
       custom/<company>/<category>/<module> and includes each combo as a
       project — but only excludes directories named build or docker. It
       does not exclude licenses.
    3. Because past runs already wrote license report output (including
       unpacked per-jar license files) into custom/licenses/...,
       custom/acme/licenses/..., etc., those output folders now look
       like valid company/category/module paths to the settings.gradle
       scanner. Gradle happily registers hundreds of bogus phantom
       projects like :custom:licenses:commons-lang3-3.20.0.jar:META-INF
       and :custom:acme:licenses:spring-core-6.2.18.jar.
    4. build.gradle:378-392 does the same directory walk and applies the
       full java plugin to every one of those phantom projects via
       configure(project.fineractJavaProjects) { apply plugin: 'java'
       ... }.
    5. Since license-report is on allprojects, each phantom project gets
       its own generateLicenseReport task whose output again lands at
       $projectDir/licenses — nesting the mess one level deeper every
       time the task runs (I found
       custom/acme/licenses/licenses/licenses on disk — 3 generations
       deep already).

    I confirmed this directly: running ./gradlew generateLicenseReport
    --parallel just now produced 812 actionable tasks, most named after
    individual jar files
    (:custom:licenses:commons-lang3-3.20.0.jar:META-INF:generateLicenseReport,
    etc.) — these should not exist as Gradle projects at all.

    With org.gradle.parallel=true set in gradle.properties, Gradle
    executes hundreds of these bogus generateLicenseReport tasks
    concurrently. At that scale, a thread-safety bug (in Gradle's
    dependency-resolution internals or the gradle-license-report 2.9
    plugin itself) gets tripped, surfacing as the
    ConcurrentModificationException on the classpath property — it's a
    race condition, which is why running the single task in isolation
    just now succeeded fine.

    I verified these licenses directories under custom/ are
    untracked/gitignored build output (not committed), so deleting them
    is safe.

    Proposed fix (two parts):

    1. Cleanup: delete all the runaway custom/**/licenses directories so
       the phantom projects disappear.
    2. Root-cause patch: harden the eachDir walks in settings.gradle and
       build.gradle to only treat a directory as a real custom module if
       it actually contains a build.gradle file (robust against any
       future output-directory name), or at minimum also exclude
       licenses.

I reviewed and tested the code and it all LGTM, but just a
heads up that I'm not an expert with Gradle nor the Fineract build.

I don't need this fix to release 1.15.0, I can just manually do this for
now:

    git clean -fdx custom
and fix the reference to "what you will ask the community to do in..."
1. Signing is no longer optional.
2. Might be better to wait to push the tag until just before vote.
things changed a bit since FSIP-7
maybe we will once it moves to beta or GA
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant